Arcade.xyz - zhaojie's results

The first of its kind Web3 platform to enable liquid lending markets for NFTs.

General Information

Platform: Code4rena

Start Date: 21/07/2023

Pot Size: $90,500 USDC

Total HM: 8

Participants: 60

Period: 7 days

Judge: 0xean

Total Solo HM: 2

Id: 264

League: ETH

Arcade.xyz

Findings Distribution

Researcher Performance

Rank: 48/60

Findings: 1

Award: $194.68

QA:
grade-a

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

194.678 USDC - $194.68

Labels

bug
grade-a
QA (Quality Assurance)
sponsor disputed
Q-16

External Links

Dependent functions (outside the scope) that can use more efficient algorithms.

GSCVault.proveMembership

function proveMembership( address[] calldata votingVaults, bytes[] calldata extraData ) external { // Check for call validity assert(votingVaults.length > 0); // We loop through the voting vaults to check they are authorized // We check all up front to prevent any reentrancy or weird side effects //@audit <----> for loops can be merged for (uint256 i = 0; i < votingVaults.length; i++) { // No repeated vaults in the list for (uint256 j = i + 1; j < votingVaults.length; j++) { require(votingVaults[i] != votingVaults[j], "duplicate vault"); } // Call the mapping the core voting contract to check that // the provided address is in fact approved. // Note - Post Berlin hardfork this repeated access is quite cheap. bool vaultStatus = coreVoting.approvedVaults(votingVaults[i]); require(vaultStatus, "Voting vault not approved"); } // Now we tally the caller's voting power uint256 totalVotes = 0; // Parse through the list of vaults for (uint256 i = 0; i < votingVaults.length; i++) { // Call the vault to check last block's voting power // Last block to ensure there's no flash loan or other // intra contract interaction uint256 votes = IVotingVault(votingVaults[i]).queryVotePower( msg.sender, block.number - 1, extraData[i] ); // Add up the votes totalVotes += votes; } // Require that the caller has proven that they have enough votes //@audit <----> can put it in the for loop require(totalVotes >= votingPowerBound, "Not enough votes"); // if the caller has already provedMembership, update their votingPower without // resetting their idle duration. if (members[msg.sender].joined != 0) { members[msg.sender].vaults = votingVaults; } else { members[msg.sender] = Member(votingVaults, block.timestamp); } // Emit the event tracking this emit MembershipProved(msg.sender, block.timestamp); }

The modified code is as follows:

function proveMembership11( address[] calldata votingVaults, bytes[] calldata extraData ) external { // Check for call validity assert(votingVaults.length > 0); // We loop through the voting vaults to check they are authorized // We check all up front to prevent any reentrancy or weird side effects uint256 totalVotes = 0; for (uint256 i = 0; i < votingVaults.length; i++) { // No repeated vaults in the list for (uint256 j = i + 1; j < votingVaults.length; j++) { require(votingVaults[i] != votingVaults[j], "duplicate vault"); } // Call the mapping the core voting contract to check that // the provided address is in fact approved. // Note - Post Berlin hardfork this repeated access is quite cheap. bool vaultStatus = coreVoting.approvedVaults(votingVaults[i]); require(vaultStatus, "Voting vault not approved"); // Call the vault to check last block's voting power // Last block to ensure there's no flash loan or other // intra contract interaction uint256 votes = IVotingVault(votingVaults[i]).queryVotePower( msg.sender, block.number - 1, extraData[i] ); // Add up the votes totalVotes += votes; require(totalVotes >= votingPowerBound, "Not enough votes"); } // Require that the caller has proven that they have enough votes // if the caller has already provedMembership, update their votingPower without // resetting their idle duration. if (members[msg.sender].joined != 0) { members[msg.sender].vaults = votingVaults; } else { members[msg.sender] = Member(votingVaults, block.timestamp); } // Emit the event tracking this emit MembershipProved(msg.sender, block.timestamp); }

Although this contracts are not in scope, there is still a need for improvement.

#0 - c4-judge

2023-08-10T22:37:27Z

0xean marked the issue as grade-a

#1 - PowVT

2023-08-15T14:38:16Z

This seems like it is out-of-scope to me. The GSCVault and its functionality is inherited by the governance protocol. This submission does not show any major effects on how governance operates or how votes are counted.

#2 - c4-sponsor

2023-08-15T14:38:49Z

PowVT marked the issue as sponsor disputed

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter