Skip to content
This repository has been archived by the owner on Jan 21, 2024. It is now read-only.

r0bert - Setting a new Vote Factor through a setVoteFactor() call could cause a Denial of Service in the airdrops #148

Closed
sherlock-admin2 opened this issue Jul 22, 2023 · 0 comments
Labels
Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label Medium A valid Medium severity issue Reward A payout will be made for this issue

Comments

@sherlock-admin2
Copy link

sherlock-admin2 commented Jul 22, 2023

r0bert

high

Setting a new Vote Factor through a setVoteFactor() call could cause a Denial of Service in the airdrops

Summary

Setting a new Vote Factor through a setVoteFactor() call could cause a Denial of Service in the airdrops as during the claim "voting power" is burnt. If the voting factor is increased contracts would try to burn more tokens than what they were minted in the first place, reverting and blocking the airdrops.

Vulnerability Detail

Setting a new Vote Factor through a setVoteFactor() call could cause a Denial of Service in the airdrops as during the claim "voting power" is burnt:
AdvanceDistributor contract:

  function _executeClaim(
    address beneficiary,
    uint256 totalAmount
  ) internal virtual override returns (uint256 _claimed) {
    _claimed = super._executeClaim(beneficiary, totalAmount);

    // reduce voting power through ERC20Votes extension
    _burn(beneficiary, tokensToVotes(_claimed));
  }
  function tokensToVotes(uint256 tokenAmount) private view returns (uint256) {
    return (tokenAmount * voteFactor) / fractionDenominator;
  }

If the voting factor is increased contracts would try to burn more tokens than what they were minted in the first place, reverting and blocking the airdrops.

For example, based in the following tranches:

Tranche[] memory _tranches = new Tranche[](3);
_tranches[0].time = uint128(block.timestamp + 2 weeks);
_tranches[0].vestedFraction = 2000;
_tranches[1].time = uint128(block.timestamp + 4 weeks);
_tranches[1].vestedFraction = 5000;
_tranches[2].time = uint128(block.timestamp + 8 weeks);
_tranches[2].vestedFraction = 10000;

After the week 4, user has claimed 50% of the tokens. Owner calls contract_CrosschainTrancheVestingMerkle.setVoteFactor(30000);. (Previous vote factor was 20000).

Then after week 8, user tries to claim his remaining vested tokens but it reverts:

User1 calls -> contract_CrosschainTrancheVestingMerkle(user1_merkle, user1_amount, user1_proof)) [staticcall]
    │   └─ ← ()
    ├─ [6449] CrosschainTrancheVestingMerkle::claimByMerkleProof(0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC, 1000000000000000000000, [0xf5b0a8ab36ea660fc49be7b652379674f63c6f27ff3ff540ef241d665d5f4c43])       
    │   └─ ← "ERC20: burn amount exceeds balance"
    └─ ← "ERC20: burn amount exceeds balance"

Impact

Airdrops would be blocked. Users would not be able to claim.

Code Snippet

Tool used

Manual Review

Recommendation

Disallow setting a new voting factor after contract initialization.

Duplicate of #55

@github-actions github-actions bot added Medium A valid Medium severity issue Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label labels Jul 26, 2023
@sherlock-admin2 sherlock-admin2 changed the title Custom Chiffon Mantis - Setting a new Vote Factor through a setVoteFactor() call could cause a Denial of Service in the airdrops r0bert - Setting a new Vote Factor through a setVoteFactor() call could cause a Denial of Service in the airdrops Aug 6, 2023
@sherlock-admin2 sherlock-admin2 added the Reward A payout will be made for this issue label Aug 6, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label Medium A valid Medium severity issue Reward A payout will be made for this issue
Projects
None yet
Development

No branches or pull requests

1 participant