Crea tus propios tokens ERC-20

En este nuevo artículo vamos a crear nuestros propios tokens Aprende Blockchain Coins (ABC) con el estándar ERC-20 para crear tokens fungibles. Usaremos una de las posibles implementaciones que cumplen el estándar ERC-20 con el que posteriormente podemos crear tokens con parámetros específicos.

Contrato abstracto ERC-20

Lo que vamos a hacer es crear un contrato abstracto que defina las funciones necesarias para nuestros contratos ERC-20. Para aquellos que no sepan que es un contrato abstracto, el concepto es similar a una clase abstracta. Un contrato abstracto es un contrato que no puede ser instanciado pero puede ser usado como base para otros contratos. Un contrato pasa a ser abstracto cuando al menos una de sus funciones no incluye la implementación, dejando que las clases que hereden de dicho contrato sean los responsables de la implementación.

contract ERC20Interface {
    function totalSupply() public view returns (uint);
    function balanceOf(address tokenOwner) public view returns (uint balance);
    function allowance(address tokenOwner, address spender) public view returns (uint remaining);
    function transfer(address to, uint tokens) public returns (bool success);
    function approve(address spender, uint tokens) public returns (bool success);
    function transferFrom(address from, address to, uint tokens) public returns (bool success);

    event Transfer(address indexed from, address indexed to, uint tokens);
    event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}

El objetivo de cada una de las funciones se explican posteriormente en el código.

Librería Safe maths

Es importante usar operaciones matemáticas seguras que lancen excepciones en caso de que el el resultado de un cálculo no sea correcto. Con esta librería evitaríamos, por ejemplo, el problema de overflow generado al sumar dos números cuyo resultado es mayor que el máximo aceptado por el tipo usado. Por ejemplo, usando el tipo uint8 el mayor número que podemos representar es 255 (28-1). Si a 255 le sumáramos un 1, el resultado sería 0 porque se produce desbordamiento (overflow), y que no es el resultado esperado. Este tipo de errores han causado problemas en contratos de tokens ERC20 recientemente y deben ser evitados. Puedes leer más sobre el tema en https://media.consensys.net/detecting-batchoverflow-and-similar-flaws-in-ethereum-smart-contracts-93cf5a5aaac8

El código de nuestra librería de operaciones matemáticas seguras sería:

safemaths

Contrato token ERC-20

El siguiente contrato implementa las funciones de nuestro contrato abstracto ERC-20 y además añade las variables de estado para el símbolo, nombre, número total de tokens y número de decimales de nuestro token. Cuando se crea el contrato, los tokens son inicialmente asignados al creador del contrato.

contract ERC20Token is ERC20Interface {
    
    using SafeMath for uint; //use our safe math library
    
    string public symbol;
    string public  name;
    uint8 public decimals;
    uint _totalSupply;
    
    mapping(address => uint) balances;
    mapping(address => mapping(address => uint)) allowed;
    
    // ------------------------------------------------------------------------
    // Constructor
    // ------------------------------------------------------------------------
    constructor (
        uint256 _initialAmount,
        string _tokenName,
        uint8 _decimalUnits,
        string _tokenSymbol

    ) public {
        balances[msg.sender] = _initialAmount; 
        _totalSupply = _initialAmount;
        name = _tokenName;
        decimals = _decimalUnits;
        symbol = _tokenSymbol;
    }
    
    // ------------------------------------------------------------------------
    // Fixed Total supply
    // ------------------------------------------------------------------------
    function totalSupply() public view returns (uint) {
        return _totalSupply;
    }
    
    // ------------------------------------------------------------------------
    // Get the token balance for account `tokenOwner`
    // ------------------------------------------------------------------------
    function balanceOf(address tokenOwner) public view returns (uint balance) {
        return balances[tokenOwner];
    }
    
    // ------------------------------------------------------------------------
    // Transfer the balance from token owner's account to `to` account
    // - Owner's account must have sufficient balance to transfer
    // - 0 value transfers are allowed
    // ------------------------------------------------------------------------
    function transfer(address to, uint tokens) public returns (bool success) {
        balances[msg.sender] = balances[msg.sender].sub(tokens);
        balances[to] = balances[to].add(tokens);
        emit Transfer(msg.sender, to, tokens);
        return true;
    }
    
    // ------------------------------------------------------------------------
    // Token owner can approve for `spender` to transferFrom(...) `tokens`
    // from the token owner's account
    //
    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
    // recommends that there are no checks for the approval double-spend attack
    // as this should be implemented in user interfaces 
    // ------------------------------------------------------------------------
    function approve(address spender, uint tokens) public returns (bool success) {
        allowed[msg.sender][spender] = tokens;
        emit Approval(msg.sender, spender, tokens);
        return true;
    }
    
    // ------------------------------------------------------------------------
    // Transfer `tokens` from the `from` account to the `to` account
    // 
    // The calling account must already have sufficient tokens approve(...)-d
    // for spending from the `from` account and
    // - From account must have sufficient balance to transfer
    // - Spender must have sufficient allowance to transfer
    // - 0 value transfers are allowed
    // ------------------------------------------------------------------------
    function transferFrom(address from, address to, uint tokens) public returns (bool success) {
        balances[from] = balances[from].sub(tokens);
        allowed[from][msg.sender] = allowed[from][msg.sender].sub(tokens);
        balances[to] = balances[to].add(tokens);
        emit Transfer(from, to, tokens);
        return true;
    }

    // ------------------------------------------------------------------------
    // Returns the amount of tokens approved by the owner that can be
    // transferred to the spender's account
    // ------------------------------------------------------------------------
    function allowance(address tokenOwner, address spender) public view returns (uint remaining) {
        return allowed[tokenOwner][spender];
    }
    

    // ------------------------------------------------------------------------
    // Fallback function. Don't accept ETH
    // ------------------------------------------------------------------------
    function () public payable {
        revert();
    }

}

