veRWA - ADM'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: 43/125

Findings: 1

Award: $41.17

🌟 Selected for report: 1

🚀 Solo Findings: 0

Awards

41.1665 USDC - $41.17

Labels

bug
3 (High Risk)
primary issue
satisfactory
selected for report
upgraded by judge
H-06

External Links

Lines of code

https://github.com/code-423n4/2023-08-verwa/blob/9a2e7be003bc1a77b3b87db31f3d5a1bcb48ed32/src/VotingEscrow.sol#L356-L387

Vulnerability details

Impact

Due to a check requiring users only be able to delegate to others or themselves with longer lock times and verwa's restrictions of all changes increasing lock times by 5 years users may be forced to remain delegated to someone they do not wish to be or extend their lock much longer than they wish.

Proof of Concept

If a user does not delegate to another user who started their lock during the same epoch they will be unable to undelegate back to themselves without extending their own lock. This is not much of an issue if they wish to do so early in the lock period but can become a problem if they wish to delegate to themselves after a longer period of time. i.e.

  1. Bob creates lock in week 1.
  2. Dave create lock in week 2 & Bob delegates to Dave.
  3. 3 years pass and Bob decides he wishes to undelegate his votes back to himself and calls delegate(msg.sender) but the call will fail due to the check in VotingEscrow#L384:
require(toLocked.end >= fromLocked.end, "Only delegate to longer lock");
  1. In the original FiatDAO contracts a user would be able to just extend their lock by one week to get around this however any changes in the verwa contract results in an extension of 5 years which the user may not want extend their lock by such a long time just to be able to undelegate.

The undelegate fail can be shown by modifying the test testSuccessDelegate to:

    function testSuccessDelegate() public {
        // successful delegate
        testSuccessCreateLock();
        vm.warp(8 days); // warp more than 1 week so both users are not locking in same epoch
        vm.prank(user2);
        ve.createLock{value: LOCK_AMT}(LOCK_AMT);
        vm.prank(user1);
        ve.delegate(user2);
        (, , , address delegatee) = ve.locked(user1);
        assertEq(delegatee, user2);
        (, , int128 delegated, ) = ve.locked(user2);
        assertEq(delegated, 2000000000000000000);
    }

and running: forge test --match testSuccessUnDelegate

Tools Used

Manual Review

Modify VotingEscrow#L384 to:

require(toLocked.end >= locked_.end, "Only delegate to self or longer lock");

which will allow users to delegate either to longer locks or undelegate back to themselves.

Assessed type

Timing

#0 - c4-pre-sort

2023-08-12T11:12:27Z

141345 marked the issue as duplicate of #178

#1 - c4-judge

2023-08-24T07:13:58Z

alcueca marked the issue as duplicate of #82

#2 - c4-judge

2023-08-24T07:20:31Z

alcueca changed the severity to 3 (High Risk)

#3 - c4-judge

2023-08-24T07:20:40Z

alcueca changed the severity to 2 (Med Risk)

#4 - c4-judge

2023-08-24T07:37:55Z

alcueca marked the issue as satisfactory

#5 - c4-judge

2023-08-24T21:19:56Z

alcueca marked the issue as selected for report

#6 - c4-judge

2023-08-29T06:37:38Z

alcueca changed the severity to 3 (High Risk)

#7 - alcueca

2023-08-29T06:40:03Z

I'm merging #245 into this one as the root cause and general mechanics are the same, only that in the 245 group the intent was malicious and in this group is not.

At the same time, I'm upgrading the severity to High. Locking CANTO for an additional 5 years, considering that this is by nature a volatile environment, has an extremely high chance of resulting in losses due to market movements or other factors.

#8 - JeffCX

2023-08-29T11:41:21Z

Emmm please corrrect if I am wrong but this report seems saying delegating for 5 years is too long and if the user want to change his mind within 5 years he cannot do it

but this is considered as known issue and should be marked as out of scope

https://github.com/code-423n4/2023-08-verwa/tree/main#automated-findings--publicly-known-issues

Checkpoint is called at least once in five years: Curve and FIAT DAO have the assumption that the VotingEscrow._checkpoint function is called at least once in a five year period. Because we use the same contracts, we also inherit this assumption.

#9 - OpenCoreCH

2023-09-01T09:56:55Z

#10 - alcueca

2023-09-29T15:01:09Z

Emmm please corrrect if I am wrong but this report seems saying delegating for 5 years is too long and if the user want to change his mind within 5 years he cannot do it

@JeffCX, locking is for 5 years minimum, but delegation should be able to be revoked anytime. In some cases, to undelegate, users are forced to lock their canto for 5 additional years.

#11 - JeffCX

2023-09-29T15:52:55Z

Emmm please corrrect if I am wrong but this report seems saying delegating for 5 years is too long and if the user want to change his mind within 5 years he cannot do it

@JeffCX, locking is for 5 years minimum, but delegation should be able to be revoked anytime. In some cases, to undelegate, users are forced to lock their canto for 5 additional years.

Srrry yeah I agree!

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