Platform: Code4rena
Start Date: 12/07/2022
Pot Size: $75,000 USDC
Total HM: 16
Participants: 100
Period: 7 days
Judge: LSDan
Total Solo HM: 7
Id: 145
League: ETH
Rank: 24/100
Findings: 1
Award: $390.12
🌟 Selected for report: 1
🚀 Solo Findings: 0
🌟 Selected for report: 0xKitsune
Also found by: 0x040, 0x1f8b, 0x29A, 0xNazgul, 0xNineDec, 0xsam, 8olidity, Aussie_Battlers, Aymen0909, Bnke0x0, CRYP70, Ch_301, Chom, Deivitto, Dravee, ElKu, Fitraldys, Funen, GimelSec, IllIllI, JC, JohnSmith, Lambda, MiloTruck, Noah3o6, RedOneN, ReyAdmirado, Rohan16, Rolezn, Ruhum, Sm4rty, TomJ, Tomio, Waze, _Adam, __141345__, ajtra, ak1, arcoun, asutorufos, benbaessler, brgltd, bulej93, c3phas, cRat1st0s, cryptonue, delfin454000, durianSausage, fatherOfBlocks, gogo, hake, hyh, joestakey, karanctf, kyteg, lcfr_eth, lucacez, m_Rassska, rajatbeladiya, rbserver, robee, rokinot, sach1r0, sahar, samruna, sashik_eth, seyni, simon135, zuhaibmohd
390.1243 USDC - $390.12
The following sections detail the gas optimizations found throughout the codebase. Each optimization is documented with the setup, an explainer for the optimization, a gas report and line identifiers for each optimization across the codebase. For each section's gas report, the optimizer was turned on and set to 10000 runs. You can replicate any tests/gas reports by heading to 0xKitsune/gas-lab and cloning the repo. Then, simply copy/paste the contract examples from any section and run forge test --gas-report
. You can also easily update the optimizer runs in the foundry.toml
.
contract GasTest is DSTest { Contract0 c0; Contract1 c1; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); } function testGas() public view { c0.solidityHash(2309349, 2304923409); c1.assemblyHash(2309349, 2304923409); } } contract Contract0 { function solidityHash(uint256 a, uint256 b) public view { //unoptimized keccak256(abi.encodePacked(a, b)); } } contract Contract1 { function assemblyHash(uint256 a, uint256 b) public view { //optimized assembly { mstore(0x00, a) mstore(0x20, b) let hashedVal := keccak256(0x00, 0x40) } } }
╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract0 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 36687 ┆ 214 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ solidityHash ┆ 313 ┆ 313 ┆ 313 ┆ 313 ┆ 1 │ ╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯ ╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract1 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 31281 ┆ 186 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ assemblyHash ┆ 231 ┆ 231 ┆ 231 ┆ 231 ┆ 1 │ ╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
ReverseRegistrar.sol:82
ReverseRegistrar.sol:150
ETHRegistrarController.sol:73
ETHRegistrarController.sol:82
ETHRegistrarController.sol:97
ETHRegistrarController.sol:105
ETHRegistrarController.sol:167
ETHRegistrarController.sol:175
ETHRegistrarController.sol:194
ETHRegistrarController.sol:255
NameWrapper.sol:217
NameWrapper.sol:259
NameWrapper.sol:406
NameWrapper.sol:435
NameWrapper.sol:516
NameWrapper.sol:552
NameWrapper.sol:713
NameWrapper.sol:738
NameWrapper.sol:894
BytesUtil.sol:31
unchecked{++i}
instead of i++
(or use assembly when applicable)Use ++i
instead of i++
. This is especially useful in for loops but this optimization can be used anywhere in your code. You can also use unchecked{++i;}
for even more gas savings but this will not check to see if i
overflows. For extra safety if you are worried about this, you can add a require statement after the loop checking if i
is equal to the final incremented value. For best gas savings, use inline assembly, however this limits the functionality you can achieve. For example you cant use Solidity syntax to internally call your own contract within an assembly block and external calls must be done with the call()
or delegatecall()
instruction. However when applicable, inline assembly will save much more gas.
contract GasTest is DSTest { Contract0 c0; Contract1 c1; Contract2 c2; Contract3 c3; Contract4 c4; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); c2 = new Contract2(); c3 = new Contract3(); c4 = new Contract4(); } function testGas() public { c0.iPlusPlus(); c1.plusPlusI(); c2.uncheckedPlusPlusI(); c3.safeUncheckedPlusPlusI(); c4.inlineAssemblyLoop(); } } contract Contract0 { //loop with i++ function iPlusPlus() public pure { uint256 j = 0; for (uint256 i; i < 10; i++) { j++; } } } contract Contract1 { //loop with ++i function plusPlusI() public pure { uint256 j = 0; for (uint256 i; i < 10; ++i) { j++; } } } contract Contract2 { //loop with unchecked{++i} function uncheckedPlusPlusI() public pure { uint256 j = 0; for (uint256 i; i < 10; ) { j++; unchecked { ++i; } } } } contract Contract3 { //loop with unchecked{++i} with additional overflow check function safeUncheckedPlusPlusI() public pure { uint256 j = 0; uint256 i = 0; for (i; i < 10; ) { j++; unchecked { ++i; } } //check for overflow assembly { if lt(i, 10) { mstore(0x00, "loop overflow") revert(0x00, 0x20) } } } } contract Contract4 { //loop with inline assembly function inlineAssemblyLoop() public pure { assembly { let j := 0 for { let i := 0 } lt(i, 10) { i := add(i, 0x01) } { j := add(j, 0x01) } } } }
╭────────────────────┬─────────────────┬──────┬────────┬──────┬─────────╮ │ Contract0 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪══════╪════════╪══════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 37687 ┆ 219 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ iPlusPlus ┆ 2039 ┆ 2039 ┆ 2039 ┆ 2039 ┆ 1 │ ╰────────────────────┴─────────────────┴──────┴────────┴──────┴─────────╯ ╭────────────────────┬─────────────────┬──────┬────────┬──────┬─────────╮ │ Contract1 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪══════╪════════╪══════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 37287 ┆ 217 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ plusPlusI ┆ 1989 ┆ 1989 ┆ 1989 ┆ 1989 ┆ 1 │ ╰────────────────────┴─────────────────┴──────┴────────┴──────┴─────────╯ ╭────────────────────────┬─────────────────┬──────┬────────┬──────┬─────────╮ │ Contract3 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════════╪═════════════════╪══════╪════════╪══════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 42693 ┆ 244 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ safeUncheckedPlusPlusI ┆ 1355 ┆ 1355 ┆ 1355 ┆ 1355 ┆ 1 │ ╰────────────────────────┴─────────────────┴──────┴────────┴──────┴─────────╯ ╭────────────────────┬─────────────────┬──────┬────────┬──────┬─────────╮ │ Contract2 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪══════╪════════╪══════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 35887 ┆ 210 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ uncheckedPlusPlusI ┆ 1329 ┆ 1329 ┆ 1329 ┆ 1329 ┆ 1 │ ╰────────────────────┴─────────────────┴──────┴────────┴──────┴─────────╯ ╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract4 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 26881 ┆ 164 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ inlineAssemblyLoop ┆ 709 ┆ 709 ┆ 709 ┆ 709 ┆ 1 │ ╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
DNSSECImpl.sol:93
ETHRegistrarController.sol:256
BytesUtils.sol:266
BytesUtils.sol:313
ERC1155Fuse.sol:92
ERC1155Fuse.sol:205
StringUtils.sol:14
Use assembly for math instead of Solidity. You can check for overflow/underflow in assembly to ensure safety. If using Solidity versions < 0.8.0 and you are using Safemath, you can gain significant gas savings by using assembly to calculate values and checking for overflow/underflow.
contract GasTest is DSTest { Contract0 c0; Contract1 c1; Contract2 c2; Contract3 c3; Contract4 c4; Contract5 c5; Contract6 c6; Contract7 c7; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); c2 = new Contract2(); c3 = new Contract3(); c4 = new Contract4(); c5 = new Contract5(); c6 = new Contract6(); c7 = new Contract7(); } function testGas() public { c0.addTest(34598345, 100); c1.addAssemblyTest(34598345, 100); c2.subTest(34598345, 100); c3.subAssemblyTest(34598345, 100); c4.mulTest(34598345, 100); c5.mulAssemblyTest(34598345, 100); c6.divTest(34598345, 100); c7.divAssemblyTest(34598345, 100); } } contract Contract0 { //addition in Solidity function addTest(uint256 a, uint256 b) public pure { uint256 c = a + b; } } contract Contract1 { //addition in assembly function addAssemblyTest(uint256 a, uint256 b) public pure { assembly { let c := add(a, b) if lt(c, a) { mstore(0x00, "overflow") revert(0x00, 0x20) } } } } contract Contract2 { //subtraction in Solidity function subTest(uint256 a, uint256 b) public pure { uint256 c = a - b; } } contract Contract3 { //subtraction in assembly function subAssemblyTest(uint256 a, uint256 b) public pure { assembly { let c := sub(a, b) if gt(c, a) { mstore(0x00, "underflow") revert(0x00, 0x20) } } } } contract Contract4 { //multiplication in Solidity function mulTest(uint256 a, uint256 b) public pure { uint256 c = a * b; } } contract Contract5 { //multiplication in assembly function mulAssemblyTest(uint256 a, uint256 b) public pure { assembly { let c := mul(a, b) if lt(c, a) { mstore(0x00, "overflow") revert(0x00, 0x20) } } } } contract Contract6 { //division in Solidity function divTest(uint256 a, uint256 b) public pure { uint256 c = a * b; } } contract Contract7 { //division in assembly function divAssemblyTest(uint256 a, uint256 b) public pure { assembly { let c := div(a, b) if gt(c, a) { mstore(0x00, "underflow") revert(0x00, 0x20) } } } }
╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract0 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 40493 ┆ 233 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ addTest ┆ 303 ┆ 303 ┆ 303 ┆ 303 ┆ 1 │ ╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯ ╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract1 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 37087 ┆ 216 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ addAssemblyTest ┆ 263 ┆ 263 ┆ 263 ┆ 263 ┆ 1 │ ╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯ ╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract2 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 40293 ┆ 232 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ subTest ┆ 300 ┆ 300 ┆ 300 ┆ 300 ┆ 1 │ ╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯ ╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract3 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 37287 ┆ 217 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ subAssemblyTest ┆ 263 ┆ 263 ┆ 263 ┆ 263 ┆ 1 │ ╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯ ╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract4 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 41893 ┆ 240 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ mulTest ┆ 325 ┆ 325 ┆ 325 ┆ 325 ┆ 1 │ ╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯ ╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract5 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 37087 ┆ 216 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ mulAssemblyTest ┆ 265 ┆ 265 ┆ 265 ┆ 265 ┆ 1 │ ╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯ ╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract6 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 41893 ┆ 240 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ divTest ┆ 325 ┆ 325 ┆ 325 ┆ 325 ┆ 1 │ ╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯ ╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract7 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 37287 ┆ 217 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ divAssemblyTest ┆ 265 ┆ 265 ┆ 265 ┆ 265 ┆ 1 │ ╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
DNSSECImpl.sol:187
DNSSECImpl.sol:309
DNSSECImpl.sol:318
ETHRegistrarController.sol:121
ETHRegistrarController.sol:138
ETHRegistrarController.sol:182
ETHRegistrarController.sol:184
ETHRegistrarController.sol:204
ETHRegistrarController.sol:233
ETHRegistrarController.sol:239
BytesUtils.sol:12
BytesUtils.sol:69
BytesUtils.sol:71
BytesUtils.sol:79
BytesUtils.sol:104
BytesUtils.sol:116
BytesUtils.sol:146
BytesUtils.sol:159
BytesUtils.sol:172
BytesUtils.sol:185
BytesUtils.sol:200
BytesUtils.sol:219
BytesUtils.sol:235
BytesUtils.sol:267
BytesUtils.sol:269
BytesUtils.sol:271
BytesUtils.sol:277
BytesUtils.sol:301
BytesUtils.sol:313
BytesUtil.sol:13
BytesUtil.sol:28
BytesUtil.sol:45
BytesUtil.sol:49
RRUtils.sol:24
RRUtils.sol:29
RRUtils.sol:54
RRUtils.sol:94
RRUtils.sol:146
RRUtils.sol:160
RRUtils.sol:178
RRUtils.sol:194
RRUtils.sol:195
RRUtils.sol:196
RRUtils.sol:197
RRUtils.sol:213
RRUtils.sol:214
RRUtils.sol:215
RRUtils.sol:216
RRUtils.sol:260
RRUtils.sol:267
RRUtils.sol:271
RRUtils.sol:310
RRUtils.sol:315
RRUtils.sol:316
RRUtils.sol:322
RRUtils.sol:324
RRUtils.sol:326
RRUtils.sol:327
RRUtils.sol:329
RRUtils.sol:331
calldata
instead of memory
for function arguments that do not get mutated.Mark data types as calldata
instead of memory
where possible. This makes it so that the data is not automatically loaded into memory. If the data passed into the function does not need to be changed (like updating values in an array), it can be passed in as calldata
. The one exception to this is if the argument must later be passed into another function that takes an argument that specifies memory
storage.
contract GasTest is DSTest { Contract0 c0; Contract1 c1; Contract2 c2; Contract3 c3; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); c2 = new Contract2(); c3 = new Contract3(); } function testGas() public { uint256[] memory arr = new uint256[](10); c0.calldataArray(arr); c1.memoryArray(arr); bytes memory data = abi.encode("someText"); c2.calldataBytes(data); c3.memoryBytes(data); } } contract Contract0 { function calldataArray(uint256[] calldata arr) public { uint256 j; for (uint256 i; i < arr.length; i++) { j = arr[i] + 10; } } } contract Contract1 { function memoryArray(uint256[] memory arr) public { uint256 j; for (uint256 i; i < arr.length; i++) { j = arr[i] + 10; } } } contract Contract2 { function calldataBytes(bytes calldata data) public { bytes32 val; for (uint256 i; i < 10; i++) { val = keccak256(abi.encode(data, i)); } } } contract Contract3 { function memoryBytes(bytes memory data) public { bytes32 val; for (uint256 i; i < 10; i++) { val = keccak256(abi.encode(data, i)); } } }
╭───────────────────────────────────────────┬─────────────────┬──────┬────────┬──────┬─────────╮ │ src/test/GasTest.t.sol:Contract0 contract ┆ ┆ ┆ ┆ ┆ │ ╞═══════════════════════════════════════════╪═════════════════╪══════╪════════╪══════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 97947 ┆ 521 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ calldataArray ┆ 2824 ┆ 2824 ┆ 2824 ┆ 2824 ┆ 1 │ ╰───────────────────────────────────────────┴─────────────────┴──────┴────────┴──────┴─────────╯ ╭───────────────────────────────────────────┬─────────────────┬──────┬────────┬──────┬─────────╮ │ src/test/GasTest.t.sol:Contract1 contract ┆ ┆ ┆ ┆ ┆ │ ╞═══════════════════════════════════════════╪═════════════════╪══════╪════════╪══════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 128171 ┆ 672 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ memoryArray ┆ 3755 ┆ 3755 ┆ 3755 ┆ 3755 ┆ 1 │ ╰───────────────────────────────────────────┴─────────────────┴──────┴────────┴──────┴─────────╯ ╭───────────────────────────────────────────┬─────────────────┬──────┬────────┬──────┬─────────╮ │ src/test/GasTest.t.sol:Contract2 contract ┆ ┆ ┆ ┆ ┆ │ ╞═══════════════════════════════════════════╪═════════════════╪══════╪════════╪══════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 100547 ┆ 534 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ calldataBytes ┆ 4934 ┆ 4934 ┆ 4934 ┆ 4934 ┆ 1 │ ╰───────────────────────────────────────────┴─────────────────┴──────┴────────┴──────┴─────────╯ ╭───────────────────────────────────────────┬─────────────────┬──────┬────────┬──────┬─────────╮ │ src/test/GasTest.t.sol:Contract3 contract ┆ ┆ ┆ ┆ ┆ │ ╞═══════════════════════════════════════════╪═════════════════╪══════╪════════╪══════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 135183 ┆ 707 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ memoryBytes ┆ 7551 ┆ 7551 ┆ 7551 ┆ 7551 ┆ 1 │ ╰───────────────────────────────────────────┴─────────────────┴──────┴────────┴──────┴─────────╯
ReverseRegistrar.sol:9
ReverseRegistrar.sol:112
ReverseRegistrar.sol:136
DNSSECImpl.sol:46
DNSSECImpl.sol:80
DNSSECImpl.sol:91
DNSSECImpl.sol:110
DNSSECImpl.sol:147
DNSSECImpl.sol:183
DNSSECImpl.sol:209
DNSSECImpl.sol:233
DNSSECImpl.sol:273
DNSSECImpl.sol:299
DNSSECImpl.sol:335
ETHRegistrarController.sol:67
ETHRegistrarController.sol:77
ETHRegistrarController.sol:81
ETHRegistrarController.sol:87
ETHRegistrarController.sol:227
ETHRegistrarController.sol:271
BytesUtils.sol:11
BytesUtils.sol:27
BytesUtils.sol:44
BytesUtils.sol:91
BytesUtils.sol:103
BytesUtils.sol:115
BytesUtils.sol:125
BytesUtils.sol:135
BytesUtils.sol:145
BytesUtils.sol:158
BytesUtils.sol:171
BytesUtils.sol:184
BytesUtils.sol:198
BytesUtils.sol:234
BytesUtils.sol:261
BytesUtils.sol:312
NameWrapper.sol:541
NameWrapper.sol:741
NameWrapper.sol:773
NameWrapper.sol:786
NameWrapper.sol:886
ERC1155Fuse.sol:78
ERC1155Fuse.sol:174
ERC1155Fuse.sol:191
ERC1155Fuse.sol:192
ERC1155Fuse.sol:193
ERC1155Fuse.sol:279
ERC1155Fuse.sol:307
ERC1155Fuse.sol:336
ERC1155Fuse.sol:337
ERC1155Fuse.sol:338
StringUtils.sol:10
SHA1.sol:6
BytesUtil.sol:12
BytesUtil.sol:25
BytesUtil.sol:41
RRUtils.sol:19
RRUtils.sol:38
RRUtils.sol:49
RRUtils.sol:85
RRUtils.sol:97
RRUtils.sol:120
RRUtils.sol:131
RRUtils.sol:139
RRUtils.sol:168
RRUtils.sol:177
RRUtils.sol:193
RRUtils.sol:212
RRUtils.sol:219
RRUtils.sol:270
RRUtils.sol:279
You can save gas by breaking up a require statement with multiple conditions, into multiple require statements with a single condition.
contract GasTest is DSTest { Contract0 c0; Contract1 c1; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); } function testGas() public { c0.singleRequire(3); c1.multipleRequire(3); } } contract Contract0 { function singleRequire(uint256 num) public { require(num > 1 && num < 10 && num == 3); } } contract Contract1 { function multipleRequire(uint256 num) public { require(num > 1); require(num < 10); require(num == 3); } }
╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract0 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 35487 ┆ 208 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ singleRequire ┆ 286 ┆ 286 ┆ 286 ┆ 286 ┆ 1 │ ╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯ ╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract1 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 35887 ┆ 210 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ multipleRequire ┆ 270 ┆ 270 ┆ 270 ┆ 270 ┆ 1 │ ╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
BytesUtils.sol:268
ERC1155Fuse.sol:216
ERC1155Fuse.sol:291
contract GasTest is DSTest { Contract0 c0; Contract1 c1; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); } function testGas() public { c0.updateOwner(0x158B28A1b1CB1BE12C6bD8f5a646a0e3B2024734); c1.assemblyUpdateOwner(0x158B28A1b1CB1BE12C6bD8f5a646a0e3B2024734); } } contract Contract0 { address owner = 0xb4c79daB8f259C7Aee6E5b2Aa729821864227e84; function updateOwner(address newOwner) public { owner = newOwner; } } contract Contract1 { address owner = 0xb4c79daB8f259C7Aee6E5b2Aa729821864227e84; function assemblyUpdateOwner(address newOwner) public { assembly { sstore(owner.slot, newOwner) } } }
╭────────────────────┬─────────────────┬──────┬────────┬──────┬─────────╮ │ Contract0 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪══════╪════════╪══════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 60623 ┆ 261 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ updateOwner ┆ 5302 ┆ 5302 ┆ 5302 ┆ 5302 ┆ 1 │ ╰────────────────────┴─────────────────┴──────┴────────┴──────┴─────────╯ ╭────────────────────┬─────────────────┬──────┬────────┬──────┬─────────╮ │ Contract1 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪══════╪════════╪══════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 54823 ┆ 232 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ assemblyUpdateOwner┆ 5236 ┆ 5236 ┆ 5236 ┆ 5236 ┆ 1 │ ╰────────────────────┴─────────────────┴──────┴────────┴──────┴─────────╯
Owned.sol:15
Owned.sol:19
ETHRegistrarController.sol:61
ETHRegistrarController.sol:62
contract GasTest is DSTest { Contract0 c0; Contract1 c1; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); } function testGas() public view { c0.ownerNotZero(address(this)); c1.assemblyOwnerNotZero(address(this)); } } contract Contract0 { function ownerNotZero(address _addr) public pure { require(_addr != address(0), "zero address)"); } } contract Contract1 { function assemblyOwnerNotZero(address _addr) public pure { assembly { if iszero(_addr) { mstore(0x00, "zero address") revert(0x00, 0x20) } } } }
╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract0 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 61311 ┆ 338 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ ownerNotZero ┆ 258 ┆ 258 ┆ 258 ┆ 258 ┆ 1 │ ╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯ ╭──────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract1 contract ┆ ┆ ┆ ┆ ┆ │ ╞══════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 44893 ┆ 255 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ assemblyOwnerNotZero ┆ 252 ┆ 252 ┆ 252 ┆ 252 ┆ 1 │ ╰──────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
ReverseRegistrar.sol:53
DNSSECImpl.sol:336
ETHRegistrarController.sol:100
NameWrapper.sol:132
NameWrapper.sol:139
NameWrapper.sol:318
NameWrapper.sol:661
NameWrapper.sol:763
NameWrapper.sol:799
NameWrapper.sol:911
ERC1155Fuse.sol:61
ERC1155Fuse.sol:176
ERC1155Fuse.sol:199
ERC1155Fuse.sol:248
ERC1155Fuse.sol:249
You can use selfbalance()
instead of address(this).balance
when getting your contract's balance of ETH to save gas. Additionally, you can use balance(address)
instead of address.balance()
when getting an external contract's balance of ETH.
contract GasTest is DSTest { Contract0 c0; Contract1 c1; Contract2 c2; Contract3 c3; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); c2 = new Contract2(); c3 = new Contract3(); } function testGas() public { c0.addressInternalBalance(); c1.assemblyInternalBalance(); c2.addressExternalBalance(address(this)); c3.assemblyExternalBalance(address(this)); } } contract Contract0 { function addressInternalBalance() public returns (uint256) { return address(this).balance; } } contract Contract1 { function assemblyInternalBalance() public returns (uint256) { assembly { let c := selfbalance() mstore(0x00, c) return(0x00, 0x20) } } } contract Contract2 { function addressExternalBalance(address addr) public { uint256 bal = address(addr).balance; bal++; } } contract Contract3 { function assemblyExternalBalance(address addr) public { uint256 bal; assembly { bal := balance(addr) } bal++; } }
╭────────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract0 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 23675 ┆ 147 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ addressInternalBalance ┆ 148 ┆ 148 ┆ 148 ┆ 148 ┆ 1 │ ╰────────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯ ╭─────────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract1 contract ┆ ┆ ┆ ┆ ┆ │ ╞═════════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 27081 ┆ 165 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ assemblyInternalBalance ┆ 133 ┆ 133 ┆ 133 ┆ 133 ┆ 1 │ ╰─────────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯ ╭────────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract2 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 61511 ┆ 339 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ addressExternalBalance ┆ 417 ┆ 417 ┆ 417 ┆ 417 ┆ 1 │ ╰────────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯ ╭─────────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract3 contract ┆ ┆ ┆ ┆ ┆ │ ╞═════════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 57105 ┆ 317 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ assemblyExternalBalance ┆ 411 ┆ 411 ┆ 411 ┆ 411 ┆ 1 │ ╰─────────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
A typical for loop definition may look like: for (uint256 i; i < arr.length; i++){}
. Instead of using array.length
, cache the array length before the loop, and use the cached value to safe gas. This will avoid an MLOAD
every loop for arrays stored in memory and an SLOAD
for arrays stored in storage. This can have significant gas savings for arrays with a large length, especially if the array is stored in storage.
contract GasTest is DSTest { Contract0 c0; Contract1 c1; Contract2 c2; Contract3 c3; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); c2 = new Contract2(); c3 = new Contract3(); } function testGas() public view { uint256[] memory arr = new uint256[](10); c0.nonCachedMemoryListLength(arr); c1.cachedMemoryListLength(arr); c2.nonCachedStorageListLength(); c3.cachedStorageListLength(); } } contract Contract0 { function nonCachedMemoryListLength(uint256[] memory arr) public pure { uint256 j; for (uint256 i; i < arr.length; i++) { j = arr[i] + 10; } } } contract Contract1 { function cachedMemoryListLength(uint256[] memory arr) public pure { uint256 j; uint256 length = arr.length; for (uint256 i; i < length; i++) { j = arr[i] + 10; } } } contract Contract2 { uint256[] arr = new uint256[](10); function nonCachedStorageListLength() public view { uint256 j; for (uint256 i; i < arr.length; i++) { j = arr[i] + 10; } } } contract Contract3 { uint256[] arr = new uint256[](10); function cachedStorageListLength() public view { uint256 j; uint256 length = arr.length; for (uint256 i; i < length; i++) { j = arr[i] + 10; } } }
╭───────────────────────────────────────────┬─────────────────┬──────┬────────┬──────┬─────────╮ │ src/test/GasTest.t.sol:Contract0 contract ┆ ┆ ┆ ┆ ┆ │ ╞═══════════════════════════════════════════╪═════════════════╪══════╪════════╪══════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 128171 ┆ 672 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ nonCachedMemoryListLength ┆ 3755 ┆ 3755 ┆ 3755 ┆ 3755 ┆ 1 │ ╰───────────────────────────────────────────┴─────────────────┴──────┴────────┴──────┴─────────╯ ╭───────────────────────────────────────────┬─────────────────┬──────┬────────┬──────┬─────────╮ │ src/test/GasTest.t.sol:Contract1 contract ┆ ┆ ┆ ┆ ┆ │ ╞═══════════════════════════════════════════╪═════════════════╪══════╪════════╪══════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 128777 ┆ 675 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ cachedMemoryListLength ┆ 3733 ┆ 3733 ┆ 3733 ┆ 3733 ┆ 1 │ ╰───────────────────────────────────────────┴─────────────────┴──────┴────────┴──────┴─────────╯ ╭───────────────────────────────────────────┬─────────────────┬───────┬────────┬───────┬─────────╮ │ src/test/GasTest.t.sol:Contract2 contract ┆ ┆ ┆ ┆ ┆ │ ╞═══════════════════════════════════════════╪═════════════════╪═══════╪════════╪═══════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 118474 ┆ 539 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ nonCachedStorageListLength ┆ 27979 ┆ 27979 ┆ 27979 ┆ 27979 ┆ 1 │ ╰───────────────────────────────────────────┴─────────────────┴───────┴────────┴───────┴─────────╯ ╭───────────────────────────────────────────┬─────────────────┬───────┬────────┬───────┬─────────╮ │ src/test/GasTest.t.sol:Contract3 contract ┆ ┆ ┆ ┆ ┆ │ ╞═══════════════════════════════════════════╪═════════════════╪═══════╪════════╪═══════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 118674 ┆ 540 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ cachedStorageListLength ┆ 26984 ┆ 26984 ┆ 26984 ┆ 26984 ┆ 1 │ ╰───────────────────────────────────────────┴─────────────────┴───────┴────────┴───────┴─────────╯
DNSSECImpl.sol:93
ETHRegistrarController.sol:256
ERC1155Fuse.sol:92
ERC1155Fuse.sol:205
RRUtils.sol:310
You can mark public or external functions as payable to save gas. Functions that are not payable have additional logic to check if there was a value sent with a call, however, making a function payable eliminates this check. This optimization should be carefully considered due to potentially unwanted behavior when a function does not need to accept ether.
contract GasTest is DSTest { Contract0 c0; Contract1 c1; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); } function testGas() public { c0.isNotPayable(); c1.isPayable(); } } contract Contract0 { function isNotPayable() public view { uint256 val = 0; val++; } } contract Contract1 { function isPayable() public payable { uint256 val = 0; val++; } }
╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract0 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 32081 ┆ 190 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ isNotPayable ┆ 198 ┆ 198 ┆ 198 ┆ 198 ┆ 1 │ ╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯ ╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract1 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 29681 ┆ 178 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ isPayable ┆ 174 ┆ 174 ┆ 174 ┆ 174 ┆ 1 │ ╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
ReverseRegistrar.sol:51
ReverseRegistrar.sol:65
ReverseRegistrar.sol:76
ReverseRegistrar.sol:97
ReverseRegistrar.sol:112
ReverseRegistrar.sol:132
ReverseRegistrar.sol:148
DNSSECImpl.sol:58
DNSSECImpl.sol:69
DNSSECImpl.sol:80
DNSSECImpl.sol:91
Owned.sol:14
Owned.sol:18
ETHRegistrarController.sol:67
ETHRegistrarController.sol:77
ETHRegistrarController.sol:81
ETHRegistrarController.sol:86
ETHRegistrarController.sol:120
ETHRegistrarController.sol:210
ETHRegistrarController.sol:214
NameWrapper.sol:76
NameWrapper.sol:90
NameWrapper.sol:105
NameWrapper.sol:117
NameWrapper.sol:128
NameWrapper.sol:165
NameWrapper.sol:185
NameWrapper.sol:210
NameWrapper.sol:251
NameWrapper.sol:271
NameWrapper.sol:295
NameWrapper.sol:335
NameWrapper.sol:356
NameWrapper.sol:373
NameWrapper.sol:401
NameWrapper.sol:429
NameWrapper.sol:456
NameWrapper.sol:504
NameWrapper.sol:539
NameWrapper.sol:584
NameWrapper.sol:609
NameWrapper.sol:624
NameWrapper.sol:683
NameWrapper.sol:693
ERC1155Fuse.sol:25
ERC1155Fuse.sol:33
ERC1155Fuse.sol:53
ERC1155Fuse.sol:78
ERC1155Fuse.sol:102
ERC1155Fuse.sol:119
ERC1155Fuse.sol:132
ERC1155Fuse.sol:169
ERC1155Fuse.sol:188
Controllable.sol:11
contract GasTest is DSTest { Contract0 c0; Contract1 c1; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); } function testFailGas() public { c0.stringErrorMessage(); c1.customErrorMessage(); } } contract Contract0 { function stringErrorMessage() public { bool check = false; require(check, "error message"); } } contract Contract1 { error CustomError(); function customErrorMessage() public { bool check = false; if (!check) { revert CustomError(); } } }
╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract0 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 34087 ┆ 200 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ stringErrorMessage ┆ 218 ┆ 218 ┆ 218 ┆ 218 ┆ 1 │ ╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯ ╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ Contract1 contract ┆ ┆ ┆ ┆ ┆ │ ╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ 26881 ┆ 164 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ customErrorMessage ┆ 161 ┆ 161 ┆ 161 ┆ 161 ┆ 1 │ ╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
ReverseRegistrar.sol:46
ReverseRegistrar.sol:54
ETHRegistrarController.sol:101
ETHRegistrarController.sol:139
ETHRegistrarController.sol:198
ETHRegistrarController.sol:234
ETHRegistrarController.sol:240
ETHRegistrarController.sol:242
ETHRegistrarController.sol:261
ERC1155Fuse.sol:62
ERC1155Fuse.sol:87
ERC1155Fuse.sol:109
ERC1155Fuse.sol:176
ERC1155Fuse.sol:179
ERC1155Fuse.sol:197
ERC1155Fuse.sol:199
ERC1155Fuse.sol:202
ERC1155Fuse.sol:217
ERC1155Fuse.sol:248
ERC1155Fuse.sol:249
ERC1155Fuse.sol:252
ERC1155Fuse.sol:292
BytesUtil.sol:28
BytesUtil.sol:42
Controllable.sol:17
RRUtils.sol:307
#0 - jefflau
2022-08-01T08:16:48Z
High quality submission with gas tables and reproduction