💱Using Transmuter

Interact with Transmuter to mint, burn or redeem Angle stablecoins

Transmuter is a minting module for Angle stablecoins. It is typically this module that allows minting/burning Angle stablecoins with no fees from USDC or EURC.

The contract works as a Diamond Proxy with multiple implementation facets. This repo contains the contract implementation with all its facets.

In this guide, we explain how to interact with the Transmuter and fetch basical information from it. For more in depth information on how the Transmuter and its functions work, you can directly look into the code and comments in the angle-transmuter repo.

Transmuter can be used for any Angle Protocol stablecoins: find its deployment addresses here.

Mint/Burn stablecoins

Transmuter enables minting and burning Angle stablecoins at oracle value and with dynamic fees with any of the supported collateral assets. Typically for USDA, it allows minting with USDC 1:1 with no fees, or for EURA it allows minting with EURC 1:1 with no fees.

For both mint and burn operations, the contract leaves the opportunity to specify an exact amount of tokens to bring (quoteIn / swapExactInput) or an exact amount of tokens to get (quoteOut / swapExactOutput) in its mint/burn related functions.

In fact, the same functions can be called for mint and burn actions: these functions are called swap functions. For all these functions, a tokenIn and tokenOut parameter must be given: they must refer to either the stablecoin or a supported collateral asset, otherwise they revert.

If tokenIn is a collateral, then the operation is a mint, if tokenOut is a collateral, then the operation is a burn.

Get a quote

There are two functions that exactly estimate what would be the output of a swap if executed at a given block with the parameters specified.

function quoteIn(uint256 amountIn, address tokenIn, address tokenOut) external view returns (uint256 amountOut);

Parameters:

  • amountIn: Amount of tokenIn to bring

  • tokenIn: Token to bring for the swap

  • tokenOut: Token to get out of the swap

Return Value:

  • amountOut: Amount of tokenOut a swap of amountIn of tokenIn would give if executed right at the same block

function quoteOut(uint256 amountOut, address tokenIn, address tokenOut) external view returns (uint256 amountIn);

In this case, amountOut is the amount of tokenOut to obtain, and the amountIn value returned is the exact amount of tokenIn to bring to get this amountOut through a swap at the exact same block.

If called for a burn operation (tokenIn = agToken), the functions revert if there are not enough funds available on the contract (because for instance these funds are invested on a strategy elsewhere).

Generally these functions will revert in any of the conditions that would lead one of the swap functions to revert was verified. For instance, if the operation requested (mint or burn) is paused for the chosen collateral asset or if the collateral parameters passed are invalid, the quoteIn and quoteOut functions will revert.

Execute the swap

Getting a quote is a first step in estimating the output of a swap: it can be used notably to estimate the slippage values to set. There are four functions that can then be used to execute a swap.

For instance, swapExactInput swaps (mints or burns) an exact amount of tokenIn for an amount of tokenOut.

    function swapExactInput(
        uint256 amountIn,
        uint256 amountOutMin,
        address tokenIn,
        address tokenOut,
        address to,
        uint256 deadline
    ) external returns (uint256 amountOut);

Parameters:

  • amountIn: Amount of tokenIn to bring

  • amountOutMin: Minimum amount of tokenOut to get: if amountOut is inferior to this amount, the function will revert

  • tokenIn: Token to bring for the swap

  • tokenOut: Token to get out of the swap

  • to: Address to which tokenOut must be sent

  • deadline: Timestamp before which the transaction must be executed. A value of 0 for this parameter means that there will be no timestamp check made when the swap is executed

Return value:

  • amountOut: Amount of tokenOut obtained through the swap

Note that when using swapExactInput, you must have approved for tokenIn this contract for at least amountIn. With this function and with all other swap functions, no approvals are needed for burn transactions.

swapExactInput is to quoteIn what swapExactOutput is to quoteOut.

    function swapExactOutput(
        uint256 amountOut,
        uint256 amountInMax,
        address tokenIn,
        address tokenOut,
        address to,
        uint256 deadline
    ) external returns (uint256 amountIn);

If using this function, you must specify an exact amount of tokens to obtain amountOut, and with amountInMax a maximum amount of tokenIn you're ready to use for the swap. The other parameters are otherwise the same as swapExactInput.

For mint transactions, you must have approved this contract for an amount bigger than what amountIn will be before calling this function for a mint. Approving the contract for tokenIn with amountInMax will always be enough in this case.

Use Permits

The swapExactInput and swapExactOutput functions have their counterpart which enable them to be used in the case of mint functions without passing an approval, but by using Uniswap Permit2 signatures for this.

The functions are swapExactInputWithPermit and swapExactOutputWithPermit.

    function swapExactInputWithPermit(
        uint256 amountIn,
        uint256 amountOutMin,
        address tokenIn,
        address to,
        uint256 deadline,
        bytes calldata permitData
    ) external returns (uint256 amountOut);

As they can only be used to mint, tokenOut is not needed in any of the functions. The equivalent approval pre-requisites apply to the two functions.

Redemptions

Transmuter enables redeeming stablecoins against a portion of the collateral in the backing. This feature exists per se and does not need to be activated by governance to be used.

Quote a redemption

Like the swap functions, redemptions come with a quote function that simulates the exact output that a redemption of stablecoins would give at a given block.

    function quoteRedemptionCurve(
        uint256 amount
    ) external view returns (address[] memory tokens, uint256[] memory amounts);

