Canto v2 contest - Bnke0x0's results

Execution layer for original work.

General Information

Platform: Code4rena

Start Date: 28/06/2022

Pot Size: $25,000 USDC

Total HM: 14

Participants: 50

Period: 4 days

Judge: GalloDaSballo

Total Solo HM: 7

Id: 141

League: ETH

Canto

Findings Distribution

Researcher Performance

Rank: 17/50

Findings: 2

Award: $113.38

๐ŸŒŸ Selected for report: 0

๐Ÿš€ Solo Findings: 0

Awards

49.435 USDC - $49.44

Labels

bug
QA (Quality Assurance)

External Links

#Low Risk

[L-01] require() should be used instead of assert() :-

1. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 100): `assert(msg.sender == address(wcanto));` 2. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 245): `assert(amountAOptimal <= amountADesired);` 3. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 291): `assert(wcanto.transfer(pair, amountCANTO));` 4. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 437): `assert(wcanto.transfer(pairFor(routes[0].from, routes[0].to, routes[0].stable), amounts[0]));` 5. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 81-82): `address public immutable factory; IWCANTO public immutable wcanto;`

[L-02] Unused receive() function will lock Ether in contract (If the intention is for the Ether to be used, the function should call another function, otherwise it should revert) :-

1. File: lending-market-v2/contracts/Treasury/TreasuryDelegator.sol (line 135): `receive() external payable override {` 2. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 99): `receive() external payable {` 3. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 291): `assert(wcanto.transfer(pair, amountCANTO));`

[L-03] Missing checks for address(0x0) when assigning values to address state variables :-

1. File: manifest-v2/contracts/ERC20MinterBurnerDecimals.sol (line 52): `_decimals = decimals_;` 2. File: lending-market-v2/contracts/Treasury/TreasuryDelegator.sol (line 35): `implementation = implementation_;` 3. File: lending-market-v2/contracts/Treasury/TreasuryDelegator.sol (line 92): `baseRatePerYear = _baseRatePerYear;` 4. File: lending-market-v2/contracts/Reservoir.sol (line 35-37): ` dripRate = dripRate_; token = token_; target = target_;` 5. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 92): `factory = _factory;`

[L-04] abi.encodePacked() should not be used with dynamic types when passing the result to a hash function such as keccak256() {Use abi.encode() instead which will pad items to 32 bytes, which will prevent hash collisions (e.g. abi.encodePacked(0x123,0x456) => 0x123456 => abi.encodePacked(0x1,0x23456), but abi.encode(0x123,0x456) => 0x0...1230...456). "Unless there is a compelling reason, abi.encode should be preferred". If there is only one argument to abi.encodePacked() it can often be cast to bytes() or bytes32() instead.} :-

1. File: manifest-v2/contracts/ERC20MinterBurnerDecimals.sol (line 112-117): `pair = address(uint160(uint256(keccak256(abi.encodePacked( hex"ff", factory, keccak256(abi.encodePacked(token0, token1, stable)), pairCodeHash // init code hash )))));`

[L-05] Open TODOs (Code architecture, incentives, and error handling/reporting questions/issues should be resolved before deployment):-

1. File: lending-market-v2/contracts/Reservoir.sol (line 49): `// TODO: Verify this is a static call` # Non-Critical Issues

[N-01] Adding a return statement when the function defines a named return variable, is redundant:-

1. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 237): `return _prices;` 2. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 360): `return y;` 3. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 465): `return amounts;` 4. File: lending-market-v2/contracts/Stableswap/test/calculations.sol (line 76): `return y;` 5. File: lending-market-v2/contracts/Accountant/AccountantDelegator.sol (line 87): `return returnData;` 6. File: lending-market-v2/contracts/Treasury/TreasuryDelegator.sol (line 112): `return returnData;` 7. File: lending-market-v2/contracts/CNote.sol (line 108): return balanceAfter;`

[N-02] REQUIRE()/REVERT() STATEMENTS SHOULD HAVE DESCRIPTIVE REASON STRINGS :-

1. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 468): `require(token.code.length > 0);` 2. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 360): `return y;` 3. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 465): `return amounts;` 4. File: lending-market-v2/contracts/Stableswap/test/calculations.sol (line 76): `return y;` 5. File: lending-market-v2/contracts/Accountant/AccountantDelegator.sol (line 87): `return returnData;` 6. File: lending-market-v2/contracts/Treasury/TreasuryDelegator.sol (line 112): `return returnData;` 7. File: lending-market-v2/contracts/CNote.sol (line 108): return balanceAfter;`

[N-03] Use a more recent version of solidity {Use a solidity version of at least 0.8.15 to get string.concat() to be used instead of abi.encodePacked(<str>,<str>)} :-

1. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 2): `pragma solidity 0.8.11;` 2. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 3): `pragma solidity 0.8.11;` 3. File: lending-market-v2/contracts/Stableswap/test/Token.sol (line 2): `pragma solidity 0.8.11;` 4. File: lending-market-v2/contracts/Accountant/AccountantDelegator.sol (line 1): `pragma solidity ^0.8.10;` 5. File: lending-market-v2/contracts/Governance/Comp.sol (line 2): `pragma solidity ^0.8.10;` 6. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 2): `pragma solidity ^0.8.10;` 7. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 2): `pragma solidity ^0.8.10;` 8. File: lending-market-v2/contracts/Governance/GovernorBravoDelegator.sol (line 2): `pragma solidity 0.8.10;` 9. File: lending-market-v2/contracts/Treasury/TreasuryDelegator.sol (line 1): `pragma solidity 0.8.10;`

[N-04] Variable names that consist of all capital letters should be reserved for const/immutable variables :-

1. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 53): `bytes32 internal DOMAIN_SEPARATOR;` 2. File: lending-market-v2/contracts/Stableswap/test/Token.sol (line 18): `bytes32 public DOMAIN_SEPARATOR;`

[N-05] Event is missing indexed fields (Each event should use three indexed fields if there are three or more fields) :-

1. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 90-104): `event Mint(address indexed sender, uint amount0, uint amount1); event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); event Swap( address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to ); event Sync(uint reserve0, uint reserve1); event Claim(address indexed sender, address indexed recipient, uint amount0, uint amount1); event Transfer(address indexed from, address indexed to, uint amount); event Approval(address indexed owner, address indexed spender, uint amount);` 2. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 489): `event PairCreated(address indexed token0, address indexed token1, bool stable, address pair, uint);` 3. File: lending-market-v2/contracts/Stableswap/test/Token.sol (line 14-16): `event Transfer(address from, address to, uint256 value); event Approval(address owner, address spender, uint256 value); event LogChangeVault(address indexed oldVault, address indexed newVault, uint indexed effectiveTime);` 4. File: lending-market-v2/contracts/Accountant/AccountantInterfaces.sol (line 24-27): ` event AcctInit(address lendingMarketAddress); event AcctSupplied(uint amount, uint err); event AcctRedeemed(uint amount); error SweepError(address treasury, uint amount); ` 5. File: lending-market-v2/contracts/Governance/Comp.sol (line 48-57): ` event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); /// @notice An event thats emitted when a delegate account's vote balance changes event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance); /// @notice The standard EIP-20 transfer event event Transfer(address indexed from, address indexed to, uint256 amount); /// @notice The standard EIP-20 approval event event Approval(address indexed owner, address indexed spender, uint256 amount);` 6. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 115-119): ` /// @notice An event emitted when a new proposal is created event ProposalCreated(uint id, address proposer, address[] targets, uint[] values, string[] signatures, bytes[] calldatas, uint startBlock, uint endBlock, string description); /// @notice An event emitted when a vote has been cast on a proposal event VoteCast(address voter, uint proposalId, bool support, uint votes);` 7. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 125): `event ProposalQueued(uint id, uint eta);` 8. File: lending-market-v2/contracts/Governance/GovernorBravoInterfaces.sol (line 8-30): ` /// @notice An event emitted when a new proposal is created event ProposalCreated(uint id, address proposer, address[] targets, uint[] values, string[] signatures, bytes[] calldatas, uint startBlock, uint endBlock, string description); /// @notice An event emitted when a proposal has been canceled event ProposalCanceled(uint id); /// @notice An event emitted when a proposal has been queued in the Timelock event ProposalQueued(uint id, uint eta); /// @notice An event emitted when a proposal has been executed in the Timelock event ProposalExecuted(uint id); /// @notice Emitted when implementation is changed event NewImplementation(address oldImplementation, address newImplementation); /// @notice Emitted when proposal threshold is set event ProposalThresholdSet(uint oldProposalThreshold, uint newProposalThreshold); /// @notice Emitted when pendingAdmin is changed event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin); /// @notice Emitted when pendingAdmin is accepted, which means admin is updated event NewAdmin(address oldAdmin, address newAdmin);` 9. File: lending-market-v2/contracts/Treasury/TreasuryInterfaces.sol (line 22-23): ` event NewImplementation(address oldImplementation, address newImplementation); event Received(address sender, uint amount); ` 10. File: lending-market-v2/contracts/CNote.sol (line 22-23): `event AccountantSet(address accountant, address accountantPrior); ` 11. File: lending-market-v2/contracts/NoteInterest.sol (line 64-79): ` event NewBaseRate(uint oldBaseRateMantissa, uint newBaseRateMantissa); /// @notice Emitted when adjuster coefficient is changed by admin event NewAdjusterCoefficient(uint oldAdjusterCoefficient, uint newAdjusterCoefficient); /// @notice Emitted when update frequency is changed by admin event NewUpdateFrequency(uint oldUpdateFrequency, uint newUpdateFrequency); /// @notice Emitted when new baserateperblock is set event NewInterestParams(uint baserateperblock); /// @notice Emitted when new PriceOracle is set event NewPriceOracle(address oldOracle, address newOracle); /// @notice Emitted when new admin is set event NewAdmin(address oldAdmin, address newAdmin);`

[N-06] Constant redefined elsewhere (Consider defining in only one contract so that values cannot become out of sync when only one location is updated. A cheap way to store constants in a single location is to create an internal constant in a library. If the variable is a local cache of another contract's value, consider making the cache variable internal or private, which will require external users to query the contract with the source of truth, so that callers don't get out of sync.) :-

1. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 46): `bool public immutable stable;` 2. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 60-61): `address public immutable token0; address public immutable token1;` 3. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 71): `address public immutable USDC; ` 4. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 73): `address public immutable Comptroller;` 5. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 81-82): `address public immutable factory; IWCANTO public immutable wcanto;`

#0 - GalloDaSballo

2022-08-13T22:25:06Z

[L-01] require() should be used instead of assert() :-

Valid L

L-02

Disputed https://github.com/Plex-Engineer/lending-market-v2/blob/443a8c0fed3c5018e95f3881a31b81a555c42b2d/contracts/Treasury/TreasuryDelegate.sol#L66-L67

[L-03] Missing checks for address(0x0)

Valid L

abi.encodePacked() should not be used with dynamic types when passing the result to a hash function such as keccak256()

Disagree as in this case the token0, token1 and stable is always a unique combination (as token0 << token1 for all tokens)

[L-05] Open TODOs

NC

[N-01] Adding a return statement

After inspecting the first few, which are all false positives, am marking this invalid

N-02 & N-03

Disagree (also N-02 is all false positives except the first)

[N-04] Variable names that consist

Valid R (also DOMAIN_SEP should be made into a constant)

Rest I disagree with


This report feels like the usual copy paste, poorly executed, would recommend putting more of your own effort / perspective

2L 1R 1NC

Awards

63.9437 USDC - $63.94

Labels

bug
G (Gas Optimization)

External Links

[G-01] STATE VARIABLES ONLY SET IN THE CONSTRUCTOR SHOULD BE DECLARED IMMUTABLE Avoids a Gsset (20000 gas):-

1. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 24): `TimelockInterface public timelock;` 2. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 27): `CompInterface public comp;` 3. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 30): `address public guardian;` 4. File: lending-market-v2/contracts/Governance/GovernorBravoInterfaces.sol (line 36): `address public admin;` 5. File: lending-market-v2/contracts/Governance/GovernorBravoInterfaces.sol (line 39): `address public pendingAdmin;` 6. File: lending-market-v2/contracts/Governance/GovernorBravoInterfaces.sol (line 42): `address public implementation;` 7. File: lending-market-v2/contracts/NoteInterest.sol (line 55): `CErc20 public cNote;` 8. File: lending-market-v2/contracts/NoteInterest.sol (line 50): `address private admin;` 7. File: lending-market-v2/contracts/Reservoir.sol (line 19): `EIP20Interface public token;` 8. File: lending-market-v2/contracts/Reservoir.sol (line 22): `address public target;`

[G-02] X = X + Y IS CHEAPER THAN X += Y:-

1. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 403): `totalSupply -= amount;` 2. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 404): `balanceOf[dst] -= amount;` 3. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 461): `balanceOf[src] -= amount;` 4. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 397): `totalSupply += amount;` 5. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 398): `balanceOf[dst] += amount;` 6. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 462): `balanceOf[dst] += amount;` 7. File: lending-market-v2/contracts/Stableswap/test/Token.sol (line 88): `balanceOf[_to] += _amount;` 8. File: lending-market-v2/contracts/Stableswap/test/Token.sol (line 89): `totalSupply += _amount;` 7. File: lending-market-v2/contracts/Stableswap/test/Token.sol (line 100): `balanceOf[_to] += _value;`

[G-03] <ARRAY>.LENGTH SHOULD NOT BE LOOKED UP IN EVERY LOOP OF A FOR-LOOP {Even memory arrays incur the overhead of bit tests and bit shifts to calculate the array length. Storage array length checks incur an extra Gwarmaccess (100 gas) PER-LOOP.}:-

1. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 210): `for (uint i = 0; i < _prices.length; i++) {` 2. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 154): `for (uint i = 0; i < routes.length; i++) {` 3. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 380): `for (uint i = 0; i < routes.length; i++) {` 4. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 181): `for (uint i = 0; i < proposal.targets.length; i++) {` 5. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 197): `for (uint i = 0; i < proposal.targets.length; i++) {` 6. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 211): `for (uint i = 0; i < proposal.targets.length; i++) {` 7. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 66): `for (uint i = 0; i < newProposal.targets.length; i++) {` 8. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 88): `for (uint i = 0; i < proposal.targets.length; i++) {`

[G-04] REQUIRE()/REVERT() STRINGS LONGER THAN 32 BYTES COST EXTRA GAS:-

1. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 104): `require(tokenA != tokenB, "BaseV1Router: IDENTICAL_ADDRESSES");` 2. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 106): `require(token0 != address(0), "BaseV1Router: ZERO_ADDRESS");` 3. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 122): `require(amountA > 0, "BaseV1Router: INSUFFICIENT_AMOUNT");` 4. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 123): `require(reserveA > 0 && reserveB > 0, "BaseV1Router: INSUFFICIENT_LIQUIDITY");` 5. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 151): `require(routes.length >= 1, "BaseV1Router: INVALID_PATH");` 6. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 241): `require(amountBOptimal >= amountBMin, "BaseV1Router: INSUFFICIENT_B_AMOUNT");` 7. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 246): `require(amountAOptimal >= amountAMin, "BaseV1Router: INSUFFICIENT_A_AMOUNT");` 8. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 313): `require(amountA >= amountAMin, "BaseV1Router: INSUFFICIENT_A_AMOUNT");` 9. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 314): `require(amountB >= amountBMin, "BaseV1Router: INSUFFICIENT_B_AMOUNT");` 10. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 405): `require(amounts[amounts.length - 1] >= amountOutMin, "BaseV1Router: INSUFFICIENT_OUTPUT_AMOUNT");` 11. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 420): `require(amounts[amounts.length - 1] >= amountOutMin, "BaseV1Router: INSUFFICIENT_OUTPUT_AMOUNT");` 12. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 433): `require(routes[0].from == address(wcanto), "BaseV1Router: INVALID_PATH");` 13. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 435): `require(amounts[amounts.length - 1] >= amountOutMin, "BaseV1Router: INSUFFICIENT_OUTPUT_AMOUNT");` 14. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 446): `require(routes[routes.length - 1].to == address(wcanto), "BaseV1Router: INVALID_PATH");` 15. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 448): `require(amounts[amounts.length - 1] >= amountOutMin, "BaseV1Router: INSUFFICIENT_OUTPUT_AMOUNT");` 16. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 470): `require(success, "TransferHelper: ETH_TRANSFER_FAILED");` 17. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 481): `require(token.code.length > 0, "token code length failure");` 18. File: lending-market-v2/contracts/Stableswap/test/Token.sol (line 145): `require(_pendingRouter != address(0), "AnyswapV3ERC20: address(0x0)");` 19. File: lending-market-v2/contracts/Accountant/AccountantDelegate.sol (line 87): `require(cNoteAmt >= noteDiff, "AccountantDelegate::sweepInterest:Error calculating interest to sweep");` 20. File: lending-market-v2/contracts/Accountant/AccountantDelegate.sol (line 101): `require(cnote.balanceOf(treasury) == 0, "AccountantDelegate::sweepInterestError");` 21. File: lending-market-v2/contracts/Accountant/AccountantDelegator.sol (line 42): `require(msg.sender == admin, "AccountantDelegator::_setImplementation: admin only");` 22. File: lending-market-v2/contracts/Accountant/AccountantDelegator.sol (line 43): `require(implementation_ != address(0), "AccountantDelegator::_setImplementation: invalid implementation address");` 23. File: lending-market-v2/contracts/Accountant/AccountantDelegator.sol (line 123): `require(msg.value == 0,"AccountantDelegator:fallback: cannot send value to fallback");` 24. File: lending-market-v2/contracts/Governance/Comp.sol (line 166): `require(signatory != address(0), "Comp::delegateBySig: invalid signature");` 25. File: lending-market-v2/contracts/Governance/Comp.sol (line 167): `require(nonce == nonces[signatory]++, "Comp::delegateBySig: invalid nonce");` 26. File: lending-market-v2/contracts/Governance/Comp.sol (line 168): `require(block.timestamp <= expiry, "Comp::delegateBySig: signature expired");` 27. File: lending-market-v2/contracts/Governance/Comp.sol (line 190): `require(blockNumber < block.number, "Comp::getPriorVotes: not yet determined");` 28. File: lending-market-v2/contracts/Governance/Comp.sol (line 234): `require(src != address(0), "Comp::_transferTokens: cannot transfer from the zero address");` 29. File: lending-market-v2/contracts/Governance/Comp.sol (line 235): `require(dst != address(0), "Comp::_transferTokens: cannot transfer to the zero address");` 30. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 137): `require(comp.getPriorVotes(msg.sender, sub256(block.number, 1)) > proposalThreshold(), "GovernorAlpha::propose: proposer votes below proposal threshold");` 31. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 138): `require(targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, "GovernorAlpha::propose: proposal function information arity mismatch");` 32. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 139): `require(targets.length != 0, "GovernorAlpha::propose: must provide actions");` 33. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 140): `require(targets.length <= proposalMaxOperations(), "GovernorAlpha::propose: too many actions");` 34. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 145): `require(proposersLatestProposalState != ProposalState.Active, "GovernorAlpha::propose: one live proposal per proposer, found an already active proposal");` 35. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 146): `require(proposersLatestProposalState != ProposalState.Pending, "GovernorAlpha::propose: one live proposal per proposer, found an already pending proposal");` 36. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 156): `require(newProposal.id == 0, "GovernorAlpha::propose: ProposalID collsion");` 37. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 178): `require(state(proposalId) == ProposalState.Succeeded, "GovernorAlpha::queue: proposal can only be queued if it is succeeded");` 38. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 189): `require(!timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data, eta))), "GovernorAlpha::_queueOrRevert: proposal action already queued at eta");` 39. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 194): `require(state(proposalId) == ProposalState.Queued, "GovernorAlpha::execute: proposal can only be executed if it is queued");` 40. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 205): `require(state != ProposalState.Executed, "GovernorAlpha::cancel: cannot cancel executed proposal");` 41. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 208): `require(msg.sender == guardian || comp.getPriorVotes(proposal.proposer, sub256(block.number, 1)) < proposalThreshold(), "GovernorAlpha::cancel: proposer above threshold");` 42. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 228): `require(proposalCount >= proposalId && proposalId > 0, "GovernorAlpha::state: invalid proposal id");` 43. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 258): `require(signatory != address(0), "GovernorAlpha::castVoteBySig: invalid signature");` 44. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 263): `require(state(proposalId) == ProposalState.Active, "GovernorAlpha::_castVote: voting is closed");` 45. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 266): `require(receipt.hasVoted == false, "GovernorAlpha::_castVote: voter already voted");` 46. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 283): `require(msg.sender == guardian, "GovernorAlpha::__acceptAdmin: sender must be gov guardian");` 47. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 288): `require(msg.sender == guardian, "GovernorAlpha::__abdicate: sender must be gov guardian");` 48. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 293): `require(msg.sender == guardian, "GovernorAlpha::__queueSetTimelockPendingAdmin: sender must be gov guardian");` 49. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 298): `require(msg.sender == guardian, "GovernorAlpha::__executeSetTimelockPendingAdmin: sender must be gov guardian");` 50. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 304): `require(c >= a, "addition overflow");` 51. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 309): `require(b <= a, "subtraction underflow");` 52. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 25): `require(address(timelock) == address(0), "GovernorBravo::initialize: can only initialize once");` 53. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 26): `require(msg.sender == admin, "GovernorBravo::initialize: admin only");` 54. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 27): `require(timelock_ != address(0), "GovernorBravo::initialize: invalid timelock address");` 55. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 42-45): `require(unigovProposal.targets.length == unigovProposal.values.length && unigovProposal.targets.length == unigovProposal.signatures.length && unigovProposal.targets.length == unigovProposal.calldatas.length, "GovernorBravo::propose: proposal function information arity mismatch");` 56. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 46): `require(unigovProposal.targets.length != 0, "GovernorBravo::propose: must provide actions");` 57. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 47): `require(unigovProposal.targets.length <= proposalMaxOperations, "GovernorBravo::propose: too many actions");` 58. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 76): ` require(!timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data, eta))), "GovernorBravo::queueOrRevertInternal: identical proposal action already queued at eta");` 59. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 85): `require(state(proposalId) == ProposalState.Queued, "GovernorBravo::execute: proposal can only be executed if it is queued");` 60. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 128): `require(msg.sender == admin, "GovernorBravo::_initiate: admin only");` 61. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 129): `require(initialProposalId == 0, "GovernorBravo::_initiate: can only initiate once");` 62. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 140): `require(msg.sender == admin, "GovernorBravo:_setPendingAdmin: admin only");` 63. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 158): `require(msg.sender == pendingAdmin, "GovernorBravo:_acceptAdmin: pending admin only");` 64. File: lending-market-v2/contracts/Governance/GovernorBravoDelegator.sol (line 27): `require(msg.sender == admin, "GovernorBravoDelegator::_setImplementation: admin only");` 65. File: lending-market-v2/contracts/Governance/GovernorBravoDelegator.sol (line 28): `require(implementation_ != address(0), "GovernorBravoDelegator::_setImplementation: invalid implementation address");` 66. File: lending-market-v2/contracts/Governance/GovernorBravoDelegator.sol (line 40): `require(msg.sender == admin, "GovernorBravoDelegator::_initiateDelegated: admin only");` 67. File: lending-market-v2/contracts/Governance/GovernorBravoDelegator.sol (line 48): `require(msg.sender == admin, "GovernorBravoDelegator::_acceptInitialAdminDelegated: admin only");` 68. File: lending-market-v2/contracts/Governance/GovernorBravoDelegator.sol (line 56): `require(msg.sender == admin, "GovernorBravoDelegator::_setPendingAdminDelegated: admin only");` 69. File: lending-market-v2/contracts/Treasury/TreasuryDelegator.sol (line 31): `require(msg.sender == admin, "GovernorBravoDelegator::setImplementation: admin only");` 70. File: lending-market-v2/contracts/Treasury/TreasuryDelegator.sol (line 32): `require(implementation_ != address(0), "GovernorBravoDelegator::setImplementation: invalid implementation address");` 71. File: lending-market-v2/contracts/Treasury/TreasuryDelegator.sol (line 121): `require(msg.value == 0, "TreasuryDelegator::fallback:cannot send value to fallback");` 72. File: lending-market-v2/contracts/CNote.sol (line 17): `require(msg.sender == admin, "CNote::_setAccountantContract:Only admin may call this function");` 73. File: lending-market-v2/contracts/CNote.sol (line 94): `require(success, "TOKEN_TRANSFER_IN_FAILED");` 74. File: lending-market-v2/contracts/CNote.sol (line 105): `require(balanceCur == 0, "Accountant has not been correctly supplied");` 75. File: lending-market-v2/contracts/CNote.sol (line 147): `require(success, "TOKEN_TRANSFER_OUT_FAILED");` 76. File: lending-market-v2/contracts/CNote.sol (line 148): `require(token.balanceOf(address(this)) == 0, "cNote::doTransferOut: TransferOut Failed");` 77. File: lending-market-v2/contracts/NoteInterest.sol (line 167): `require(msg.sender == admin, "only the admin may set the base rate");` 78. File: lending-market-v2/contracts/NoteInterest.sol (line 180): `require(msg.sender == admin, "only the admin may set the adjuster coefficient");` 79. File: lending-market-v2/contracts/NoteInterest.sol (line 193): `require(msg.sender == admin, "only the admin may set the update frequency");` 80. File: lending-market-v2/contracts/CNote.sol (line 17): `require(msg.sender == admin, "CNote::_setAccountantContract:Only admin may call this function");` 81. File: lending-market-v2/contracts/CNote.sol (line 94): `require(success, "TOKEN_TRANSFER_IN_FAILED");` 82. File: lending-market-v2/contracts/CNote.sol (line 105): `require(balanceCur == 0, "Accountant has not been correctly supplied");` 83. File: lending-market-v2/contracts/CNote.sol (line 147): `require(success, "TOKEN_TRANSFER_OUT_FAILED");` 84. File: lending-market-v2/contracts/CNote.sol (line 148): `require(token.balanceOf(address(this)) == 0, "cNote::doTransferOut: TransferOut Failed");` 85. File: manifest-v2/contracts/ERC20MinterBurnerDecimals.sol (line 72): `require(hasRole(MINTER_ROLE, _msgSender()), "ERC20MinterBurnerDecimals: must have minter role to mint");` 86. File: manifest-v2/contracts/ERC20MinterBurnerDecimals.sol (line 86): `require(hasRole(BURNER_ROLE, _msgSender()), "ERC20MinterBurnerDecimals: must have burner role to burn");` 87. File: manifest-v2/contracts/ERC20MinterBurnerDecimals.sol (line 100): `require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20MinterBurnerDecimals: must have pauser role to pause");` 88. File: manifest-v2/contracts/ERC20MinterBurnerDecimals.sol (line 114): `require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20MinterBurnerDecimals: must have pauser role to unpause");` 89. File: manifest-v2/contracts/ERC20Burnable.sol (line 37): `require(currentAllowance >= amount, "ERC20: burn amount exceeds allowance");`

[G-05] Not using the named return variables when a function returns, wastes deployment gas :-

1. File: lending-market-v2/contracts/Governance/Comp.sol (line 149): `return _delegate(msg.sender, delegatee);` 2. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 250): `return _castVote(msg.sender, proposalId, support);`

[G-06] USING > 0 COSTS MORE GAS THAN != 0 WHEN USED ON A UINT IN A REQUIRE() STATEMENT :-

1. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 256): `require(liquidity > 0, 'ILM');` 2. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 275): `require(amount0 > 0 && amount1 > 0, 'ILB');` 3. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 289): `require(amount0Out > 0 || amount1Out > 0, 'IOA');` 4. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 306): `require(amount0In > 0 || amount1In > 0, 'IIA');` 5. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 468): `require(token.code.length > 0);` 6. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 122): `require(amountA > 0, "BaseV1Router: INSUFFICIENT_AMOUNT");` 7. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 123): `require(reserveA > 0 && reserveB > 0, "BaseV1Router: INSUFFICIENT_LIQUIDITY");` 8. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 474): `require(token.code.length > 0);` 9. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 481): `require(token.code.length > 0, "token code length failure");` 10. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 228): `require(proposalCount >= proposalId && proposalId > 0, "GovernorAlpha::state: invalid proposal id");`

[G-07] IT COSTS MORE GAS TO INITIALIZE VARIABLES TO ZERO THAN TO LET THE DEFAULT OF ZERO BE APPLIED :-

1. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 210): `for (uint i = 0; i < _prices.length; i++) {` 2. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 340): `for (uint i = 0; i < 255; i++) {` 3. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 154): `for (uint i = 0; i < routes.length; i++) {` 4. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 380): `for (uint i = 0; i < routes.length; i++) {` 5. File: lending-market-v2/contracts/Stableswap/test/calculations.sol (line 63): `for (uint i = 0; i < 255; i++) {` 6. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 181): `for (uint i = 0; i < proposal.targets.length; i++) {` 7. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 197): `for (uint i = 0; i < proposal.targets.length; i++) {` 8. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 211): `for (uint i = 0; i < proposal.targets.length; i++) {` 9. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 66): `for (uint i = 0; i < newProposal.targets.length; i++) {` 10. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 88): `for (uint i = 0; i < proposal.targets.length; i++) {`

[G-08] ++i COSTS LESS GAS THAN i++, ESPECIALLY WHEN ITโ€™S USED IN FOR-LOOPS (--I/I-- TOO) :-

1. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 210): `for (uint i = 0; i < _prices.length; i++) {` 2. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 340): `for (uint i = 0; i < 255; i++) {` 3. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 154): `for (uint i = 0; i < routes.length; i++) {` 4. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 380): `for (uint i = 0; i < routes.length; i++) {` 5. File: lending-market-v2/contracts/Stableswap/test/calculations.sol (line 63): `for (uint i = 0; i < 255; i++) {` 6. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 181): `for (uint i = 0; i < proposal.targets.length; i++) {` 7. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 197): `for (uint i = 0; i < proposal.targets.length; i++) {` 8. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 211): `for (uint i = 0; i < proposal.targets.length; i++) {` 9. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 66): `for (uint i = 0; i < newProposal.targets.length; i++) {` 10. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 88): `for (uint i = 0; i < proposal.targets.length; i++) {`

[G-09] Splitting require() statements that use && can use more gas :-

1. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 275): `require(amount0 > 0 && amount1 > 0, 'ILB');` 2. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 291): `require(amount0Out < _reserve0 && amount1Out < _reserve1, 'IL');` 3. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 297): `require(to != _token0 && to != _token1, 'IT');` 4. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 434): `require(recoveredAddress != address(0) && recoveredAddress == owner, 'BaseV1: INVALID_SIGNATURE');` 5. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 471): `require(success && (data.length == 0 || abi.decode(data, (bool))));` 6. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 123): `require(reserveA > 0 && reserveB > 0, "BaseV1Router: INSUFFICIENT_LIQUIDITY");` 7. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 477): `require(success && (data.length == 0 || abi.decode(data, (bool))));` 8. File: lending-market-v2/contracts/Stableswap/test/Token.sol (line 69): `require(recoveredAddress != address(0) && recoveredAddress == owner, 'StableV1: INVALID_SIGNATURE');` 9. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 138): ` require(targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, "GovernorAlpha::propose: proposal function information arity mismatch");` 10. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 228): `require(proposalCount >= proposalId && proposalId > 0, "GovernorAlpha::state: invalid proposal id");` 11. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 42-45): ` require(unigovProposal.targets.length == unigovProposal.values.length && unigovProposal.targets.length == unigovProposal.signatures.length && unigovProposal.targets.length == unigovProposal.calldatas.length, "GovernorBravo::propose: proposal function information arity mismatch");`

[G-10] Usage of uints/ints smaller than 32 bytes (256 bits) incurs overhead {When using elements that are smaller than 32 bytes, your contractโ€™s gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size.} :-

1. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 43): `uint8 public constant decimals = 18;` 2. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 9): `function decimals() external view returns (uint8);` 3. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 34): `function decimals() external view returns (uint8);` 4. File: manifest-v2/contracts/ERC20MinterBurnerDecimals.sol (line 58): `function decimals() public view virtual override returns (uint8)` 5. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 491): `uint8 stable;` 6. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 542): `function _returnStableBooleans(uint8 stable) internal pure returns (bool, bool)` 7. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 18): `function getReserves() external view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast);` 8. File: lending-market-v2/contracts/Governance/Comp.sol (line 12): `uint8 public constant decimals = 18;` 9. File: lending-market-v2/contracts/Governance/Comp.sol (line 28): `uint32 fromBlock;` 10. File: lending-market-v2/contracts/Governance/Comp.sol (line 33): `mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;` 11. File: lending-market-v2/contracts/Governance/Comp.sol (line 36): `mapping (address => uint32) public numCheckpoints;` 12. File: lending-market-v2/contracts/Governance/Comp.sol (line 178): `uint32 nCheckpoints = numCheckpoints[account];` 13. File: lending-market-v2/contracts/Governance/Comp.sol (line 275-278): ` function safe32(uint n, string memory errorMessage) internal pure returns (uint32) { require(n < 2**32, errorMessage); return uint32(n); }` 14. File: manifest-v2/contracts/ERC20MinterBurnerDecimals.sol (line 38): ` constructor(string memory name, string memory symbol, uint8 decimals_)` 15. File: manifest-v2/contracts/ERC20MinterBurnerDecimals.sol (line 51): `function _setupDecimals(uint8 decimals_)`

[G-10] Expressions for constant values such as a call to keccak256(), should use immutable rather than constant :-

1. File: lending-market-v2/contracts/Governance/Comp.sol (line 39): `bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");` 2. File: lending-market-v2/contracts/Governance/Comp.sol (line 42): `bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");` 3. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 110): `bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");` 4. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 113): `bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,bool support)");` 5. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 15): `bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");` 6. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 18): `bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,uint8 support)");` 7. File: lending-market-v2/contracts/Treasury/TreasuryDelegate.sol (line 12): `bytes32 constant cantoDenom = keccak256(bytes("CANTO"));` 8. File: lending-market-v2/contracts/Treasury/TreasuryDelegate.sol (line 13): `bytes32 constant noteDenom = keccak256(bytes("NOTE"));` 9. File: manifest-v2/contracts/ERC20MinterBurnerDecimals.sol (line 27-29): ` bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");`

[G-11] require() or revert() statements that check input arguments should be at the top of the function :-

1. File: lending-market-v2/contracts/Stableswap/BaseV1-core.sol (line 526): `require(token0 != address(0), 'ZA');` 2. File: lending-market-v2/contracts/Stableswap/test/Token.sol (line 145): `require(_pendingRouter != address(0), "AnyswapV3ERC20: address(0x0)");` 3. File: lending-market-v2/contracts/Accountant/AccountantDelegator.sol (line 22): `require(admin_ != address(0));` 4. File: lending-market-v2/contracts/Accountant/AccountantDelegator.sol (line 43): `require(implementation_ != address(0), "AccountantDelegator::_setImplementation: invalid implementation address");` 5. File: lending-market-v2/contracts/Governance/Comp.sol (line 166): `require(signatory != address(0), "Comp::delegateBySig: invalid signature");` 6. File: lending-market-v2/contracts/Governance/Comp.sol (line 234-235): `require(src != address(0), "Comp::_transferTokens: cannot transfer from the zero address"); require(dst != address(0), "Comp::_transferTokens: cannot transfer to the zero address");` 7. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 258): `require(signatory != address(0), "GovernorAlpha::castVoteBySig: invalid signature");` 8. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 25): `require(address(timelock) == address(0), "GovernorBravo::initialize: can only initialize once");` 9. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 27): `require(timelock_ != address(0), "GovernorBravo::initialize: invalid timelock address");` 10. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 158): `require(msg.sender == pendingAdmin, "GovernorBravo:_acceptAdmin: pending admin only");` 11. File: lending-market-v2/contracts/Governance/GovernorBravoDelegator.sol (line 28): `require(implementation_ != address(0), "GovernorBravoDelegator::_setImplementation: invalid implementation address");` 12. File: lending-market-v2/contracts/Treasury/TreasuryDelegator.sol (line 13): `require(admin_ != address(0));` 13. File: lending-market-v2/contracts/Treasury/TreasuryDelegator.sol (line 32): `require(implementation_ != address(0), "GovernorBravoDelegator::setImplementation: invalid implementation address");` 14. File: lending-market-v2/contracts/CNote.sol (line 74): `require(address(_accountant) != address(0));` 15. File: lending-market-v2/contracts/CNote.sol (line 121): `require(address(_accountant) != address(0)); ` 16. File: lending-market-v2/contracts/Note.sol (line 23): `require(address(accountant) == address(0));`

[G-11] Use a more recent version of solidity (Use a solidity version of at least 0.8.15 to have external calls skip contract existence checks if the external call has a return value):-

1. File: lending-market-v2/contracts/Stableswap/test/calculations.sol (line 3): `pragma solidity ^0.8.6;` 2. File: manifest-v2/contracts/ERC20Burnable.sol (line 3): `pragma solidity ^0.8.0;` 3. File: manifest-v2/contracts/ERC20MaliciousDelayed.sol (line 3): `pragma solidity ^0.8.0;` 4. File: manifest-v2/contracts/ERC20MinterBurnerDecimals.sol (line 3): `require(implementation_ != address(0), "AccountantDelegator::_setImplementation: invalid implementation address");` 5. File: manifest-v2/contracts/Proposal-Store.sol (line 3): `pragma solidity ^0.8.0;`

[G-12] Use custom errors rather than revert()/require() strings to save gas:-

1. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 104): `require(tokenA != tokenB, "BaseV1Router: IDENTICAL_ADDRESSES");` 2. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 106): `require(token0 != address(0), "BaseV1Router: ZERO_ADDRESS");` 3. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 122): `require(amountA > 0, "BaseV1Router: INSUFFICIENT_AMOUNT");` 4. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 123): `require(reserveA > 0 && reserveB > 0, "BaseV1Router: INSUFFICIENT_LIQUIDITY");` 5. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 151): `require(routes.length >= 1, "BaseV1Router: INVALID_PATH");` 6. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 241): `require(amountBOptimal >= amountBMin, "BaseV1Router: INSUFFICIENT_B_AMOUNT");` 7. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 246): `require(amountAOptimal >= amountAMin, "BaseV1Router: INSUFFICIENT_A_AMOUNT");` 8. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 313): `require(amountA >= amountAMin, "BaseV1Router: INSUFFICIENT_A_AMOUNT");` 9. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 314): `require(amountB >= amountBMin, "BaseV1Router: INSUFFICIENT_B_AMOUNT");` 10. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 405): `require(amounts[amounts.length - 1] >= amountOutMin, "BaseV1Router: INSUFFICIENT_OUTPUT_AMOUNT");` 11. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 420): `require(amounts[amounts.length - 1] >= amountOutMin, "BaseV1Router: INSUFFICIENT_OUTPUT_AMOUNT");` 12. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 433): `require(routes[0].from == address(wcanto), "BaseV1Router: INVALID_PATH");` 13. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 435): `require(amounts[amounts.length - 1] >= amountOutMin, "BaseV1Router: INSUFFICIENT_OUTPUT_AMOUNT");` 14. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 446): `require(routes[routes.length - 1].to == address(wcanto), "BaseV1Router: INVALID_PATH");` 15. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 448): `require(amounts[amounts.length - 1] >= amountOutMin, "BaseV1Router: INSUFFICIENT_OUTPUT_AMOUNT");` 16. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 470): `require(success, "TransferHelper: ETH_TRANSFER_FAILED");` 17. File: lending-market-v2/contracts/Stableswap/BaseV1-periphery.sol (line 481): `require(token.code.length > 0, "token code length failure");` 18. File: lending-market-v2/contracts/Stableswap/test/Token.sol (line 145): `require(_pendingRouter != address(0), "AnyswapV3ERC20: address(0x0)");` 19. File: lending-market-v2/contracts/Accountant/AccountantDelegate.sol (line 87): `require(cNoteAmt >= noteDiff, "AccountantDelegate::sweepInterest:Error calculating interest to sweep");` 20. File: lending-market-v2/contracts/Accountant/AccountantDelegate.sol (line 101): `require(cnote.balanceOf(treasury) == 0, "AccountantDelegate::sweepInterestError");` 21. File: lending-market-v2/contracts/Accountant/AccountantDelegator.sol (line 42): `require(msg.sender == admin, "AccountantDelegator::_setImplementation: admin only");` 22. File: lending-market-v2/contracts/Accountant/AccountantDelegator.sol (line 43): `require(implementation_ != address(0), "AccountantDelegator::_setImplementation: invalid implementation address");` 23. File: lending-market-v2/contracts/Accountant/AccountantDelegator.sol (line 123): `require(msg.value == 0,"AccountantDelegator:fallback: cannot send value to fallback");` 24. File: lending-market-v2/contracts/Governance/Comp.sol (line 166): `require(signatory != address(0), "Comp::delegateBySig: invalid signature");` 25. File: lending-market-v2/contracts/Governance/Comp.sol (line 167): `require(nonce == nonces[signatory]++, "Comp::delegateBySig: invalid nonce");` 26. File: lending-market-v2/contracts/Governance/Comp.sol (line 168): `require(block.timestamp <= expiry, "Comp::delegateBySig: signature expired");` 27. File: lending-market-v2/contracts/Governance/Comp.sol (line 190): `require(blockNumber < block.number, "Comp::getPriorVotes: not yet determined");` 28. File: lending-market-v2/contracts/Governance/Comp.sol (line 234): `require(src != address(0), "Comp::_transferTokens: cannot transfer from the zero address");` 29. File: lending-market-v2/contracts/Governance/Comp.sol (line 235): `require(dst != address(0), "Comp::_transferTokens: cannot transfer to the zero address");` 30. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 137): `require(comp.getPriorVotes(msg.sender, sub256(block.number, 1)) > proposalThreshold(), "GovernorAlpha::propose: proposer votes below proposal threshold");` 31. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 138): `require(targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, "GovernorAlpha::propose: proposal function information arity mismatch");` 32. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 139): `require(targets.length != 0, "GovernorAlpha::propose: must provide actions");` 33. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 140): `require(targets.length <= proposalMaxOperations(), "GovernorAlpha::propose: too many actions");` 34. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 145): `require(proposersLatestProposalState != ProposalState.Active, "GovernorAlpha::propose: one live proposal per proposer, found an already active proposal");` 35. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 146): `require(proposersLatestProposalState != ProposalState.Pending, "GovernorAlpha::propose: one live proposal per proposer, found an already pending proposal");` 36. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 156): `require(newProposal.id == 0, "GovernorAlpha::propose: ProposalID collsion");` 37. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 178): `require(state(proposalId) == ProposalState.Succeeded, "GovernorAlpha::queue: proposal can only be queued if it is succeeded");` 38. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 189): `require(!timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data, eta))), "GovernorAlpha::_queueOrRevert: proposal action already queued at eta");` 39. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 194): `require(state(proposalId) == ProposalState.Queued, "GovernorAlpha::execute: proposal can only be executed if it is queued");` 40. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 205): `require(state != ProposalState.Executed, "GovernorAlpha::cancel: cannot cancel executed proposal");` 41. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 208): `require(msg.sender == guardian || comp.getPriorVotes(proposal.proposer, sub256(block.number, 1)) < proposalThreshold(), "GovernorAlpha::cancel: proposer above threshold");` 42. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 228): `require(proposalCount >= proposalId && proposalId > 0, "GovernorAlpha::state: invalid proposal id");` 43. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 258): `require(signatory != address(0), "GovernorAlpha::castVoteBySig: invalid signature");` 44. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 263): `require(state(proposalId) == ProposalState.Active, "GovernorAlpha::_castVote: voting is closed");` 45. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 266): `require(receipt.hasVoted == false, "GovernorAlpha::_castVote: voter already voted");` 46. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 283): `require(msg.sender == guardian, "GovernorAlpha::__acceptAdmin: sender must be gov guardian");` 47. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 288): `require(msg.sender == guardian, "GovernorAlpha::__abdicate: sender must be gov guardian");` 48. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 293): `require(msg.sender == guardian, "GovernorAlpha::__queueSetTimelockPendingAdmin: sender must be gov guardian");` 49. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 298): `require(msg.sender == guardian, "GovernorAlpha::__executeSetTimelockPendingAdmin: sender must be gov guardian");` 50. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 304): `require(c >= a, "addition overflow");` 51. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 309): `require(b <= a, "subtraction underflow");` 52. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 25): `require(address(timelock) == address(0), "GovernorBravo::initialize: can only initialize once");` 53. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 26): `require(msg.sender == admin, "GovernorBravo::initialize: admin only");` 54. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 27): `require(timelock_ != address(0), "GovernorBravo::initialize: invalid timelock address");` 55. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 42-45): `require(unigovProposal.targets.length == unigovProposal.values.length && unigovProposal.targets.length == unigovProposal.signatures.length && unigovProposal.targets.length == unigovProposal.calldatas.length, "GovernorBravo::propose: proposal function information arity mismatch");` 56. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 46): `require(unigovProposal.targets.length != 0, "GovernorBravo::propose: must provide actions");` 57. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 47): `require(unigovProposal.targets.length <= proposalMaxOperations, "GovernorBravo::propose: too many actions");` 58. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 76): ` require(!timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data, eta))), "GovernorBravo::queueOrRevertInternal: identical proposal action already queued at eta");` 59. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 85): `require(state(proposalId) == ProposalState.Queued, "GovernorBravo::execute: proposal can only be executed if it is queued");` 60. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 128): `require(msg.sender == admin, "GovernorBravo::_initiate: admin only");` 61. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 129): `require(initialProposalId == 0, "GovernorBravo::_initiate: can only initiate once");` 62. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 140): `require(msg.sender == admin, "GovernorBravo:_setPendingAdmin: admin only");` 63. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 158): `require(msg.sender == pendingAdmin, "GovernorBravo:_acceptAdmin: pending admin only");` 64. File: lending-market-v2/contracts/Governance/GovernorBravoDelegator.sol (line 27): `require(msg.sender == admin, "GovernorBravoDelegator::_setImplementation: admin only");` 65. File: lending-market-v2/contracts/Governance/GovernorBravoDelegator.sol (line 28): `require(implementation_ != address(0), "GovernorBravoDelegator::_setImplementation: invalid implementation address");` 66. File: lending-market-v2/contracts/Governance/GovernorBravoDelegator.sol (line 40): `require(msg.sender == admin, "GovernorBravoDelegator::_initiateDelegated: admin only");` 67. File: lending-market-v2/contracts/Governance/GovernorBravoDelegator.sol (line 48): `require(msg.sender == admin, "GovernorBravoDelegator::_acceptInitialAdminDelegated: admin only");` 68. File: lending-market-v2/contracts/Governance/GovernorBravoDelegator.sol (line 56): `require(msg.sender == admin, "GovernorBravoDelegator::_setPendingAdminDelegated: admin only");` 69. File: lending-market-v2/contracts/Treasury/TreasuryDelegator.sol (line 31): `require(msg.sender == admin, "GovernorBravoDelegator::setImplementation: admin only");` 70. File: lending-market-v2/contracts/Treasury/TreasuryDelegator.sol (line 32): `require(implementation_ != address(0), "GovernorBravoDelegator::setImplementation: invalid implementation address");` 71. File: lending-market-v2/contracts/Treasury/TreasuryDelegator.sol (line 121): `require(msg.value == 0, "TreasuryDelegator::fallback:cannot send value to fallback");` 72. File: lending-market-v2/contracts/CNote.sol (line 17): `require(msg.sender == admin, "CNote::_setAccountantContract:Only admin may call this function");` 73. File: lending-market-v2/contracts/CNote.sol (line 94): `require(success, "TOKEN_TRANSFER_IN_FAILED");` 74. File: lending-market-v2/contracts/CNote.sol (line 105): `require(balanceCur == 0, "Accountant has not been correctly supplied");` 75. File: lending-market-v2/contracts/CNote.sol (line 147): `require(success, "TOKEN_TRANSFER_OUT_FAILED");` 76. File: lending-market-v2/contracts/CNote.sol (line 148): `require(token.balanceOf(address(this)) == 0, "cNote::doTransferOut: TransferOut Failed");` 77. File: lending-market-v2/contracts/NoteInterest.sol (line 167): `require(msg.sender == admin, "only the admin may set the base rate");` 78. File: lending-market-v2/contracts/NoteInterest.sol (line 180): `require(msg.sender == admin, "only the admin may set the adjuster coefficient");` 79. File: lending-market-v2/contracts/NoteInterest.sol (line 193): `require(msg.sender == admin, "only the admin may set the update frequency");` 80. File: lending-market-v2/contracts/CNote.sol (line 17): `require(msg.sender == admin, "CNote::_setAccountantContract:Only admin may call this function");` 81. File: lending-market-v2/contracts/CNote.sol (line 94): `require(success, "TOKEN_TRANSFER_IN_FAILED");` 82. File: lending-market-v2/contracts/CNote.sol (line 105): `require(balanceCur == 0, "Accountant has not been correctly supplied");` 83. File: lending-market-v2/contracts/CNote.sol (line 147): `require(success, "TOKEN_TRANSFER_OUT_FAILED");` 84. File: lending-market-v2/contracts/CNote.sol (line 148): `require(token.balanceOf(address(this)) == 0, "cNote::doTransferOut: TransferOut Failed");` 85. File: manifest-v2/contracts/ERC20MinterBurnerDecimals.sol (line 72): `require(hasRole(MINTER_ROLE, _msgSender()), "ERC20MinterBurnerDecimals: must have minter role to mint");` 86. File: manifest-v2/contracts/ERC20MinterBurnerDecimals.sol (line 86): `require(hasRole(BURNER_ROLE, _msgSender()), "ERC20MinterBurnerDecimals: must have burner role to burn");` 87. File: manifest-v2/contracts/ERC20MinterBurnerDecimals.sol (line 100): `require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20MinterBurnerDecimals: must have pauser role to pause");` 88. File: manifest-v2/contracts/ERC20MinterBurnerDecimals.sol (line 114): `require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20MinterBurnerDecimals: must have pauser role to unpause");` 89. File: manifest-v2/contracts/ERC20Burnable.sol (line 37): `require(currentAllowance >= amount, "ERC20: burn amount exceeds allowance");`

[G-13] Consider making some constants as non-public to save gas (Reducing from public to private or internal can save gas when a constant isnโ€™t used outside of its contract. I suggest changing the visibility from public to internal or private ) :-

1. File: lending-market-v2/contracts/Governance/Comp.sol (line 39): `bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");` 2. File: lending-market-v2/contracts/Governance/Comp.sol (line 42): `bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");` 3. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 110): `bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");` 4. File: lending-market-v2/contracts/Governance/GovernorAlpha.sol (line 113): `bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,bool support)");` 5. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 15): `bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");` 6. File: lending-market-v2/contracts/Governance/GovernorBravoDelegate.sol (line 18): `bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,uint8 support)");` 7. File: manifest-v2/contracts/ERC20MinterBurnerDecimals.sol (line 27-29): ` bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");`

#0 - GalloDaSballo

2022-08-14T20:40:17Z

[G-01] STATE VARIABLES ONL

Some false positives, giving you 3 * 2100

Rest is negligible (less than 300 gas)

6300 + 300

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