No tienes acceso a esta clase

¬°Contin√ļa aprendiendo! √önete y comienza a potenciar tu carrera

Compra acceso a todo Platzi por 1 a√Īo

Antes: $249

Currency
$209/a√Īo

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

15D
7H
25M
5S
Curso de Introducción a OpenZeppelin

Curso de Introducción a OpenZeppelin

Sebasti√°n Leonardo Perez

Sebasti√°n Leonardo Perez

Reto: utilidades

16/19
Recursos

Nuevo reto para poner a prueba lo aprendido hasta aquí. Vamos a trabajar con algunas utilidades de OpenZeppelin para resolver el desafío.

Desafío de detección de interfaces

El reto para ti es simple, utilizando los contratos de introspección de OpenZeppelin, deberás desarrollar un contrato inteligente que verifique si una determinada dirección, implementa o no los estándares ERC20 y ERC721.

Ponte manos a la obra, has el esfuerzo de desarrollar este contrato y cuando lo hayas resuelto, compártelo con el resto de la comunidad y compara tu solución con la de otro estudiante.


Contribución creada por: Kevin Fiorentino (Platzi contributor).

Aportes 8

Preguntas 1

Ordenar por:

¬ŅQuieres ver m√°s aportes, preguntas y respuestas de la comunidad?

o inicia sesión.

Comparto mi solución:

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

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";

contract IdentificadorToken {

      using ERC165Checker for address;
      
      modifier onlyERC20(address _direccion) {
            require(_direccion.supportsInterface(type(IERC20).interfaceId),"La Direccion no es compatible, no es un token ERC20");
            _;
      }
      modifier onlyERC721 (address _direccion){
            require(_direccion.supportsInterface(type(IERC721).interfaceId),"La Direccion no es compatible, no es un token ERC721");
            _;
      }

      function verificarERC20(address _direccion) onlyERC20(_direccion) public view returns(string memory) {
            return "La Direccion es compatible, es un token ERC20";
      }

      function verificarERC721(address _direccion) onlyERC721(_direccion) public view returns(string memory) {
           return "La Direccion es compatible, es un token ERC721";
      } 
}

Reto, otra solucion:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import "@openzeppelin/contracts/interfaces/IERC20.sol";
import "@openzeppelin/contracts/interfaces/IERC721.sol";

contract introspectionReto3 {

    function whatTypeOfTokenIsIt (address account) public view returns(string memory) {
        if(ERC165Checker.supportsInterface(account, type(IERC20).interfaceId)){
            return "It's ERC-20 Token";
        } else if (ERC165Checker.supportsInterface(account, type(IERC721).interfaceId)){
            return "It's ERC-721 token";
        } else {
            return "It's none";
        }   
    }        
}

Mi solución al desafio:

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";

contract Verification {
    using ERC165Checker for address;

    bytes4 private InterfaceId_ERC721 = 0x80ac58cd;
    bytes4 private InterfaceId_ERC20 = 0x36372b07;

    function tryERC721(
        address token
    )
        public view returns(bool)
    {
        return token.supportsInterface(InterfaceId_ERC721);
        
    }

    function tryERC20(
        address token
    )
        public view returns(bool)
    {
        return token.supportsInterface(InterfaceId_ERC20);
        
    }
}

Luego de ver la solucion entendi mejor el uso de using en librerias.

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

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";

contract IdentificadorToken {
    
    using ERC165Checker for address;
    error InvalidTokenFormat (string message);

    function isERC20 (address _address) public view returns (string memory) {
        if (!_address.supportsInterface(type(IERC20).interfaceId)) {
            revert InvalidTokenFormat("El formato del token no es valido, no hace referencia a un estandar ERC20");
        }
        return "Este contrato si cumple con los requisitos de ERC20";
    }

    function isERC721 (address _address) public view returns (string memory) {
        if (!_address.supportsInterface(type(IERC721).interfaceId)) {
            revert InvalidTokenFormat("El formato del token no es valido, no hace referencia a un estandar ERC721");
        }
        return "Este contrato si cumple con los requisitos de ERC721";
    }
}

Encontré esta parte de interfaces muy apropiado para este caso: https://www.tutorialspoint.com/solidity/solidity_interfaces.htm

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import "@openzeppelin/contracts/interfaces/IERC1155.sol";
import "@openzeppelin/contracts/interfaces/IERC721.sol";
import "@openzeppelin/contracts/interfaces/IERC20.sol";

interface ITest {
    function isERC1155(address Address) external returns (bool);
    function isERC721(address Address) external returns (bool);
    function isERC20(address Address) external returns (bool);
}

contract Test is ITest, IERC165 {
    using ERC165Checker for address; 

    bytes4 public constant IID_ITEST = type(ITest).interfaceId;
    bytes4 public constant IID_IERC165 = type(IERC165).interfaceId;
    bytes4 public constant IID_IERC20 = type(IERC20).interfaceId;
    bytes4 public constant IID_IERC1155 = type(IERC1155).interfaceId;
    bytes4 public constant IID_IERC721 = type(IERC721).interfaceId;
    
    function isERC1155(address Address) external view returns (bool) {
        return Address.supportsInterface(IID_IERC1155);
    }    
    
    function isERC721(address Address) external view returns (bool) {
        return Address.supportsInterface(IID_IERC721);
    }

    function isERC20(address Address) external view returns (bool) {
        return Address.supportsInterface(IID_IERC20);
    }
    
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == IID_ITEST || interfaceId == IID_IERC165;
    }
}

Tuve alg√ļn conflicto con mi contrato ERC20 realizado en clases anteriores que hereda AccessControl.
Por lo que estuve investigando, hay que tener alg√ļn reparo cuando un contrato hereda m√°s de 2 interfaces. El orden es importante. Adem√°s, REMIX me daba algunos errores y tambi√©n tuve que hacer el override de AccessControl en la funci√≥n supportsInterface de la siguiente manera:

    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, AccessControl) returns (bool) {
        // ..
    }

Comparto el código del Token ERC20 y el código del ERC165 que desarrollé. Funciona!

Reto:

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import "@openzeppelin/contracts/interfaces/IERC20.sol";
import "@openzeppelin/contracts/interfaces/IERC721.sol";



contract obervador  {

    function isTokenERC20(address account) public view returns (bool) {
        return ERC165Checker.supportsInterface(account, type(IERC20).interfaceId);
    }

    function isTokenERC721(address account) public view returns (bool) {
        return ERC165Checker.supportsInterface(account, type(IERC721).interfaceId);
    }
        
}