No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Caso práctico: servicios financieros

4/11
Recursos

Los tokens son activos digitales que necesitan una crypto subyacente que los respalde y pueden representar el valor digital de lo que imagines en Internet. Por ejemplo, puntos en un juego, votos, el nivel de habilidad de un personaje, reputación, o realmente lo que se te ocurra.

En una Blockchain se pueden representar activos económicos a través de criptomonedas o tokens. Estos también permiten interactuar con un contrato inteligente para intercambiarlos, crear más tokens, destruirlos o participar de cualquier tipo de regla de negocio.

Criptomonedas vs. Tokens

Las criptomonedas no son lo mismo que un token. Existe una delgada línea entre ambos y podemos confundirlos al principio.

Una criptomoneda es el activo digital nativo que vive en una Blockchain, mientras que los tokens requieren de una crypto y de una Blockchain para existir.

Un ejemplo de criptomoneda es Ether o ETH de la Blockchain de Ethereum. En este sistema podrás encontrar tokens como USDT, USDC, DAI o BUSD.

Características de los tokens

Los tokens comparten características con el dinero de cualquier país con el fin de convertirse en activos financieros.

  1. Divisibilidad del mismo, un solo token se puede dividir en pequeñas partes, igual que el peso o el dólar se divide en centavos.
  2. Fungibilidad, es decir, que no existen propiedades que distingan a una moneda de otra. Ocurre igual que como un dólar vale lo mismo que otro, un lingote de oro vale lo mismo que otro y un token vale lo mismo que otro de la misma colección.

Creación de tokens

Crear una criptomoneda nueva implica necesitar de toda una Blockchain para que la misma exista. Con todos los desafíos que implica, como la infraestructura, descentralización, protocolos de consenso, por solo nombrar algunos requisitos técnicos.

Es mucho más fácil crear un nuevo token y para esto existen estándares a seguir para lograrlo.

El estándar por excelencia para la creación de tokens es denominado ERC20, proveniente de la propuesta EIP20. La misma estandarizó una interfaz y características de cómo deben ser los tokens que viven en la Blockchain de Ethereum.

Implementando el estándar ERC20

Para cumplir con el estándar, se exige que el token implemente los siguientes métodos y eventos.

function name() public view returns (string)
function symbol() public view returns (string)
function decimals() public view returns (uint8)
function totalSupply() public view returns (uint256)
function balanceOf(address _owner) public view returns (uint256 balance)
function transfer(address _to, uint256 _value) public returns (bool success)
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
function approve(address _spender, uint256 _value) public returns (bool success)
function allowance(address _owner, address _spender) public view returns (uint256 remaining)
event Transfer(address indexed _from, address indexed _to, uint256 _value)
event Approval(address indexed _owner, address indexed _spender, uint256 _value)

De esta manera, puede considerarse que el token hereda del estándar ERC20 y es compatible con gran parte del ecosistema de Ethereum.

Como desarrolladores de software, podemos implementar nosotros mismos cada función del estándar, o bien, utilizar una implementación de un tercero. Empresas como OpenZeppelin ofrecen una implementación del estándar ERC20 auditada por la comunidad y lista para usarse en nuestros contratos.

Economía de tokens

Te preguntarás qué es lo que hace que el precio de una criptomoneda o token suba y baje. Detrás de eso existen un nuevo concepto denominado Tokenomics o Economía de Tokens y está relacionado con la usabilidad del token, liquidez, intercambio, gobernanza, etc.

Muchos conceptos de las finanzas tradicionales, también aplican a este tipo de activos financieros. Como la oferta y demanda o el funcionamiento de un mercado económicos. Platzi tiene mucho para enseñarte al respecto iniciando por el Curso de Introducción al Análisis Técnico de Mercados Financieros.

Desafío de los servicios financieros

Si bien podemos utilizar implementaciones del estándar ERC20 de terceros e incluso es lo más recomendable dado que son contratos seguros y auditados, es un buen ejercicio realizar la implementación del estándar por nuestra cuenta para aprender más al respecto sobre cómo funciona por detrás.

También podemos investigar cómo funcionan los proyectos DeFi más populares como Aave o Uniswap. Aprender poco a poco la teoría y los fundamentos para posteriormente investigar sus contratos y así poder desarrollar nuestros propios contratos inteligentes DeFi.


Contribución creada por: Kevin Fiorentino.

Aportes 7

Preguntas 3

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Este curso es super interesante…

Es muy interesante poder desarrollar nosotros mismos el estandar ERC20. Más allá de que podemos utilizar las implementaciones ya auditadas como la de OpenZeppelin. Es muy valioso ver una aproximación a cómo se desarrolla este tipo de estándares.

El total supply debe estar multiplicado por 10 elevado a la cantidad de decimales del token.

Para el ejemplo mostrado colocar la variable decimals no cambia el funcionamiento del contrato. En el estandar ERC20 no hay una variable, sino una función llamada decimals ( ) que devuelve el numero de decimales que debe tener el token creado. Mientras que en los contratos se trabaja con la minima unidad entera soportada en solidity (wei), a los usuarios se les muestra un valor con decimales. La funcion decimals ( ) es para mejorar la usabilidad del usuario como en los exploradores de bloques o Metamask, para que no tengan que lidiar con numeros grandes.

RESUMEN CLASE 4:
CASO PRACTICO
SERVICIOS FINANCIEROS

REMIX:

Balance.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;

