#0 Valha integrations - How to deal with Angle-SLPs?
Valha
0xe31a
December 19th, 2022

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:

medium.com
medium.com

Angle presentation

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.

Angle multiplier effect - Yield opportunity
Angle multiplier effect - Yield opportunity

Integration focus

  • 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.

High level design

  1. 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
    
  2. Gauge Contracts

    Gauge contracts are a type of staking contracts for users to deposit their LP token in.

    address sanDAI_EUR_Gauge = 0x8E2c0CbDa6bA7B65dbcA333798A3949B07638026
    
  3. Liquidity Pool Tokens

    “Liquidity Pool Tokens” or “LP Tokens” are tokens representing the share of a SLP into a pool.

  4. Underlying Tokens

    “Underlying Tokens” are the tokens used to enter a liquidity pool for SLP.

Interactions

☝️☝️☝️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);
    }

To go further

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.

Subscribe to Valha
Receive the latest updates directly to your inbox.
Nft graphic
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.
Arweave Transaction
dSwpeXJGPMaXq-l…3FlH-LkxMq2eQPA
Author Address
0xe31a2BCbcE39489…bb041384e8A3247
Nft Address
0xaa41D83F5afd912…ac28C7EBDa0Ea61
Content Digest
lOrQ9bafdH6HQaH…AL7NowzLVOikEWw
More from Valha
View All

Skeleton

Skeleton

Skeleton

15 Collectors
LOADING TEXT
#1
LOADING TEXT
#2
LOADING TEXT
#3
LOADING TEXT
#4
LOADING TEXT
#5
LOADING TEXT
#6
LOADING TEXT
#7
LOADING TEXT
#8
LOADING TEXT
#9
LOADING TEXT
#10
LOADING TEXT
#11
LOADING TEXT
#12
LOADING TEXT
#13
LOADING TEXT
#14
LOADING TEXT
#15