To mint new WUSD, use the addLiquidity function of the WUSDExtensionController contract.

The inputs of this function are as follows:

uint256 ammPosition,
uint256 liquidityPoolPosition,
uint256 liquidityPoolAmount,
bool byLiquidityPool
  • ammPosition -> the position of the AMM you're going to use inside the allowedAMM array

  • liquidityPoolPosition -> the position of the liquidity pool you're going to use inside the allowedAMM array

  • liquidityPoolAmount -> the amount of tokens of which you want to mint the corresponding amount of WUSD. If byLiquidityPool is true, this parameter represents an LP token amount, if byLiquidityPool is false, this parameter represents the pair token amounts.

  • byLiquidityPool -> a boolean value that represents if the amount passed is of an LP token (true) or of the pair tokens (false)

Starting with the AMM and passed LP positions, the LP address is retrieved:

address liquidityPoolAddress = _allowedAMMs[ammPosition].liquidityPools[liquidityPoolPosition];

The AMM address is then retrieved from the AMM position passed as the following input:

IAMM amm = IAMM(_allowedAMMs[ammPosition].ammAddress);

The corresponding amount in LP tokens is then calculated calling the byLiquidityPoolAmount of that specific AMM (see the AMM Aggregator section for more):

(uint256[] memory amounts, address[] memory tokens) = amm.byLiquidityPoolAmount(liquidityPoolAddress, liquidityPoolAmount);

This function previews two cases regarding the value of the parameter byLiquidityPool:

  • if byLiquidityPool is true, you are passing LP tokens:

The corresponding amount in LP tokens is sent using _safeTransferFrom from the msg.sender to the WUSDExtensionController contract itself; these will be used to mint the corresponding amount of WUSD.

_safeTransferFrom(liquidityPoolAddress, msg.sender, address(this), toMint = liquidityPoolAmount);
  • if byLiquidityPool is false, you are passing pair tokens:

The corresponding amounts of each pair tokens, recovered from the previous byLiquidityPoolAmount call, are sent using _safeTransferFrom from msg.sender to the WUSDExtensionController contract itself, and the _safeApprove method is called to approve the AMM to add liquidity to the pool using tokens sent by the user :

_safeTransferFrom(tokens[i], msg.sender, address(this), amounts[i]);
_safeApprove(tokens[i], address(amm), amounts[i]);

At this point, the amount of LP tokens / pair tokens needed to mint WUSD is calculated by adding liquidity using the addLiquidity function on the chosen AMM:

(toMint, spent,) = amm.addLiquidity(LiquidityPoolData(

The addLiquidity function takes as input the following:

  • liquidityPoolAddress

  • liquidityPoolAmount

  • address(0)-> tokenAddress passed as 0x0000000000000000000000000000000000000000 because the operation is managed using LP tokens

  • true -> amountIsLiquidityPool

  • false -> involvingETH

  • address -> receiver address

Now in both cases (byLiquidityPool true/false) _safeApprove is called on the LP tokens / pair tokens and the corresponding WUSD amount is finally minted using the mintFor function on the WUSDExtension contract, and then sent to the msg.sender.

WUSDExtension(_extension).mintFor(_allowedAMMs[ammPosition].ammAddress, liquidityPoolAddress, toMint, msg.sender);

If there is a positive difference between what was sent by the user (in pair tokens or LP tokens) and what was actually spent by the function to mint new WUSD, this difference is automatically returned to the user by internally calling the _safeTransfer function:

for(uint256 i = 0; i < spent.length; i++) {
    uint256 difference = amounts[i] - spent[i];
    if(difference > 0) {
       _safeTransfer(tokens[i], msg.sender, difference);

Last updated