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: 70/141
Findings: 3
Award: $101.25
๐ Selected for report: 0
๐ Solo Findings: 0
๐ 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
Use call instead of transfer to send ether. And return value must be checked if sending ether is successful or not. Sending ether with the transfer is no longer recommended.
function leave(address _vault, uint256 _proposalId) external { // Reverts if address is not a registered vault (address token, uint256 id) = IVaultRegistry(registry).vaultToToken( _vault ); if (id == 0) revert NotVault(_vault); // Reverts if buyout state is not inactive (, , State current, , , ) = IBuyout(buyout).buyoutInfo(_vault); State required = State.INACTIVE; if (current != required) revert IBuyout.InvalidState(required, current); // Gets the migration proposal for the given ID Proposal storage proposal = migrationInfo[_vault][_proposalId]; // Updates fraction balances of the proposal and caller uint256 amount = userProposalFractions[_proposalId][msg.sender]; proposal.totalFractions -= amount; userProposalFractions[_proposalId][msg.sender] = 0; // Updates ether balances of the proposal and caller uint256 ethAmount = userProposalEth[_proposalId][msg.sender]; proposal.totalEth -= ethAmount; userProposalEth[_proposalId][msg.sender] = 0; // Withdraws fractions from contract back to caller IFERC1155(token).safeTransferFrom( address(this), msg.sender, id, amount, "" ); // Withdraws ether from contract back to caller payable(msg.sender).transfer(ethAmount); }
Manual review
i suggest to change payable(msg.sender).transfer(ethAmount); to
(bool result, ) = payable(msg.sendert).call{value: ethAmount}(""); require(result, โFailed to send Etherโ);
fix this to : https://github.com/code-423n4/2022-07-fractional/blob/e2c5a962a94106f9495eb96769d7f60f7d5b14c9/src/modules/Migration.sol#L325
#0 - mehtaculous
2022-07-19T21:50:25Z
Duplicate of #325
#1 - HardlyDifficult
2022-07-28T15:47:01Z
Duping to #504
๐ 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
61.9379 USDC - $61.94
#1 missing comment receiver n royaltyamount impact return has a natspec comment which is missing the receiver and royaltyAmount function parameter. Issues with comments are low risk based on Code4rena risk categories.
proof of concept https://github.com/code-423n4/2022-07-fractional/blob/e2c5a962a94106f9495eb96769d7f60f7d5b14c9/src/FERC1155.sol#L238
Tool Used manual review
Recommendation Mitigation Steps add natspec comment on return in the function parameter receiver and royaltyAmount.
#2 missing return hash impact return has a natspec comment hash which is missing. it decrease readibility
proof of concept https://github.com/code-423n4/2022-07-fractional/blob/e2c5a962a94106f9495eb96769d7f60f7d5b14c9/src/FERC1155.sol#L345
Tool Used Manual review
Recommendation Mitigation Steps add natspec return of hash
#3 mint() doesnt have require of amount impact function incomplete due to the amount was missing
proof of concept https://github.com/code-423n4/2022-07-fractional/blob/e2c5a962a94106f9495eb96769d7f60f7d5b14c9/src/FERC1155.sol#L79
Tool Used manual review
Recommendation Mitigation Steps Add to mint() function: require(amount > 0, "Amount cannot be 0")
#4 permitAll missing requirement operator cannot be caller impact operator can be caller
proof of concept https://github.com/code-423n4/2022-07-fractional/blob/e2c5a962a94106f9495eb96769d7f60f7d5b14c9/src/FERC1155.sol#L145
Tool Used Manual review
Recommendation Mitigation Steps add to permitAll() function: require(operator != msg.sender, "operator can't be caller")
#5 tx.origin impact tx.origin is a global variable in Solidity which returns the address of the account that sent the transaction. Using the variable for authorization could make a contract vulnerable if an authorized account calls into a malicious contract. A call could be made to the vulnerable contract that passes the authorization check since tx.origin returns the original sender of the transaction which in this case is the authorized account.
proof of concept https://github.com/code-423n4/2022-07-fractional/blob/e2c5a962a94106f9495eb96769d7f60f7d5b14c9/src/VaultFactory.sol#L62-L90
Tool Used
Recommendation Mitigation Steps tx.origin should not be used for authorization. Use msg.sender instead.
#6 missing indexed vault impact event is missing indexed fields.
proof of concept https://github.com/code-423n4/2022-07-fractional/blob/e2c5a962a94106f9495eb96769d7f60f7d5b14c9/src/interfaces/IBuyout.sol#L74-L83
Tool Used Manual review
Recommendation Mitigation Steps Add indexed at vault.
#7 missing immutable impact state registry, supply, and transfer can't be initialized
proof of concept https://github.com/code-423n4/2022-07-fractional/blob/e2c5a962a94106f9495eb96769d7f60f7d5b14c9/src/modules/Buyout.sol#L28-L33
Tool Used Manual review
Recommendation Mitigation Steps add immutable on the state
#8 missing immutable impact state buyout and registry can't be initialized
proof of concept https://github.com/code-423n4/2022-07-fractional/blob/e2c5a962a94106f9495eb96769d7f60f7d5b14c9/src/modules/Migration.sol#L36-L39
Tool Used manual review
Recommendation Mitigation Steps add immutable on the state
#9 supply contract was missing and missing immutable impact state supply was missing makes state cant be initialized and missing immutable on state
proof of concept https://github.com/code-423n4/2022-07-fractional/blob/e2c5a962a94106f9495eb96769d7f60f7d5b14c9/src/modules/Migration.sol#L37-L60
Tool Used Manual review Recommendation Mitigation Steps add address public immutable supply and add immutable to others
#10 missing immutable supply impact supply state can't be initialized
proof of concept https://github.com/code-423n4/2022-07-fractional/blob/e2c5a962a94106f9495eb96769d7f60f7d5b14c9/src/modules/Minter.sol#L14
Tool Used manual review
Recommendation Mitigation Steps add immutable to the state
#11 missing immutable registry impact registry can't be initialized
proof of concept https://github.com/code-423n4/2022-07-fractional/blob/e2c5a962a94106f9495eb96769d7f60f7d5b14c9/src/modules/protoforms/BaseVault.sol#L24 https://github.com/code-423n4/2022-07-fractional/blob/e2c5a962a94106f9495eb96769d7f60f7d5b14c9/src/FERC1155.sol#L345
Tool Used manual review
Recommendation Mitigation Steps add immutable to the registry state
๐ Selected for report: joestakey
Also found by: 0x1f8b, 0x29A, 0xA5DF, 0xKitsune, 0xNazgul, 0xNineDec, 0xalpharush, 0xkatana, 0xsanson, 0xsolstars, 8olidity, Avci, Bnke0x0, BowTiedWardens, Chom, Deivitto, ElKu, Fitraldys, Funen, IllIllI, JC, Kaiziron, Lambda, Limbooo, MEP, NoamYakov, PwnedNoMore, RedOneN, ReyAdmirado, Rohan16, Ruhum, Saintcode_, Sm4rty, TomJ, Tomio, TrungOre, Tutturu, Waze, _Adam, __141345__, ajtra, apostle0x01, asutorufos, benbaessler, brgltd, c3phas, codexploder, cryptphi, delfin454000, dharma09, djxploit, durianSausage, fatherOfBlocks, giovannidisiena, gogo, horsefacts, hrishibhat, hyh, ignacio, jocxyen, jonatascm, karanctf, kebabsec, kyteg, m_Rassska, mektigboy, oyc_109, pedr02b2, rbserver, robee, rokinot, sach1r0, sashik_eth, simon135, slywaters
37.9119 USDC - $37.91
#1 Visibility
change visibility from public to private or internal can save gas. so i recommend to change it.
#2 use calldata instead memory
In the external functions where the function argument is read-only, the function() has an inputed parameter that using memory, if this function didnt change the parameter, its cheaper to use calldata then memory. so we suggest to change it.
#3 cache controllerAddress
cache controllerAddress to the memory becasue mload more cheaper than sload.
#4 increment
pre-increment more cheap than post increment. so use pre increment e.g. ++i
#5 looping
default uint is 0 so remove unnecassary explicit can reduce gas. pre increment e.g ++i more cheaper gas than post increment e.g i++. i suggest to use pre increment.
#6 use storage instead memory
Use storage instead of memory to reduce the gas fee. i suggest to change from
VaultInfo memory info = vaultToToken[msg.sender];
to
VaultInfo storage info = vaultToToken[msg.sender];
#7 cache IVault(vault)
cache to the memory because IVault(vault) use multiple times.it can reduce the gas.
IVault(vault).setMerkleRoot(_merkleRoot); IVault(vault).install(_selectors, _plugins);
#8 sort the struct
sort the struct can reduce the gas . i suggest to change from
struct Auction { // Time of when buyout begins uint256 startTime; // Address of proposer creating buyout address proposer; // Enum state of the buyout auction State state; // Price of fractional tokens uint256 fractionPrice; // Balance of ether in buyout pool uint256 ethBalance; // Total supply recorded before a buyout started uint256 lastTotalSupply; }
to
struct Auction { // Time of when buyout begins uint256 startTime; // Enum state of the buyout auction State state; // Price of fractional tokens uint256 fractionPrice; // Balance of ether in buyout pool uint256 ethBalance; // Total supply recorded before a buyout started uint256 lastTotalSupply; // Address of proposer creating buyout address proposer; }
#9 cache tokens.length
cache the _tokens.length can reduce gas it caused access to a local variable is more cheap than query storage / calldata / memory in solidity. #10 cache modules.length
cache the modules.length can reduce gas it caused access to a local variable is more cheap than query storage / calldata / memory in solidity.
#11 cache leaves.length
cache the leaves.length can reduce gas it caused access to a local variable is more cheap than query storage / calldata / memory in solidity.
#12 cache data.length
cache the data.length can reduce gas it caused access to a local variable is more cheap than query storage / calldata / memory in solidity.