At Valha we are building a DeFi abstraction layer for developers in order to easily deal with integrations.
We introduce this series of articles where we explain for developers how to easily interact with some of the protocols in DeFi especially to deposit/redeem/stake funds in yield generating pools.
These explanations are an appetizer for integration. Valha offers comprehensive resources to leverage them in a more complete and detailed way.
In this first episode, we are looking at Angle Protocol.
You can also read this story on Medium:
Angle is a decentralized, capital efficient and over-collateralized stablecoin protocol.
The Stablecoin peg relies on three groups of stakeholders: 1) Stable seekers and holders, 2) Hedging Agents and 3) Standard Liquidity Providers.
Stable Seekers or Users: they can mint stablecoins by depositing collateral and conversely redeem collateral by burning stablecoin.
Hedging Agents (HAs): they get leveraged positions with the multiple of their choice on a pair collateral/stablecoin in the form of perpetual futures. By doing so, they insure the Core module against the volatility of the collateral.
Standard Liquidity Providers (SLPs): they lend money to the Core module to act as a protection layer for the protocol and make up for the Hedging Agents and Stable seekers unbalanced positions. In return they get 1) a part of the transaction fees induced by stable seekers minting and burning, as well as 2) a part of the returns made from lending capital to lending pools and DeFi strategies (like Compound, Aave, Yearn).
An interesting thing to mention about SLPs is that they can get more yield than what they would get on Compound or Aave because they receive yield on collateral they did not bring initially. Thanks to this multiplier effect, Angle offers yield opportunities to SLPs that cannot be replicated.
Protocol: Angle Protocol
Scope: SLPs
Version: V0
Angle's Valha integration focuses solely on SLPs. Since LPs generate yield by depositing their tokens within specific vaults, this is an attractive way to easily access lucrative yield.
Stable Master Contract
StableMaster
is the contract handling all the accounting. It contains the logic for the fees that are taken to users minting and burning, and for the exchange rate between sanTokens and collateral. This contract is one of the point of entry in the protocol for SLPs (and also for Stable seekers).
address stableMasterFront = 0x5adDc89785D75C86aB939E9e15bfBBb7Fc086A87
Gauge Contracts
Gauge
contracts are a type of staking contracts for users to deposit their LP token in.
address sanDAI_EUR_Gauge = 0x8E2c0CbDa6bA7B65dbcA333798A3949B07638026
Liquidity Pool Tokens
“Liquidity Pool Tokens” or “LP Tokens” are tokens representing the share of a SLP into a pool.
Underlying Tokens
“Underlying Tokens” are the tokens used to enter a liquidity pool for SLP.
☝️☝️☝️In the following snippets, we consider that the contract implementing the functions has enough ERC20 balance to execute the function.
NB: There are other ways to integrate with Angle protocol, if you think that there is better way to achieve some of the interactions above, feel free to jump in the Discord to discuss it with the team!
A) Deposit
interface IERC20 {
function approve(address spender, uint256 value) external;
}
interface IStableMasterInteraction {
function deposit(
uint256 amount,
address user,
address poolManager
) external;
function withdraw(
uint256 amount,
address burner,
address dest,
address poolManager
) external;
}
/// @notice External function to deposit an underlying token into a SLP pool
/// @param _amount Amount of underlying token to deposit
/// @param _receiver Address that will receive the LP Tokens
/// @param _poolAddress Pool address to deposit in
/// @param _token Underlying token address that it uses to deposit
/// @dev Once this function is called, LP token will be minted for the corresponding amount of underlying token and distributed to the _receiver.
function deposit(uint256 _amount, address _receiver, address _poolAddress, address _token) external {
address poolManager = getPoolManager(_poolAddress);
IERC20(_token).approve(stableMasterFront, _amount);
IStableMasterInteraction(stableMasterFront).deposit(_amount, _receiver, poolManager);
}
B) Redeem
interface IERC20 {
function approve(address spender, uint256 value) external;
}
interface IStableMasterInteraction {
function deposit(
uint256 amount,
address user,
address poolManager
) external;
function withdraw(
uint256 amount,
address burner,
address dest,
address poolManager
) external;
}
/// @notice External function to withdraw LP tokens from a SLP pool
/// @param _amount Amount of LP token to redeem
/// @param _burner Address that owns the LP token to be redeemed
/// @param _receiver Address that will receive the underlying token
/// @param _pool Address Pool address to withdraw from
/// @dev Once this function is called, LP tokens will be burnt and the corresponding amount of underlying token will be transferred to the _receiver.
function redeem(uint256 _amount, address _burner, address _receiver, address _poolAddress) external {
address poolManager = getPoolManager(_poolAddress);
IERC20(_poolAddress).approve(stableMasterFront, _amount);
IStableMasterInteraction(stableMasterFront).withdraw(_amount, _burner, _receiver, poolManager);
}
C) Stake
interface IGaugeInteraction {
function deposit(
uint256 amount,
address user
) external;
function withdraw(
uint256 amount,
bool claim_rewards
) external;
function claim_rewards(
address user,
address receiver
) external;
}
interface IERC20 {
function approve(address spender, uint256 value) external;
}
/// @notice External function to withdraw LP tokens from a SLP pool
/// @param _amount Amount of LP token to deposit in the gauge
/// @param _receiver Address which will own the LP tokens once staked. LP token ownership could be transferred to a new address
/// @param _poolAddress LP token pool address
///@param _gaugeAddress Address in which the LP token amount is staked
function stake(uint256 _amount, address _receiver, address _poolAddress, address _gaugeAddress) external {
IERC20(_poolAddress).approve(_gaugeAddress, _amount);
IGaugeInteraction(_gaugeAddress).deposit(_amount, _receiver);
}
D) Unstake
This function enables to get back your LP tokens from the staking addresses.
interface IGaugeInteraction {
function deposit(
uint256 amount,
address user
) external;
function withdraw(
uint256 amount,
bool claim_rewards
) external;
function claim_rewards(
address user,
address receiver
) external;
}
interface IERC20 {
function approve(address spender, uint256 value) external;
}
/// @notice External function to redeem LP tokens from a SLP pool
/// @param _amount Amount of LP token to redeem from the gauge
///@param _gaugeAddress Address in which the LP token amount is redeemed
function unstake(uint256 _amount, address _gaugeAddress) external {
IERC20(_gaugeAddress).approve(_gaugeAddress, _amount);
IGaugeInteraction(_gaugeAddress).withdraw(_amount, false);
}
E) Claim
This method enables to get liquidity mining rewards in ANGLE tokens.
interface IGaugeInteraction {
function deposit(
uint256 amount,
address user
) external;
function withdraw(
uint256 amount,
bool claim_rewards
) external;
function claim_rewards(
address user,
address receiver
) external;
}
/// @notice This reward can be earned once the LP tokens are staked
///@param _gaugeAddress Address in which the LP token amount is staked
///@param _user Address associated to the staked LP tokens
///@param _receiver Address receiving the claim rewards
function claim_rewards(address _gaugeAddress, address _user, address _receiver) external {
IGaugeInteraction(_gaugeAddress).claim_rewards(_user, _receiver);
}
At Valha, we have the mission to make DeFi easier for developers. We want to make the promise of composability more tangible than ever by creating an abstraction layer on top of which it is intuitive, secure and efficient to integrate with any protocol in DeFi.
If you do not want to maintain all your integrations yourself, check our documentation or jump into our Discord to discuss it.
We also maintain an open-source repository of many DeFi integrations and are always for the lookup for new contributors, so feel free to explore or Github.
Reach out to us on Twitter or in our Discord for potential collaboration in the future.