Desplegar nuestro contrato en la red de test de Ethereum

Una vez definido nuestro contrato es hora de desplegarlo en la testnet de Ethereum. Para ello sólo tendremos que copiar el código anterior en Remix indicando los parámetros para inicializar nuestro contrato de tokens (supply, nombre, decimales y símbolo).
Ten en cuenta que en el supply debe incluir los decimales, es decir, si quieres que haya un total de 1.000 tokens “completos” y sean divisibles con 2 decimales, en supply deberías introducir 100.000 unidades (ó 1.000,00 tokens).

02.png

05.png

Etherscan

Podemos ver que el contrato se ha creado correctamente en la dirección 0x5131DbF853ab6341298938fAc2Ca18b1dd172feA en Etherscan:

06.png

Ya somos los orgullosos poseedores de 1.000 ABC tokens 🙂

A partir de ahora ya podremos empezar a jugar enviando y recibiendo tokens.

Añadir nuestro ABC token a MetaMask

Al haber seguido el estándar ERC-20, podremos usar cualquier wallet que soporte dicho estándar.

MetaMask no soporta en estos momentos el envío de tokens ERC-20 pero si nos sirve para visualizarlos. Para visualizar nuestros tokens es necesario indicar la dirección donde se desplegó el contrato y automáticamente se rellenarán el símbolo y número de decimales:

08.png

Una vez añadido el token ya podremos ver nuestro saldo de ABC tokens:

09.png

Enviar ABC tokens a otra dirección

Como decíamos, no es posible enviar tokens ERC-20 únicamente con MetaMask pero si que podemos conectar MetaMask y MyEtherWallet para enviar tokens. MyEtherWallet tiene la opción de acceder a una cuenta usando MetaMask y de esa forma no tener que estar introduciendo nuestra clave privada directamente:

09a.png

Necesitaremos añadir el token ABC a MyEtherWallet:

09b.png

Una vez echo ésto ya veremos nuestro saldo de ABC tokens en MyEtherWallet y podremos enviar tokens a otra dirección:

12.png

13.png

Confirmamos el envío de la transacción en MetaMask:

14.png

Una vez la transacción haya sido minada podemos ver la transacción en Etherscan y que el saldo de la Cuenta 1 es ahora 900 ABC tokens y la Cuenta 2 muestra ahora 100 ABC tokens:

17.png

15.png      16.png

Y hasta aquí este artículo. Espero que os haya gustado y si quieres ABC tokens no dudes en contactar conmigo y compartiré unos cuantos con vosotros, quien sabe, ¡igual en unos años valen una fortuna!

Puedes encontrar todo el código descrito en el repositorio GitHub.

 

Anuncios

WordPress.com.

Subir ↑

A %d blogueros les gusta esto: