veRWA - rjs'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: 12/125

Findings: 2

Award: $314.08

QA:
grade-a
Analysis:
grade-a

🌟 Selected for report: 0

🚀 Solo Findings: 0

[01] Lack of events is error prone

Description Events are used by users and other systems to reliably detect protocol state for integration, market information and exploit detection purposes.

There are some critical operations that do not emit events:

Recommendation Implement the listed events to improve contract transparency.

[02] Lack of documentation is error prone

Description While much of the code is based on well-established protocols, the various modifications and specializations would benefit from clear documentation about the broader context, types of users, interactions with and between contracts, arithmetic properties and access controls. The lack of documentation makes the protocol difficult to review.

Recommendation Fully document the solution

[03] No incentive to vote early in GaugeController

Description This issue was identified in the original Curve Finance audit, finding ID TOB-CURVE-DAO-017. It remains unresolved in the mkt.market implementation.

GaugeController voting offers no incentive to vote early, so late-voting users have a benefit over early voters.

Given that votes are public, earlier voters reveal information to other voters. An unethical voter could wait until the last moment to vote, and calculate the minimal effective vote. Effectively, earlier voters have to use more power for the same effect as last-minute voters.

Recommendation Consider using a decreasing vote weight to compensate early voters for revealing their intentions, or use a blind voting protocol.

[04] Inconsistent use of user and gauge in tests

Scope: While the tests are out of scope for the audit, the test still effectively form part of the documentation for the project.

The tests setup 2 test user and gauge addresses each:

/home/rjs/Desktop/code-423n4/2023-08-verwa/src/test/GaugeController.t.sol:27
27:         users = utils.createUsers(5);
28:         (gov, user1, user2, gauge1, gauge2) = (users[0], users[1], users[2], users[3], users[4]);

But the test code mixes the usage of addresses, which makes it difficult to understand the intention behind the test.

For example, in the below test, user1's address is the gauge:

src/test/GaugeController.t.sol:34
34:     function testAddGauge() public {
35:         assertTrue(!gc.isValidGauge(user1));
36:         vm.startPrank(gov);
37:         gc.add_gauge(user1);
38:         vm.stopPrank();
39:         assertTrue(gc.isValidGauge(user1));
40:     }

Whereas in this test, user1 is the user:

src/test/GaugeController.t.sol:159
159:     function testVoteGaugeWeight50Pcnt() public {
160:         // vote_for_gauge_weights valid vote 50%
161:         // Should vote for gauge and change weights accordingly
162:         vm.startPrank(gov);
163:         gc.add_gauge(gauge1);
164:         gc.add_gauge(gauge2);
165:         gc.change_gauge_weight(gauge1, 50);
166:         gc.change_gauge_weight(gauge2, 50);
167:         vm.stopPrank();
168: 
169:         vm.startPrank(user1);
170:         ve.createLock{value: 1 ether}(1 ether);
171:         gc.vote_for_gauge_weights(gauge1, 5000); // vote 50% for gauge1
172:         gc.vote_for_gauge_weights(gauge2, 5000); // vote 50% for gauge2
173: 
174:         assertEq((gc.get_total_weight() * 5000) / 10000, gc.get_gauge_weight(gauge1));
175:     }

#0 - 141345

2023-08-13T08:04:40Z

#1 - c4-judge

2023-08-22T13:49:17Z

alcueca marked the issue as grade-a

Findings Information

Labels

analysis-advanced
grade-a
A-02

Awards

304.2648 USDC - $304.26

External Links

[01] Summary

1.1. Introduction

veRWA is a voting escrow implementation for CANTO Real World Assets. The implementation under audit covers the core GaugeController, VotingEscrow and LendingLedger contracts. The first two contracts are heavily based on Curve Finance's original Vyper implementation, while the LendingLedger is a an original piece of code.

1.2. Approach

This was a 3 day contest:

  • Day 1 (4 hours)
    • Read readme.md and drafted an audit strategy
    • Reviewed RWA & Curve documentation around Liquidity Gauges and Voting Escrow
    • Collected and reviewed audit reports from the projects in the code lineage (Curve Finance, mkt.market, mStable, FIAT DAO)
    • Reviewed tests (24)
  • Day 2 (12 hours)
    • Line-by-line review of GaugeController.sol, VotingEscrow.sol and LendingLedger.sol
    • Compared GaugeController.sol to Curve's Vyper implementation, line-by-line
    • Compared VotingEscrow.sol to FIAT DAO implementation using file diff
    • Verified the implementation against the Additional Context section of the readme.md file
    • Drafted reports
  • Day 3 (6 hours)
    • Finalised and submitted reports

1.3. Documentation

The readme.md did not link to a project documentation page. I tried to track down veCANTO and veRWA but was unable to turn up further information. RWA appears to be a generic term, and CANTO documentation doesn't appear to reference the project either . The mkt.market site didn't appear to have project information.

The code documentation did have very well-documented lineage in 2 out of 3 cases, and I was able to reference sufficient relevant documentation to audit those contracts.

1.4. Codebase

Codebase had good test coverage, and was relatively well laid out.

1.5. Mechanism Review

The mechanism here is based heavily on the Curve Finance protocol:

  • RWA Implementation: veRWA is a non-standard ERC20 token, represented by the VotingEscrow contract on the Ethereum mainnet.
  • Obtaining veRWA: veRWA cannot be transferred and is obtained by locking CANTO. The maximum lock time is five years.
  • Balance Decay: A user's veRWA balance decays linearly as the remaining time until the CANTO unlock decreases. The decay is proportional to the lock time.
  • User Voting Power: Voting power decreases linearly from the moment of lock, and changes are recorded in user_point_history.
  • Total Voting Power: Changes in total voting power are recorded in point_history, and future slope changes are scheduled in slope_changes.
  • Implementation Efficiency: The system avoids periodic check-ins and limits the end of user locks to whole weeks, making reads from the blockchain more efficient.
  • Expiration Times: All possible expiration times are rounded to whole weeks to optimize the number of reads from the blockchain.
  • Liquidity Gauges: Directs inflation to users providing liquidity, measured via individual liquidity gauges. Users deposit LP tokens into the gauge, receiving a share of minted RWA/CANTO.
  • Gauge Weight Voting: Users can allocate their veRWA towards gauges, affecting the distribution of newly minted RWA/CANTO tokens. Weight votes are applied at the start of the next epoch week.
  • The Gauge Controller: Manages the list of gauges and their types and weights, handling the linear character of voting power. Records points, scheduled changes, and per-user slopes.

[02] Architecture Recommendations

2.1. Consider adding an incentive to vote early in GaugeController

As discussed in my QA report, voting early reveals information to other voters. This effectively reduces the power of a user's vote. To compensate for this, consider implementing:

  • A decreasing vote weight, thus creating an advantage for early voters
  • A blind vote

2.2. Consider adding ability to remove whitelisted lending markets in LendingLedger

While the readme states that governance operations are always assumed to be correct, human error should always be considered in protocol design.

[03] Risks

3.1. Founder Disbursements

The recent CRV hack exposed a problem where one of the founders had used $280 million CRV as loan collateral for a $100 Real World Asset (a house), and the devaluing of the CRV used as collateral put the loan at risk of liquidation.

This would have dumped millions of CRV onto the market, and caused the price of CRV to collapse further. This would have caused liquidity providers to withdraw from Curve.

Fortunately this has not yet happened, but demonstrates the problems of large disbursements of liquidity tokens to founders in these styles of protocols.

[04] References

Time spent:

22 hours

#0 - c4-judge

2023-08-22T06:54:42Z

alcueca marked the issue as grade-a

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