Saltar al contenido principal

Usando Foundry con la Avalanche C-Chain

Introducción

Esta guía muestra cómo implementar e interactuar con contratos inteligentes utilizando Foundry en una Red Avalanche local y la C-Chain Fuji.

Foundry toolchain es una herramienta de desarrollo de contratos inteligentes escrita en Rust. Gestiona tus dependencias, compila tu proyecto, ejecuta pruebas, implementa y te permite interactuar con la cadena desde la línea de comandos.

Conocimientos recomendados

Requisitos

  • Has instalado Foundry y ejecutado foundryup. Esta instalación incluye los binarios forge y cast utilizados en este recorrido.
  • NodeJS versión 16.x

AvalancheGo y Avalanche Network Runner

AvalancheGo es una implementación de nodo Avalanche escrita en Go.

Avalanche Network Runner es una herramienta para implementar rápidamente redes de prueba locales. Juntos, pueden implementar redes de prueba locales y ejecutar pruebas en ellas.

Inicia una red Avalanche local de cinco nodos:

cd /ruta/a/avalanche-network-runner
# inicia una red de cinco nodos de staking
./go run examples/local/fivenodenetwork/main.go

Una red Avalanche de cinco nodos está funcionando en tu máquina. La red se ejecutará hasta que presiones Ctrl + C para salir.

Empezando

Esta sección te guiará a través de la creación de un ERC721.

Clonar Avalanche Smart Contract Quick Start

Clona el repositorio de inicio rápido e instala los paquetes necesarios a través de yarn.

git clone https://github.com/ava-labs/avalanche-smart-contract-quickstart.git
cd avalanche-smart-contract-quickstart
yarn
info

El método de clonación del repositorio utilizado es HTTPS, pero también se puede utilizar SSH:

git clone [email protected]:ava-labs/avalanche-smart-contract-quickstart.git

Puedes encontrar más información sobre SSH y cómo usarlo aquí.

Para implementar contratos, necesitas tener algunos AVAX. Puedes obtener AVAX de la testnet desde el Avalanche Faucet, que es una forma fácil de jugar con Avalanche. Si ya tienes un saldo de AVAX mayor que cero en Mainnet, pega tu dirección de C-Chain allí y solicita tokens de prueba. De lo contrario, por favor solicita un cupón de faucet en Guild. Los administradores y moderadores en el Discord oficial pueden proporcionar AVAX de testnet si los desarrolladores no pueden obtenerlo de las otras dos opciones. Después de familiarizarte con tu código, puedes ejecutarlo en Mainnet después de hacer los cambios necesarios en tu flujo de trabajo.

Escribir Contratos

Utilizaremos nuestro ejemplo de contrato inteligente ERC721, NFT.sol, que se encuentra en ./contracts de nuestro proyecto.

//SPDX-License-Identifier: MIT
// contracts/ERC721.sol

pragma solidity >=0.6.2;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract NFT is ERC721 {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;

constructor() ERC721("GameItem", "ITM") {}

// commented out unused variable
// function awardItem(address player, string memory tokenURI)
function awardItem(address player)
public
returns (uint256)
{
_tokenIds.increment();

uint256 newItemId = _tokenIds.current();
_mint(player, newItemId);
// _setTokenURI(newItemId, tokenURI);

return newItemId;
}
}

Examinemos esta implementación de un NFT como un Ítem de Juego. Comenzamos importando los contratos de nuestros módulos de nodo. Importamos la implementación de código abierto de OpenZeppelin del estándar ERC721 que nuestro contrato NFT heredará. Nuestro constructor toma los argumentos _name y _symbol para nuestro NFT y los pasa al constructor de la implementación ERC721 padre. Por último, implementamos la función awardItem que permite a cualquiera acuñar un NFT en la dirección de billetera de un jugador. Esta función incrementa el currentTokenId y utiliza la función _mint de nuestro contrato padre.

Compilar, Implementar y Verificar con Forge

