veRWA - qpzm's results

Incentivization Primitive for Real World Assets on Canto

General Information

Platform: Code4rena

Start Date: 07/08/2023

Pot Size: $36,500 USDC

Total HM: 11

Participants: 125

Period: 3 days

Judge: alcueca

Total Solo HM: 4

Id: 274

League: ETH

Canto

Findings Distribution

Researcher Performance

Rank: 42/125

Findings: 1

Award: $43.21

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

43.2097 USDC - $43.21

Labels

bug
3 (High Risk)
satisfactory
upgraded by judge
edited-by-warden
duplicate-268

External Links

Lines of code

https://github.com/code-423n4/2023-08-verwa/blob/main/src/VotingEscrow.sol#L331 https://github.com/code-423n4/2023-08-verwa/blob/main/src/VotingEscrow.sol#L383

Vulnerability details

Impact

The delegator must extend his lock period by 5 years through increaseAmount and undelegate. After 5 years, he can finally withdraw. It is desirable that the delegator can withdraw when both locks expire.

Proof of Concept

Add the test in VotingEscrow.t.sol and run forge test --mt testDelegateExpired. I left comments to explain.

function testDelegateExpired() public {
    testSuccessCreateLock();
    (, uint256 end, , ) = ve.locked(user1);

    vm.prank(user2);
    ve.createLock{value: LOCK_AMT}(LOCK_AMT);

    // @audit user1 delegates to user2
    vm.prank(user1);
    ve.delegate(user2);

    int128 delegated;
    (, end, delegated, ) = ve.locked(user1);
    (, , delegated, ) = ve.locked(user2);
    assertEq(delegated, 2000000000000000000);

    // @audit delegatee user2 withdraws after his lock expires
    (, uint256 end2, , ) = ve.locked(user2);
    vm.warp(end2 + 1);
    vm.prank(user2);
    ve.withdraw();

    // @audit delegator user1 cannot undelegate and withdraw
    vm.prank(user1);
    vm.expectRevert("Delegatee lock expired");
    ve.delegate(user1);
    vm.prank(user1);
    ve.withdraw();
}

Tools Used

Foundry

Skip toLocked.end > block.timestamp check when the msg.sender undelegates. This passes the test above.

function delegate(address _addr)
    external
    override
    nonReentrant
{
    // ...

    // @audit Skip toLocked.end > block.timestamp check when undelegating.
-    require(toLocked.end > block.timestamp, "Delegatee lock expired");
+    require(_addr == msg.sender || toLocked.end > block.timestamp, "Delegatee lock expired");
    
    // ...
}

https://github.com/code-423n4/2023-08-verwa/blob/main/src/VotingEscrow.sol#L383

Assessed type

Other

#0 - c4-pre-sort

2023-08-11T11:57:11Z

141345 marked the issue as duplicate of #223

#1 - c4-pre-sort

2023-08-13T12:00:43Z

141345 marked the issue as duplicate of #112

#2 - c4-judge

2023-08-24T07:16:12Z

alcueca marked the issue as duplicate of #82

#3 - c4-judge

2023-08-24T07:20:40Z

alcueca changed the severity to 2 (Med Risk)

#4 - c4-judge

2023-08-24T07:29:17Z

alcueca marked the issue as satisfactory

#5 - c4-pre-sort

2023-08-24T08:20:08Z

141345 marked the issue as not a duplicate

#6 - c4-pre-sort

2023-08-24T08:20:26Z

141345 marked the issue as not a duplicate

#7 - c4-pre-sort

2023-08-24T08:22:54Z

141345 marked the issue as duplicate of #211

#8 - c4-judge

2023-08-26T21:24:30Z

alcueca changed the severity to 3 (High Risk)

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