Anchor Vault is a smart contract that allows to convert rebasing stETH token into a constant-balance bETH token and periodically send all accrued stETH rewards to the Terra blockchain through a bridge. The bETH token is used as a collateral in the Terra Anchor protocol.
The Anchor Vault is deployed & functions already, and was audited by MixBytes() on July, 30th, 2021. The main reason for the audit request is the coming migration from the Shuttle bridge to the Wormhole. The Vault's bridge_connector
would be set to BridgeConnectorWormhole
contract (to be deployed).
The contracts aside from the BridgeConnectorWormhole
are deployed to the Ethereum mainnet:
Currently integration uses the Shuttle bridge for cross-chain interactions. The bridge connector contract is deployed there:
Deployment script with post-deployment tests for the current integration can be found here: https://github.com/lidofinance/anchor-collateral-steth/blob/8d52ce72cb42d48dff1851222e3b624c941ddb30/scripts/final_check.py.
Wormhole bridge connector deployment scripts can be found here:
deploy_wormhole_connector
: https://github.com/lidofinance/anchor-collateral-steth/blob/8d52ce72cb42d48dff1851222e3b624c941ddb30/scripts/deploy_wormhole_connector.pywormhole_connector_check
: https://github.com/lidofinance/anchor-collateral-steth/blob/8d52ce72cb42d48dff1851222e3b624c941ddb30/scripts/wormhole_connector_check.pyTests are located in https://github.com/lidofinance/anchor-collateral-steth/tree/8d52ce72cb42d48dff1851222e3b624c941ddb30/tests. Note that the Wormhole bridge connector tests are here:
https://github.com/lidofinance/anchor-collateral-steth/blob/8d52ce72cb42d48dff1851222e3b624c941ddb30/tests/test_connector_wormhole.py
RewardsLiquidator
, InsuranceConnector
and BridgeConnectorWormhole
contracts are installed as delegates to the AnchorVault contract and are used by the latter for performing various tasks (see the description above). These contracts can be replaced by the vault admin.
The BridgeConnectorWormhole
contract is designed to interoperate with the Wormhole Ethereum-Terra bridge. The Bridge contract source code can be found here: https://github.com/certusone/wormhole/blob/9bc408ca1912e7000c5c2085215be9d44713028b/ethereum/contracts/bridge/Bridge.sol
Minting bETH: a user can submit stETH to the vault contract and receive the corresponding amount of freshly-minted bETH tokens which get immediately transferred to a user-specified Terra address via the bridge. The received stETH tokens are locked inside the vault contract.
Burning bETH: a user can burn their bETH tokens (which should be already on the Ethereum side) in exchange for stETH tokens from the vault’s balance.
The amount of bETH minted per one stETH locked, as well as the amount of stETH released per one bETH burnt, is determined by the current bETH/stETH rate. Normally, this rate is 1, but it might become less than 1 if Lido validators get penalized or slashed. If that happens, the only way of recovering the rate would be applying protocol-wide insurance. The rate cannot be greater than 1.
stETH is a rebasable token. Balance of each address is internally represented in non-normalized shares, where total number of shares is not bounded, and stETH balance is calculated from shares balance as follows:
Rebases are performed as a result of Lido oracles reporting Beacon chain rewards or penalties, which results in total_lido_controlled_ether
changing (and hence balances of all stETH holders increasing or decreasing). This happens once in ~24h.
A rebase might also be triggered by applying protocol-wide insurance, which is done by minting stETH in exchange for ETH (which proportionally increases both total_lido_controlled_ether
and total_shares
) and burning the minted stETH shares right away, which results in total_shares
decreasing and share_price
increasing. The total number of shares burnt to apply insurance since the protocol inception is tracked by the protocol and stored onchain.
All increases in AnchorVault’s stETH balance that result from Beacon rewards should be periodically sold to UST (Anchor-issued stablecoin) and forwarded to a pre-defined Terra address via the bridge.
Balance increases resulting from insurance applications should NOT be sold to UST and should instead result in recovering bETH/stETH rate.
stETH rebases happen at most once in 24h. Once a rebase has occured, the vault should prohibit submitting and withdrawing stETH until the rewards accrued since the last sell are sold to UST and forwarded to Terra. It should be impossible to sell rewards twice within 24h.
Method _transfer_asset()
is an internal method to transfer required assets from Ethereum blockchain to Terra blockchain via Wormhole token bridge. Aside from common arguments, there is additional _extra_data
argument to provide ability to submit arbitrary bytes. Leading 64 bytes are reserved to pass nonce
and arbiter_fee
to comply the Wormhole token bridge interface while maintaining backward compatibility for AnchorVault
instance.
Method forward_beth()
transfers bETH to Terra chain by using _transfer_asset()
with predefined values.
Method forward_ust()
transfers UST to Terra chain by using _transfer_asset()
with predefined values.
Method adjust_amount()
allowing to adjust amount of assets to transfer and comply with bridge limitations for fractioning.
Rewards collection is impossible if the current pool prices differ significantly from the ones reported by price oracles. In the event of oracle failure or Ethereum network congestion, rewards collection may be delayed for an indeterminate amount of time.
Conversion between stETH and bETH is impossible after stETH has rebased and between AnchorVault.collect_rewards()
call. Normally, an offchain rewards collection bot performs such a call as soon as it detects a rebase. Thus:
AnchorVault.collect_rewards()
call is made.