💸Integrating Savings Contracts

Integrate Angle Savings Contracts to earn from your assets

Angle Savings contracts enable depositing Angle stablecoins to earn a yield from it.

These are simple ERC4626 contracts (see implementation) which do not invest the tokens deposited in it, but simply mint new tokens based on a rate defined by governance.

The flow is the following: if one user deposits 100 USDA in the contract, and governance encodes a 2% yearly rate, then after a year when the user wants to withdraw its USDA, the contract mints 2 USDA (it has a minting right on the token), and the user can withdraw 2 USDA.

As such, apart from the savings contract smart contract risk, there is no extra trust assumption between owning a stablecoin and owning a stablecoin in a staking contract to earn a yield from it.

Savings contracts addresses for Angle stablecoins across all chains can be obtained here.

For more details on how to get into Angle stablecoins (EURA & USDA) with no fees from Angle Price Stability module (called the Transmuter), you may refer to this guide here.

Deposit & withdraw

Angle Savings contract implementation is a very simple extension of the baseline ERC4626 contract. As such, the logic to deposit or withdraw assets, as well as to mint or redeem shares is exactly the same as explained here.

The only thing that changes is that in case of unforeseen events, governance has the power to pause depositing and withdrawing from the contract. To check whether the contract is paused, you can check the paused variable of the contract which is equal to 1 when contract is paused.

The contract also comes with the usual convertToShares, convertToAssets, maxDeposit, maxWithdraw, maxMint, maxRedeem functions which have no specifities.

Fetch APY and inflation rate

From Angle API

To get the APY on a given chain, you may use Angle API and call this endpoint: https://api.angle.money/v2/savings?chainId=1.

You may change the chainId depending on the chain on which you're trying to get data.

This endpoint will return for each stablecoin the apy of the corresponding savings solution on the chain as well as some details on the TVL held by the savings product.

From the smart contract

If you don't want to rely on the Angle API to get the rate that a savings contract is paying, you can also call the rate parameter of the smart contract. It's the per second inflation rate given in base 27.

The contract also comes with a wrapper estimatedAPR function which gives the estimated APY in base 18 for depositing in this contract (rewards in the savings contract are compounding and so what this function returns is an APY rather than an APR).

A 1% APY for this function would correspond to a value of 10000000000000000.

In the same vein, you can anticipate (assuming the inflation rate does not change) how much you'll earn for a period of time by depositing in the contract by calling the computeUpdatedAssets function:

function computeUpdatedAssets(uint256 _totalAssets, uint256 exp) external view returns (uint256);

Parameters:

  • _totalAssets: How much you're depositing in the contract

  • exp: Period in second for which you want to estimate your earnings

Return Value:

  • Value of your assets after exp seconds in the contract should the inflation rate remain constant

Get a staked token price

The functions convertToShares and convertToAssets can be used to estimate the price of the share of the savings contract (=the staked token) in reference token.

Basically, the value of 1 share in reference asset is convertToAssets(1 ether).

Different implementations for Angle savings contracts may be deployed on different chains. It's important to note that while contract addresses may be the same, the prices of the corresponding shares may completely vary from one chain to another.

Estimate profits of a given address

To compute the lifetime interest earned by an address with stUSD or stEUR on a given chain, you can use the Angle API by calling this endpoint (first=1 to get only the latest data):

https://api.angle.money/v2/historical/savings?user=0x0000000000000000000000000000000000000000&first=1

Replace the address in the URL with the address you want to query.

The response will be a JSON array containing objects for each chain and stablecoin combination where the user has earned interest. Here's an example of the response structure:

[
  {
    "42161": {
      "EURA": [
        {
          "accrued": "5896.098602929735",
          "agTokenSymbol": "stEUR",
          "deposited": "335260.1900845909644987243341411076",
          "shares": "325635.565377983023469225",
          "timestamp": 1727353064,
          "user": "0x3350bef226f7bdca874c5561320ab7ef9dc89e70"
        }
      ]
    }
  }
]

To get the lifetime interest earned:

  1. Look for the accrued field in the response. This value represents the total interest earned.

  2. The response includes data for all chains and stablecoins (EURA, USDA) associated with the address.

  3. The agTokenSymbol field indicates whether it's for stEUR or stUSD.

  4. The deposited field shows the total amount deposited minus the amount withdrawn.

  5. The timestamp field indicates when this data was last updated.

By default, this endpoint returns data for all chains and stablecoins associated with the given address. If you need to filter for a specific chain or stablecoin, you may need to process the response accordingly in your application.

For more detailed information about the API and its parameters, you can refer to the Angle API documentation.

Rate modifications

The inflation rate in an Angle Savings contract is encoded by governance. As such, it is non dilutive and does not vary as people deposit more capital or withdraw their assets.

Depending on the stablecoin and on the setup, governance may follow different update schedules. And the frequency of updates may vary from every week to every several months. Between two updates, depositors in Angle Savings contract are guaranteed to earn a fixed rate on their assets.

Last updated