[ARFC] Repay Excess CRV Debt on Ethereum v2

Hi @float, thanks for the question. This proposal had a number of steps and each was significantly complex. It is important that we allowed enough time for contracts to be developed, peer-reviewed internally, and peer-reviewed by BGD. It is not in Aave’s best interest to compromise on security for the sake of speed. As Marc said, AIP-146 was executed successfully yesterday: the contract allowed the acquisition of 2.7m units of CRV within 15 hours, clearing the remaining excess debt on Aave V2. Having said that, we agree we could have communicated more during this period and hope to clarify things here.

November 23, 2022: Along with Gauntlet, we co-authored an initial discussion for how Aave could repay excess debt in the CRV market [1]. At this point, we noted there were 2 options forward:

  1. Repay the debt using the Safety Module
  2. Repay the debt using the Aave V2 Collector Contract

Given the size of the debt and technical complexity involved with option 1, we recommended the DAO repay the debt using the Collector Contract. At this point, we allowed the community to weigh in and simultaneously began preparing a plan for repaying the debt from the Collector Contract, as well as coordinating with Gauntlet on the logistics of the insolvency refund.

November 30, 2022: We shared more details about CRV repayment using Aave’s V2 Collector Contract [2]. We recommended that the community retain existing CRV holdings due to their strategic value and acquire enough CRV in the market with USDC from the treasury to offset excess debt. As this would result in an outflow of USDC, we also outlined plans to consolidate long-tail holdings in order to offset this USDC outflow. We shared more information about this plan here [3].

While we present recommendations to the DAO, ultimately we will follow the community’s decision regarding the treasury and protocol. While most of the community agreed with our approach to acquire more CRV rather than using Aave’s existing aCRV (which would only have offset a portion of the excess debt), a significant portion of the community also favored using existing aCRV holdings. We decided to allow some time for debate on the forum, after which we posted an ARFC with more details on our proposed solution.

December 8, 2022: We published an ARFC [4] with more technical and financial details on how Aave could repay the bad debt. As there was still no overwhelming community sentiment, we then presented a Snapshot to allow the community to decide on the best course of action.

December 12-16, 2022: A Snapshot [5] was run to determine the best path forward. The DAO ultimately voted to use USDC to acquire CRV rather than using existing aCRV + USDC to acquire CRV (66% to 34%). At this point, we began working on developing the proposal payload. In parallel, we also began work on consolidating the Collector Contract in order to offset any outflows in USDC.

December 16, 2023 - January 5, 2023: Internal Development. This was a complex proposal that involved multiple steps and sophisticated contracts, rather than a simple transfer/approval. We did have several Aave related proposal payloads in the timeline, but prioritized development on this one. In order to ensure everything was working as intended, we also had to write a comprehensive test suite along with integration testing with Aave governance against a forked instance of mainnet to ensure code coverage for all scenarios.

Contracts involved:

CRV Bad Debt Repayment Contract: This was the most sophisticated contract as part of this proposal with multiple moving parts, external system dependencies and validations:

  1. function purchase(uint256 _amountIn, bool _toUnderlying) external returns (uint256) that allows a user to purchase USDC/aUSDC using CRV. The user receives a 10 bps premium for doing so. The first parameter is the amount of CRV they are sending in uint256 _amountIn and the second parameter bool _toUnderlying is for the user to choose whether to receive USDC (true) or aUSDC (false).
  2. function availableCRVToBeFilled() public view returns (uint256) informs the user on how much CRV is left to be sold to this contract. Users should call this view function before calling purchase to know how much CRV there’s available to sell through this contract.
  3. function availableAUSDCToBeSold() public view returns (uint256) informs the user how much USDC/aUSDC is left to be purchased through this contract. User should call this function prior to calling purchase to see how much USDC is left to be purchased.
  4. function getAmountOut(uint256 amountIn) public view returns (uint256) informs the user how much USDC/aUSDC they are going to get from their purchase, with the 10bps premium included.
  5. function getOraclePrice() public view returns (uint256) informs the user the current CRV price, per the specified Chainlink Oracle. It also includes logic to throw an error if price crosses the MAX_ORACLE_PRICE that this contract is willing to purchase CRV at.
  6. function repay() external returns (uint256) that sends the CRV balance of the Aave v2 Collector contract to the AAVE V2 pool to repay the bad debt generated by address 0x57E04786E231Af3343562C062E0d058F25daCE9E.
  7. function rescueTokens(address[] calldata tokens) external This is a rescue function that can be called by anyone to transfer any tokens accidentally sent to this contract to the Aave v2 Collector contract.
  8. uint256 public totalCRVReceived The amount of CRV received by the contract.
  9. uint256 public totalAUSDCSold The amount of USDC/aUSDC sold by the contract.

Proposal Payload: This payload did 3 distinct actions:

  1. Converted the existing USDC balance within the Aave v2 Collector contract to aUSDC so that it was not sitting idle in the treasury.
  2. Approved the CRV Bad Debt Repayment Contract to spend up to the aUSDC Cap defined in the CRV Bad Debt Repayment Contract from the Aave v2 Collector contract. This was required to enable the CRV purchase
  3. Approved the CRV Bad Debt Repayment Contract to spend up to the CRV Cap defined in the CRV Bad Debt Repayment Contract from the Aave v2 Collector contract. This was required to pay back the CRV bad debt on behalf of Aave.

January 5, 2023 - January 9, 2023: Internal Review. There were a couple of things that were caught in internal review and fixed during this time:

  1. Ensuring that the CRV Bad Debt Repayment Contract held no custody of CRV and aUSDC/USDC as part of the swap and instead have it custodied in the Aave v2 Collector contract
  2. Some fixes related to precision math
  3. Ensuring to deposit the idle USDC within the Aave v2 Collector contract to aUSDC as part of the Proposal Payload.
  4. More extensive tests to ensure all scenarios are covered.

January 10, 2023: Proposal payload sent to BGD for external review.

January 10, 2023 - January 13, 2023: BGD external review. We received the following feedback during this external review which we went ahead and implemented:

  1. Extend interfaces for all our contracts so that it makes programmatic interaction with the contracts more convenient.
  2. Allow calling repay() whenever there is some CRV for repayment (instead of waiting for the entire CRV Cap to be filled) so that the debt can be repaid over time.
  3. Define a MAX_ORACLE_PRICE so that the purchase is within budget and not depleted if CRV price goes up beyond that threshold.
  4. More extensive tests to ensure all scenarios are covered.

January 13, 2023 (Friday): Due to generally lower voter turnout on weekends (multiple proposals have failed after being put up for a vote on weekends), we opted to wait until Monday. At this point, CRV was also nearing the price cap set in the contract.

January 16, 2023 (Monday): By this point, the price of CRV had exceeded the earlier approved budget. As Aave’s governance process did not make it clear whether another Snapshot vote needed to be run or not, we decided to publish a comment on the forum [6] outlining the potential options.

January 17, 2023: We updated the threshold of USDC/aUSDC that could be spent by the DAO from $2,000,000 to $3,105,000 (CRV price from $0.75 to $1.15).

January 20, 2023: Proposal published on-chain [7].

January 25, 2023: Proposal executed on-chain. 2.7m CRV acquired and cleared remaining excess debt on Aave V2 in roughly 15 hours and ~12 transactions ahead of the V3 launch.

We can’t control market prices; what’s in our control is coordinating with different stakeholders, working on a secure payload, and shipping it in a timely fashion.

We are working to increase transparency on the timeline of our active proposals so the community can more easily see where proposals are in development.

4 Likes