Forge es una herramienta de línea de comandos que se incluye con Foundry. Forge prueba, compila e implementa tus contratos inteligentes.

Requiere alguna configuración inicial del proyecto en forma de un foundry.toml que se puede generar ejecutando:

forge init --no-git --no-commit --force

El foundry.toml por defecto apunta a las carpetas que agregó. Queremos cambiar esto para asegurarnos de que src apunte al directorio contracts. Cambia tu foundry.toml para que se vea como el siguiente:

[profile.default]
src = 'contracts'
out = 'out'
libs = ["node_modules", "lib"]
remappings = [
'@ensdomains/=node_modules/@ensdomains/',
'@openzeppelin/=node_modules/@openzeppelin/',
'hardhat/=node_modules/hardhat/',
]

# Ver más opciones de configuración en https://github.com/foundry-rs/foundry/tree/master/config

Para compilar el contrato NFT, ejecuta:

forge build

Por defecto, los artefactos del contrato estarán en el directorio out, como se especifica en el foundry.toml. Para implementar nuestro contrato compilado con Forge, tenemos que establecer variables de entorno para el punto final RPC y la clave privada que queremos usar para implementar.

Establece tus variables de entorno ejecutando:

export RPC_URL=<TU-PUNTO-FINAL-RPC>
export PRIVATE_KEY=<TU-CLAVE-PRIVADA>

Dado que estamos implementando en la testnet Fuji, nuestra exportación de RPC_URL debería ser:

export RPC_URL=https://api.avax-test.network/ext/bc/C/rpc

Si desea verificar sus contratos durante el proceso de implementación (la forma más rápida y fácil), obtenga una Clave de API de Snowtrace. Agregue esto como una variable de entorno:

export ETHERSCAN_API_KEY=<TU-CLAVE-DE-API-DE-SNOWTRACE>

Una vez configurado, puede implementar su NFT con Forge ejecutando el siguiente comando mientras agrega los valores para _name y _symbol, los argumentos de constructor relevantes de la contrato NFT. Puede verificar los contratos con Snowtrace agregando --verify antes de --constructor-args:

forge create NFT --rpc-url=$RPC_URL --private-key=$PRIVATE_KEY --verify --constructor-args GameItem ITM

Después de una implementación exitosa, verá la dirección de la billetera que implementó, la dirección del contrato y el hash de transacción impresos en su terminal.

Aquí hay un ejemplo de salida de una implementación y verificación de NFT.

[⠔] Compiling...
No se han cambiado archivos, se omitió la compilación
Implementador: 0x8db97c7cece249c2b98bdc0226cc4c2a57bf52fc
Implementado en: 0x52c84043cd9c865236f11d9fc9f56aa003c1f922
Hash de transacción: 0xf35c40dbbdc9e4298698ad1cb9937195e5a5e74e557bab1970a5dfd42a32f533

Después de una verificación exitosa, después de su implementación verá el estado de verificación del contrato como verificado exitosamente:

Iniciando verificación de contrato...
Esperando a que etherscan detecte la implementación del contrato...
Comenzando a verificar el contrato `0x8e982a4ef70430f8317b5652bd5c28f147fbf912` implementado en fuji

Enviando verificación para [contracts/NFT.sol:NFT] "0x8e982a4Ef70430f8317B5652Bd5C28F147FBf912".

Enviando verificación para [contracts/NFT.sol:NFT] "0x8e982a4Ef70430f8317B5652Bd5C28F147FBf912".
Contrato enviado para verificación:
Respuesta: `OK`
GUID: `cfkyqwvjjauafirepxt8qhks2zhptczzccqege9uefu9ma8wiz`
URL:
https://testnet.snowtrace.io/address/0x8e982a4ef70430f8317b5652bd5c28f147fbf912
Estado de verificación del contrato:
Respuesta: `NOTOK`
Detalles: `Pendiente en cola`
Estado de verificación del contrato:
Respuesta: `OK`
Detalles: `Pasar - Verificado`
Contrato verificado exitosamente

Nota: Por favor, guarde la dirección Implementado en para usarla en las siguientes secciones.

Verificación Después de la Implementación

Si no verificó durante el proceso de implementación, aún puede verificar un contrato implementado con foundry, usando forge verify-contract.

Nota: El archivo foundry.toml y las variables de entorno deberán estar configuradas como lo estaban en la sección anterior

Por ejemplo, si quisiéramos verificar el contrato NFT que acabamos de implementar en la sección anterior, se vería así:

forge verify-contract --chain-id 43113 --watch --constructor-args $(cast abi-encode "constructor(string,string)" "GameItem" "ITM") 0x8e982a4ef70430f8317b5652bd5c28f147fbf912 NFT

Después de una verificación exitosa, verá el estado de verificación del contrato como verificado exitosamente:

Iniciando verificación de contrato...
Esperando a que etherscan detecte la implementación del contrato...
Comenzando a verificar el contrato `0x8e982a4ef70430f8317b5652bd5c28f147fbf912` implementado en fuji

Enviando verificación para [contracts/NFT.sol:NFT] "0x8e982a4Ef70430f8317B5652Bd5C28F147FBf912".

Enviando verificación para [contracts/NFT.sol:NFT] "0x8e982a4Ef70430f8317B5652Bd5C28F147FBf912".
Contrato enviado para verificación:
Respuesta: `OK`
GUID: `cfkyqwvjjauafirepxt8qhks2zhptczzccqege9uefu9ma8wiz`
URL:
https://testnet.snowtrace.io/address/0x8e982a4ef70430f8317b5652bd5c28f147fbf912
Estado de verificación del contrato:
Respuesta: `NOTOK`
Detalles: `Pendiente en cola`
Estado de verificación del contrato:
Respuesta: `OK`
Detalles: `Pasar - Verificado`
Contrato verificado exitosamente

Usando Cast para Interactuar con el Contrato Inteligente

Podemos llamar a funciones en nuestro contrato NFT con Cast, la herramienta de línea de comandos de Foundry para interactuar con contratos inteligentes, enviar transacciones y obtener datos de la cadena. En este escenario, vamos a crear un NFT de un Ítem de Juego en la billetera de un jugador usando la función awardItem en nuestro contrato inteligente.

Cree un NFT desde su contrato reemplazando <NFT-CONTRACT-ADDRESS> con su dirección Implementado en y <NFT-RECIPIENT-ADDRESS> con una dirección de su elección.

Nota: Esta sección asume que ya ha configurado sus variables de entorno de RPC y clave privada durante la implementación

cast send --rpc-url=$RPC_URL  <NFT-CONTRACT-ADDRESS> "awardItem(address)" <NFT-RECIPIENT-ADDRESS> --private-key=$PRIVATE_KEY

Después de un éxito, la línea de comandos mostrará los datos de transacción.

blockHash               0x1d9b0364fe002eeddd0e32be0c27d6797c63dffb51fe555ea446357759e6a6f8
blockNumber 10714448
contractAddress
cumulativeGasUsed 90837
effectiveGasPrice 28000000000
gasUsed 90837
logs [{"address":"0x45857b942723fff8ee7acd2b1d6515d9965c16e5","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000845095a03a6686e24b90fed55e11f4ec808b1ab3","0x0000000000000000000000000000000000000000000000000000000000000001"],"data":"0x","blockHash":"0x1d9b0364fe002eeddd0e32be0c27d6797c63dffb51fe555ea446357759e6a6f8","blockNumber":"0xa37d50","transactionHash":"0x4651ae041a481a6eeb852e5300e9be48e66a1d2332733df22d8e75cf460b0c2c","transactionIndex":"0x0","logIndex":"0x0","removed":false}]
logsBloom 0x000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000400000000000000000000000000080100000000000000000400000000000

Was this page helpful?