sherlock-audit / 2024-10-ethos-network-judging

0 stars 0 forks source link

pashap9990 - votesInRangeFor will be reverted because of out of gas error #267

Open sherlock-admin4 opened 3 weeks ago

sherlock-admin4 commented 3 weeks ago

pashap9990

Medium

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 },

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:

  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)

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 error

Mitigation

pass required chunk from voteIndexes to _votesInRange function instead of pass whole array