The Graph L2 bridge contest - Saintcode_'s results

A protocol for indexing and querying blockchain data.

General Information

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

The Graph

Findings Distribution

Researcher Performance

Rank: 44/62

Findings: 1

Award: $20.79

๐ŸŒŸ Selected for report: 0

๐Ÿš€ Solo Findings: 0

USE CALLDATA INSTEAD OF MEMORY

When a function with a memory array is called externally, the abi.decode() step has to use a for-loop to copy each index of the calldata to the memory index. Each iteration of this for-loop costs at least 60 gas (i.e. 60 * <mem_array>.length). Using calldata directly, obliviates the need for such a loop in the contract code and runtime execution.

When arguments are read-only on external functions, the data location should be calldata

5 Instances: -L1GraphTokenGateway.sol lines 290, 331 -Managed.sol line 173 -L2GraphTokenGateway.sol lines 266, 286

USE MULTIPLE REQUIRE() STATMENTS INSTEAD OF REQUIRE(EXPRESSION && EXPRESSION && ...)

2 Instances: -L1GraphTokenGateway.sol line 142 -Governed.sol line 55 -GraphProxy.sol line 143

&& and || SHORTCIRCUIT

L1GraphTokenGateway.sol line 142

The order of the functions inside the if statement in line 142:

require(_escrow != address(0) && Address.isContract(_escrow), "INVALID_ESCROW");

can be switched to:

require(Address.isContract(_escrow) && _escrow != address(0), "INVALID_ESCROW");

for optimal gas usage because Address.isContract(_escrow) is more probable to be FALSE hence second one wonโ€™t be executed and hence save you gas.

Same case in GraphProxy.sol 143

The order of the functions inside the if statement in line 142:

require( _pendingImplementation != address(0) && msg.sender == _pendingImplementation, "Caller must be the pending implementation" );

can be switched to:

require(msg.sender == _pendingImplementation && _pendingImplementation != address(0) , "Caller must be the pending implementation" );

for optimal gas usage because msg.sender == _pendingImplementation is more probable to be FALSE hence second one wonโ€™t be executed and hence save you gas.

>= COSTS LESS GAS THAN >

The compiler uses opcodes GT and ISZERO for solidity code that uses >, but only requires LT for >=, which saves 3 gas

4 Instances: -L1GraphTokenGateway lines 201, 217 -L2GraphTokenGateway lines 146, 147

REQUIRE()/REVERT() STRINGS LONGER THAN 32 BYTES COST EXTRA GAS

Each extra memory word of bytes past the original 32 incurs an MSTORE which costs 3 gas

Instances: -GraphTokenGateway.sol line 21 -Managed.sol line 53 -GraphProxy.sol lines 105, 141, 144 -GraphUpgradeable.sol line 32

USING PRIVATE RATHER THAN PUBLIC FOR CONSTANTS, SAVES GAS

If needed, the value can be read from the verified contract source code. Savings are due to the compiler not having to create non-payable getter functions for deployment calldata, and not adding another entry to the method ID table

USE A MORE RECENT VERSION OF SOLIDITY

Use a solidity version above 0.8.0, it integrates overflow/underflow checking so there would be no need to use Safemath

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax ยฉ 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter