Venus Prime - squeaky_cactus's results

Earn, borrow & lend on the #1 Decentralized Money Market on the BNB chain.

General Information

Platform: Code4rena

Start Date: 28/09/2023

Pot Size: $36,500 USDC

Total HM: 5

Participants: 115

Period: 6 days

Judge: 0xDjango

Total Solo HM: 1

Id: 290

League: ETH

Venus Protocol

Findings Distribution

Researcher Performance

Rank: 87/115

Findings: 1

Award: $4.37

QA:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Lines of code

https://github.com/code-423n4/2023-09-venus/blob/b11d9ef9db8237678567e66759003138f2368d23/contracts/Tokens/Prime/Prime.sol#L349-L357

Vulnerability details

Impact

When performing the bulk issuing of revocable Prime tokens, if a member of the address set already has a Prime token, the transaction reverts rather than gracefully handling to allow the other members of the set to receive their tokens.

A new transaction without the offending address in the set must be submitted, which is an inconvenience in both time and cost, compounded if there's also governance aspect surrounding the update.

Description

Prime.issue directly issues of either Irrevocable or revocable Prime tokens to a list of addresses.

Only after a user has their Prime token minted do they accrue interest, providing a financial incentive to claim their token as soon as possible.

Prime.issue contains access control, meaning it may be invoked via governance process, usually a larger time delay than a centralised admin.

When a Prime token is minted, if the address already possesses one then the custom error IneligibleToClaim is thrown.

Prime.issue of revocable assumes none of the given addresses already possess a Prime token.

Proof of Concept

Add the below test to the mint and burn describe in tests/hardhat/integration/index.ts and you have the issue failing with the custom error IneligibleToClaim in _mint:

it("bulk issue grief for revocable Prime token", async () => { const userOneAddress = user1.getAddress(); const userTwoAddress = user2.getAddress(); expect((await prime.tokens(userOneAddress)).exists).to.be.false; expect((await prime.tokens(userTwoAddress)).exists).to.be.false; // User1 stakes then claims their revocable Prime token await xvs.connect(user1).approve(xvsVault.address, bigNumber18.mul(10000)); await xvsVault.connect(user1).deposit(xvs.address, 0, bigNumber18.mul(10000)); await prime.stakedAt(userOneAddress); await mine(90 * 24 * 60 * 60); await prime.connect(user1).claim() expect((await prime.tokens(userOneAddress)).exists).to.be.true; // Transaction reverts (i.e. no tokens issued) as user1 already has a revocable token await expect(prime.issue(false, [userOneAddress, userTwoAddress])).to.be.revertedWithCustomError(prime, "IneligibleToClaim"); })

Tools Used

Webstorm

Update the code to check whether the address already possesses a Prime token, if true then skips over as they have already been issued one, by some mechanism.

Prime.sol#L350 + if(!tokens[users[i]].exists) {_mint(false, users[i]);} - _mint(false, users[i]);

Assessed type

Invalid Validation

#0 - 0xRobocop

2023-10-06T23:52:27Z

See #187

#1 - c4-pre-sort

2023-10-06T23:52:31Z

0xRobocop marked the issue as low quality report

#2 - c4-judge

2023-11-01T20:11:41Z

fatherGoose1 marked the issue as unsatisfactory: Invalid

#3 - c4-judge

2023-11-01T20:12:36Z

fatherGoose1 changed the severity to QA (Quality Assurance)

#4 - fatherGoose1

2023-11-01T20:13:21Z

QA. The griefing is easily remedied by passing a critical governance proposal. The griefer will have made little impact after having to have staked for >90 days.

#5 - c4-judge

2023-11-03T02:07:09Z

fatherGoose1 marked the issue as grade-b

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