List of Gas Savings that you should apply without thinking too much, with math
Saves 5 gas
Saves 80 gas on average
Saves 2100 per first SLOAD, 100 for each subsequent SLOAD
The first read will cost an extra 6 gas (MSTORE + MLOAD) Saves 97 gas (3 is MLOAD) for each subsequent read
This only works in certain cases, either low optimizations or outside an unchecked block, also dependent on solidity version, always test it
Generally will save gas as Memory is copied from the calldata into memory, vs calldata being read directly.
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.13;
import "../../lib/test.sol";
import "../../lib/Console.sol";
contract Exploit is DSTest {
GasSample testC;
function testExploit(uint256 nonce) public {
testC = new GasSample();
uint256[] memory temp = new uint256[](3);
temp[0] = 12;
temp[1] = 32;
temp[2] = 54;
testC.getData(temp);
}
}
contract GasSample {
function getData(uint256[] memory values) external returns (uint256) {
uint256 length = values.length;
uint256 acc;
for(uint i; i < length; ) {
acc += values[i];
unchecked { ++i; }
}
return acc;
}
}
│ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ getData ┆ 999 ┆ 999 ┆ 999 ┆ 999 ┆ 1 │
### With Memory
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ getData ┆ 1364 ┆ 1364 ┆ 1364 ┆ 1364 ┆ 1
https://gist.github.com/IllIllI000/bf2c3120f24a69e489f12b3213c06c94
https://twitter.com/GalloDaSballo/status/1543729080926871557 They cost the same at runtime
https://twitter.com/GalloDaSballo/status/1543729467465629696
>
is cheaper (less opcodes)
The compiler is purposefully set up to optimize these: ethereum/solidity#4024
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.14;
import "../../lib/test.sol";
import "../../lib/Console.sol";
contract GasTest is DSTest {
Contract0 c0;
function setUp() public {
c0 = new Contract0();
}
function testGas() public {
uint256 value = c0.getData();
assertTrue(value > 0);
}
}
contract Contract0 {
mapping(bytes32 => uint256) internal uintStorage;
constructor () {
uintStorage[keccak256("NOPClaim.RewardsCycleTotal")] = block.timestamp;
}
function getUint(bytes32 key) internal returns (uint256){
return uintStorage[key];
}
function getData() external returns (uint256) {
return getUint(keccak256("NOPClaim.RewardsCycleTotal"));
}
}
| src/test/GasTest.t.sol:Contract0 contract | | | | | |
|-------------------------------------------|-----------------|------|--------|------|---------|
| Deployment Cost | Deployment Size | | | | |
| 60613 | 298 | | | | |
| Function Name | min | avg | median | max | # calls |
| getData | 2267 | 2267 | 2267 | 2267 | 1 |