Platform: Code4rena
Start Date: 09/09/2021
Pot Size: $100,000 SUSHI
Total HM: 4
Participants: 11
Period: 7 days
Judge: ghoulsol
Total Solo HM: 3
Id: 28
League: ETH
Rank: 5/11
Findings: 2
Award: $5,333.70
🌟 Selected for report: 9
🚀 Solo Findings: 0
🌟 Selected for report: pauliax
149.5769 SUSHI - $1,500.26
pauliax
function createEscrow first assigns an index for the new isChildEscrow and only then pushes the struct to the array. When first escrow is being created, the array contains 0 elements so escrows.length-1 will underflow and return a max uint value: isChildEscrow[address(newEscrow)] = Fermenter(true,_templateId,escrows.length-1); escrows.push(newEscrow);
isChildEscrow[address(newEscrow)] = Fermenter(true,_templateId,escrows.length); escrows.push(newEscrow);
#0 - maxsam4
2021-09-16T05:30:08Z
The issue is correct but the risk is low because this functionality is only used offchain, by the UIs etc. The index is not consumed onchain.
#1 - Clearwood
2021-10-05T18:05:15Z
#2 - ghoul-sol
2021-10-05T19:52:03Z
per sponsor comment, low risk
🌟 Selected for report: pauliax
149.5769 SUSHI - $1,500.26
pauliax
function lockTokens in contract TokenVault should check that _withdrawer is not empty (0x0) to prevent accidentally locked forever (burned) tokens.
require(_withdrawer != address(0));
#0 - Clearwood
2021-10-05T18:28:13Z
🌟 Selected for report: pauliax
13.8408 SUSHI - $138.82
pauliax
No need for this line in function initMISOMarket as it gets this value by default: auctionTemplateId = 0;
Consider removing useless initialization.
🌟 Selected for report: pauliax
13.8408 SUSHI - $138.82
pauliax
It is unclear why MISOTokenFactory contract needs its own TOKEN_MINTER_ROLE when similar role is already defined in MISOAccessControls: bytes32 public constant TOKEN_MINTER_ROLE = keccak256("TOKEN_MINTER_ROLE"); // MISOTokenFactory bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); // MISOAccessControls Especially considering that both of these roles have the same privileges, that is to deployToken when the contract is locked:
/// @dev If the contract is locked, only admin and minters can deploy. if (locked) { require(accessControls.hasAdminRole(msg.sender) || accessControls.hasMinterRole(msg.sender) || hasTokenMinterRole(msg.sender), "MISOTokenFactory: Sender must be minter if locked" ); }
Similarly with MARKET_MINTER_ROLE in MISOMarket and other contracts.
Consider removing this surplus role to eliminate the confusion and improve gas usage.
🌟 Selected for report: pauliax
13.8408 SUSHI - $138.82
pauliax
WETH state variable in MISOLauncher is practically useless as it is not used in any meaningful way. Similarly, SECONDS_PER_DAY is not used in PostAuctionLauncher.
Consider removing unused variables.
🌟 Selected for report: pauliax
13.8408 SUSHI - $138.82
pauliax
The purpose of allDepositIds in TokenVault is unclear, it gets pushed every _id and these values are never deleted so it basically contains all the numbers starting from 1 to depositId. I do not understand why you cannot just rely on depositId and create this array in the frontend if needed. This will improve gas usage.
Consider getting rid of allDepositIds.
🌟 Selected for report: pauliax
13.8408 SUSHI - $138.82
pauliax
There are structs that could be optimized for storage slots (packed tightly) to reduce gas usage. For instance, struct Item in TokenVault, we know that a max value for unlockTime is 10000000000 so this does not need uint256 space, userIndex also won't exceed billions in practice. I see other structs are more optimized, so consider doing the same with this one.
Pack 'em even tighter.
🌟 Selected for report: pauliax
13.8408 SUSHI - $138.82
pauliax
No need to check that _startTime < 10000000000 as it is later checked against _endTime which is also < 10000000000 : require(_startTime < 10000000000, "Crowdsale: enter an unix timestamp in seconds, not miliseconds"); require(_endTime < 10000000000, "Crowdsale: enter an unix timestamp in seconds, not miliseconds"); ... require(_endTime > _startTime, "Crowdsale: end time must be older than start price");
Remove this line: require(_startTime < 10000000000, "Crowdsale: enter an unix timestamp in seconds, not miliseconds");
🌟 Selected for report: pauliax
149.5769 SUSHI - $1,500.26
pauliax
contract MISORecipe01 incorrectly declares interfaces for IMISOTokenFactory function createToken and IMISOFarmFactory function createFarm. The actual implementations have different parameters so these functions will not be found at runtime.
To make it consistent across different contracts, you should extract interfaces separately and enforce implementations to implement them as "implements" is checked during compile time and could prevent such mistakes.
#0 - maxsam4
2021-09-16T05:14:36Z
This contract is not used anymore. Even if it was, I'd debate the severity because there's no risk here. Worse case, we realize after deployment and deploy again.
#1 - ghoul-sol
2021-10-05T19:53:44Z
per sponsor comment, low risk