Comment on page
💧
Liquidity Gauges - Angle Staking Contracts
Smart contract used for distributing ANGLE rewards on mainnet
- Contract Name:
LiquidityGaugeV4.sol
- ABI:
The
LiquidityGaugeV4
allows to stake an ERC20 token to receive as a reward another ERC20 token. The contract used at Angle was forked from Curve, with some modifications from the Angle Core Team.This contract is the staking contract used to distribute ANGLE rewards to some Angle Protocol stakeholders (SLPs, LPs of pools with agTokens) on mainnet.
The particularity of this contract is that it supports multiple reward tokens (up to 8) and it allows veANGLE holders to get boosts on their ANGLE rewards when they stake their tokens.
The different
LiquidityGaugeV4
contracts are connected to the AngleDistributor
which automatically and every week distributes ANGLE rewards to these contracts based on how veANGLE holders voted in gauges. People staking in liquidity gauges can then directly claim their ANGLE tokens (and potentially other reward tokens in the contract).People staking in this contract and earning veANGLE tokens can receive a boost on their ANGLE rewards. Note that boosts do not apply on other types of rewards. Like if CRV are given as a reward in this contract, if there were two people staking the same amount of tokens, but one with veANGLE and one without, these two people would receive the same amount of CRV rewards.
This contract is by itself an ERC-20 token, meaning people staking in a liquidity gauge contract own a token they can transfer.
Implements
ERC20
. This contract is upgradeable (note that this is one of the main differences with respect to Curve's contract).Most of key functions of this contract are detailed on Curve docs.
Compared with Curve's implementation of
LiquidityGaugeV4
contract, Angle contract is upgradeable.The way this was implemented was simply by removing the content of the
__init__
function (the constructor), putting it in the initialize
function and having a boolean initialized
variable set to true once initialize
is called. To avoid hostile takeovers of the implementation, the same initialized
boolean is modified in the __init__
function.The main difference between Curve and Angle implementation is that Angle system considers ANGLE rewards the same way as general rewards. However just like Curve, ANGLE rewards do not get accrued the same way as other rewards would: boost can apply to ANGLE rewards for addresses that own veANGLE tokens.
We highlight below some changes in key functions.
@internal
def _checkpoint_rewards(_user: address, _total_supply: uint256, _claim: bool, _receiver: address, _only_checkpoint:bool = False):
This function claims pending rewards and checkpoints rewards for a user and for a given token. It is this function that was modified to handle ANGLE rewards differently than CRV rewards are handled in Curve's equivalent.
To determine the amount of rewards for an address, this function uses
total_supply
of staked tokens, and the user_balance
which corresponds to the amount of tokens staked.To treat ANGLE rewards differently than other tokens, this function considers that if the reward token is the ANGLE token, the
total_supply
is equal to the working_supply
of the contract, that is the supply modified by considering that people staking veANGLE tokens are staking more tokens.@external
@nonreentrant("lock")
def deposit_reward_token(_reward_token: address, _amount: uint256):
It is at the level of this function that reward tokens, included ANGLE, are distributed to this contract.
In Curve implementation, the amount of CRV rewards accruing to a gauge is determined directly in this
LiquidityGaugeV4
contract that queries directly the GaugeController
to know the relative weight. This is no longer needed with Angle, as the AngleDistributor
can use this deposit_reward_token
function to send each week the ANGLE rewards voted in the GaugeController
.The
_checkpoint
function from Curve contract which called the GaugeController
was therefore removed as the logic of it is now included in the new version of the _checkpoint_rewards
and in the new architecture routing ANGLE tokens to gauges.