Ante Test failure investigation: TVL plunge test

Ante
Ante Labs

--

Before we get into the investigation: Ribbon’s TVL is at normal levels and funds in their vaults are unaffected.

Due to Ante v0.5 treating test reversions as failures, a missed edge case caused the Ante Test checking Ribbon vault balances to fail, resulting in funds staked in the test being paid out to test challengers.

We informed the Ribbon team immediately and began working on an updated version of the test with the edge case removed, which is now staked here.

So why did the test fail?

Missed check in the Ante Test

To recap, each Ante Test contains a checkTestPasses function that contains the main test logic. The Ribbon TVL test has:

AnteRibbonV2ThetaVaultPlungeTest.sol, lines 65–73

If any of the tested Theta Vault balances drop below its corresponding failure threshold, the test fails. Pretty straightforward so far! What about calculateAssetBalance?

AnteRibbonV2ThetaVaultPlungeTest.sol, lines 49–60

Funds deposited in Ribbon Theta Vaults can be in one of two locations: the Ribbon vault itself, or Opyn. Summing the two balances should give a true picture of total Ribbon vault assets. Indeed, this is how the Ribbon vault’s own totalBalance function works.

Each week, Ribbon closes out its Opyn position in closeRound and opens a new position in rollToNextOption. During this window (~1.5 hrs), 100% of funds live in the Ribbon vault.

One might assume that during this time, opynVault.collateralAmounts[0] would return the value 0.

[delegatecall][15796][Controller].getVault(
_owner=[Ribbon Finance: ETH Covered Call V2],
_vaultId=63
) → ((
shortOtokens=[],
longOtokens=[],
collateralAssets=[],
shortAmounts=[],
longAmounts=[],
collateralAmounts=[]
))

Uh-oh.

It turns out that when the Opyn vault is settled, it doesn’t just zero out the collateral amounts, it straight-up deletes it. You can follow the call trace here:

  1. RibbonThetaVaultWithSwap.closeRoundVaultLifecycleWithSwap.settleShortController.operate_runActions on ActionType.SettleVault
  2. This calls _settleVault, which includes the line delete vaults[_args.owner][_args.vaultId];, clearing out the collateralAssets array

Any time the test tries to access opynVault.collateralAsset[0] during an Opyn vault change, it will revert with panic code 0x32(array accessed at an out-of-bounds or negative index).

If otherwise unchecked, this revert would typically bubble back up to the Ante Pool and revert the checkTest transaction. But Ante Pool doesn’t ignore reversions.

Test reversions treated as failures

In Ante v0.5, Ante Pools treat test reversions as failures.

AntePool.sol, lines 567–573

This design choice was made in Ante v0.5 to guard against attacks such as block stuffing that could be used to prevent a test from failing.

However, the tradeoff is that if a test could be made to revert, an attacker could trigger test failure. Ante v0.5's audits noted this possibility in the form of a 63/64 gas forwarding attack. While none of the current live tests are believed to be vulnerable to the gas forwarding exploit, a flawed test that reverts could still trigger false test failure as it did with the Ribbon test.

When the challenger checked the test during the the short period each week (<1% of the time) where the test would revert, the test was treated as having failed and the payout triggered.

Resolving the revert edge case

The updated Ribbon Theta Vault TVL Plunge Ante Test makes several changes. First, the test checks that collateralAssets is not empty and ignores it if it is, avoiding the revert scenario.

The updated test was tested on a mainnet fork against the historical blocks where the previous test failed and successfully avoided test reversion, confirming the edge case was removed.

Making the test reflect current vaults

At the time the original test was written, there were only two V2 Theta Vaults (ETH and WBTC covered calls). When adding the additional Theta Vaults that had been introduced since then to the test, the original method of determining vault asset using vaultParams no longer worked for all potential Theta Vaults.

No on-chain reference was 100% reliable for determining vault asset

Thus, the updated test also stores the vault asset so that it can be referenced reliably under the assumption that each Ribbon vault’s collateral asset will not change (valid under the current implementation of the vaults).

The stETH vault, in particular, uses a different balance calculation formula due to being able to take user deposits in WETH and stETH but depositing wstETH in Opyn, as well as stETH and wstETH having a variable exchange rate. To accommodate the stETH vault, the updated test supports multiple vault assets and includes a conversion check for wstETH. Here’s what the final calculateVaultBalance looks like:

Future proofing the test

In addition to the technical fixes, the updated test also allows an admin to add new vaults to test as well as sunset deprecated vaults. This can prolong the test’s life by allowing it to continue reflecting the actual portfolio of Ribbon Theta Vaults. However, doing so responsibly would require maintenance by a trusted individual/entity. The updated test will still work as intended on its current set of vaults without maintenance.

As the various vault intricacies have shown, additional future proofing could also be done by having a standard way to safely measure TVL on-chain. Ante community members are currently discussing various ways to prototype standardized TVL “oracles” that builders could reference.

The path forward

The updated Ribbon Theta Vault Test is live: check it out here! Special thanks to Zellic and the Ribbon team for reviewing the updated test.

In Ante v0.6 (in audit), test reversions are NOT treated as failures, eliminating false test failures due to reversion.

Ante Tests provide the flexibility to encode elements of trust and make them available on-chain so that others can build upon them in a decentralized way. Decentralized trust ratings are still in their early stages, but thanks to the Ribbon team and community for being an early partner in pioneering this new form of on-chain trust signaling!

--

--

Ante
Ante Labs

Building a Smart Tests Community for @AnteFinance