contract TokenBasic {
    string public constant name = "PlatziCoin";
    string public constant symbol = "PZC";
    uint8 public constant decimals = 18;

    uint256 _totalSupply;

    mapping(address => uint256) balances;
    mapping(address => mapping(address => uint256)) allowed;

    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(
        address indexed _owner,
        address indexed _spender,
        uint256 _value
    );

    constructor(uint256 total) {
        _totalSupply = total;
        balances[msg.sender] = total;
    }

    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address _owner) public view returns (uint256) {
        return balances[_owner];
    }

    function transfer(address _to, uint256 _value)
        public
        returns (bool success)
    {
        require(
            _value <= balances[msg.sender],
            "There are not enough funds to do the transfer"
        );
        balances[msg.sender] = balances[msg.sender] - _value;
        balances[_to] = balances[_to] + _value;
        emit Transfer(msg.sender, _to, _value);
        success = true;
    }

    function approve(address _spender, uint256 _value)
        public
        returns (bool success)
    {
        allowed[msg.sender][_spender] = _value;
        emit Approval(msg.sender, _spender, _value);
        success = true;
    }

    function allowance(address _owner, address _spender)
        public
        view
        returns (uint256 remaining)
    {
        remaining = allowed[_owner][_spender];
    }

    function transferFrom(
        address _from,
        address _to,
        uint256 _value
    ) public returns (bool success) {
        require(
            _value <= balances[_from],
            "There are not enough funds to do the transfer"
        );
        require(_value <= allowed[_from][msg.sender], "Sender not allowed");

        balances[_from] = balances[_from] - _value;
        allowed[_from][msg.sender] = allowed[_from][msg.sender] - _value;
        balances[_to] = balances[_to] + _value;
        emit Transfer(_from, _to, _value);
        success = true;
    }
}
Creee un contrato nuevo basado en el estandat ERC-20 este tiene 3 modificaciones especiales las cuales me di a la tarea de investigar y de contemplar como posibles mejoras a un token la primera es que para usar al momento de despliegue del contrato en alguno red el monto como supply inicial con el metodo mint esto ayuda a que no se haga un llamado nuevo para ello como suele pasar con los contratos normales, esto economisa costo pero si alguien tiene un objecion esto atento a ello ```js constructor(uint256 _totalSupply) ERC20("Nova-platzi-Coin", "n-plc") { owner = msg.sender; _mint(msg.sender, _totalSupply); } ``` function totalSupply() public view override virtual onlyOwner returns (uint256) { return ERC20.totalSupply(); } modifier onlyOwner { require(msg.sender == owner, "only owner can check the supply"); \_; }el segundo cambio va con ese tema es que el totalsupply es provado al owner jajaj casi como una cbdc ,jejeje no. es mas para entender los conceptos de privado y publico asi como over ride que fueron muy buenos para estudiarlos en practica. lo que hago es llaamr el valor del metodo del padre. ```js function totalSupply() public view override virtual onlyOwner returns (uint256) { return ERC20.totalSupply(); } modifier onlyOwner { require(msg.sender == owner, "only owner can check the supply"); _; } ```por ultimo pongo un update que es demaciado util pero que me llevo tiempo de estudio y es el tema del aproval. es molesto que tengamos que hacer aproval del valor y si queremos incrementarlo pues sea actualizar el mapping y no de manera incrementa, esto a mi forma de pensar funcionaria si el token es usado en una familia de manera comprartida por los hijo donde ellos pueden hacer una forma de "staking" pasivo por la asignacion del representante, una idea fumada pero linda. eso requierio crear en el contrato el mismo prop que en el padre haciendo overide? pues no! por que override solo le hacer a la publicas si es privada te jodes y tienes que crearla interna y hacerla tu mismo el overide de los metodos para que usen la local del hijo aqui les dejo mi ejemplo es drogo pero funciona // SPDX-License-Identifier: MIT// Compatible with OpenZeppelin Contracts ^5.0.0pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract novaPlatziCoin is ERC20 { mapping(address account => mapping(address spender => uint256)) private \_allowances; address private owner; constructor(uint256 \_totalSupply) ERC20("Nova-platzi-Coin", "n-plc") { owner = msg.sender; \_mint(msg.sender, \_totalSupply); } function totalSupply() public view override virtual onlyOwner returns (uint256) { return ERC20.totalSupply(); } modifier onlyOwner { require(msg.sender == owner, "only owner can check the supply"); \_; } function \_approve(address owner, address spender, uint256 value, bool emitEvent) internal override virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } \_allowances\[owner]\[spender] += value; if (emitEvent) { emit Approval(owner, spender, value); } } function allowance(address owner, address spender) public view virtual override returns (uint256) { return \_allowances\[owner]\[spender]; } function balanceOf(address account) public view virtual override returns (uint256) { return ERC20.balanceOf(msg.sender); } }```js // SPDX-License-Identifier: MIT // Compatible with OpenZeppelin Contracts ^5.0.0 pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract novaPlatziCoin is ERC20 { mapping(address account => mapping(address spender => uint256)) private _allowances; address private owner; constructor(uint256 _totalSupply) ERC20("Nova-platzi-Coin", "n-plc") { owner = msg.sender; _mint(msg.sender, _totalSupply); } function totalSupply() public view override virtual onlyOwner returns (uint256) { return ERC20.totalSupply(); } modifier onlyOwner { require(msg.sender == owner, "only owner can check the supply"); _; } function _approve(address owner, address spender, uint256 value, bool emitEvent) internal override virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } _allowances[owner][spender] += value; if (emitEvent) { emit Approval(owner, spender, value); } } function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } function balanceOf(address account) public view virtual override returns (uint256) { return ERC20.balanceOf(msg.sender); } } ``` Pd: Dejo el contrato aqui y en un git me disculpan las formas. si me preguntan ando cansado, y mi pais anda en peos politicos asi que no tengo muchas capacidades para un lexico, ortografia y redaccion pulcra.