# How to integrate with Gauntlet USD Alpha

[gtUSDa](https://basescan.org/address/0x000000000001CdB57E58Fa75Fe420a0f4D6640D5) is the ERC20 for our flagship stablecoin vault on Base, Arbitrum, Optimism, and Ethereum Mainnet, which can be integrated into other DeFi applications. Here is a basic integration guide to incorporate gtUSDa into your protocol or app.

{% hint style="info" %}
**gtUSDa is a transferable ERC20 on Base, Arbitrum, Optimism, and Ethereum Mainnet.**
{% endhint %}

We also have a dedicated frontend for supplying into this vault at [app.gauntlet.xyz/vaults/gtusda](https://app.gauntlet.xyz/vaults/gtusda).

### Contract Addresses

**gtUSDa vault addresses**

* `0x000000000001CdB57E58Fa75Fe420a0f4D6640D5` (gtUSDa contract on Base)
* `0x3bd9248048df95Db4fBD748C6CD99C1bAa40bAD0` (gtUSDa contract on Ethereum)
* `0x000000001DC8bd45d7E7829fb1c969cbe4D0D1eC` (gtUSDa contract on Arbitrum)
* `0x000000001DC8bd45d7E7829fb1c969cbe4D0D1eC` (gtUSDa contract on Optimism)

**Token addresses**

* &#x20;`0x833589fcd6edb6e08f4c7c32d4f71b54bda02913` (USDC contract on Base)
* &#x20;`0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48` (USDC contract on Ethereum Mainnet)&#x20;
* &#x20;`0xaf88d065e77c8cC2239327C5EDb3A432268e5831` (USDC contract on Arbitrum)&#x20;
* &#x20;`0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85` (USDC contract on Optimism)

**Provisioner addresses**

* `0x18CF8d963E1a727F9bbF3AEffa0Bd04FB4dBdA07` (provisioner contract on Base)
* `0x74C4A66CE4F4779B11E7c63D42e51EEef3A80D11` (provisioner contract on Ethereum)
* `0xDd4a42603E6d8E515C3468789375A98c376821b3` (provisioner contract on Arbitrum)
* `0xCC923371F0d3A9cA75d98E767Df9dE1cdf5799Ef` (provisioner contract on Optimism)

{% hint style="info" %}
Note: All examples below are executed on Base.&#x20;
{% endhint %}

### Supplying via Contract Calls

Supplying into gtUSDa is a combination of 2 function calls: an `approve` call to spend the USDC, and a `requestDeposit` call.

1. call [`approve`](https://basescan.org/token/0x833589fcd6edb6e08f4c7c32d4f71b54bda02913#writeProxyContract#F1) on the USDC contract to allow the USDC amount to be spent by the [provisioner contract](https://basescan.org/address/0x18CF8d963E1a727F9bbF3AEffa0Bd04FB4dBdA07)
   1. Note that this is not the vault contract itself, as the request runs through the provisioner to issue vault units asynchronously via a solving mechanism (see [https://docs.aera.finance/entry-exit-with-provisioner](https://docs.aera.finance/entry-exit-with-provisioner "mention") for more details)
2. [`requestDeposit`](https://basescan.org/address/0x18CF8d963E1a727F9bbF3AEffa0Bd04FB4dBdA07#writeContract#F7) . `requestDeposit` is an asynchronous operation, the user will submit the USDC to the provisioner and after the request is solved gtUSDa units will be sent back to the users wallet directly. This will generally happen within 6 hours though can take up to as long as 3 days (or otherwise based on deadline). See [https://docs.aera.finance/entry-exit-with-provisioner](https://docs.aera.finance/entry-exit-with-provisioner "mention") for more details
   1. token:  `0x833589fcd6edb6e08f4c7c32d4f71b54bda02913` (USDC contract on Base)
   2. tokensIn: USDC amount in (decimal adjusted value)
   3. minUnitsOut: This parameter needs to be based on the current price of gtUSDa. To calculate it refer to the [PriceAndFeeCalculator](https://basescan.org/address/0x69dD4D44eed6BbC33B8A0bdFe17897Ab9044372e#code) contract, specifically the [`convertTokenToUnits`](https://basescan.org/address/0x69dD4D44eed6BbC33B8A0bdFe17897Ab9044372e#readContract#F4) function call.
      1. `convertTokenToUnits(0x000000000001CdB57E58Fa75Fe420a0f4D6640D5, 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913, tokensIn)` -> Returns the decimal adjusted gtUSDa units.
      2. Multiply the above value by 0.97 (some buffer in case there are price changes)
   4. solverTip: `0`
   5. deadline: `block.timestamp + 259200` (3 days in seconds)
   6. maxPriceAge: `3600` (1 hour in seconds)
   7. isFixedPrice: `False`

{% hint style="info" %}
`minUnitsOut` is technically not required for automatically priced orders if the vault price is trusted but is highly recommended for safety.\
\
Please do not include a `solverTip` as the solver will not solve these requests.\
\
Please do not include a large deadline as unfillable orders cannot be refunded ahead of the `deadline`.
{% endhint %}

#### Example Request to deposit 1000 USDC

Call [`approve`](https://basescan.org/token/0x833589fcd6edb6e08f4c7c32d4f71b54bda02913#writeProxyContract#F1) on the Base USDC contract to allow the provisioner to spend

```
approve(
    0x18CF8d963E1a727F9bbF3AEffa0Bd04FB4dBdA07, // Provisioner Contract Address 
    1000000000 // USDC amount decimal adjusted
)
```

call [`requestDeposit`](https://basescan.org/address/0x18CF8d963E1a727F9bbF3AEffa0Bd04FB4dBdA07#writeContract#F7) on the provisioner, parameterizing this call is important

```
requestDeposit(
    0x833589fcd6edb6e08f4c7c32d4f71b54bda02913, // USDC Contract on base
    1000000000, // USDC amount decimal adjusted
    0.97 * convertTokensToUnit(0x000000000001CdB57E58Fa75Fe420a0f4D6640D5, 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913, 1000000000), // minUnitsOut see above for more details
    0, // solverTip
    block.timestamp + 259200, // deadline: Set to at least 3 days, this is 3 days in seconds
    3600, // maxPriceAge: Set to 1 hour, 1 hour in seconds
    False // isFixedPrice
)
```

### Withdrawing via contract calls

To withdraw you similarly need to do an `approve` call followed by `requestRedeem` on the [Provisioner Contract](https://basescan.org/address/0x18CF8d963E1a727F9bbF3AEffa0Bd04FB4dBdA07) with the correct parameters.

1. call [`approve`](https://basescan.org/address/0x000000000001CdB57E58Fa75Fe420a0f4D6640D5#writeContract#F2) on the gtUSDa contract to allow the gtUSDa amount to be spent by the [provisioner contract](https://basescan.org/address/0x18CF8d963E1a727F9bbF3AEffa0Bd04FB4dBdA07)
2. [`requestRedeem`](https://basescan.org/address/0x18CF8d963E1a727F9bbF3AEffa0Bd04FB4dBdA07#writeContract#F8) This is similarly an asynchronous call where the user provides vaultUnits back to the Provisioner contract and after the request is solved the user will receive USDC in their wallet
   1. token: `0x833589fcd6edb6e08f4c7c32d4f71b54bda02913` (USDC contract on base)
   2. unitsIn: The amount of vault units you wish to redeem, correctly decimal adjusted. If you want to calculate the `unitsIn` based on the USDC value for the user you can again use the [`convertTokenToUnits`](https://basescan.org/address/0x69dD4D44eed6BbC33B8A0bdFe17897Ab9044372e#readContract#F4) function on the [PriceAndFeeCalculator](https://basescan.org/address/0x69dD4D44eed6BbC33B8A0bdFe17897Ab9044372e#code) contract as per the deposit call.
   3. minTokensOut: This parameter needs to be based on the current price of gtUSDa. To calculate it refer to the [PriceAndFeeCalculator](https://basescan.org/address/0x69dD4D44eed6BbC33B8A0bdFe17897Ab9044372e#code) contract, specifically the [`convertUnitsToToken`](https://basescan.org/address/0x69dD4D44eed6BbC33B8A0bdFe17897Ab9044372e#readContract#F7) function.
      1. `convertUnitsToToken(0x000000000001CdB57E58Fa75Fe420a0f4D6640D5, 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913, unitsIn)` -> Returns the Decimal adjusted USDC value of the VaultUnits
      2. Multiply the above value by 0.97 (some buffer in case there are price changes)
   4. solverTip: `0`
   5. deadline: `block.timestamp + 259200` (3 days in seconds)
   6. maxPriceAge: `3600` (1 hour in seconds)
   7. isFixedPrice: `False`

{% hint style="info" %}
`minTokensOut` is technically not required for automatically priced orders if the vault price is trusted but is highly recommended for safety.\
\
Please do not include a `solverTip` as the solver will not solve these requests.\
\
Please do not include a large deadline as unfillable orders cannot be refunded ahead of the `deadline`.
{% endhint %}

#### Example Request to withdraw 1000 USDC

call [`approve`](https://basescan.org/address/0x000000000001CdB57E58Fa75Fe420a0f4D6640D5#writeContract#F2) on the gtUSDa contract to allow the provisioner to spend

```
approve(
    0x18CF8d963E1a727F9bbF3AEffa0Bd04FB4dBdA07, // Provisioner Contract Address 
    convertTokensToUnit(0x000000000001CdB57E58Fa75Fe420a0f4D6640D5, 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913, 1000000000) // gtusda amount decimal adjusted
)
```

call [`requestRedeem`](https://basescan.org/address/0x18CF8d963E1a727F9bbF3AEffa0Bd04FB4dBdA07#writeContract#F8) on the provisioner, parameterizing this call is important

```
requestRedeem(
    0x833589fcd6edb6e08f4c7c32d4f71b54bda02913, // token: USDC Contract on base
    convertTokensToUnit(0x000000000001CdB57E58Fa75Fe420a0f4D6640D5, 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913, 1000000000), // unitsIn: 1000 USDC via the PriceAndFee calculator
    0.97 * convertUnitsToToken(0x000000000001CdB57E58Fa75Fe420a0f4D6640D5, 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913, unitsIn), // minTokensOut: unitsIn is the previous line response
    0, // solverTip
    block.timestamp + 259200, // deadline: Set to at least 3 days, this is 3 days in seconds
    3600, // maxPriceAge: Set to 1 hour days, this is 1 hour in seconds
    False // isFixedPrice
)
```

### \[ADVANCED] Monitoring and refunding orders

**Tracking orders**

When an asynchronous order is placed, the user will have an active but unfilled order. To provide additional transparency to users, these orders can be monitored by tracking the following `DepositRequested` or `RedeemRequested` events:

```
/// @notice Emitted when a user creates a deposit request
/// @param user The address requesting the deposit
/// @param token The token being deposited
/// @param tokensIn The amount of tokens to deposit
/// @param minUnitsOut The minimum amount of units expected
/// @param solverTip The tip offered to the solver in deposit token terms
/// @param deadline Timestamp until which the request is valid
/// @param maxPriceAge Maximum age of price data that solver can use
/// @param isFixedPrice Whether the request is a fixed price request
/// @param depositRequestHash The hash of the deposit request
event DepositRequested(
    address indexed user,
    IERC20 indexed token,
    uint256 tokensIn,
    uint256 minUnitsOut,
    uint256 solverTip,
    uint256 deadline,
    uint256 maxPriceAge,
    bool isFixedPrice,
    bytes32 depositRequestHash
);

/// @notice Emitted when a user creates a redeem request
/// @param user The address requesting the redemption
/// @param token The token requested in return for units
/// @param minTokensOut The minimum amount of tokens the user expects to receive
/// @param unitsIn The amount of units being redeemed
/// @param solverTip The tip offered to the solver in redeem token terms
/// @param deadline The timestamp until which this request is valid
/// @param maxPriceAge Maximum age of price data that solver can use
/// @param isFixedPrice Whether the request is a fixed price request
/// @param redeemRequestHash The hash of the redeem request
event RedeemRequested(
    address indexed user,
    IERC20 indexed token,
    uint256 minTokensOut,
    uint256 unitsIn,
    uint256 solverTip,
    uint256 deadline,
    uint256 maxPriceAge,
    bool isFixedPrice,
    bytes32 redeemRequestHash
);
```

**Checking when orders are filled**

When a deposit or redeem is filled, one of the following events will be emitted in the Provisioner:

```
/// @notice Emitted when a deposit request is solved successfully
/// @param depositHash The unique identifier of the deposit request that was solved
event DepositSolved(bytes32 indexed depositHash);

/// @notice Emitted when a redeem request is solved successfully
/// @param redeemHash The unique identifier of the redeem request that was solved
event RedeemSolved(bytes32 indexed redeemHash);
```

**Refunding expired orders**

If the deadline passes but an order isn't solved (rare), the user has to claim back their USDC or gtUSDa tokens using the `refundRequest` function.

```
/// @notice Request parameters for deposits and redemptions
/// @dev
/// - For deposits:
///   - units: minimum units the user wants to receive (minUnitsOut)
///   - tokens: amount of tokens the user is providing (tokensIn)
/// - For redemptions:
///   - units: amount of units the user is redeeming (unitsIn)
///   - tokens: minimum tokens the user wants to receive (minTokensOut)
struct Request {
    /// @notice Request type(deposit/redeem + auto/fixed price)
    RequestType requestType;
    /// @notice User address making the request
    address user;
    /// @notice Amount of vault units
    uint256 units;
    /// @notice Amount of underlying tokens
    uint256 tokens;
    /// @notice Tip paid to solver, always in tokens
    uint256 solverTip;
    /// @notice Timestamp after which request expires
    uint256 deadline;
    /// @notice Maximum age of price data allowed
    uint256 maxPriceAge;
}

/// @notice Refund an expired deposit or redeem request
/// @param token The token involved in the request
/// @param request The request to refund
/// @dev Can only be called after request deadline has passed
function refundRequest(IERC20 token, Request calldata request) external;
```

### Getting the User's balance of gtUSDa

Simply call the [balanceOf](https://basescan.org/address/0x000000000001CdB57E58Fa75Fe420a0f4D6640D5#readContract#F5) function on [gtUSDa](https://basescan.org/address/0x000000000001CdB57E58Fa75Fe420a0f4D6640D5) with the user's address.

### Pricing gtUSDa units in USDC (and vice versa)

We provide simple price conversion utilities between gtUSDa and USDC via the [PriceAndFeeCalculator](https://basescan.org/address/0x69dD4D44eed6BbC33B8A0bdFe17897Ab9044372e) contract.

Specifically there are two functions of relevance

* [`convertTokensToUnits`](https://basescan.org/address/0x69dD4D44eed6BbC33B8A0bdFe17897Ab9044372e#readContract#F4) -> Takes in USDC value and returns amount of vaultUnits at current price
  * vault: `0x000000000001CdB57E58Fa75Fe420a0f4D6640D5` (gtUSDa vault contract)
  * token: `0x833589fcd6edb6e08f4c7c32d4f71b54bda02913` (USDC contract on base)
  * tokenAmount: Decimal adjusted USDC value (USDC has [6 decimals](https://basescan.org/token/0x833589fcd6edb6e08f4c7c32d4f71b54bda02913#readProxyContract#F11))
* [`convertUnitsToTokens`](https://basescan.org/address/0x69dD4D44eed6BbC33B8A0bdFe17897Ab9044372e#readContract#F7) -> Takes in vaultUnits and returns USDC value at current price
  * vault: `0x000000000001CdB57E58Fa75Fe420a0f4D6640D5` (gtUSDa vault contract)
  * token: `0x833589fcd6edb6e08f4c7c32d4f71b54bda02913` (USDC contract on base)
  * unitsAmount: Decimal adjusted gtUSDa value (gtUSDa has [18 decimals](https://basescan.org/address/0x000000000001CdB57E58Fa75Fe420a0f4D6640D5#readContract#F7))

### Fetching the APY of the vault

This one is a little trickier as of right now, but we aim to make this simpler in the future via an API. As of right now the best way to get the APY of the vault is to index the price of the vault units in USDC over a given time period and extrapolate this to a yearly APY number.

### Calculating the TVL of the vault

To get the total TVL of the vault use the [`convertUnitsToTokens`](https://basescan.org/address/0x69dD4D44eed6BbC33B8A0bdFe17897Ab9044372e#readContract#F7) function and use the [`totalSupply`](https://basescan.org/address/0x000000000001CdB57E58Fa75Fe420a0f4D6640D5#readContract#F21) of gtUSDa as an input.
