Platform: Code4rena
Start Date: 27/01/2022
Pot Size: $75,000 USDT
Total HM: 6
Participants: 29
Period: 7 days
Judge: leastwood
Total Solo HM: 6
Id: 72
League: ETH
Rank: 2/29
Findings: 3
Award: $6,006.20
π Selected for report: 1
π Solo Findings: 1
π Selected for report: defsec
4882.8125 USDT - $4,882.81
defsec
Eth sent to Timelock will be locked in current implementation. I came across this problem while playing around with the governance contract.
await proxy.propose( [signers[3].address], [ethers.utils.parseEther("0.1")], [""], [ethers.BigNumber.from(0)], "Send funds to 3rd signer" );
await proxy.execute(2); // this fails await proxy.execute(2, {value: ethers.utils.parseEther("0.1")}) // this would work 0.1 eth will be sent out, but it is sent from the msg.sender not from the timelock contract.
Consider implementing the following code.
function execute(uint proposalId) external { require(state(proposalId) == ProposalState.Queued, "GovernorAlpha::execute: proposal can only be executed if it is queued"); Proposal storage proposal = proposals[proposalId]; proposal.executed = true; for (uint i = 0; i < proposal.targets.length; i++) { timelock.executeTransaction(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], proposal.eta); } emit ProposalExecuted(proposalId); }
##Β Reference
https://github.com/compound-finance/compound-protocol/pull/177/files
#0 - 0xleastwood
2022-02-19T11:22:06Z
I agree with this finding!
π Selected for report: cccz
Also found by: defsec, mics, sirhashalot
defsec
On the helper contract, It has been observed that to safeIncreaseAllowance and safeDecreaseAllowance are commented out. (https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2268) safeApprove function is deprecated.
Code Review
Consider to enable functions and use safeIncreaseAllowance and safeDecreaseAllowance instead of safeApprove.
#0 - ColaM12
2022-02-03T05:47:38Z
Duplicate to #87
defsec
++i is more gas efficient than i++ in loops forwarding.
https://github.com/code-423n4/2022-01-openleverage/blob/main/openleverage-contracts/contracts/Airdrop.sol#L64 https://github.com/code-423n4/2022-01-openleverage/blob/main/openleverage-contracts/contracts/ControllerV1.sol#L303 https://github.com/code-423n4/2022-01-openleverage/blob/main/openleverage-contracts/contracts/OpenLevV1.sol#L52 https://github.com/code-423n4/2022-01-openleverage/blob/main/openleverage-contracts/contracts/OpenLevV1Lib.sol#L260 https://github.com/code-423n4/2022-01-openleverage/blob/main/openleverage-contracts/contracts/dex/bsc/BscDexAggregatorV1.sol#L46 https://github.com/code-423n4/2022-01-openleverage/blob/main/openleverage-contracts/contracts/dex/bsc/UniV2ClassDex.sol#L60
Code Review
It is recommend to use unchecked{++i} and change i declaration to uint256.
#0 - ColaM12
2022-01-30T02:23:59Z
Duplicate to #13
10.3004 USDT - $10.30
defsec
Reading array length at each iteration of the loop takes 6 gas (3 for mload and 3 to place memory_offset) in the stack.
Caching the array length in the stack saves around 3 gas per iteration.
https://github.com/code-423n4/2022-01-openleverage/blob/main/openleverage-contracts/contracts/Airdrop.sol#L64 https://github.com/code-423n4/2022-01-openleverage/blob/main/openleverage-contracts/contracts/ControllerV1.sol#L303 https://github.com/code-423n4/2022-01-openleverage/blob/main/openleverage-contracts/contracts/OpenLevV1.sol#L52 https://github.com/code-423n4/2022-01-openleverage/blob/main/openleverage-contracts/contracts/OpenLevV1Lib.sol#L260 https://github.com/code-423n4/2022-01-openleverage/blob/main/openleverage-contracts/contracts/dex/bsc/BscDexAggregatorV1.sol#L46 https://github.com/code-423n4/2022-01-openleverage/blob/main/openleverage-contracts/contracts/dex/bsc/UniV2ClassDex.sol#L60
None
Consider to cache array length.
#0 - ColaM12
2022-01-30T02:25:22Z
Duplicate to #15
defsec
During the code review, It has been observed that startTime and endTime do not have necessity checks and that will cause to broken functionality on the contract. That will be resulted with re-deployment.
Code Review
Consider initialize variables with comparision block.timestamp. Endtime should be bigger than starttime.
#0 - ColaM12
2022-02-03T05:49:15Z
Duplicate to #160
19.0749 USDT - $19.07
defsec
Using newer compiler versions and the optimizer gives gas optimizations and additional safety checks are available for free.
The advantages of versions 0.8.* over <0.8.0 are:
All Contracts
None
Consider to upgrade pragma to at least 0.8.4.
#0 - ColaM12
2022-01-29T01:58:04Z
duplicate to #18
47.0985 USDT - $47.10
defsec
In the Lpooldepositor contract, re-entrancy guard is defined but Its not used. Removing re-entrancy guard from the contract will provide gas optimization.
Code Remove
IT is recommended to delete un-used & redundant inheritance.
#0 - ColaM12
2022-02-03T06:01:29Z
Duplicate to #2
#1 - 0xleastwood
2022-02-21T01:43:56Z
I think this is actually a duplicate of #209 and not #2
defsec
In some cases, having function arguments in calldata instead of memory is more optimal.
Consider the following generic example:
contract C { function add(uint[] memory arr) external returns (uint sum) { uint length = arr.length; for (uint i = 0; i < arr.length; i++) { sum += arr[i]; } } }
In the above example, the dynamic array arr has the storage location memory. When the function gets called externally, the array values are kept in calldata and copied to memory during ABI decoding (using the opcode calldataload and mstore). And during the for loop, arr[i] accesses the value in memory using a mload. However, for the above example this is inefficient. Consider the following snippet instead:
contract C { function add(uint[] calldata arr) external returns (uint sum) { uint length = arr.length; for (uint i = 0; i < arr.length; i++) { sum += arr[i]; } } }
In the above snippet, instead of going via memory, the value is directly read from calldata using calldataload. That is, there are no intermediate memory operations that carries this value.
Gas savings: In the former example, the ABI decoding begins with copying value from calldata to memory in a for loop. Each iteration would cost at least 60 gas. In the latter example, this can be completely avoided. This will also reduce the number of instructions and therefore reduces the deploy time cost of the contract.
In short, use calldata instead of memory if the function argument is only read.
Note that in older Solidity versions, changing some function arguments from memory to calldata may cause "unimplemented feature error". This can be avoided by using a newer (0.8.*) Solidity compiler.
Examples Note: The following pattern is prevalent in the codebase:
function f(bytes memory data) external { (...) = abi.decode(data, (..., types, ...)); }
Here, changing to bytes calldata will decrease the gas. The total savings for this change across all such uses would be quite significant.
Examples:
https://github.com/code-423n4/2022-01-openleverage/blob/main/openleverage-contracts/contracts/OpenLevV1.sol#L52 https://github.com/code-423n4/2022-01-openleverage/blob/main/openleverage-contracts/contracts/OpenLevV1Lib.sol#L260 https://github.com/code-423n4/2022-01-openleverage/blob/main/openleverage-contracts/contracts/dex/bsc/BscDexAggregatorV1.sol#L46 https://github.com/code-423n4/2022-01-openleverage/blob/main/openleverage-contracts/contracts/dex/bsc/UniV2ClassDex.sol#L60
None
Change memory definition with calldata.
#0 - ColaM12
2022-01-30T02:29:53Z
Duplicate to #29
defsec
The assert
keyword is used in several instances within the OpenLeverage
smart contract suite. This keyword will revert a transaction in the event the condition is not satisfied, however, no gas is refunded to the user. As a result, this may lead to poor user experience and other issues if the supplied gas/gas price is considerably high.
https://github.com/code-423n4/2022-01-openleverage/blob/main/openleverage-contracts/contracts/XOLE.sol#L304 https://github.com/code-423n4/2022-01-openleverage/blob/main/openleverage-contracts/contracts/farming/FarmingPools.sol#L78
Code Review
Consider replacing all instances of the assert
keyword with require
.
#0 - ColaM12
2022-01-30T02:31:24Z
Duplicate to #43