Skip to content

Instantly share code, notes, and snippets.

@jdnichollsc
Last active November 5, 2023 15:42
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jdnichollsc/34e8a37efd508b5a944d541000673736 to your computer and use it in GitHub Desktop.
Save jdnichollsc/34e8a37efd508b5a944d541000673736 to your computer and use it in GitHub Desktop.
Bootcamp para Desarrolladores de Smart Contracts

Blockchain

Una red altamente segura. Demo: https://andersbrownworth.com/blockchain/blockchain

Problema actual Finanzas centralizadas

Descentralización

  • Arquitectura
  • Política
  • Lógica

Beneficios

  • Tolerancia a fallos
  • Resistente a ataques
  • Resistente a la colusión (Participantes que traten de vulnerar el sistema)

Hashing

Método de criptografía que convierte cualquier dato en un texto único. Merkle tree es el método usado para generar ese hash, teniendo en cuenta al anterior y el hash de cada transacción. El nonce es un número aleatorio y de características únicas que tiene como finalidad ser usado en sistemas criptográficos.

Contract

Un acuerdo vinculante entre 2 o más partes. Digital Agreements

Condiciones óptimas con finanzas centralizadas: CeFi funcionando correctamente

Pero cuando hay problemas: CeFi cuando no funciona correctamente

Smart Contracts

Smart Contracts

  • Seguridad: No puede ser alterado, es inmutable
  • Garantía de ejecución: Siempre está activa, funcionando mientras haya un nodo operando.
  • Transparencia: Es un derecho incorporado por el código.
  • Mínima confianza: Reducción del riesgo sin tener que confiar en el otro.
  • Eficiencia: Automatizar procesos manuales.

Problemas sociales

Ethereum

Cadena de bloques, pública y Open Source, sin permisos. Se puede considerar como una máquina de estados entre las transacciones. Actualmente usa el mecanismo de consenso Proof of Work (PoW)

  • Nodos
  • Cuentas
  • Transacciones: Etherscan nos permite visualizar las transacciones de la red.
  • Transacciones pendientes (mempool): Hasta que el bloque sea confirmada se visualiza como Pending Transactions.

Ethereum Virtual Machine

Todos los nodos ejecutan el cliente de Ethereum que a su vez maneja la máquina virtual.

Ether

Criptomoneda nativa de la red de Ethereum, el símbolo es ETH.

Tokens

Representación de cualquier bien o servicio. No es más que un contrato inteligente que actualiza el estado del contrato

  • ER-C20: construir tokens
  • ERC-677: el token de Chainlink

Solidity

Lenguaje de alto nivel orientado a los contratos. Sintaxis similar a C# y JS, donde los contratos y herencia son similares a Programación Orientada a Objetos.

Compilar código en Solidity

Acceder al contrato

Tax fee

El gas es el costo de la ejecución de las transacciones. Los mineros realizan la confirmación de las transacciones y por tanto reciben un pago como recompensa. El gas es la unidad que mide el trabajo computacional requerido para correr transacciones o smart contracts en la EVM.

fee = gas usado * precio del ETH.

Gas

Límite de Gas

Un bloque se mina cada 15 segundos aproximadamente en Ethereum.

Operaciones y Gas

Contratos y funciones

Contratos y funciones

Visibilidad de la función

Función en Solidity

Tipos de datos en Solidity

Array en Solidity

Mappings en Solidity

Structs en Solidity

Ejercicios de Smart Contracts

Online editor - Remix: https://remix.ethereum.org/ Instrucciones de Instalación: Brownie Track - https://docs.google.com/document/d/1o4DAjqIMes4YHpKeOPoWxxr5bFr7dBB7Racl_rGQKtE/edit?usp=sharing Día 1 Ejercicios: https://docs.google.com/document/d/1CtROewhnKTlsoBIv6jODFt2nyJL_ZFuOGyORyIsVy8Q/edit?usp=sharing

  1. Mi primer Smart Contract:
// SPDX-License-Identifier: MIT
pragma solidity 0.6.7;

contract MyFirstContract {
    uint256 number;
    
    function setNumber(uint256 _number) public {
        number = _number;
    }
    
    function getNumber() public view returns(uint256) {
        return number;
    }
}

Verificar deploy del contrato: https://kovan.etherscan.io/address/0xe76b8a218eed9b9f1eed05d06ccb9d7c3f91e1ee

  1. Usando Mappings
// SPDX-License-Identifier: MIT
pragma solidity 0.6.7;

contract MappingsContract {
    
    string[] names;
    mapping (string => uint) public phoneNumbers;
    
    function addPhoneNumber(string memory _name, uint _phoneNumber) public {
        phoneNumbers[_name] = _phoneNumber;
    }
    
    function getPhoneNumber(string memory _name) public view returns(uint)  {
        return phoneNumbers[_name];
    }
    
    function addName(string memory _name) public {
        names.push(_name);
    }
    
    function getName(uint256 _num) public view returns(string memory) {
        return names[_num];
    }
}

