Platform: Code4rena
Start Date: 07/10/2022
Pot Size: $50,000 USDC
Total HM: 4
Participants: 62
Period: 5 days
Judge: 0xean
Total Solo HM: 2
Id: 169
League: ETH
Rank: 41/62
Findings: 1
Award: $20.79
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, 0xNazgul, 0xSmartContract, 0xdeadbeef, B2, Bnke0x0, Deivitto, ElKu, Jujic, KoKo, Pheonix, RaymondFam, RedOneN, RockingMiles, Rolezn, Saintcode_, Shinchan, TomJ, Tomio, __141345__, ajtra, aysha, c3phas, carlitox477, catchup, delfin454000, emrekocak, erictee, fatherOfBlocks, gerdusx, gianganhnguyen, gogo, martin, mcwildy, medikko, oyc_109, pedr02b2, rbserver, ret2basic, rotcivegaf, saian, sakman, zishansami
20.7905 USDC - $20.79
Issue | Instances | |
---|---|---|
GAS‑1 | Multiple Address Mappings Can Be Combined Into A Single Mapping Of An Address To A Struct, Where Appropriate | 1 |
GAS‑2 | require() /revert() Strings Longer Than 32 Bytes Cost Extra Gas | 4 |
GAS‑3 | Using Bools For Storage Incurs Overhead | 2 |
GAS‑4 | Using > 0 Costs More Gas Than != 0 When Used On A Uint In A require() Statement | 3 |
GAS‑5 | Splitting require() Statements That Use && Saves Gas | 1 |
GAS‑6 | abi.encode() Is Less Efficient Than abi.encodepacked() | 6 |
GAS‑7 | Use assembly to check for address(0) | 18 |
GAS‑8 | Public Functions To External | 11 |
GAS‑9 | Usage of uints /ints smaller than 32 bytes (256 bits) incurs overhead | 3 |
GAS‑10 | Use of Custom Errors Instead of String | 55 |
GAS‑11 | Optimize names to save gas | 12 |
Total: 116 instances over 11 issues
Saves a storage slot for the mapping. Depending on the circumstances and sizes of types, can avoid a Gsset (20000 gas) per mapping combined. Reads and subsequent writes can also be cheaper when a function requires both values and they both fit in the same storage slot.
mapping(address => bool) private _minters; mapping(address => uint256) public nonces;
require()
/revert()
Strings Longer Than 32 Bytes Cost Extra Gasrequire(msg.sender == controller.getGovernor(), "Caller must be Controller governor");
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/governance/Managed.sol#L53
require(_newAdmin != address(0), "Cannot change the admin of a proxy to the zero address");
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/upgrades/GraphProxy.sol#L105
require(Address.isContract(_pendingImplementation), "Implementation must be a contract");
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/upgrades/GraphProxy.sol#L141
require(msg.sender != _admin(), "Cannot fallback to proxy target");
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/upgrades/GraphProxy.sol#L157
Booleans are more expensive than uint256 or any type that takes up a full word because each write operation emits an extra SLOAD to first read the slot's contents, replace the bits taken up by the boolean, and then write back. This is the compiler's defense against contract upgrades and pointer aliasing, and it cannot be disabled.
mapping(address => bool) public callhookWhitelist;
mapping(address => bool) private _minters;
> 0
Costs More Gas Than != 0
When Used On A Uint In A require()
StatementThis change saves 6 gas per instance
require(_amount > 0, "INVALID_ZERO_AMOUNT");
require(maxSubmissionCost > 0, "NO_SUBMISSION_COST");
require(_amount > 0, "INVALID_ZERO_AMOUNT");
require()
Statements That Use &&
Saves GasSee https://github.com/code-423n4/2022-01-xdefi-findings/issues/128 which describes the fact that there is a larger deployment gas cost, but with enough runtime calls, the change ends up being cheaper
require(_escrow != address(0) && Address.isContract(_escrow), "INVALID_ESCROW");
abi.encode()
Is Less Efficient Than abi.encodepacked()
return abi.encode(seqNum);
abi.encode(emptyBytes, _data)
return abi.encode(id);
abi.encode(0, _data));
abi.encode(PERMIT_TYPEHASH, _owner, _spender, _value, nonces[_owner], _deadline)
abi.encode(
address(0)
Save 6 gas per instance if using assembly to check for address(0)
e.g. assembly { if iszero(_addr) { mstore(0x00, "AddressZero") revert(0x00, 0x20) } }
function setPauseGuardian(address _newPauseGuardian) external onlyGovernor {
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/gateway/GraphTokenGateway.sol#L30
function setArbitrumAddresses(address _inbox, address _l1Router) external onlyGovernor {
function setArbitrumAddresses(address _inbox, address _l1Router) external onlyGovernor {
function setL2TokenAddress(address _l2GRT) external onlyGovernor {
function setL2CounterpartAddress(address _l2Counterpart) external onlyGovernor {
function setEscrowAddress(address _escrow) external onlyGovernor {
function addToCallhookWhitelist(address _newWhitelisted) external onlyGovernor {
function removeFromCallhookWhitelist(address _notWhitelisted) external onlyGovernor {
function transferOwnership(address _newGovernor) external onlyGovernor {
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/governance/Governed.sol#L40
function _setController(address _controller) internal {
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/governance/Managed.sol#L103
function setL2Router(address _l2Router) external onlyGovernor {
function setL1TokenAddress(address _l1GRT) external onlyGovernor {
function setL1CounterpartAddress(address _l1Counterpart) external onlyGovernor {
function addMinter(address _account) external onlyGovernor {
function initialize(address _owner) external onlyImpl {
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/l2/token/L2GraphToken.sol#L48
function setGateway(address _gw) external onlyGovernor {
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/l2/token/L2GraphToken.sol#L59
function setL1Address(address _addr) external onlyGovernor {
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/l2/token/L2GraphToken.sol#L69
function setAdmin(address _newAdmin) external ifAdmin {
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/upgrades/GraphProxy.sol#L104
The following functions could be set external to save gas and improve code quality. External call cost is less expensive than of public functions.
function getOutboundCalldata( address _l1Token, address _from, address _to, uint256 _amount, bytes memory _data ) public pure returns (bytes memory) {
function outboundTransfer( address _l1Token, address _to, uint256 _amount, uint256, uint256, bytes calldata _data ) public payable override notPaused nonReentrant returns (bytes memory) {
function calculateL2TokenAddress(address l1ERC20) public view override returns (address) {
function getOutboundCalldata( address _token, address _from, address _to, uint256 _amount, bytes memory _data ) public pure returns (bytes memory) {
function isMinter(address _account) public view returns (bool) {
function getProxyImplementation(IGraphProxy _proxy) public view returns (address) {
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/upgrades/GraphProxyAdmin.sol#L30
function getProxyPendingImplementation(IGraphProxy _proxy) public view returns (address) {
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/upgrades/GraphProxyAdmin.sol#L43
function getProxyAdmin(IGraphProxy _proxy) public view returns (address) {
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/upgrades/GraphProxyAdmin.sol#L55
function changeProxyAdmin(IGraphProxy _proxy, address _newAdmin) public onlyGovernor {
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/upgrades/GraphProxyAdmin.sol#L68
function upgrade(IGraphProxy _proxy, address _implementation) public onlyGovernor {
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/upgrades/GraphProxyAdmin.sol#L77
function acceptProxy(GraphUpgradeable _implementation, IGraphProxy _proxy) public onlyGovernor {
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/upgrades/GraphProxyAdmin.sol#L86
uints
/ints
smaller than 32 bytes (256 bits) incurs overheadWhen using elements that are smaller than 32 bytes, your contract’s gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size.
https://docs.soliditylang.org/en/v0.8.11/internals/layout_in_storage.html
Each operation involving a uint8
costs an extra 22-28 gas (depending on whether the other operand is also a variable of type uint8
) as compared to ones involving uint256
, due to the compiler having to clear the higher bits of the memory word before operating on the uint8
, as well as the associated stack operations of doing so. Use a larger size then downcast where needed
uint32 cooldownBlocks;
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/staking/IStakingData.sol#L37
uint32 indexingRewardCut;
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/staking/IStakingData.sol#L38
uint32 queryFeeCut;
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/staking/IStakingData.sol#L39
To save some gas the use of custom errors leads to cheaper deploy time cost and run time cost. The run time cost is only relevant when the revert condition is met.
File: \2022-10-thegraph\contracts\gateway\GraphTokenGateway.sol
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/gateway/GraphTokenGateway.sol#L40
File: \2022-10-thegraph\contracts\gateway\L1GraphTokenGateway.sol
File: \2022-10-thegraph\contracts\governance\Governed.sol
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/governance/Governed.sol#L41
File: \2022-10-thegraph\contracts\governance\Managed.sol
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/governance/Managed.sol#L104
File: \2022-10-thegraph\contracts\l2\gateway\L2GraphTokenGateway.sol
File: \2022-10-thegraph\contracts\l2\token\GraphTokenUpgradeable.sol
File: \2022-10-thegraph\contracts\l2\token\L2GraphToken.sol
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/l2/token/L2GraphToken.sol#L70
File: \2022-10-thegraph\contracts\upgrades\GraphProxy.sol
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/upgrades/GraphProxy.sol#L157
File: \2022-10-thegraph\contracts\upgrades\GraphProxyStorage.sol
File: \2022-10-thegraph\contracts\upgrades\GraphUpgradeable.sol
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/upgrades/GraphUpgradeable.sol#L32
Use Custom Errors instead of strings.
public
/external
function names and public
member variable names can be optimized to save gas. See this link for an example of how it works. Method IDs that have two leading zero bytes can save 128 gas each during deployment, and renaming functions to have lower method IDs will save 22 gas per call, per sorted position shifted
File: \2022-10-thegraph\contracts\gateway\GraphTokenGateway.sol
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/gateway/GraphTokenGateway.sol
File: \2022-10-thegraph\contracts\gateway\L1GraphTokenGateway.sol
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/gateway/L1GraphTokenGateway.sol
File: \2022-10-thegraph\contracts\governance\Governed.sol
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/governance/Governed.sol
File: \2022-10-thegraph\contracts\governance\Managed.sol
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/governance/Managed.sol
File: \2022-10-thegraph\contracts\governance\Pausable.sol
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/governance/Pausable.sol
File: \2022-10-thegraph\contracts\l2\gateway\L2GraphTokenGateway.sol
File: \2022-10-thegraph\contracts\l2\token\GraphTokenUpgradeable.sol
File: \2022-10-thegraph\contracts\l2\token\L2GraphToken.sol
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/l2/token/L2GraphToken.sol
File: \2022-10-thegraph\contracts\upgrades\GraphProxy.sol
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/upgrades/GraphProxy.sol
File: \2022-10-thegraph\contracts\upgrades\GraphProxyAdmin.sol
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/upgrades/GraphProxyAdmin.sol
File: \2022-10-thegraph\contracts\upgrades\GraphProxyStorage.sol
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/upgrades/GraphProxyStorage.sol
File: \2022-10-thegraph\contracts\upgrades\GraphUpgradeable.sol
https://github.com/code-423n4/2022-10-thegraph/tree/main/contracts/upgrades/GraphUpgradeable.sol
#0 - tmigone
2022-10-21T20:06:23Z
We've found this submission to be of high quality.