Platform: Code4rena
Start Date: 04/03/2024
Pot Size: $140,000 USDC
Total HM: 19
Participants: 69
Period: 21 days
Judge: 0xean
Total Solo HM: 4
Id: 343
League: ETH
Rank: 67/69
Findings: 1
Award: $26.76
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: DadeKuma
Also found by: 0x11singh99, 0xAnah, 0xhacksmithh, Auditor2947, IllIllI, K42, MrPotatoMagic, Pechenite, SAQ, SM3_SS, SY_S, Sathish9098, albahaca, caglankaan, cheatc0d3, clara, dharma09, hihen, hunter_w3b, oualidpro, pavankv, pfapostol, rjs, slvDev, sxima, unique, zabihullahazadzoi
26.7572 USDC - $26.76
no | Issue | Instances | |
---|---|---|---|
[G-01] | Use assembly to check for address(0) | 6 | |
[G-02] | abi.encode() is less efficient than abi.encodepacked() | 4 | |
[G-03] | Use assembly to validate msg.sender | more than 1 | |
[G-04] | State varaibles only set in the Constructor should be declared Immutable | 1 | |
[G-05] | Do not calculate constant | 1 | |
[G-06] | Use assembly to emit events | 3 | |
[G-07] | Use assembly to calculate hashes to save gas | 4 | |
[G-08] | Use hardcode address instead address(this) | 2 | |
[G-09] | require() Should Be Used Instead Of assert() | 1 | |
[G-10] | Expressions for constant values such as a call to keccak256(), should use immutable rather than constant | 1 | - |
address(0)
file: /contracts/common/AddressResolver.sol 81 if (addressManager == address(0)) revert RESOLVER_INVALID_MANAGER(); 85 if (!_allowZeroAddress && addr_ == address(0)) {
file: /contracts/common/EssentialContract.so 105 if (_addressManager == address(0)) revert ZERO_ADDR_MANAGER();
file: /contracts/libs/LibAddress.sol 24 if (_to == address(0)) revert ETH_TRANSFER_FAILED();
file: /contracts/L1/hooks/AssignmentHook.sol 120 if (input.tip != 0 && block.coinbase != address(0)) {
file: /contracts/L1/libs/LibProving.sol 163 if (verifier != address(0)) {
abi.encode()
is less efficient than abi.encodepacked()
In terms of efficiency, abi.encodePacked() is generally considered to be more gas-efficient than abi.encode(), because it skips the step of adding function signatures and other metadata to the encoded data. However, this comes at the cost of reduced safety, as abi.encodePacked() does not perform any type checking or padding of data.
file: /contracts/automata-attestation/utils/SigVerifyLib.sol 136 bytes memory args = abi.encode(sha256(tbs), r, s, gx, gy);
file: /contracts/bridge/Bridge.sol 450 return keccak256(abi.encode("TAIKO_MESSAGE", _message));
file: /contracts/L1/provers/GuardianProver.sol 46 bytes32 hash = keccak256(abi.encode(_meta, _tran));
file: /contracts/team/airdrop/ERC20Airdrop2.sol 80 _verifyClaim(abi.encode(user, amount), proof);
We can use assembly to efficiently validate msg.sender for the didPay and uniswapV3SwapCallback functions with the least amount of opcodes necessary. Additionally, we can use xor() instead of iszero(eq()), saving 3 gas. We can also potentially save gas on the unhappy path by using scratch space to store the error selector, potentially avoiding memory expansion costs.
file: /contracts/bridge/Bridge.sol 294 if (msg.sender == refundTo) {
Immutable
file: /contracts/automata-attestation/utils/SigVerifyLib.sol 18 address private ES256VERIFIER; constructor(address es256Verifier) { ES256VERIFIER = es256Verifier; }
When you define a constant in Solidity, the compiler can calculate its value at compile-time and replace all references to the constant with its computed value. This can be helpful for readability and reducing the size of the compiled code, but it can also increase gas usage at runtime.
file: contracts/L1/libs/LibProposing.sol 21 uint256 public constant MAX_BYTES_PER_BLOB = 4096 * 32;
We can use assembly to emit events efficiently by utilizing scratch space and the free memory pointer. This will allow us to potentially avoid memory expansion costs. Note: In order to do this optimization safely, we will need to cache and restore the free memory pointer.
file: /contracts/common/AddressManager.sol 50 emit AddressSet(_chainId, _name, _newAddress, oldAddress);
file: /contracts/common/EssentialContract.sol 80 emit Unpaused(msg.sender);
file: /contracts/L1/hooks/AssignmentHook.sol 129 emit BlockAssigned(_blk.assignedProver, _meta, assignment);
Using assembly to calculate hashes can save 80 gas per instance
file: /contracts/automata-attestation/AutomataDcapV3Attestation.sol 292 bytes32 issuerPubKeyHash = keccak256(issuer.pubKey);
file: /contracts/L1/libs/LibProposing.sol 189 meta_.blobHash = keccak256(_txList); meta_.txListByteOffset = 0; meta_.txListByteSize = uint24(_txList.length); }
file: /contracts/signal/SignalService.so 186 return keccak256(abi.encode(_chainId, _kind, _blockId));
file: /contracts/bridge/Bridge.sol 174 if (!ISignalService(signalService).isSignalSent(address(this), msgHash)) {
file: /contracts/L1/libs/LibProposing.sol 253 IHook(params.hookCalls[i].hook).onBlockProposed{ value: address(this).balance }(
require()
Should Be Used Instead Of assert()
file: /contracts/bridge/Bridge.sol 486 assert(_message.from != address(this));
While it doesn't save any gas because the compiler knows that developers often make this mistake, it's still best to use theright tool for the task at hand. There is a difference between constant variables and immutable variables, and they shouldeach be used in their appropriate contexts. constants should be used for literal values written into the code, and immutablevariables should be used for expressions, or values calculated in, or passed into the constructor.
file: 20 bytes32 public constant RETURN_LIVENESS_BOND = keccak256("RETURN_LIVENESS_BOND"); 23 bytes32 public constant TIER_OP = bytes32("tier_optimistic");
#0 - c4-judge
2024-04-10T10:05:08Z
0xean marked the issue as grade-b