Platform: Code4rena
Start Date: 07/07/2022
Pot Size: $75,000 USDC
Total HM: 32
Participants: 141
Period: 7 days
Judge: HardlyDifficult
Total Solo HM: 4
Id: 144
League: ETH
Rank: 3/141
Findings: 7
Award: $4,819.19
🌟 Selected for report: 1
🚀 Solo Findings: 1
🌟 Selected for report: cccz
4477.7307 USDC - $4,477.73
In the end function of the Buyout contract, when the buyout fails, ERC1155 tokens are sent to the proposer. A malicious proposer can start a buyout using a contract that cannot receive ERC1155 tokens, and if the buyout fails, the end function fails because it cannot send ERC1155 tokens to the proposer. This prevents a new buyout from being started.
None
Consider saving the status of the proposer after a failed buyout and implementing functions to allow the proposer to withdraw the ERC1155 tokens and eth
#0 - HardlyDifficult
2022-08-16T20:42:12Z
The 1155 receiver can prevent a failed buyout from ending, which prevents a new one from starting. Agree with severity.
🌟 Selected for report: berndartmueller
Also found by: 0xA5DF, 0xSky, 0xsanson, ElKu, Kumpa, Treasure-Seeker, TrungOre, cccz, cryptphi, hansfriese, jonatascm, kenzo, minhquanym, s3cunda, shenwilly, smiling_heretic, zzzitron
41.4866 USDC - $41.49
BuyoutInfo[_vault].ethBalance was not updated in the cash function of the Buyout contract, resulting in incorrect eth distribution. Considering that there are currently 40 eth in the contract, the total supply of ERC1155 tokens is still 400. User A uses 200 ERC1155 tokens to withdraw eth, User A will get 40 * 200/400 = 20 eth. User B uses 100 ERC1155 tokens to withdraw eth, and User B will get 40 * 100/200 = 20 eth. When user C uses 100 ERC1155 tokens to withdraw eth, the eth cannot be withdrawn because the eth in the contract has been exhausted
None
uint256 buyoutShare = (tokenBalance * ethBalance) / (totalSupply + tokenBalance); + buyoutInfo[_vault].ethBalance -= buyoutShare; _sendEthOrWeth(msg.sender, buyoutShare);
#0 - ecmendenhall
2022-07-15T03:00:23Z
🌟 Selected for report: xiaoming90
Also found by: 0x52, Lambda, cccz, codexploder, hyh, kenzo, oyc_109, zzzitron
In the Migration contract, when a proposal is committed and successfully bought out, the settleVault function can be called to set the newVault, and the MigrateVault* function can be called to transfer the assets to the newVault. However, since the MigrateVault* function does not check if the newVault is address 0, a malicious user can call the MigrateVault* function immediately after a successful buyout to send the assets to address 0.
None
Add 0 address check to the newVault in the MigrateVault* function of the Migration contract
#0 - stevennevins
2022-07-20T15:26:21Z
#1 - HardlyDifficult
2022-08-02T23:53:34Z
🌟 Selected for report: byterocket
Also found by: 0x1f8b, 242, ACai, BradMoon, Chom, Lambda, PwnedNoMore, Twpony, __141345__, ayeslick, berndartmueller, cccz, giovannidisiena, infosec_us_team, minhtrng, nine9, oyc_109, reassor, slywaters, sseefried, tofunmi, unforgiven
4.9607 USDC - $4.96
The _execute function of the Vault contract will use delegatecall to call functions of other contracts. In order to avoid the delegatecall from modifying the owner variable, the function checks whether the owner has changed. However, if the delegatecall modifies merkleRoot or methods, the attacker can manipulate the Vault contract via the delegatecall. Consider the following scenario, if a module in the Vault contract can modify merkleRoot, an attacker can first call the module to modify the merkleRoot of the Vault contract, and then delegatecall a function that matches the new merkleRoot to destroy the Vault contract or transfer the assets in the Vault contract.
https://github.com/code-423n4/2022-07-fractional/blob/8f2697ae727c60c93ea47276f8fa128369abfe51/src/Vault.sol#L131-L132 https://github.com/code-423n4/2022-07-fractional/blob/8f2697ae727c60c93ea47276f8fa128369abfe51/src/Vault.sol#L15-L21
None
Consider requiring that the merkleRoot and methods of the Vault contract not be changed after the _execute function calls delegatecall
#0 - mehtaculous
2022-07-19T15:52:58Z
Duplicate of #535
#1 - HardlyDifficult
2022-07-27T00:04:11Z
Duping to #487
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, 0x29A, Amithuddar, Avci, BowTiedWardens, Kthere, Limbooo, MEP, Ruhum, StyxRave, TomJ, Treasure-Seeker, TrungOre, Tutturu, Waze, bardamu, c3phas, cccz, codexploder, cryptphi, hake, horsefacts, hyh, oyc_109, pashov, peritoflores, scaraven, simon135, slywaters, sseefried, tofunmi, xiaoming90
1.3977 USDC - $1.40
The withdrawContribution and leave functions of the Migration contract use payable.transfer to send eth to the user. This is unsafe as transfer has hard coded gas budget and can fail when the user is a smart contract. Whenever the user either fails to implement the payable fallback function or cumulative gas cost of the function sequence invoked on a native token transfer exceeds 2300 gas consumption limit the native tokens sent end up undelivered and the corresponding user funds return functionality will fail each time.
https://github.com/code-423n4/2022-07-fractional/blob/8f2697ae727c60c93ea47276f8fa128369abfe51/src/modules/Migration.sol#L172-L173 https://github.com/code-423n4/2022-07-fractional/blob/8f2697ae727c60c93ea47276f8fa128369abfe51/src/modules/Migration.sol#L325-L326 https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/
None
Using low-level call.value(amount) with the corresponding result check or using the OpenZeppelin Address.sendValue is advised:
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol#L60
#0 - stevennevins
2022-07-19T21:48:54Z
Duplicate of #325
#1 - HardlyDifficult
2022-07-28T15:46:45Z
Duping to #504
🌟 Selected for report: 0xA5DF
Also found by: 0x52, 0xDjango, 0xsanson, Lambda, PwnedNoMore, Ruhum, Treasure-Seeker, async, berndartmueller, cccz, hubble, kenzo, scaraven, shenwilly, sseefried, xiaoming90
14.6423 USDC - $14.64
A malicious proposer can use 1 ERC1155 token and 0 eth to start a buyout. While other users can buy this ERC1155 token without spending eth, the malicious proposer can prevent others from starting buyouts for 4 days. And the malicious proposer can do this repeatedly to prevent others from starting buyouts
None
Consider setting the minimum number of tokens required to start a buyout in the start function to prevent malicious buyouts.
#0 - 0x0aa0
2022-07-18T16:22:20Z
Duplicate of #87
#1 - HardlyDifficult
2022-08-02T21:54:50Z
🌟 Selected for report: xiaoming90
Also found by: 0x1f8b, 0x29A, 0x52, 0xA5DF, 0xDjango, 0xNazgul, 0xNineDec, 0xf15ers, 0xsanson, 0xsolstars, 242, 8olidity, Amithuddar, Aymen0909, Bnke0x0, BowTiedWardens, David_, Deivitto, ElKu, Funen, Hawkeye, IllIllI, JC, Kaiziron, Keen_Sheen, Kthere, Kulk0, Kumpa, Lambda, MEP, ReyAdmirado, Rohan16, Ruhum, Sm4rty, TomJ, Tomio, Treasure-Seeker, TrungOre, Tutturu, Viksaa39, Waze, _Adam, __141345__, ak1, apostle0x01, asutorufos, async, ayeslick, aysha, bbrho, benbaessler, berndartmueller, c3phas, cccz, chatch, cloudjunky, codexploder, cryptphi, delfin454000, dipp, durianSausage, dy, exd0tpy, fatherOfBlocks, hake, hansfriese, horsefacts, hubble, joestakey, jonatascm, kebabsec, kenzo, kyteg, mektigboy, neumo, oyc_109, pashov, pedr02b2, peritoflores, rajatbeladiya, rbserver, robee, rokinot, s3cunda, sach1r0, sahar, sashik_eth, scaraven, shenwilly, simon135, sorrynotsorry, sseefried, svskaushik, unforgiven, z3s, zzzitron
64.7984 USDC - $64.80
The controller can set royaltyPercent to 100 in the setRoyalties function of the FERC1155 contract. If the royaltyInfo function is used to obtain royalty information when a user purchases an NFT, this may frontrun the selling process, causing the seller to lose assets
None
Consider limiting royaltyPercent in setRoyalties function
The comment on line 333 should be
// Executes transfer of ERC20 token to caller
None
- // Executes transfer of ERC721 token to caller + // Executes transfer of ERC20 token to caller
#0 - HardlyDifficult
2022-07-26T19:08:29Z
Merging with #135, https://github.com/code-423n4/2022-07-fractional-findings/issues/134