Caviar contest - HardlyCodeMan's results

A fully on-chain NFT AMM that allows you to trade every NFT in a collection.

General Information

Platform: Code4rena

Start Date: 12/12/2022

Pot Size: $36,500 USDC

Total HM: 8

Participants: 103

Period: 7 days

Judge: berndartmueller

Id: 193

League: ETH

Caviar

Findings Distribution

Researcher Performance

Rank: 79/103

Findings: 1

Award: $14.83

Gas:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

14.833 USDC - $14.83

Labels

bug
G (Gas Optimization)
grade-b
edited-by-warden
G-11

External Links

2022-12-caviar

Gas Report


Two gas optimisations in two areas were found other than the C4udit public findings.


Owned.sol not functionally implemented in Caviar.sol

AreaGas Saving
Deployment60500
owner()144 - 2144

Owned.sol is only really utilised (through the onlyOwner modifier) in LPToken.sol and therefore inherited into Pair.sol via import. There is no actual utilisation of Owned.sol in Caviar.sol other than setting the owner variable which is called in Pair.sol returning address(msg.sender) from the contract creation.

By removing Owned.sol utility from Caviar.sol and simply using address public immutable owner; and setting owner = msg.sender in constructor(), the owner variable is still availbe to Pair.sol via caviar.owner() due to the owner variable being public and solidity automatically creatign a getter function for it. There is no code to suggest any change in ownership so the variable can also be set immutable, saving further gas at runtime.

Pre

Caviar.sol

import "../lib/solmate/src/auth/Owned.sol";
...
constructor() Owned(msg.sender) {}

Post

//import "../lib/solmate/src/auth/Owned.sol";
...
address public immutable owner;
constructor() { owner = msg.sender; }
Area
(Pre) Deployment Cost4625247
(Post) Deployment Cost4564747
Cost Saving60500
Function Nameminavgmedianmax# calls
(Pre) owner34816812348234812
(Post) owner20420420420412
Gas Diff1441477214421440

Additional to auto C4audit finding

The automated findings correctly reported tokenIds.length should be cached outside for loops in Pair.sol, however additionally to the use of tokenIds.length in the loops witin wrap() and unwrap() there is an additional use to within these functions fractionalTokenAmount = tokenIds.length * ONE; which should also be referenced by the recommended fix of cached uint for the array length.

Proposed Additional Fix Example

// *** Effects *** //
uint arrayLen = tokenIds.length; /// @audit Cache array length for multiple references as well as use in the for loop

// mint fractional tokens to sender
fractionalTokenAmount = arrayLen * ONE; /// @audit used cached value
_mint(msg.sender, fractionalTokenAmount);

// *** Interactions *** //

// transfer nfts from sender
for (uint256 i = 0; i < arrayLen; i++) { /// @audit used cached value
    ERC721(nft).safeTransferFrom(msg.sender, address(this), tokenIds[i]);
}```

#0 - c4-judge

2023-01-14T17:19:56Z

berndartmueller marked the issue as grade-b

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