# imAssets (SAVE)

imAssets are interest-bearing mAssets. They represent the deposited mAsset in SAVE and accrue in value.

Contracts are upgradable.

{% tabs %}
{% tab title="Ethereum Mainnet" %}

| Contracts                                                                                                   | Address                                                                                                             |
| ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| [imUSD](https://github.com/mstable/mStable-contracts/blob/master/contracts%2Fsavings%2FSavingsContract.sol) | [0x30647a72dc82d7fbb1123ea74716ab8a317eac19](https://etherscan.io/token/0x30647a72dc82d7fbb1123ea74716ab8a317eac19) |
| [imBTC](https://github.com/mstable/mStable-contracts/blob/master/contracts%2Fsavings%2FSavingsContract.sol) | [0x17d8cbb6bce8cee970a4027d1198f6700a7a6c24](https://etherscan.io/token/0x17d8cbb6bce8cee970a4027d1198f6700a7a6c24) |
| {% endtab %}                                                                                                |                                                                                                                     |

{% tab title="Ropsten Testnet" %}

| Contract      | Address                                    |
| ------------- | ------------------------------------------ |
| imUSD         | 0x5b7f01dAe6BCE656c9cA4175Eb3E406ADC6c7957 |
| imBTC         | 0xBfe31D984d688628d06Ae2Da1D640Cf5D9e242A5 |
| {% endtab %}  |                                            |
| {% endtabs %} |                                            |

Both imAssets (imUSD and imBTC) follow the ERC20 and ERC4626 standards:&#x20;

For ERC20, the non-standard [`decreaseAllowance`](https://docs.openzeppelin.com/contracts/2.x/api/token/erc20#ERC20-decreaseAllowance-address-uint256-) and [`increaseAllowance`](https://docs.openzeppelin.com/contracts/2.x/api/token/erc20#ERC20-increaseAllowance-address-uint256-) functions have been added to mitigate the well-known issues around setting allowances. These are based on the OpenZeppelin ERC20 implementation.

For [ERC4626: Tokenized Vault Standard](https://eips.ethereum.org/EIPS/eip-4626), the non-standard functions `deposit(uint256 assets, address receiver, address referrer)` and `shares(uint256 shares, address receiver, address referrer)`  have been added to be used with the [Alliance Referral program](https://mips.mstable.org/MIPS/mip-22.html)

The following list describes functions that are part of this implementation and cover both assets.

## ERC-4626 Functions&#x20;

### asset()

`function asset() external view returns (address assetTokenAddress);`

The address of the underlying token used for the Vault uses for accounting, depositing, and withdrawing.

### totalAssets()

`function totalAssets() external view returns (uint256 totalManagedAssets);`

Total amount of the underlying asset that is “managed” by Vault.

### convertToShares()

`function convertToShares(uint256 assets) external view returns (uint256 shares);`

The amount of shares that the Vault would exchange for the amount of assets provided, in an ideal scenario where all the conditions are met.

<table data-header-hidden><thead><tr><th>Parameter</th><th width="150">Type</th><th>Description</th></tr></thead><tbody><tr><td>Parameter</td><td>Type</td><td>Description</td></tr><tr><td><code>assets</code></td><td>uint256</td><td>The amount of underlying assets to be convert to vault shares.</td></tr></tbody></table>

### convertToAssets()

`function convertToAssets(uint256 shares) external view returns (uint256 assets);`

The amount of assets that the Vault would exchange for the amount of shares provided, in an ideal scenario where all the conditions are met.

<table data-header-hidden><thead><tr><th>Parameter</th><th width="150">Type</th><th>Description</th></tr></thead><tbody><tr><td>Parameter</td><td>Type</td><td>Description</td></tr><tr><td><code>shares</code></td><td>uint256</td><td>The amount of vault shares to be converted to the underlying assets.</td></tr></tbody></table>

### maxDeposit()

`function maxDeposit(address caller) external view returns (uint256 maxAssets);`

The maximum number of underlying assets that caller can deposit.

<table data-header-hidden><thead><tr><th>Parameter</th><th width="150">Type</th><th>Description</th></tr></thead><tbody><tr><td>Parameter</td><td>Type</td><td>Description</td></tr><tr><td><code>caller</code></td><td>address</td><td>Account that the assets will be transferred from.</td></tr></tbody></table>

### previewDeposit()

`function previewDeposit(uint256 assets) external view returns (uint256 shares);`

Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given current on-chain conditions.

<table data-header-hidden><thead><tr><th>Parameter</th><th width="150">Type</th><th>Description</th></tr></thead><tbody><tr><td>Parameter</td><td>Type</td><td>Description</td></tr><tr><td><code>assets</code></td><td>uint256</td><td>The amount of underlying assets to be convert to vault shares.</td></tr></tbody></table>

### deposit()

`function deposit(uint256 assets, address receiver) external returns (uint256 shares);`

Mint vault shares to receiver by transferring exact amount of underlying asset tokens from the caller.

<table data-header-hidden><thead><tr><th>Parameter</th><th width="150">Type</th><th>Description</th></tr></thead><tbody><tr><td>Parameter</td><td>Type</td><td>Description</td></tr><tr><td><code>assets</code></td><td>uint256</td><td>The amount of underlying assets to be convert to vault shares.</td></tr><tr><td><code>receiver</code></td><td>address</td><td>The account that the vault shares will be minted to.</td></tr></tbody></table>

### deposit()

`function deposit(uint256 assets, address receiver, address referrer) external returns (uint256 shares);`

Overloaded  non-standard `deposit` method with an optional referrer address

<table data-header-hidden><thead><tr><th>Parameter</th><th width="150">Type</th><th>Description</th></tr></thead><tbody><tr><td>Parameter</td><td>Type</td><td>Description</td></tr><tr><td><code>assets</code></td><td>uint256</td><td>The amount of underlying assets to be convert to vault shares.</td></tr><tr><td><code>receiver</code></td><td>address</td><td>The account that the vault shares will be minted to.</td></tr><tr><td><code>referrer</code></td><td>address</td><td>Referrer address for this deposit.</td></tr></tbody></table>

### maxMint()

`function maxMint(address caller) external view returns (uint256 maxShares);`

The maximum number of vault shares that caller can mint.

<table data-header-hidden><thead><tr><th>Parameter</th><th width="150">Type</th><th>Description</th></tr></thead><tbody><tr><td>Parameter</td><td>Type</td><td>Description</td></tr><tr><td><code>caller</code></td><td>address</td><td>Account that the underlying assets will be transferred from.</td></tr></tbody></table>

### previewMint()

`function previewMint(uint256 shares) external view returns (uint256 assets);`

Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given current on-chain conditions.

<table data-header-hidden><thead><tr><th>Parameter</th><th width="150">Type</th><th>Description</th></tr></thead><tbody><tr><td>Parameter</td><td>Type</td><td>Description</td></tr><tr><td><code>shares</code></td><td>uint256</td><td>The amount of vault shares to be minted</td></tr></tbody></table>

### mint()

`function mint(uint256 shares, address receiver) external returns (uint256 shares);`

Mint exact amount of vault shares to the receiver by transferring enough underlying asset tokens from the caller.

<table data-header-hidden><thead><tr><th>Parameter</th><th width="150">Type</th><th>Description</th></tr></thead><tbody><tr><td>Parameter</td><td>Type</td><td>Description</td></tr><tr><td><code>shares</code></td><td>uint256</td><td>The amount of vault shares to be minted</td></tr><tr><td><code>receiver</code></td><td>address</td><td>The account that the vault shares will be minted to.</td></tr></tbody></table>

### mint()

`function mint(uint256 shares, address receiver, address referrer) external returns (uint256 shares);`

Overloaded  non-standard  `mint` method with an optional referrer address

<table data-header-hidden><thead><tr><th>Parameter</th><th width="150">Type</th><th>Description</th></tr></thead><tbody><tr><td>Parameter</td><td>Type</td><td>Description</td></tr><tr><td><code>shares</code></td><td>uint256</td><td>The amount of vault shares to be minted</td></tr><tr><td><code>receiver</code></td><td>address</td><td>The account that the vault shares will be minted to.</td></tr><tr><td><code>referrer</code></td><td>address</td><td>Referrer address for this mint.</td></tr></tbody></table>

### maxWithdraw()

`function maxWithdraw(address owner) external view returns (uint256 maxAssets);`

The maximum number of underlying assets that owner can withdraw.

<table data-header-hidden><thead><tr><th>Parameter</th><th width="150">Type</th><th>Description</th></tr></thead><tbody><tr><td>Parameter</td><td>Type</td><td>Description</td></tr><tr><td><code>owner</code></td><td>address</td><td>Account that owns the vault shares.</td></tr></tbody></table>

### previewWithdraw()

`function previewWithdraw(uint256 assets) external view returns (uint256 shares);`

Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block, given current on-chain conditions.

<table data-header-hidden><thead><tr><th>Parameter</th><th width="150">Type</th><th>Description</th></tr></thead><tbody><tr><td>Parameter</td><td>Type</td><td>Description</td></tr><tr><td><code>assets</code></td><td>uint256</td><td>The amount of underlying assets to be withdrawn.</td></tr></tbody></table>

### withdraw()

`function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);`

Burns enough vault shares from owner and transfers the exact amount of underlying asset tokens to the receiver.

<table data-header-hidden><thead><tr><th>Parameter</th><th width="150">Type</th><th>Description</th></tr></thead><tbody><tr><td>Parameter</td><td>Type</td><td>Description</td></tr><tr><td><code>assets</code></td><td>uint256</td><td>The amount of underlying assets to be withdrawn from the vault.</td></tr><tr><td><code>receiver</code></td><td>address</td><td>The account that the underlying assets will be transferred to.</td></tr><tr><td><code>owner</code></td><td>address</td><td>Account that owns the vault shares to be burnt</td></tr></tbody></table>

### maxRedeem()

`function maxRedeem(address owner) external view returns (uint256 maxShares);`

The maximum number of shares an owner can redeem for underlying assets.

<table data-header-hidden><thead><tr><th>Parameter</th><th width="150">Type</th><th>Description</th></tr></thead><tbody><tr><td>Parameter</td><td>Type</td><td>Description</td></tr><tr><td><code>owner</code></td><td>address</td><td>Account that owns the vault shares.</td></tr></tbody></table>

### previewRedeem()

`function previewRedeem(uint256 shares) external view returns (uint256 assets);`

Allows an on-chain or off-chain user to simulate the effects of their redemption at the current block, given current on-chain conditions.

<table data-header-hidden><thead><tr><th>Parameter</th><th width="150">Type</th><th>Description</th></tr></thead><tbody><tr><td>Parameter</td><td>Type</td><td>Description</td></tr><tr><td><code>shares</code></td><td>uint256</td><td>The amount of vault shares to be burnt.</td></tr></tbody></table>

### redeem()

`function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);`

Burns exact amount of vault shares from owner and transfers the underlying asset tokens to the receiver.

<table data-header-hidden><thead><tr><th>Parameter</th><th width="180.33333333333331">Type</th><th>Description</th></tr></thead><tbody><tr><td>Parameter</td><td>Type</td><td>Description</td></tr><tr><td><code>shares</code></td><td>uint256</td><td>The amount of vault shares to be burnt.</td></tr><tr><td><code>receiver</code></td><td>address</td><td>he account the underlying assets will be transferred to.</td></tr><tr><td><code>owner</code></td><td>address</td><td>The account that owns the vault shares to be burnt</td></tr></tbody></table>

## ERC-20 Functions

### totalSupply()

`function totalSupply () external returns (uint256)`

Returns the amount of tokens in existence.

### balanceOf()

`function balanceOf () external returns (uint256)`

Returns the amount of tokens owned by `account`.

### transfer()

`function transfer () external returns (bool)`

Moves `amount` tokens from the caller's account to `recipient`.

Returns a boolean value indicating whether the operation succeeded.

Emits a {Transfer} event.

### allowance()

`function allowance () external returns (uint256)`

Returns the remaining number of tokens that`spender`will be allowed to spend on behalf of`owner`through {transferFrom}. This is zero by default.

This value changes when {approve} or {transferFrom} are called.

### approve()

`function approve () external returns (bool)`

Sets `amount` as the allowance of `spender` over the caller's tokens.

Returns a boolean value indicating whether the operation succeeded.

IMPORTANT: Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: <https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729>

Emits an {Approval} event.

### transferFrom()

`function transferFrom () external returns (bool)`

Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. `amount` is then deducted from the caller's allowance.

Returns a boolean value indicating whether the operation succeeded.

Emits a {Transfer} event.&#x20;

### increaseAllowance()

`function increaseAllowance () public returns (bool)`

Atomically increases the allowance granted to `spender` by the caller.

This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}.

Emits an {Approval} event indicating the updated allowance.

Requirements:

* `spender` cannot be the zero address.

### decreaseAllowance()

`function decreaseAllowance () public returns (bool)`

Atomically decreases the allowance granted to `spender` by the caller.

This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}.

Emits an {Approval} event indicating the updated allowance.

Requirements:

* `spender` cannot be the zero address.
* `spender` must have allowance for the caller of at least

  `subtractedValue`.

## Save functions

### balanceOfUnderlying()

`function balanceOfUnderlying (address _user) external returns (uint256 balance)`

Returns the underlying balance of a given user

| Parameter | Type    | Description                  |
| --------- | ------- | ---------------------------- |
| `_user`   | address | Address of the user to check |

### underlyingToCredits()

`function underlyingToCredits (uint256 _underlying) external returns (uint256 credits)`

Converts a given underlying amount into credits

| Parameter     | Type    | Description         |
| ------------- | ------- | ------------------- |
| `_underlying` | uint256 | Units of underlying |

### creditsToUnderlying()

`function creditsToUnderlying (uint256 _credits) external returns (uint256 amount)`

Converts a given credit amount into underlying

| Parameter  | Type    | Description      |
| ---------- | ------- | ---------------- |
| `_credits` | uint256 | Units of credits |

### creditBalances()

Deprecated in favour of \`balanceOf(address)\`. Maintained for backwards compatibility. Returns the credit balance of a given user

`function creditBalances (address _user) external returns (uint256)`

### depositSavings()

`function depositSavings (uint256 _underlying) external returns (uint256 creditsIssued)`

Deposit the senders savings to the vault, and credit them internally with "credits". Credit amount is calculated as a ratio of deposit amount and exchange rate: credits = underlying / exchangeRate We will first update the internal exchange rate by collecting any interest generated on the underlying.

<table data-header-hidden><thead><tr><th>Parameter</th><th width="150">Type</th><th>Description</th></tr></thead><tbody><tr><td>Parameter</td><td>Type</td><td>Description</td></tr><tr><td><code>_underlying</code></td><td>uint256</td><td>Units of underlying to deposit into savings vault</td></tr></tbody></table>

### depositSavings()

`function depositSavings (uint256 _underlying, address _beneficiary) external returns (uint256 creditsIssued)`

Deposit the senders savings to the vault, and credit them internally with "credits". Credit amount is calculated as a ratio of deposit amount and exchange rate: credits = underlying / exchangeRate We will first update the internal exchange rate by collecting any interest generated on the underlying.

| Parameter      | Type    | Description                                                      |
| -------------- | ------- | ---------------------------------------------------------------- |
| `_underlying`  | uint256 | Units of underlying to deposit into savings vault                |
| `_beneficiary` | address | Immediately transfer the imUSD token to this beneficiary address |

### depositSavings()

`function depositSavings (uint256 _underlying, address _beneficiary, address _referrer) external returns (uint256 creditsIssued)`

Overloaded `depositSavings` method with an optional referrer address.

| Parameter      | Type    | Description                                                        |
| -------------- | ------- | ------------------------------------------------------------------ |
| `_underlying`  | uint256 | Units of underlying to deposit into savings vault. eg mUSD or mBTC |
| `_beneficiary` | address | Address to the new credits will be issued to.                      |
| `_referrer`    | address | Referrer address for this deposit.                                 |

### redeem()

`function redeem () external returns (uint256 massetReturned)`

### redeemCredits()

`function redeemCredits (uint256 _credits) external returns (uint256 massetReturned)`

Redeem specific number of the senders "credits" in exchange for underlying. Payout amount is calculated as a ratio of credits and exchange rate: payout = credits \* exchangeRate

| Parameter  | Type    | Description                 |
| ---------- | ------- | --------------------------- |
| `_credits` | uint256 | Amount of credits to redeem |

### redeemUnderlying()

`function redeemUnderlying (uint256 _underlying) external returns (uint256 creditsBurned)`

Redeem credits into a specific amount of underlying. Credits needed to burn is calculated using: credits = underlying / exchangeRate

| Parameter     | Type    | Description                    |
| ------------- | ------- | ------------------------------ |
| `_underlying` | uint256 | Amount of underlying to redeem |

### redeemAndUnwrap()

`function redeemAndUnwrap (uint256 _amount, bool _isCreditAmt, uint256 _minAmountOut, address _output, address _beneficiary, address _router, bool _isBassetOut) external returns (uint256 creditsBurned, uint256 massetReturned, uint256 outputQuantity)`

Redeem credits into a specific amount of underlying, unwrap into a selected output asset, and send to a beneficiary Credits needed to burn is calculated using: credits = underlying / exchangeRate

| Parameter       | Type    | Description                                                                                                                                                                                                                                                                                                                                                                               |
| --------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `_amount`       | uint256 | Units to redeem (either underlying or credit amount).                                                                                                                                                                                                                                                                                                                                     |
| `_isCreditAmt`  | bool    | `true` if `amount` is in credits. eg imUSD. `false` if `amount` is in underlying. eg mUSD.                                                                                                                                                                                                                                                                                                |
| `_minAmountOut` | uint256 | Minimum amount of `output` tokens to unwrap for. This is to the same decimal places as the `output` token.                                                                                                                                                                                                                                                                                |
| `_output`       | address | <p>Asset to receive in exchange for the redeemed mAssets. This can be a bAsset or a fAsset. For example:<br>- bAssets (USDC, DAI, sUSD or USDT) or fAssets (GUSD, BUSD, alUSD, FEI or RAI) for mainnet imUSD Vault.<br>- bAssets (USDC, DAI or USDT) or fAsset FRAX for Polygon imUSD Vault.<br>- bAssets (WBTC, sBTC or renBTC) or fAssets (HBTC or TBTCV2) for mainnet imBTC Vault.</p> |
| `_beneficiary`  | address | Address to send `output` tokens to.                                                                                                                                                                                                                                                                                                                                                       |
| `_router`       | address | mAsset address if the output is a bAsset. Feeder Pool address if the output is a fAsset.                                                                                                                                                                                                                                                                                                  |
| `_isBassetOut`  | bool    | `true` if `output` is a bAsset. `false` if `output` is a fAsset.                                                                                                                                                                                                                                                                                                                          |

### poke()

`function poke () external`

External poke function allows for the redistribution of collateral between here and the current&#x20;