Parameter:

  • amount: Amount of stablecoins to redeem

Return Values:

  • tokens: List of tokens that would be given

  • amounts: Amount that would be obtained for each token in the tokens array

Note that this function does not revert if redemptions have been temporarily paused.

In normal conditions, the amount of tokens outputted by this function is the amount of collateral assets supported by the system, following their order in the collateralList.

Yet, if one collateral has its liquidity managed through strategies, then it's possible that this asset has sub-collaterals with it. In this situation, these sub-collaterals may be sent during the redemption process and the minAmountOuts array length will be bigger than the collateralList length. If there are 3 collateral assets and the 2nd collateral asset in the list (at index 1) consists of 3 sub-collaterals, then the ordering of the token list will be as follows: [collat 1, sub-collat 1 of collat 2, sub-collat 2 of collat 2, sub-collat 3 of collat 2, collat 3]

Execute a redemption

The main function to process a redemption with Transmuter is the redeem function.

    function redeem(
        uint256 amount,
        address receiver,
        uint256 deadline,
        uint256[] memory minAmountOuts
    ) external returns (address[] memory tokens, uint256[] memory amounts);

Parameters:

  • amount: Amount of stablecoins to redeem

  • receiver: Address which should be receiving the output tokens

  • deadline: Timestamp before which the redemption should have occured

  • minAmountOuts: Minimum amount of each token given back in the redemption to obtain. The function reverts if the redemption brings less than what was specified for a given token. The order of the amounts given in this list must reflect the order of tokens returned by the quoteRedemptionCurve function.

Return Values:

  • tokens: List of tokens returned (exactly the same as quoteRedemptionCurve)

  • amounts: Amount given for each token in the tokens array

To correctly order the elements in the minAmountOuts array, it is recommended to call the quoteRedemptionCurve function.

If the Transmuter does not have enough tokens at hand (because these are invested in another contract), but redemption computations estimate that tokens must still be sent, then the redeem call will revert when the contract is trying to process the token transfer.

It is possible to instruct the system to forfeit some tokens in the redemption process by using the redeemWithForfeit function.

    function redeemWithForfeit(
        uint256 amount,
        address receiver,
        uint256 deadline,
        uint256[] memory minAmountOuts,
        address[] memory forfeitTokens
    ) external returns (address[] memory tokens, uint256[] memory amounts);

If a token is forfeited because its address is in the forfeitTokens array, then Transmuter will not try to send the tokens to receiver even if it has enough at hand to do so. The length and the ordering of the addresses in the forfeitTokens array can be set at will: before sending a token, the redemptionWithForfeit function just checks whether this token address can be found in the forfeitTokens array.

No approval is needed before calling redemption functions.

Redemptions can be extraordinarily paused by governance. In which case, all the redemption functions would revert (but not the quoteRedemptionCurve function).

Get the contract's facet addresses

As a Diamond Proxy, Transmuter is a proxy contract which delegates calls that are made to it to corresponding facets. The contract has a dummy implementation facet which enables anyone to directly call the Transmuter functions on Etherscan, just like you'd do with a TransparentUpgradeableProxy contract.

As such when clicking on Etherscan to view the implementation contract of Transmuter, you'll be directed to this dummy implementation.

To get the facet addresses of a Transmuter implementation, you can simply call the facetAddresses function of the contract which gives the list of all supported facets.

Get the system's supported collateral assets

Transmuter supports different collateral assets to mint a stablecoin. Many functions in the contract take as argument a supported collateral and revert if the address given does not correspond to a collateral.

The getCollateralList function returns the list of all valid collateral assets.

For all the collateral assets supported here, you may then call any of the view functions to get information about how they are setup in the system:

  • getCollateralMintFees, getCollateralBurnFees: mint and burn fee parameters for a collateral asset

  • isWhitelistedCollateral, getCollateralWhitelistData: whether burns and redemptions are whitelisted for a collateral asset and how the whitelist is setup. To understand why and how whitelists are operated in Transmuter, check out this page

  • getIssuedByCollateral: to get how many stablecoins were issued from a collateral and overall

  • getOracle, getOracleValues: how oracles are setup for a specific collateral (which feeds are read) and what values would be used for a mint, a burn or redemption operation

  • isPaused: whether minting with or burning for a collateral asset is paused

  • getManagerData: whether a collateral is invested externally in other strategies

About whitelists

Transmuter includes the possibility for governance to whitelist collateral assets, meaning that they can only be sent to addresses during a burn or a redemption to an address which has been whitelisted in some way. If Transmuter includes one collateral that requires a whitelist, and someone tries to redeem without forfeiting any tokens to an address which has not been whitelisted, then the redemption will revert.

In fact, if there are n collateral assets, with m of them requiring a whitelist, if all the whitelists are different, for a full redemption to occur successfully, the to address would need to be whitelisted for all the m collateral assets. Otherwise, to still be able to redeem something out of your stablecoins, you need to forfeit the tokens for which the to address is not whitelisted through the redeemWithForfeit function.

On a similar note, burn operations involving collateral assets requiring a whitelist revert if the to address is not whitelisted.

The quote functions (quoteIn, quoteOut, quoteRedemptionCurve) do not revert however if there are collateral assets with whitelists involved.

Last updated