Project

One World
NFTDeFi
15,000 USDC
View results
Submission Details
Severity: high
Invalid

Critical State Inconsistency Due to Improper State Update Ordering

Summary

This vulnerability stems from updating the contract’s internal state only after external calls, which increases the contract’s susceptibility to reentrancy attacks. For example, when the joinDAO function updates the minted counter only after making an external call, an attacker could exploit this ordering by reentering the function before the update occurs, allowing them to mint tokens, join tiers, or drain funds repeatedly without state restrictions. This is particularly risky when combined with unchecked external calls and unprotected events, as it could lead to a complete breakdown of the contract’s security.

Vulnerability Details

  1. State Update Order Vulnerability: Several functions, like joinDAO and upgradeTier, perform critical state updates only after external calls, such as transferring funds or minting/burning tokens. This leaves an opportunity for an attacker to reenter the function, potentially bypassing restrictions based on those state updates.

  2. Combined Reentrancy Threat: An attacker could exploit this ordering flaw by using reentrant calls to bypass the intended limits on tier upgrades, token issuance, or fund transfers.

Link to the Affected Code

  1. function joinDAO(address daoMembershipAddress, uint256 tierIndex) external

    • https://github.com/Cyfrin/2024-11-one-world/blob/1e872c7ab393c380010a507398d4b4caca1ae32b/contracts/dao/MembershipFactory.sol#L140-L150

  2. function upgradeTier(address daoMembershipAddress, uint256 fromTierIndex) external

    • https://github.com/Cyfrin/2024-11-one-world/blob/1e872c7ab393c380010a507398d4b4caca1ae32b/contracts/dao/MembershipFactory.sol#L155-L161

Impact

Failure to correctly update internal state before making external calls can lead to reentrancy opportunities, race conditions, or inconsistencies, which may allow unauthorized actions, repeated actions, or fund siphoning. Specifically, this could impact token transfers, tier upgrades, or any actions related to membership, potentially leading to state corruption and financial loss.

Given the current function ordering and lack of reentrancy protections, the likelihood of an attacker identifying and exploiting this flaw is high. Reentrancy attacks are well-documented and widely understood, making them particularly dangerous when state updates are deferred until after external calls.

By performing state updates only after external calls, the contract exposes itself to multiple attack vectors:

  1. Repeated Function Calls: The attacker could reenter the joinDAO or upgradeTier functions repeatedly by exploiting the delay in state updates, allowing them to bypass tier limits or drain funds through repeated interactions.

  2. Tier Inflation: Exploiting these reentrancy conditions could allow attackers to mint multiple memberships or elevate their tier within a DAO multiple times without restrictions.

  3. Fund Drainage: This vulnerability could be used to drain the DAO treasury or other user-deposited funds by performing unauthorized, repeated fund transfers.

Proof of Concept

An attacker could create a malicious contract to repeatedly call joinDAO or upgradeTier, leveraging reentrancy to bypass intended restrictions on state updates. Below is an example of how this could be exploited in the joinDAO function.

// Malicious contract to exploit delayed state updates
contract MaliciousContract {
address public targetContract;
uint256 public tierIndex;
constructor(address _target, uint256 _tier) {
targetContract = _target;
tierIndex = _tier;
}
// Recursive call to exploit reentrancy vulnerability in `joinDAO`
function attack() public {
MembershipFactory(targetContract).joinDAO(address(this), tierIndex);
}
// Fallback function triggers reentrancy
fallback() external payable {
if (someCondition) {
MembershipFactory(targetContract).joinDAO(address(this), tierIndex);
}
}
}

Here, the attacker calls joinDAO repeatedly using reentrant calls, circumventing the minted state update, and potentially draining funds or obtaining unlimited membership tokens.

Tools Used

Manual Review

Recommendations

  1. Use Checks-Effects-Interactions Pattern: Update all internal state changes, like the minted counter in joinDAO or burn/mint calls in upgradeTier, before making any external calls.

  2. Apply ReentrancyGuard: Use OpenZeppelin’s ReentrancyGuard to protect functions that involve both state updates and external calls.

  3. Implement Access Control Modifiers: Only authorized addresses should be able to call sensitive functions, reducing unauthorized reentrancy risk and securing function access.

By following these recommendations, the contract will ensure consistent and secure state conditions, making it resistant to reentrancy attacks and protecting against unauthorized access and fund loss.

Updates

Lead Judging Commences

0xbrivan2 Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.