Repositorio de GitHub: - https://github.com/PradhumnaPancholi/Figbot
¡Hola a todos! Hace un tiempo, estaba aprendiendo Dapp Tools , ya que tiene herramientas fantásticas para desarrollar y auditar contratos inteligentes. Y aunque me encantó la experiencia, pronto supe que está en etapa de desarrollo clandestino. Esto significa que los usuarios ocasionales/individuales no pueden depender de los mantenedores para soporte y actualizaciones.
Entonces me topé con Foundry . Tiene todo lo que ofrece Dapp Tools además de la ejecución simbólica integrada (que no es un problema para mí, ya que uso Manticor e de Trail of Bits). Y esto está relacionado con la auditoría, por lo tanto, no es un obstáculo en el desarrollo de contratos inteligentes por ningún tramo de la imaginación.
Después de trabajar un tiempo con Foundry, disfruté la experiencia y quería compartirla con los demás. Por lo tanto, este artículo.
Este artículo analizará los beneficios de Foundry, el proceso de instalación, el desarrollo de un NFT (porque todos están interesados en eso), la prueba del contrato y su implementación con Figment Datahub .
Foundry es un kit de herramientas ultrarrápido, portátil y modular para el desarrollo de aplicaciones Ethereum escrito en Rust.
La fundición se compone de tres componentes:
El enfoque de hoy estará en Forge. Pero publicaré artículos detallados sobre Caste and Anvil en las próximas semanas.
Hay muchas herramientas de desarrollo de contratos inteligentes como Truffle, Hardhat y Brownie. Pero una de mis principales razones para buscar en Dapp Tools en primer lugar fueron las pruebas nativas de solidez. Escribir contratos inteligentes no es difícil cuando se cambia entre marcos como Hardhat y Brownie. Y son herramientas increíbles con complementos, pero uno debe estar bien versado en JavaScript/TypeScript y Python para realizar pruebas.
Foundry nos permite escribir nuestras pruebas de forma nativa en Solidity. Esto ahorra mucho tiempo en la incorporación de nuevos desarrolladores y facilita el proceso. En mi experiencia de ayudar a las personas a abrirse camino hacia el desarrollo de contratos inteligentes, he aprendido que la mejor y más eficiente manera para que los desarrolladores jóvenes se involucren con proyectos DAO/mantenidos por la comunidad es escribiendo pruebas y aprendiendo sobre el código base en sí. Recuerdo que Scupy Trooples mencionó una vez que usaron el mismo enfoque al desarrollar Alchemix Finance en Bankless .
Además de eso, el fuzzing incorporado, los códigos de trucos, Cast y Anvil lo convierten en un conjunto sólido para probar contratos inteligentes. Próximamente habrá artículos más detallados sobre esos componentes. [Analizador estático fácil de integrar]
Profundicemos y construyamos un proyecto NFT ahora.
Si está en Mac o Linux, todo lo que necesita hacer es ejecutar dos comandos:
curl -L https://foundry.paradigm.xyz | bash
foundryup
Asegúrese de cerrar la terminal antes de ejecutar foundryup
.
¡Y voilá! Ya has terminado.
Para Windows, debe tener Rust instalado y luego:
cargo install --git https://github.com/foundry-rs/foundry --locked
Para este artículo, crearemos un proyecto NFT simple llamado Figbots.
Comience creando un directorio llamado "Figbots". Y ejecute forge init
una vez que esté dentro del directorio. Este comando creará un proyecto de fundición para ti con git
inicializado.
Echemos un vistazo rápido a la estructura de carpetas. Tiene tres carpetas principales, a saber, src, lib y test. Aquí se explica por sí mismo, usted escribe sus contratos en src
, las pruebas en test
y lib
contiene todas las bibliotecas que instaló, por ejemplo, OpenZeppelin. Además de eso, obtienes foundry.toml
que contiene todas las configuraciones como hardhat.config.js
y brownie-config.yaml
si has usado esos marcos. Otra cosa dulce es .github, donde puedes escribir tus acciones de Github. Me resulta muy útil para las pruebas cuando se trabaja en equipo.
¡Empecemos a construir! Crearemos un NFT simple llamado Figbot con un suministro, costo (para acuñación) y retiro limitados. Con este enfoque, podemos cubrir bordes para diferentes pruebas. En primer lugar, cambie el nombre de Contract.sol
y test/Contract.t.sol
a Figbot.sol
y Figbot.t.sol
respectivamente. Ahora, no podemos escribir contratos inteligentes sin Openzeppelin, ¿verdad?
La instalación de bibliotecas con Foundry es ligeramente diferente a la de Hardhat y Brownie. No tenemos paquetes npm o pip. Instalamos bibliotecas directamente desde la fuente (repo de GitHub) en Foundry.
forge install Openzeppelin/openzeppelin-contracts
Ahora podemos importar la extensión ERC721URIStorage.sol para crear nuestro NFT. Para comprobar que todo está bien, podemos ejecutar el comando forge build
, y compilará nuestro proyecto. El compilador le gritará si hay algún problema. De lo contrario, obtendrá una compilación exitosa.
Al igual que cualquier otro administrador de paquetes, Forge le permite usar forge install <lib>,
forge remove <lib>
y forge update <lib>
para administrar sus dependencias.
Usaremos tres contratos de Openzeppelin. Contadores, ERC721URIStorage y Ownable. Es hora de subir nuestro activo a IPFS usando Pinata . Usamos el contrato Ownable para establecer el owner
de la dirección de implementación y tenemos acceso al modificador onlyOwner
para permitir que solo el propietario retire fondos. Counters
para ayudarnos con las identificaciones de token y ERC721URIStorage
para mantener el contrato NFT simple.
Configuración de la variable de estado:
MAX_SUPPLY
a 100COST
a 0.69 éterTOKEN_URI
a CID, recibimos de PinataUsando el contador para la identificación del token:
using Counters for Counters.Counter;
Counters.Counter private tokenIds;
Constructor ERC721:
constructor() ERC721(“Figbot”, “FBT”) {}
Función de menta:
msg.value
es mayor que COST
tokenIds.current()
es mayor o igual a MAX_SUPPLY
_safeMint
y _setTokenURI
Función de retiro:
function withdrawFunds() external onlyOwner { uint256 balance = address(this).balance; require(balance > 0, "No ether left to withdraw"); (bool success, ) = (msg.sender).call{value: balance}(""); require(success, "Withdrawal Failed"); emit Withdraw(msg.sender, balance); }
Función TotalSupply:
function totalSupply() public view returns (uint256) { return _tokenIds.current(); }
Como todos sabemos, probar nuestros contratos inteligentes es realmente importante. En esta sección, escribiremos algunas pruebas para obtener una comprensión sólida de la forge test
y acostumbrarnos a escribir pruebas en solidez nativa. Seremos tres códigos de trucos de Foundry (¡los amo!) para administrar los estados de cuenta para que se ajusten a nuestro escenario de prueba.
Estaremos probando para los siguientes escenarios:
Como podemos tener una lógica compleja en nuestros contratos inteligentes. Y se espera que se comporten de manera diferente según el estado, la cuenta utilizada para invocar, el tiempo, etc. Para lidiar con tales escenarios, podemos usar códigos de trucos para administrar el estado de la cadena de bloques. Podemos usar estos códigos de trucos usando la instancia vm
, que es parte de la biblioteca de Test
de Foundry.
Usaremos tres códigos de trucos en nuestras pruebas:
startPrank
: establece msg.sender
para todas las llamadas posteriores hasta que se llame a stopPrank
.
stopPrank
:
Detiene una broma activa iniciada por startPrank
, restableciendo msg.sender
y tx.origin
a los valores antes de llamar a startPrank
.
deal
: Establece el saldo de una dirección proporcionada en el saldo dado.
Foundry viene con una biblioteca de pruebas integrada. Comenzamos importando esta biblioteca de prueba, nuestro contrato (el que queremos probar), definiendo la prueba, configurando variables y setUp
la función.
pragma solidity ^0.8.13; import"forge-std/Test.sol"; import "../src/Figbot.sol"; contract FigbotTest is Test { Figbot figbot; address owner = address(0x1223); address alice = address(0x1889); address bob = address(0x1778); function setUp() public { vm.startPrank(owner); figbot = new Figbot(); vm.stopPrank(); } }
Para las variables de estado, creamos una variable figbot
de tipo Figbot
. Este es también el lugar donde me gusta definir las cuentas de usuario. En Foundry, puede describir una dirección utilizando la sintaxis address(0x1243)
. puede usar cuatro caracteres alfanuméricos para esto. He creado las cuentas con el nombre de propietario, Alice y bob, respectivamente.
Ahora nuestra función setUp
. Este es un requisito para escribir pruebas en Foundry. Aquí es donde hacemos todos los despliegues y cosas de esa naturaleza. Usé el código de startPrank
para cambiar al usuario al "propietario". De forma predeterminada, Foundry utiliza una dirección específica para implementar contratos de prueba. Pero eso hace que sea más difícil probar funciones con privilegios especiales como withdrawFunds
. Por lo tanto, cambiamos a la cuenta de "propietario" para esta implementación.
Comenzando con una prueba de aserción simple para aprender la convención de Foundry. Por convención, todas las funciones de prueba deben tener el prefijo test
. Y usamos assertEq
para probar si dos valores son iguales.
Llamamos a nuestra función MaxSupply
y probamos si el valor del resultado es 100, como describimos en nuestro contrato. Y usamos la forge test
para ejecutar nuestras pruebas.
¡¡¡Y voilá!!! tenemos una prueba aprobada.
Ahora que hemos escrito una prueba simple, escribamos una con códigos de trucos. La función principal de nuestro contrato.
balanceOf
Alice es 1 Tenemos otra función de prueba que se usa para las pruebas que esperamos que fallen. El prefijo utilizado para tal prueba es testFail
. Probaremos si la función de mint
se revierte si la persona que llama no tiene fondos suficientes.
balanceOf
Bob es 1 Debido a que mint no pasó, el saldo de Bob no va a ser 1. Por lo tanto, fallará, que es exactamente para lo que estamos acostumbrados a testFail
. Entonces, cuando ejecute la forge test
, pasará.
Aquí probaremos una función que solo el "propietario" puede realizar con éxito. Para esta prueba, vamos a:
withdrawFunds
de fondos (si tiene éxito, debería hacer que el saldo del propietario sea 0.69 ether)Ahora que hemos probado nuestro contrato, es hora de implementarlo. Necesitamos claves privadas para una billetera (con algunos ETH de prueba de Rinkeby) y una URL de RPC. Para nuestra URL de RPC, usaremos Figment DataHu .
Figment DataHub nos proporciona infraestructura para desarrollar sobre Web 3. Soporta múltiples cadenas como Ethereum, Celo, Solana, Terra, etc.
Puede obtener su URL de RPC para Rinkeby en la pestaña "Protocolos".
Abra su terminal para ingresar ambas cosas como variables de entorno.
export FIG_RINKEBY_URL=<Your RPC endpoint> export PVT_KEY=<Your wallets private key>
Una vez que tenemos las variables de entorno, estamos listos para implementar
forge create Figbot --rpc-url=$FIG_RINKEBY_URL --private-key=$PVT_KEY
Casi hemos terminado aquí. Hasta ahora, hemos escrito, probado e implementado un contrato inteligente con Foundry y Figment DataHub. Pero aún no hemos terminado del todo. Ahora vamos a verificar nuestro contrato. Tendremos que configurar nuestra clave API de Etherscan para eso.
export ETHERSCAN_API=<Your Etherscan API Key>
Y ahora podemos verificar nuestro contrato inteligente.
forge verify-contract --chain-id <Chain-Id> --num-of-optimizations 200 --compiler-version <Compiler Version> src/<Contract File>:<Contract> $ETHERSCAN_API
¡Felicidades! Ahora puede escribir, probar e implementar contratos inteligentes con Foundry. Espero que hayan disfrutado y aprendido de este artículo. Realmente disfruté escribiendo esto. No dude en hacerme saber sus pensamientos al respecto.