AMPL problem on Aave v2 Ethereum

Adjusted Proposal

Summary

The following analysis from BGD Labs and Chaos Labs dives into the technical aspects of aAMPL post-mortem and highlights an updated, impartial distribution methodology stemming from the root issue.

1. aAMPL Problem Description

The root cause of the problem on the AMPL reserve is a misuse of the custom aAMPL implementation of the supply and borrow indexes as if they would be the same value.

The following is a more detailed analysis of it.

Analysis

By design, the aAMPL total supply should return the AMPL available liquidity (non-borrowed) plus the total AMPL borrowed with interest (ampl-aave/contracts/protocol/tokenization/ampl/AAmplToken.sol at master · ampleforth/ampl-aave · GitHub). The available liquidity will be rebasing and increasing the total supply up and down accordingly, while the total borrowed will not, and will only increase from interest.

However, on the implementation of the _scaledTotalSupply() function, this “virtual” balance doesn’t really represent what it intends to. To understand how the incorrect calculation on the _scaledTotalSupply() is caused, we need to analyze how the code on aAMPLToken.totalSupply() differed from the formula intended: totalSupply = AMPL.balanceOf(aAMPLToken) + AmplVariableDebtToken.totalSupply()


aAMPLToken.totalSupply() depends totally on the _scaledTotalSupply() function and is also proportional to the balanceOf() of users: the sum of all user balances is equivalent to the total supply.

Let’s take a look at the implementation of the _scaledTotalSupply() function (https://github.com/ampleforth/ampl-aave/blob/master/contracts/protocol/tokenization/ampl/AAmplToken.sol#L640-L644).

function scaledTotalSupply() public view virtual override returns (uint256) {
  return _scaledTotalSupply(_fetchExtData(), _totalGonsDeposited);
}

With _fetchExtData() (ampl-aave/contracts/protocol/tokenization/ampl/AAmplToken.sol at master · ampleforth/ampl-aave · GitHub) getting data from the borrow tokens side, from this function

function getAMPLBorrowData() external view returns (uint256, int256) {
  return (super.totalSupply(), _totalGonsBorrowed);
}

For the sake of this analysis, we will look closely on two variables: _totalGonsDeposited accounted for on the aToken, and _totalGonsBorrowed , accounted for on the vToken, but received on aToken from the chain of calls getAMPLBorrowData()_fetchExtData() , and passed to _scaledTotalSupply().

These variables are calculated the following way on the respective mint() functions on aToken and vToken.

aToken

_totalGonsDeposited = _totalGonsDeposited.add(
  _amplToGons(e.totalAMPLSupply, amountScaled).toInt256Safe()
);

In this case, amountScaled uses internally the liquidity index of AMPL, which is a variable belonging completely to the supply side. It also uses the AMPL supply, submitted to rebases, but that is not meaningful to see the core of the problem.

vToken

_totalGonsBorrowed = _totalGonsBorrowed.add(
  amountScaled.mul(GONS_TOTAL_SUPPLY).div(fetchAMPLTotalSupply()).toInt256Safe()
);

Here, amountScaled uses internally the borrow index of AMPL, which is a variable belonging completely to the borrow side. Same as on the supply side, other components like the AMPL supply are used.

Now, going to how they are used on _scaledTotalSupply()

function _scaledTotalSupply(ExtData memory e, int256 totalGonsDeposited) private pure returns (uint256) {
  // require(totalGonsDeposited>=e.totalGonsBorrowed);
  return _gonsToAMPL(e.totalAMPLSupply, uint256(totalGonsDeposited.sub(e.totalGonsBorrowed)))
    .add(e.totalPrincipalBorrowed);
}

The key component to look here is uint256(totalGonsDeposited.sub(e.totalGonsBorrowed). There is something extremely evident after checking the 2 variables involved: totalGonsDeposited and totalGonsBorrowed are dependent on the supply index and borrow index respectively, as we just mentioned, two completely separate variables. However, the logic is subtracting one from the other. It is simply wrong to add/subtract two variables in factually different dimensions to derive another one.

As the total supply of aAMPL and the balanceOf() for each user uses _scaledTotalSupply() , which does that wrong subtraction, the calculation on both are simply wrong due to this.

In practice, the inflation of aAMPL supply and balances got only magnified during 2023 (post-freezing of AMPL happened end of 2022) because of the high utilization, which increased the difference over time of the borrow index and the supply index, and with it, the inherent error inflating the aToken supply.

2. Adjusted Distribution Analysis

Summary

Amend aAMPL compensation framework to provide more equitable terms for current holders.

Motivation

In our efforts to enhance overall welfare and equitably address the standing of existing aAMPL holders, we propose a modification to our initial proposal. This adjustment effectively removes the Aave Collector from the equation entirely, opting instead to utilize the liquidity index for the interest component rather than the borrow rate over time. Initially, the inclusion of the borrow rate was crucial as we aimed to ascertain the precise AMPL value per aAMPL, necessitating an assessment of all aAMPL in circulation, including the Aave Collector. However, with this modification, we focus solely on modeling the returns of the underlying users, under the assumption that the collector never obtained aAMPL to begin with. This adjustment aims to significantly enhance claims per aAMPL by artificially reducing the incorrect deviation of aAMPL from the correct returns due to inaccurate rebasing, while simultaneously increasing the relative interest accrual.

Simultaneously, we have heightened the frequency of snapshots taken to evaluate aAMPL market activity to approximately every 2.5 hours, compared to our initial analysis which relied on daily snapshots to align with the daily rebases. At a high level, these adjustments serve two primary purposes, leading to a greater payout per aAMPL in circulation:

  1. It mitigates the exponential deviation between correct and incorrect values. By disregarding the interest accrued to the collector and opting for the liquidity rate, the cumulative rate decreases. Consequently, any incorrectly applied positive rebases accumulate on a smaller principal over time.
  2. The adjustment of the reserve factor to 99%, as outlined here, contributed to the market deprecation, occurring about two months before the decrease in interest rates. By utilizing the liquidity rate, we implement the pure liquidity rate adjustment at 256% APR (1193% APY) for the adjusted correct aAMPL returns from December 16th, 2023 (the date of the reserve factor adjustment), rather than February 7th, 2024.

Quantification

Initial Cumulative Aave AMPL Returns Since Freeze Until Date of 99% RF

The plots below depict the adjusted cumulative returns for both the incorrect aAMPL returns and the expected correct aAMPL returns, incorporating our adjustments up to the date when the reserve factor transitioned from 20% to 99%.

By dividing the correct aAMPL returns by the current incorrect aAMPL returns, we establish the effective claim per aAMPL in circulation at the time of the freeze to be 46%. With an aAMPL circulating supply of 764,303 on that day, this amounts to 351,579 AMPL.

Liquidity Index Adjustment

In our ongoing efforts to ensure fair compensation for users impacted by recent events, we have introduced a continuously compounding liquidity index to account for the opportunity cost experienced since the date of freezing. This index reflects the interest that borrowers would have accrued due to significant rebases, assuming a consistent reserve factor and borrow rate at 100% utilization.

With a continuously compounding liquidity rate of 256% APR from December 16th, 2023 to the present day, the value of aAMPL claims surges by 136%. In addition, we propose including an extra number of days’ worth of interest accrual to account for the exact timing of the distribution proposals’ creation, increasing the 136% value to 140-150%, depending on the precise day of creation. This adjustment significantly enhances the terms for victims, with the total cumulative value of claims set at greater than 351,579 * 2.36 = 829,726 AMPL. Additionally, despite the recent crash in AMPL price, we maintain our initially proposed AMPL price of 1.198 per AMPL, equivalent to >$994,012 in dollar terms. This represents a substantial 54% increase from the initial proposal value, during an overall downturn in AMPL price and rebases, aiming to provide equitable compensation to those affected.

Simulating Since Market Inception

For users seeking a simulation of returns since the market’s inception on July 24th, 2021, quantifying respective returns yields a notably subpar outcome in the context of aAMPL to AMPL claims. This discrepancy primarily stems from the prevalence of negative rebases and the market’s efficiency prior to the freeze. During this period, sophisticated borrowers often capitalized on positive rebases, leaving suppliers with negative ones, given the relatively smaller effective daily interest rate. Crucially, this extractive activity did not occur as a result of any systemic bug. Instead, it stemmed from the transparent on-chain configuration of the system and its inherent economic principles.

image

This was initially illustrated above, but can also be observed on a different axis by plotting AMPL rebases against a given utilization rate until the market freeze.

image

Conclusion

We firmly believe that the quantification surrounding the compensation plan should accurately reflect the intended payoff of supplying AMPL into the Aave market, rather than erroneously compensating users with an extra premium as if they were completely detached from the Aave aAMPL custom implementation. We want to reiterate that the current aAMPL supply is nothing but virtual at the moment, and is simply utilized to derive the underlying claims per virtual aAMPL. Alternatively, the proposed plan offers numerous additional subsidies for current holders, including:

  • An additional four months of historically high liquidity rates (1193% APY) for suppliers as a time-based subsidy. This extension follows adjustments such as decreasing rates and increasing reserve factors aimed at phasing out a legacy implementation of the protocol, a substantial one and a half years after the market freeze.
  • Maintaining the previously defined $1.198 price per AMPL, despite the price falling below and negative rebases accruing on the aAMPL supply since.
  • Assuming returns started accruing at the date of the freeze, disregarding the highly extractive economic activity that occurred while the market was live.

Specification

Based on the initial pro-rata distribution of $300K, the proposed implementation results in an additional >$694K being distributed to affected users. This distribution employs the same methodology as the initial distribution, utilizing snapshot balances. For example, a user who held 20% of the total aAMPL supply on the snapshot day of the initial distribution would receive 20% of the extra >$694K, on top of what was already received in the initial distribution. Cases like Mooniswap will be handled on a case-by-case basis to ensure fair compensation for those users as well.

Next steps

Similar to any other governance proposal of a technical nature, this procedure will require the following 2 steps

  1. This ARFC proposal is to be voted on Snapshot, and the on-chain AIP factually starts the distribution. The ARFC will be created on Wednesday 24 Apr, to leave some time for discussion before.
  2. If the previous Snapshot passes, the estimation for the creation of the on-chain AIP (starting distribution) is approximately Saturday-Sunday 27-28 Apr. Any delay will be properly disclosed in advance.

We appreciate feedback from the community.

Disclaimer

This proposal is created by Chaos Labs and BGD Labs as part of our respective service provider agreements with the Aave DAO, due to the highly technical nature of the problem and remediation.

Copyright

Copyright and related rights waived under CC0.

2 Likes