votesInRangeFor will be reverted because of out of gas error
Summary
EthosVote:votesInRangeFor will be reverted because of out of gas error
Root Cause
When you use uint256[] memory voteIndexes = vg.voteIndexes;, the code attempts to create a memory copy of the entire storage array vg.voteIndexes. For large arrays, this will cause an "out of gas" error because copying the entire array to memory is very costly. Solidity tries to allocate memory for the full array, and if it exceeds the gas limit, the transaction reverts
PoC
let's assume there is 100000 active profile in ethos network and 13000 of them will be voted for an item and in result votesInRangeFor will be reverted becuase voteIndexes has been became very large
consider to add this test to EthosVote.test.ts and then update profiles[1].inviteInfo.available = 20000 in EthosProfile:initialize and add this to hardhat.config.ts
mocha: {
timeout: 100000000
},
1) EthosVote
voteFor
should update votesCountFor after multiple votes:
Error: Transaction reverted: contract call run out of gas and made the transaction revert
at EthosVote.votesInRangeFor (contracts/EthosVote.sol:267)
at ERC1967Proxy._delegate (@openzeppelin/contracts/proxy/Proxy.sol:23)
at ERC1967Proxy._fallback (@openzeppelin/contracts/proxy/Proxy.sol:59)
at EdrProviderWrapper.request (/Users/meysam-sara/Documents/2024-10-ethos-network-rickkk137/ethos/node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:444:41)
at async staticCallResult (/Users/meysam-sara/Documents/2024-10-ethos-network-rickkk137/ethos/node_modules/ethers/src.ts/contract/contract.ts:337:22)
at async staticCall (/Users/meysam-sara/Documents/2024-10-ethos-network-rickkk137/ethos/node_modules/ethers/src.ts/contract/contract.ts:303:24)
at async Proxy.votesInRangeFor (/Users/meysam-sara/Documents/2024-10-ethos-network-rickkk137/ethos/node_modules/ethers/src.ts/contract/contract.ts:351:41)
at async Context.<anonymous> (test/EthosVote.test.ts:670:16)
pashap9990
Medium
votesInRangeFor will be reverted because of out of gas error
Summary
EthosVote:votesInRangeFor
will be reverted because of out of gas errorRoot Cause
When you use uint256[] memory voteIndexes = vg.voteIndexes;, the code attempts to create a memory copy of the entire storage array vg.voteIndexes. For large arrays, this will cause an "out of gas" error because copying the entire array to memory is very costly. Solidity tries to allocate memory for the full array, and if it exceeds the gas limit, the transaction reverts
PoC
let's assume there is 100000 active profile in ethos network and 13000 of them will be voted for an item and in result votesInRangeFor will be reverted becuase voteIndexes has been became very large
consider to add this test to
EthosVote.test.ts
and then update profiles[1].inviteInfo.available = 20000 inEthosProfile:initialize
and add this to hardhat.config.ts mocha: { timeout: 100000000 },PoC
```typescript describe.only('voteFor-OOG', () => { it('should update votesCountFor after multiple votes', async () => { const { VOTER_0, VOTER_1, REVIEW_CREATOR_0, REVIEW_CREATOR_1, REVIEW_SUBJECT_0, OTHER_0, ADMIN, ethosVote, ethosReview, OWNER, ethosProfile, } = await loadFixture(deployFixture); const TARGET_CONTRACT = await ethosReview.getAddress(); let IS_UPVOTE = true; let TARGET_ID = 0; await ethosProfile.connect(ADMIN).setDefaultNumberOfInvites(10); await ethosProfile.connect(OWNER).inviteAddress(VOTER_0.address); await ethosProfile.connect(VOTER_0).createProfile(1); await ethosProfile.connect(OWNER).inviteAddress(VOTER_1.address); await ethosProfile.connect(VOTER_1).createProfile(1); await ethosProfile.connect(OWNER).inviteAddress(REVIEW_CREATOR_0.address); await ethosProfile.connect(REVIEW_CREATOR_0).createProfile(1); await ethosProfile.connect(OWNER).inviteAddress(REVIEW_CREATOR_1.address); await ethosProfile.connect(REVIEW_CREATOR_1).createProfile(1); await ethosProfile.connect(OWNER).inviteAddress(OTHER_0.address); await ethosProfile.connect(OTHER_0).createProfile(1); // create 4 reviews await addReview(ADMIN, REVIEW_CREATOR_0, REVIEW_SUBJECT_0, ethosReview); await addReview(ADMIN, REVIEW_CREATOR_1, REVIEW_SUBJECT_0, ethosReview); await addReview(ADMIN, REVIEW_CREATOR_1, REVIEW_SUBJECT_0, ethosReview); await addReview(ADMIN, REVIEW_CREATOR_0, REVIEW_SUBJECT_0, ethosReview); // 0 TARGET_ID = 3; IS_UPVOTE = true; let i = 1; let result; let newProfile; let profileIdNew; while(i < 13000){ newProfile = await ethers.getImpersonatedSigner(ethers.Wallet.createRandom().address); await ethers.provider.send("hardhat_setBalance", [ newProfile.address, "0x1000000000000000" ]); await inviteAndCreateProfile(ethosProfile, OWNER, newProfile); profileIdNew = await ethosProfile.profileIdByAddress(newProfile.address) console.log("profileIdNew:", profileIdNew); await ethosVote.connect(newProfile).voteFor(TARGET_CONTRACT, TARGET_ID, IS_UPVOTE); i++; } result = await ethosVote.votesInRangeFor(TARGET_CONTRACT, TARGET_ID, 0, 10); console.log("result:", result); }); }); ```result:
Code Snippet
https://github.com/sherlock-audit/2024-10-ethos-network/blob/main/ethos/packages/contracts/contracts/EthosVote.sol#L267C20-L267C51
also in this parts this can be problematic https://github.com/sherlock-audit/2024-10-ethos-network/blob/main/ethos/packages/contracts/contracts/EthosDiscussion.sol#L241
https://github.com/sherlock-audit/2024-10-ethos-network/blob/main/ethos/packages/contracts/contracts/EthosDiscussion.sol#L212
Impact
EthosVote:votesInRangeFor
will be reverted because of out of gas errorMitigation
pass required chunk from voteIndexes to _votesInRange function instead of pass whole array