Deploy del contrato: 0xD6BEccF3e8532D61D216Ce00bd889CdBB48318Dd

Manejar string cuesta más que integers, para que se le indique al compilador que solo se va a manejar en memoria se usa la palabra reservada memory. storage y memory son dos lugares que la EVM usa para almacenar informacion, siendo storage persistente mientras el memory se elimina al final de la transaccion.

Cuando especificas memory en el return value estas diciendo que vas a devolver por valor y no por referencia

  1. Price Feeds

Ethereum Data Feeds: https://docs.chain.link/docs/ethereum-addresses/

// SPDX-License-Identifier: MIT
pragma solidity 0.6.7;

import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";

contract PriceConsumerContract {
    
    AggregatorV3Interface internal priceFeed;
    
    constructor() public {
        // Kovan Testnet
        // Aggregator: ETH/USD
        // Address: 0x9326BFA02ADD2366b30bacB125260Af641031331
        priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331);
    }
    
    /**
     * Get the latest price
     */
    function getLatestPrice() public view returns(int) {
        (
            uint80 roundID,
            int price,
            uint startedAt,
            uint timeStamp,
            uint80 answeredInRound
        ) = priceFeed.latestRoundData();
        return price;
    }
}
  1. Llamar una API con Chainlink

Documentación: https://docs.chain.link/docs/request-and-receive-data/

// SPDX-License-Identifier: MIT
pragma solidity 0.6.7;

import "@chainlink/contracts/src/v0.6/ChainlinkClient.sol";
 
contract APIConsumer is ChainlinkClient {
  
    uint256 public volume;
    
    // Internal properties for this contract
    address private oracle;
    bytes32 private jobId;
    uint256 private fee;
    
    /**
     * Network: Kovan
     * Chainlink - 0x2f90A6D021db21e1B2A077c5a37B3C7E75D15b7e
     * Chainlink - 29fa9aa13bf1468788b7cc4a500a45b8
     * Fee: 0.1 LINK
     */
    constructor() public {
        setPublicChainlinkToken();
        oracle = 0x2f90A6D021db21e1B2A077c5a37B3C7E75D15b7e;
        jobId = "29fa9aa13bf1468788b7cc4a500a45b8";
        fee = 0.1 * 10 ** 18; // 0.1 LINK
    }
    
    /**
     * Create a Chainlink request to retrieve API response, find the target
     * data, then multiply by 1000000000000000000 (to remove decimal places from data).
     ************************************************************************************
     *                                    STOP!                                         * 
     *         THIS FUNCTION WILL FAIL IF THIS CONTRACT DOES NOT OWN LINK               *
     *         ----------------------------------------------------------               *
     *         Learn how to obtain testnet LINK and fund this contract:                 *
     *         ------- https://docs.chain.link/docs/acquire-link --------               *
     *         ---- https://docs.chain.link/docs/fund-your-contract -----               *
     *                                                                                  *
     ************************************************************************************/
    function requestVolumeData() public returns (bytes32 requestId) 
    {
        Chainlink.Request memory request = buildChainlinkRequest(jobId, address(this), this.fulfill.selector);
        
        // Set the URL to perform the GET request on
        request.add("get", "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD");
        
        // Set the path to find the desired data in the API response, where the response format is:
        // {"RAW":
        //      {"ETH":
        //          {"USD":
        //              {
        //                  ...,
        //                  "VOLUME24HOUR": xxx.xxx,
        //                  ...
        //              }
        //          }
        //      }
        //  }
        request.add("path", "RAW.ETH.USD.VOLUME24HOUR");
        
        // Multiply the result by 1000000000000000000 to remove decimals
        // Solidity don't support float numbers
        int timesAmount = 10**18;
        request.addInt("times", timesAmount);
        
        // Sends the request
        return sendChainlinkRequestTo(oracle, request, fee);
    }
    
    /**
     * Receive the response in the form of uint256
     */ 
    function fulfill(bytes32 _requestId, uint256 _volume) public recordChainlinkFulfillment(_requestId)
    {
        volume = _volume;
    }
    
    /**
     * Withdraw LINK from this contract
     * 
     * NOTE: DO NOT USE THIS IN PRODUCTION AS IT CAN BE CALLED BY ANY ADDRESS.
     * THIS IS PURELY FOR EXAMPLE PURPOSES ONLY.
     */
    function withdrawLink() external {
        LinkTokenInterface linkToken = LinkTokenInterface(chainlinkTokenAddress());
        require(linkToken.transfer(msg.sender, linkToken.balanceOf(address(this))), "Unable to transfer");
    }
}
  1. Chainlink VRF provides Verifiable Randomness:

Chainlink VRF Contract Addresses: https://docs.chain.link/docs/vrf-contracts/

  • LINK: Basicamente es el Token que vamos a usar para pagar
  • VRF Coordinator: Intermediario que realiza consultas del oraculo, que facilita la comunicación entre las diferentes partes
  • Key Hash: Usado para verificar el proceso de generación del valor random, parecido a una llave secreta
  • Fee
// SPDX-License-Identifier: MIT
pragma solidity 0.6.7;

import "@chainlink/contracts/src/v0.6/VRFConsumerBase.sol";
 
/**
 * THIS IS AN EXAMPLE CONTRACT WHICH USES HARDCODED VALUES FOR CLARITY.
 * PLEASE DO NOT USE THIS CODE IN PRODUCTION.
 */
contract RandomNumberConsumer is VRFConsumerBase {
    
    bytes32 internal keyHash;
    uint256 internal fee;
    
    uint256 public randomResult;
    
    /**
     * Constructor inherits VRFConsumerBase
     * 
     * Network: Kovan
     * Chainlink VRF Coordinator address: 0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9
     * LINK token address:                0xa36085F69e2889c224210F603D836748e7dC0088
     * Key Hash: 0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4
     */
    constructor() 
        VRFConsumerBase(
            0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9, // VRF Coordinator
            0xa36085F69e2889c224210F603D836748e7dC0088  // LINK Token
        ) public
    {
        keyHash = 0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4;
        fee = 0.1 * 10 ** 18; // 0.1 LINK (Varies by network)
    }
    
    /** 
     * Requests randomness 
     */
    function getRandomNumber() public returns (bytes32 requestId) {
        require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet");
        return requestRandomness(keyHash, fee);
    }
 
    /**
     * Callback function used by VRF Coordinator
     */
    function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
        randomResult = randomness;
    }
 
    // function withdrawLink() external {} - Implement a withdraw function to avoid locking your LINK in the contract
}

HardHat

Entorno de Desarrollo

Remix IDE

  • Basado en Web (Online)
  • Módulos para probar, depurar y desplegar contratos inteligentes
  • No puede integrar otras partes de un proyecto
  • No puede guardar archivos localmente sin plugins
  • Cualquier funcionalidad personalizada requiere crear/usar un plugin

Brownie

  • Basado en Python

Hardhat IDE

  • Basado en JavaScript
  • Red local para simular Ethereum
  • Funciones de plugin extensibles
  • Alto nivel de características de depuración

Hardhat IDE

Hardhat tasks and plugins

Mi primer proyecto Hardhat

Repo: https://github.com/jdnichollsc/my-first-hardhat

Crear un proyecto usando el Hardhat Starter Kit

Starter Kits

Hardhat Started Kit

Hardhat Started Kit: https://github.com/smartcontractkit/hardhat-starter-kithttps://github.com/jdnichollsc/chainlink-hardhat-box

Repo: https://github.com/jdnichollsc/chainlink-hardhat-box

Hardhat Local Network

Hardhat Network

Hardhat Network se puede considerar como otra red para pruebas:

Hardhat local network

Beneficios:

  • Bifurcar Mainnet para comunicarnos con protocolos
  • Estado inicial:
    • Bloque Genesis
    • 20 cuentas con 10000 ETH cada una

Mocks

Mocks para desarrollo local

Deploy al Local Network

Ganache es una red local de prueba desarrollada por trufflesuite con una interfaz visual, donde puedes ver bloques, contratos, transacciones, y demas de una manera sencilla, y tambien acepta forks de otras redes.

  • Local Network using Hardhat:
    • npx hardhat node - Start a Node using Hardhat with a forking Mainnet
    • Verify: Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/
    • npx hardhat deploy - Deploy smart contracts to a local network with Ethereum
    • npx hardhat block-number --network localhost - Verify the fork, the block number is 0 in a local network
    • npx hardhat read-price-feed --contract 0x4C4a2f8c81640e47606d3fd77B353E87Ba015584 --network localhost - Debug
    • Verify value: https://data.chain.link/ethereum/mainnet/crypto-usd/eth-usd

Seguridad

Seguridad de Smart Contracts

Toca cambiar el paradigma en cuanto a la seguridad al ser inmutable:

Ataques a Smart Contracts

Testing para Smart Contracts Probando Smart Contracts

Bug vs Vulnerabilidad (Las pruebas no evitan vulnerabilidades) Bug vs Vulnerabilidad

Tipos de Tests Tipos de Tests

Escribir buenos Tests Pasos de Testing

Tests de Integración

Tests de Integración

Herramientas de Testing

Herramientas de Testing

Testing Coverage

Testing Coverage

Testing Security

Pruebas de integración:

  • npx hardhat deploy
  • yarn test-integration - Las pruebas tienen retrasos para probar las transacciones con los nodos Chainlink

Pruebas de cobertura:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment