Comparing the way Forge, Tevm, Hardhat and forge-gas-metering will report gas usage against Sepolia testnet transactions.
There are two subsequent mint transactions on a newly deployed mock ERC20 contract, for each of the two scenarios. There are 50 0
bytes from the transaction's data in the first scenario that are turned into 1
bytes in the second one, which explains the expected 600 gas overhead (600 = 50 * (16 - 4)
).
The idea is to figure out which of these tools will report different gas usage based on the amount of zero and non-zero bytes that need to be read/written.
The process is the following:
- deploy the contract;
- mint the same amount of tokens to the same address twice.
recipient = 0x0000000000000000000000000000000000000001 | 0x1111111111111111111111111111111111111111
amount = 0x0000000000000000000000000000000000000000000000000000000000000001 | 0x1111111111111111111111111111111111111111111111111111111111111111
Medium | Zero bytes (1st) | Non-zero bytes (1st) | Zero bytes (2nd) | Non-zero bytes (2nd) | Bytes cost diff included | Exact match |
---|---|---|---|---|---|---|
Reference (Sepolia tx) | 67,839 | 68,439 | 33,639 | 34,239 | ✅ | ✅ |
Forge (isolated) | 67,839 | 68,439 | 33,639 | 34,239 | ✅ | ✅ |
Hardhat | 67,839 | 68,439 | 33,639 | 34,239 | ✅ | ✅ |
forge-gas-metering | 63,879 | 64,479 | 21,579 | 22,179 | ✅ | ❌ |
Forge | 46,495 | 46,495 | 2,695 | 2,695 | ❌ | ❌ |
Tevm | 46,495 | 46,495 | 2,695 | 2,695 | ❌ | ❌ |
git clone git@github.com:0xpolarzero/gas-metering-comparison.git
cd gas-metering-comparison
# From the root:
# Foundry
cd foundry
forge install
# Hardhat
cd hardhat
pnpm install
# Tevm
cd tevm
pnpm install
This will deploy the contract and mint the tokens twice. Which will provide both the reference Sepolia txs and the measurements from the script.
In /foundry
:
-
Create
.env
and fill it with the content in.env.example
; -
run
source .env
; -
deploy the contract and mint the tokens:
forge script script/DeployAndCall.s.sol:DeployAndCall --rpc-url $RPC_URL_SEPOLIA --broadcast -vvvv --sig "run(address, uint256)" 0x0000000000000000000000000000000000000001 0x0000000000000000000000000000000000000000000000000000000000000001
# or
forge script script/DeployAndCall.s.sol:DeployAndCall --rpc-url $RPC_URL_SEPOLIA --broadcast -vvvv --sig "run(address, uint256)" 0x1111111111111111111111111111111111111111 0x1111111111111111111111111111111111111111111111111111111111111111
In /foundry
: run forge test --mc MockERC20Foundry -vvvv --isolate
.
In /hardhat
: run pnpm hardhat test
.
In /foundry
: run forge test --mc MockERC20ForgeGasMetering -vv
.
In /tevm
: run pnpm ts-node index.ts
.