You don't have access to this class

Keep learning! Join and start boosting your career

Aprovecha el precio especial y haz tu profesi贸n a prueba de IA

Antes: $249

Currency
$209
Suscr铆bete

Termina en:

0 D铆as
0 Hrs
31 Min
10 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
Resources

New challenge to test what we have learned so far. We are going to work with some OpenZeppelin utilities to solve the challenge.

Interface detection challenge

The challenge for you is simple, using OpenZeppelin's introspection contracts, you must develop a smart contract that verifies whether or not a given address implements the ERC20 and ERC721 standards.

Get to work, make the effort to develop this contract and when you have solved it, share it with the rest of the community and compare your solution with that of another student.


Contributed by: Kevin Fiorentino (Platzi contributor).

Contributions 8

Questions 1

Sort by:

Want to see more contributions, questions and answers from the community?

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