
How to protect your crypto assets
Every day Web3 captivates the attention of more and more users, how wouldn’t it? that promise of removing power from the oppressors who unilaterally decide what should and should not be allowed, recovering our data from companies that only see us as a product and target for more ads. Web3 also allows novel ways for human coordination, public goods funding, and empowering what before was neglected, but as Uncle Ben says:“With great power comes great responsibility”Decentralization means that t...

Noir 101 for Solidity Devs
In this tutorial, we will create a simple “Secret Public Contract”, using Noir and Foundry. The contract will be deployed with an execute function which can only be executed with a secret calldata, meaning that only if you know the secret function and prove it, you can execute the contract functionality. You can see the complete code used in this tutorial in the following repository.Getting StartedNoir is a Domain Specific Language for SNARK proving systems. Its design choices are influenced ...

Noir 101 para Solidity Devs
En este tutorial, crearemos un sencillo "Contrato Público Secreto" utilizando Noir y Foundry. El contrato será desplegado con una función de ejecución que solo puede ser ejecutada con un "calldata" secreto, lo que significa que solo si conoces la función secreta y lo demuestras, podrás ejecutar la funcionalidad del contrato. Puedes ver el código completo utilizado en este tutorial en el siguiente repositorio.Primeros PasosNoir es un Lenguaje Específico de Dominio para sistemas de prueba de co...
Lead Solidity Dev @CryptexFinance 👾, Devcon V Scholar ⛓️ @Ethereum ☕, Collector of illiquid JPGs 🥃, Generative👨💻



How to protect your crypto assets
Every day Web3 captivates the attention of more and more users, how wouldn’t it? that promise of removing power from the oppressors who unilaterally decide what should and should not be allowed, recovering our data from companies that only see us as a product and target for more ads. Web3 also allows novel ways for human coordination, public goods funding, and empowering what before was neglected, but as Uncle Ben says:“With great power comes great responsibility”Decentralization means that t...

Noir 101 for Solidity Devs
In this tutorial, we will create a simple “Secret Public Contract”, using Noir and Foundry. The contract will be deployed with an execute function which can only be executed with a secret calldata, meaning that only if you know the secret function and prove it, you can execute the contract functionality. You can see the complete code used in this tutorial in the following repository.Getting StartedNoir is a Domain Specific Language for SNARK proving systems. Its design choices are influenced ...

Noir 101 para Solidity Devs
En este tutorial, crearemos un sencillo "Contrato Público Secreto" utilizando Noir y Foundry. El contrato será desplegado con una función de ejecución que solo puede ser ejecutada con un "calldata" secreto, lo que significa que solo si conoces la función secreta y lo demuestras, podrás ejecutar la funcionalidad del contrato. Puedes ver el código completo utilizado en este tutorial en el siguiente repositorio.Primeros PasosNoir es un Lenguaje Específico de Dominio para sistemas de prueba de co...
Lead Solidity Dev @CryptexFinance 👾, Devcon V Scholar ⛓️ @Ethereum ☕, Collector of illiquid JPGs 🥃, Generative👨💻
Share Dialog
Share Dialog

Subscribe to crisgarner.eth

Subscribe to crisgarner.eth
<100 subscribers
<100 subscribers
Forge is a fast and flexible testing framework, inspired by Dapp. Part of the Foundry toolkit, a blazing fast, portable and modular kit for Ethereum development written in Rust.
It’s really fast, no more wasted time while running tests.
Allows you to write tests in solidity which minimizes context switching.
A lot of testing features like fuzzing, console.log, and cheat codes give you more power and flexibility.
Non-standard directory structures support (works fine with Dapp or Hardhat repos).
Debugger and many more!
As foundry is evolving fast and has a lot of contributors, the recommended way to install is using foundryup tool.
On Linux and macOS systems can be installed like:
$ curl -L https://foundry.paradigm.xyz | bash
This command downloads foundryup. Then you can install foundry by running:
$ foundryup
In Windows, you need to install it by building from the source.
First, you need to install rust, you can follow the official documentation here:
https://www.rust-lang.org/tools/install
Then you can use cargo (the Rust package manager) to install foundry:
$ cargo install --git https://github.com/gakonst/foundry --bins --locked
As foundry is evolving fast with a lot of contributors it’s recommended to use forgeup for managing various versions of Forge.
Setup the folder that you want to use and initialize forge:
$ mkdir my-app
$ cd my-app
$ forge init
This creates a simple project structure, you can of course configure it according to your needs, but for simplicity in this tutorial, I will use the default structure.

The libraries that you install will go here, by default, ds-test is installed, this one allows you to run tests, create asserts or logs. If you want to install other libraries you can run:
$ forge install openzeppelin/openzeppelin-contracts
This will add the openZeppelin repo to lib/openzeppelin-contracts and you can use it with a simple import:
import "openzeppelin-contracts/contracts/access/Ownable.sol";
The path for the libs can be configured with remappings. See Appendix B — Using Remappings for further information.
The src folder is where your contracts are. We are going to use this simple example to run a few tests:
pragma solidity 0.8.10;
contract Blacksmith {
address public owner;
constructor(address _owner){
owner = _owner;
}
function onlyOwner() public{
require(msg.sender == owner, "Not the owner");
}
}
This is where your test lives, as a best practice, the test file is named exactly as the main contract with an appended “.t”, if your contract is named blacksmith.sol the test should be named blacksmith.t.sol.
We can define where the src and test folders are using environment variables. See Appendix A — Additional Resources for further information.
What makes a .sol file a test is inheriting from the DSTest library, which provides a complete list of assertions, equality checks, logs, and helpers that you can use. See the complete list on:
https://github.com/dapphub/ds-test/blob/master/src/test.sol
In order to run a test with forge you only need to use the command forge test . Use the following code and try it out:
pragma solidity 0.8.10;
import "ds-test/test.sol";
import "../Blacksmith.sol";
contract User {
function callOnlyOwner(Blacksmith b) public {
b.onlyOwner();
}
}
contract BlacksmithTest is DSTest {
Blacksmith blacksmith;
User user;
function setUp() public {
blacksmith = new Blacksmith(address(this));
user = new User();
}
function testOwner() public {
assertEq(blacksmith.owner(),address(this));
}
function testFailOwner() public {
user.callOnlyOwner(blacksmith);
}
function testWrongOwner() public {
user.callOnlyOwner(blacksmith); // This test will fail
}
}
Forge and Dapp use certain keywords in functions to run tests: setUp, test, and testFail.
setUp()
This function is called before each test or testFail function, perfect for initialization of contracts and additional setup.
test*()
Functions that start with the keyword test will get run with forge and expect to not revert in order to pass.
testFail*()
Functions that start with the keyword test will get run with forge and expect to revert in order to pass.
Forge implements some cheat codes that make failing tests in a better way, we will cover the cheat codes in another tutorial.
There is so much to cover with forge, but want to keep these tutorials short, will keep a small list of resources and tutorials updated in Appendix A — Additional Resources. Feel free to share this article or contact me by sending a DM on Twitter @Crisgarner.
Getting Started With Forge by Wilson - Another getting started guide with useful information about verbosity, logging, traces, and fuzzing.
Remappings help when you want to use NPM style imports, or have a hardhat repo that installs their packages in node_modules, for example:
import "@openzeppelin/contracts/access/Ownable.sol";
In order for Forge to know where to find this dependency you need to create a remappings.txt file at the top level of your project directory. So the steps you need to follow are:
forge install openzeppelin/openzeppelin-contracts (this will add the repo to lib/openzepplin-contracts)
Create a remappings file: touch remappings.txt
Add this line to remappings.txt
@openzeppelin/=lib/openzeppelin-contracts/
Forge is a fast and flexible testing framework, inspired by Dapp. Part of the Foundry toolkit, a blazing fast, portable and modular kit for Ethereum development written in Rust.
It’s really fast, no more wasted time while running tests.
Allows you to write tests in solidity which minimizes context switching.
A lot of testing features like fuzzing, console.log, and cheat codes give you more power and flexibility.
Non-standard directory structures support (works fine with Dapp or Hardhat repos).
Debugger and many more!
As foundry is evolving fast and has a lot of contributors, the recommended way to install is using foundryup tool.
On Linux and macOS systems can be installed like:
$ curl -L https://foundry.paradigm.xyz | bash
This command downloads foundryup. Then you can install foundry by running:
$ foundryup
In Windows, you need to install it by building from the source.
First, you need to install rust, you can follow the official documentation here:
https://www.rust-lang.org/tools/install
Then you can use cargo (the Rust package manager) to install foundry:
$ cargo install --git https://github.com/gakonst/foundry --bins --locked
As foundry is evolving fast with a lot of contributors it’s recommended to use forgeup for managing various versions of Forge.
Setup the folder that you want to use and initialize forge:
$ mkdir my-app
$ cd my-app
$ forge init
This creates a simple project structure, you can of course configure it according to your needs, but for simplicity in this tutorial, I will use the default structure.

The libraries that you install will go here, by default, ds-test is installed, this one allows you to run tests, create asserts or logs. If you want to install other libraries you can run:
$ forge install openzeppelin/openzeppelin-contracts
This will add the openZeppelin repo to lib/openzeppelin-contracts and you can use it with a simple import:
import "openzeppelin-contracts/contracts/access/Ownable.sol";
The path for the libs can be configured with remappings. See Appendix B — Using Remappings for further information.
The src folder is where your contracts are. We are going to use this simple example to run a few tests:
pragma solidity 0.8.10;
contract Blacksmith {
address public owner;
constructor(address _owner){
owner = _owner;
}
function onlyOwner() public{
require(msg.sender == owner, "Not the owner");
}
}
This is where your test lives, as a best practice, the test file is named exactly as the main contract with an appended “.t”, if your contract is named blacksmith.sol the test should be named blacksmith.t.sol.
We can define where the src and test folders are using environment variables. See Appendix A — Additional Resources for further information.
What makes a .sol file a test is inheriting from the DSTest library, which provides a complete list of assertions, equality checks, logs, and helpers that you can use. See the complete list on:
https://github.com/dapphub/ds-test/blob/master/src/test.sol
In order to run a test with forge you only need to use the command forge test . Use the following code and try it out:
pragma solidity 0.8.10;
import "ds-test/test.sol";
import "../Blacksmith.sol";
contract User {
function callOnlyOwner(Blacksmith b) public {
b.onlyOwner();
}
}
contract BlacksmithTest is DSTest {
Blacksmith blacksmith;
User user;
function setUp() public {
blacksmith = new Blacksmith(address(this));
user = new User();
}
function testOwner() public {
assertEq(blacksmith.owner(),address(this));
}
function testFailOwner() public {
user.callOnlyOwner(blacksmith);
}
function testWrongOwner() public {
user.callOnlyOwner(blacksmith); // This test will fail
}
}
Forge and Dapp use certain keywords in functions to run tests: setUp, test, and testFail.
setUp()
This function is called before each test or testFail function, perfect for initialization of contracts and additional setup.
test*()
Functions that start with the keyword test will get run with forge and expect to not revert in order to pass.
testFail*()
Functions that start with the keyword test will get run with forge and expect to revert in order to pass.
Forge implements some cheat codes that make failing tests in a better way, we will cover the cheat codes in another tutorial.
There is so much to cover with forge, but want to keep these tutorials short, will keep a small list of resources and tutorials updated in Appendix A — Additional Resources. Feel free to share this article or contact me by sending a DM on Twitter @Crisgarner.
Getting Started With Forge by Wilson - Another getting started guide with useful information about verbosity, logging, traces, and fuzzing.
Remappings help when you want to use NPM style imports, or have a hardhat repo that installs their packages in node_modules, for example:
import "@openzeppelin/contracts/access/Ownable.sol";
In order for Forge to know where to find this dependency you need to create a remappings.txt file at the top level of your project directory. So the steps you need to follow are:
forge install openzeppelin/openzeppelin-contracts (this will add the repo to lib/openzepplin-contracts)
Create a remappings file: touch remappings.txt
Add this line to remappings.txt
@openzeppelin/=lib/openzeppelin-contracts/
No activity yet