No tienes acceso a esta clase

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

No se trata de lo que quieres comprar, sino de quién quieres ser. Invierte en tu educación con el precio especial

Antes: $249

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

11 Días
4 Hrs
7 Min
52 Seg
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?

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);
    }
        
}