# Liquidator

The Liquidator module is responsible for collecting reward tokens from vaults, swapping them and donating back the purchased tokens to the vaults. Typically, this is swapping reward tokens to vault assets which are donated back to the vaults to increase their assets per share. For example, swapping $CRV earned in a Curve pool back to a vault asset like $DAI. There can be multiple reward tokens collected from a vault and different target tokens can be specified for each reward token.

The Liquidator's main task is to batch the swapping of rewards collected from multiple vaults. This socializes the gas costs in swapping rewards across multiple vaults.

The Liquidator uses a [Swapper](https://github.com/mstable/metavaults/blob/main/contracts/vault/swap/README.md) module to do on-chain token swaps. A swapper typically uses a swap aggregator like 1Inch or CowSwap but can use decentralized exchanges like Uniswap or Balancer.

## Liquidator Contracts

<table><thead><tr><th width="161">Contract</th><th>Address</th></tr></thead><tbody><tr><td><a href="https://github.com/mstable/metavaults/blob/main/contracts/vault/liquidator/Liquidator.sol">Liquidator</a></td><td><a href="https://etherscan.io/address/0xD298291059aed77686037aEfFCf497A321A4569e">0xD298291059aed77686037aEfFCf497A321A4569e</a></td></tr><tr><td><a href="https://github.com/mstable/metavaults/blob/main/contracts/vault/swap/CowSwapDex.sol">CowSwapDex</a></td><td><a href="https://etherscan.io/address/0xB305372B12Fd5d736EcB6BF903eaA844f2a23112">0xB305372B12Fd5d736EcB6BF903eaA844f2a23112</a></td></tr></tbody></table>

### Contract Interface

See the metavaults github repository for [contract diagrams](https://github.com/mstable/metavaults/tree/main/contracts/vault/liquidator#diagrams) and [process diagrams](https://github.com/mstable/metavaults/tree/main/contracts/vault/liquidator#processes).

### Variables

#### syncSwapper

```solidity
contract IDexSwap syncSwapper
```

Contract that implements on-chain swaps

#### asyncSwapper

```solidity
contract IDexAsyncSwap asyncSwapper
```

Contract that implements on-chain async swaps

### Functions

#### collectRewards

```solidity
function collectRewards(address[] vaults) external returns (address[][] rewardTokens, uint256[][] rewards, address[][] purchaseTokens)
```

The keeper or governor can collect different rewards from a list of vaults. The Liquidator calls each vault to collect their rewards. The vaults transfer the rewards to themselves first and then the Liquidator transfers each reward from each vault to the Liquidator. Vault rewards can be collect multiple times before they are swapped for the vault asset. It's the responsibility of the Liquidator to account for how many rewards were collected from each vault.

**Parameters**

<table><thead><tr><th width="185.33333333333331">Name</th><th width="128">Type</th><th>Description</th></tr></thead><tbody><tr><td>vaults</td><td>address[]</td><td>List of vault addresses to collect rewards from.</td></tr></tbody></table>

**Return Values**

<table><thead><tr><th width="184.33333333333331">Name</th><th width="128">Type</th><th>Description</th></tr></thead><tbody><tr><td>rewardTokens</td><td>address[][]</td><td>Reward token addresses for each vault. The first dimension is vault from the <code>vaults</code> param. The second dimension is the index of the reward token within the vault.</td></tr><tr><td>rewards</td><td>uint256[][]</td><td>Amount of reward tokens collected for each vault. The first dimension is vault from the <code>vaults</code> param. The second dimension is the index of the reward token within the vault.</td></tr><tr><td>purchaseTokens</td><td>address[][]</td><td>The token to purchase for each of the rewards. The first dimension is vault from the <code>vaults</code> param. The second dimension is the index of the reward token within the vault.</td></tr></tbody></table>

#### donateTokens

```solidity
function donateTokens(address[] rewardTokens, address[] purchaseTokens, address[] vaults) external returns (uint256[] assets)
```

The protocol Governor or Keeper can send the purchased assets in a batch back to the vaults. The order of the input elements is important to aggreate multiple deposits of the same asset to the vault.

ie. Vault 1 has Reward A, Reward B, both rewards are swapped for the same donated Token T.

* donateTokens(\[rewardA.address, rewardB.address], \[tokenT.address, tokenT.address], \[vault1.Address, vault1.Address] Only triggers one deposit of Token T to the underlying vault

**Parameters**

<table><thead><tr><th width="179.33333333333331">Name</th><th width="108">Type</th><th>Description</th></tr></thead><tbody><tr><td>rewardTokens</td><td>address[]</td><td>List of addresses of the reward token that was sold.</td></tr><tr><td>purchaseTokens</td><td>address[]</td><td>List of addresses of the token that was purchased.</td></tr><tr><td>vaults</td><td>address[]</td><td>List of addresses for the vaults with the reward to asset pair.</td></tr></tbody></table>

**Return Values**

<table><thead><tr><th width="107.33333333333331">Name</th><th width="120">Type</th><th>Description</th></tr></thead><tbody><tr><td>assets</td><td>uint256[]</td><td>Amount of asset tokens purchased for each different vault in the <code>vaults</code> parameter.</td></tr></tbody></table>

#### claimAssets

```solidity
function claimAssets(uint256 batch, address rewardToken, address assetToken) external returns (uint256 assets)
```

Vault claims the purchased assets in a batch back. Separate transactions are required if a vault has multiple reward tokens.

**Parameters**

<table><thead><tr><th width="154.33333333333331">Name</th><th width="102">Type</th><th>Description</th></tr></thead><tbody><tr><td>batch</td><td>uint256</td><td>Liquidation batch index from the previously executed <code>swap</code>.</td></tr><tr><td>rewardToken</td><td>address</td><td>Address of the reward token that was sold.</td></tr><tr><td>assetToken</td><td>address</td><td>Address of the asset token that was purchased.</td></tr></tbody></table>

**Return Values**

<table><thead><tr><th width="122.33333333333331">Name</th><th width="107">Type</th><th>Description</th></tr></thead><tbody><tr><td>assets</td><td>uint256</td><td>Amount of asset tokens purchased in the batch.</td></tr></tbody></table>

#### pendingRewards

```solidity
function pendingRewards(address rewardToken, address assetToken) external view returns (uint256 batch, uint256 rewards)
```

**Parameters**

<table><thead><tr><th width="145.33333333333331">Name</th><th width="110">Type</th><th>Description</th></tr></thead><tbody><tr><td>rewardToken</td><td>address</td><td>Address of the rewards being sold.</td></tr><tr><td>assetToken</td><td>address</td><td>Address of the assets being purchased.</td></tr></tbody></table>

**Return Values**

<table><thead><tr><th width="116.33333333333331">Name</th><th width="98">Type</th><th>Description</th></tr></thead><tbody><tr><td>batch</td><td>uint256</td><td>Current liquidation batch index.</td></tr><tr><td>rewards</td><td>uint256</td><td>Amount of reward tokens that are waiting to be swapped.</td></tr></tbody></table>

#### pendingVaultRewards

```solidity
function pendingVaultRewards(address rewardToken, address assetToken, address vault) external view returns (uint256 batch, uint256 rewards)
```

**Parameters**

<table><thead><tr><th width="143.33333333333331">Name</th><th width="103">Type</th><th>Description</th></tr></thead><tbody><tr><td>rewardToken</td><td>address</td><td>Address of the rewards being sold.</td></tr><tr><td>assetToken</td><td>address</td><td>Address of the assets being purchased.</td></tr><tr><td>vault</td><td>address</td><td>Address of the vault with the reward to asset pair.</td></tr></tbody></table>

**Return Values**

<table><thead><tr><th width="123.33333333333331">Name</th><th width="104">Type</th><th>Description</th></tr></thead><tbody><tr><td>batch</td><td>uint256</td><td>Current liquidation batch index.</td></tr><tr><td>rewards</td><td>uint256</td><td>Amount of reward tokens that are waiting to be swapped.</td></tr></tbody></table>

#### purchasedAssets

```solidity
function purchasedAssets(uint256 batch, address rewardToken, address assetToken, address vault) external view returns (uint256 assets)
```

**Parameters**

<table><thead><tr><th width="149.33333333333331">Name</th><th width="97">Type</th><th>Description</th></tr></thead><tbody><tr><td>batch</td><td>uint256</td><td>Liquidation batch index from the previously executed <code>swap</code>.</td></tr><tr><td>rewardToken</td><td>address</td><td>Address of the reward token that was sold.</td></tr><tr><td>assetToken</td><td>address</td><td>Address of the asset token that was purchased.</td></tr><tr><td>vault</td><td>address</td><td>Address of the vault with the reward to asset pair.</td></tr></tbody></table>

**Return Values**

<table><thead><tr><th width="104.33333333333331">Name</th><th width="95">Type</th><th>Description</th></tr></thead><tbody><tr><td>assets</td><td>uint256</td><td>Amount of asset tokens purchased and not yet claimed. It is zero if assets have already been claimed.</td></tr></tbody></table>

#### swap

```solidity
function swap(address rewardToken, address assetToken, uint256 minAssets, bytes data) external returns (uint256 batch, uint256 rewards, uint256 assets)
```

Swap the collected rewards to desired asset.

**Parameters**

<table><thead><tr><th width="148.33333333333331">Name</th><th width="96">Type</th><th>Description</th></tr></thead><tbody><tr><td>rewardToken</td><td>address</td><td>Address of the rewards being sold.</td></tr><tr><td>assetToken</td><td>address</td><td>Address of the assets being purchased.</td></tr><tr><td>minAssets</td><td>uint256</td><td>Minimum amount of assets that can be returned from the swap.</td></tr><tr><td>data</td><td>bytes</td><td>Is specific for the swap implementation. eg 1Inch, Cowswap, Matcha...</td></tr></tbody></table>

#### initiateSwap

```solidity
function initiateSwap(address rewardToken, address assetToken, bytes data) external returns (uint256 batch, uint256 rewards)
```

Swap the collected rewards to desired asset. Off-chain order must be created providing a "receiver" of the swap.

**Parameters**

<table><thead><tr><th width="148.33333333333331">Name</th><th width="100">Type</th><th>Description</th></tr></thead><tbody><tr><td>rewardToken</td><td>address</td><td>Address of the rewards being sold.</td></tr><tr><td>assetToken</td><td>address</td><td>Address of the assets being purchased.</td></tr><tr><td>data</td><td>bytes</td><td>Is specific for the swap implementation. eg Cowswap, Matcha...</td></tr></tbody></table>

#### initiateSwaps

```solidity
function initiateSwaps(address[] rewardTokens, address[] assetTokens, bytes[] datas) external returns (uint256[] batchs, uint256[] rewards)
```

Swaps the collected rewards to desired assets. Off-chain order must be created providing a "receiver" of the swap.

**Parameters**

<table><thead><tr><th width="162.33333333333331">Name</th><th width="109">Type</th><th>Description</th></tr></thead><tbody><tr><td>rewardTokens</td><td>address[]</td><td>Address of the rewards being sold.</td></tr><tr><td>assetTokens</td><td>address[]</td><td>Address of the assets being purchased.</td></tr><tr><td>datas</td><td>bytes[]</td><td>Is specific for the swap implementation. eg Cowswap, Matcha...</td></tr></tbody></table>

#### settleSwap

```solidity
function settleSwap(address rewardToken, address assetToken, uint256 assets, bytes data) external returns (uint256 batch, uint256 rewards)
```

settles the last batch swap of rewards for assets. `initiateSwap` must be called and the swap executed before `settleSwap`.

**Parameters**

<table><thead><tr><th width="150.33333333333331">Name</th><th width="104">Type</th><th>Description</th></tr></thead><tbody><tr><td>rewardToken</td><td>address</td><td>Address of the rewards being sold.</td></tr><tr><td>assetToken</td><td>address</td><td>Address of the assets being purchased.</td></tr><tr><td>assets</td><td>uint256</td><td>Amount of purchaed assets received from the swap.</td></tr><tr><td>data</td><td>bytes</td><td></td></tr></tbody></table>

#### settleSwaps

```solidity
function settleSwaps(address[] rewardTokens, address[] assetTokens, uint256[] assets, bytes[] datas) external returns (uint256[] batchs, uint256[] rewards)
```

Swaps the collected rewards to desired assets. initiateSwap must be called first before settleSwap

**Parameters**

<table><thead><tr><th width="163.33333333333331">Name</th><th width="119">Type</th><th>Description</th></tr></thead><tbody><tr><td>rewardTokens</td><td>address[]</td><td>Address of the rewards being sold.</td></tr><tr><td>assetTokens</td><td>address[]</td><td>Address of the assets being purchased.</td></tr><tr><td>assets</td><td>uint256[]</td><td>Amount of assets to swapped.</td></tr><tr><td>datas</td><td>bytes[]</td><td>Custom data for the swap.</td></tr></tbody></table>

#### setSyncSwapper

```solidity
function setSyncSwapper(address _syncSwapper) external
```

Sets a new implementation of the DEX syncSwapper.

**Parameters**

<table><thead><tr><th width="168.33333333333331">Name</th><th width="103">Type</th><th>Description</th></tr></thead><tbody><tr><td>_syncSwapper</td><td>address</td><td>Address of the DEX syncSwapper.</td></tr></tbody></table>

#### setAsyncSwapper

```solidity
function setAsyncSwapper(address _asyncSwapper) external
```

Sets a new implementation of the DEX asyncSwapper.

**Parameters**

<table><thead><tr><th width="177.33333333333331">Name</th><th width="121">Type</th><th>Description</th></tr></thead><tbody><tr><td>_asyncSwapper</td><td>address</td><td>Address of the DEX asyncSwapper.</td></tr></tbody></table>

#### rescueToken

```solidity
function rescueToken(address token, uint256 amount) external
```

Governor rescues tokens from the liquidator in case a vault's donateToken is failing.
