> For the complete documentation index, see [llms.txt](https://mars-protocol.gitbook.io/mars-protocol/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mars-protocol.gitbook.io/mars-protocol/contracts-c2c/fields-of-mars.md).

# Fields of Mars

The Fields of Mars contract contains a leveraged yield farming strategy utilizing contract-to-contract (C2C) lending from Mars Protocol.

## Links

* package (msgs and types): <https://github.com/mars-protocol/fields-of-mars/blob/v1.0.0/packages/fields-of-mars/src/martian_field.rs>
* contract:  <https://github.com/mars-protocol/fields-of-mars/blob/master/contracts/martian-field/src/contract.rs>
* crates.io: <https://crates.io/crates/fields-of-mars>

## Config

### `ConfigBase`

```rust
#[ruderive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct ConfigBase<T> {
    pub primary_asset_info: AssetInfoBase<T>,
    pub secondary_asset_info: AssetInfoBase<T>,
    pub astro_token_info: AssetInfoBase<T>,
    pub primary_pair: PairBase<T>,
    pub astro_pair: PairBase<T>,
    pub astro_generator: GeneratorBase<T>,
    pub red_bank: RedBankBase<T>,
    pub oracle: OracleBase<T>,
    pub treasury: T,
    pub governance: T,
    pub operators: Vec<T>,
    pub max_ltv: Decimal,
    pub fee_rate: Decimal,
    pub bonus_rate: Decimal
}
```

| Key                    | Type              | Description                                                                                                                                                                                 |
| ---------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `primary_asset_info`   | AssetInfoBase\<T> | Info of the primary asset (deposit). Primary asset is the asset which the user takes an implicit long position on when utilizing Martian Field.                                             |
| `secondary_asset_info` | AssetInfoBase\<T> | Info of the secondary asset (borrow). Secondary asset is the asset which the user takes an implicit short position on when utilizing Martian Field.                                         |
| `astro_token_info`     | AssetInfoBase\<T> | Info of the Astroport token, the staking reward that will be paid out by Astro generator.                                                                                                   |
| `primary_pair`         | PairBase\<T>      | Astroport pair consisting of the primary and secondary assets. The liquidity token of this pair will be staked/bonded in Astro generator to earn ASTRO and optionally a proxy token reward. |
| `astro_pair`           | PairBase\<T>      | Astroport pair consisting of ASTRO token and the secondary asset. This pair is used for swapping ASTRO reward so that it can be reinvested.                                                 |
| `astro_generator`      | GeneratorBase\<T> | The Astro generator contract                                                                                                                                                                |
| `red_bank`             | RedBankBase\<T>   | The Mars Protocol money market contract. We borrow the secondary asset here                                                                                                                 |
| `oracle`               | OracleBase\<T>    | The Mars Protocol oracle contract. We read prices of the primary and secondary assets here                                                                                                  |
| `treasury`             | T                 | Account to receive fee payments                                                                                                                                                             |
| `governance`           | T                 | Account who can update config                                                                                                                                                               |
| `operators`            | Vec\<T>           | Accounts who can harvest                                                                                                                                                                    |
| `max_ltv`              | Decimal           | Maximum loan-to-value ratio (LTV) above which a user can be liquidated                                                                                                                      |
| `fee_rate`             | Decimal           | Percentage of profit to be charged as performance fee                                                                                                                                       |
| `bonus_rate`           | Decimal           | During liquidation, percentage of the user's asset to be awared to the liquidator as bonus                                                                                                  |

### `ConfigUnchecked` / `Config`

```rust
pub type ConfigUnchecked = ConfigBase<String>;
pub type Config = ConfigBase<Addr>;
```

## InstantiateMsg

{% tabs %}
{% tab title="Rust" %}

```rust
pub type InstantiateMsg = ConfigUnchecked;
```

{% endtab %}

{% tab title="JSON" %}

```json
{
  "config_unchecked" 
}
```

{% endtab %}
{% endtabs %}

## ExecuteMsg

### `UpdateConfig`

Update data stored in config (only governance can call).

{% tabs %}
{% tab title="Rust" %}

```rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
    UpdateConfig {
        new_config: ConfigUnchecked
    } 
}
```

{% endtab %}

{% tab title="JSON" %}

```json
{
  "update_config": {
    "new_config": { ... }  // object of `ConfigUnchecked` type
  }
}
```

{% endtab %}
{% endtabs %}

### `UpdatePosition`

Updates the sender's position by executing a list of actions. After the actions are executed, the contract executes three more callbacks: 1. Refund all unlocked assets to the user. 2. Assert the position's LTV is below the liquidation threshold. If not, throw an error and revert all previous actions. 3. Delete cached data in storage.

{% tabs %}
{% tab title="Rust" %}

```rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
    UpdatePosition(Vec<Action>)
}
```

{% endtab %}

{% tab title="JSON" %}

```json
{
  "update_position": [
    "deposit": { ... },  // object of `AssetUnchecked` type
    "borrow": {
      "amount": "123"
    }, 
    "repay": {
      "amount": "123"
    }, 
    "bond": {
      "slippage_tolerance": "0.01"
    }, 
    "unbond": {
      "bond_units_to_reduce": "123"
    }, 
    "swap": {
      "offer_amount": "123" 
      "max_spread": "0.01"
    }
  ]
}
```

{% endtab %}
{% endtabs %}

### `Harvest`

Claim staking reward and reinvest.

{% tabs %}
{% tab title="Rust" %}

```rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
    Harvest {
        max_spread: Option<Decimal>, 
        slippage_tolerance: Option<Decimal>
    }
}
```

{% endtab %}

{% tab title="JSON" %}

```json
{
  "harvest": {
    "max_spread": "0.01",
    "slippage_tolerance": "0.01"
  }
}
```

{% endtab %}
{% endtabs %}

| Key                    | Type    | Description                                               |
| ---------------------- | ------- | --------------------------------------------------------- |
| `max_spread`\*         | Decimal | Used for ASTRO >> secondary swap and balancing operations |
| `slippage_tolerance`\* | Decimal | Used for providing primary + secondary liquidity          |

\* = optional

### `Liquidate`

Force close an underfunded position, repay all debts, and return all remaining funds to the position's owner. The liquidator is awarded a portion of the remaining funds.

{% tabs %}
{% tab title="Rust" %}

```rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
    Liquidate {
        user: String
    }
}
```

{% endtab %}

{% tab title="JSON" %}

```json
{
  "liquidate": {
    "user": "terra..."
  }
}
```

{% endtab %}
{% endtabs %}

| Key    | Type   | Description          |
| ------ | ------ | -------------------- |
| `user` | String | Address to liquidate |

### `Callback`

Callbacks; only callable by the strategy itself.&#x20;

{% tabs %}
{% tab title="Rust" %}

```rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
    Callback(CallbackMsg)
}
```

{% endtab %}

{% tab title="JSON" %}

```json
{
  "callback": {
    "provide_liquidity": {
      "user_addr": "terra...",
      "slippage_tolerance": "0.01"
    }, 
    "withdraw_liquidity": {
      "user_addr": "terra..."
    }, 
    "bond": {
      "user_addr": "terra..."
    }, 
    "unbond": {
      "user_addr": "terra...",
      "bond_units_to_reduce": "123"
    }, 
    "borrow": {
      "user_addr": "terra...",
      "borrow_amount": "10000"
    }, 
    "repay": {
      "user_addr": "terra...",
      "repay_amount": "10000"
    }, 
    "swap": {
      "user_addr": "terra...",
      "offer_asset_info": "terra...", 
      "offer_amount": "10000",
      "max_spread": "0.01"
    }, 
    "balance": {
      "max_spread": "0.01"
    }, 
    "cover": {
      "user_addr": "terra..."
    }
    "refund": {
      "user_addr": "terra...",
      "recipient_addr": "terra...", 
      "percentage": "0.01"
    }, 
    "assert_health": {
      "user_addr": "terra..."
    }, 
    "clear_bad_debt": {
      "user_addr": "terra..."
    }, 
    "purge_storage": {
      "user_addr": "terra..."
    }, 
    "snapshot": {
      "user_addr": "terra..."
    } 
  }
}
```

{% endtab %}
{% endtabs %}

## QueryMsg

### `Config`

Return strategy configurations.

{% tabs %}
{% tab title="Rust" %}

```rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
    Config {}
}
```

{% endtab %}

{% tab title="JSON" %}

```json
{
  "config": {}
}
```

{% endtab %}
{% endtabs %}

### `State`

Return the global state of the strategy.

{% tabs %}
{% tab title="Rust" %}

```rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
    State {}
}
```

{% endtab %}

{% tab title="JSON" %}

```json
{
  "state": {}
}
```

{% endtab %}
{% endtabs %}

### `Positions`

Enumerate all user positions.

{% tabs %}
{% tab title="Rust" %}

```rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
    Positions {
        start_after: Option<String>,
        limit: Option<u32>
    }
}
```

{% endtab %}

{% tab title="JSON" %}

```json
{
  "positions": {
    "start_after": "terra...",
    "limit": 10
  }
}
```

{% endtab %}
{% endtabs %}

| Key             | Type   | Description         |
| --------------- | ------ | ------------------- |
| `start_after`\* | String | Used for pagination |
| `limit`\*       | u32    | Used for pagination |

\* = optional

### `Postion`

Return data on an individual user's position.

{% tabs %}
{% tab title="Rust" %}

```rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
    Position {
        user: String
    }  
}
```

{% endtab %}

{% tab title="JSON" %}

```json
{
  "position": {
    "user": "terra..."
  }
}
```

{% endtab %}
{% endtabs %}

| Key    | Type   | Description                                    |
| ------ | ------ | ---------------------------------------------- |
| `user` | String | Address to return data on individual positions |

### `Health`

Query the health of a user's position: value of assets, debts, and LTV.

{% tabs %}
{% tab title="Rust" %}

```rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
    Health {
        user: String
    }
}
```

{% endtab %}

{% tab title="JSON" %}

```json
{
  "health": {
    "user": "terra..."
  }
}
```

{% endtab %}
{% endtabs %}

| Key    | Type   | Description               |
| ------ | ------ | ------------------------- |
| `user` | String | Address to get health for |

### `Snapshot`

Query the snapshot of a user's position. NOTE: Snapshot is a temporary functionality used for calculating the user's PnL, which is to be displayed on the frontend. Once the frontend team has built an off-chain indexing facility that can calculate PnL without the use of snapshots, this query function will be removed.

{% tabs %}
{% tab title="Rust" %}

```rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
    Snapshot {
        user: String
    }  
}
```

{% endtab %}

{% tab title="JSON" %}

```json
{
  "snapshot": {
    "user": "terra..."
  }
}
```

{% endtab %}
{% endtabs %}

| Key    | Type   | Description                 |
| ------ | ------ | --------------------------- |
| `user` | String | Address to get snapshot for |

## Structs

### `StateBase`

Global state of the contract.

```rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct StateBase<T> {
    pub total_bond_units: Uint128,
    pub total_debt_units: Uint128,
    pub pending_rewards: AssetListBase<T>
}
```

| Key                | Type              | Description                                                                         |
| ------------------ | ----------------- | ----------------------------------------------------------------------------------- |
| `total_bond_units` | Uint128           | Total amount of bond units; used to calculate each user's share of bonded LP tokens |
| `total_debt_units` | Uint128           | Total amount of debt units; used to calculate each user's share of the debt         |
| `pending_rewards`  | AssetListBase\<T> | Reward tokens that can be reinvested in the next harvest                            |

### `PositionBase`

Info of individual users' positions.

```rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct StateBase<T> {
    pub total_bond_units: Uint128,
    pub total_debt_units: Uint128,
    pub pending_rewards: AssetListBase<T>
}
```

| Key                | Type              | Description                                                                         |
| ------------------ | ----------------- | ----------------------------------------------------------------------------------- |
| `total_bond_units` | Uint128           | Total amount of bond units; used to calculate each user's share of bonded LP tokens |
| `total_debt_units` | Uint128           | Total amount of debt units; used to calculate each user's share of the debt         |
| `pending_rewards`  | AssetListBase\<T> | Reward tokens that can be reinvested in the next harvest                            |

### `Health`

Info of individual users' health.

```rust
#[derive(Default, Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct Health {
    pub bond_amount: Uint128,
    pub bond_value: Uint128,
    pub debt_amount: Uint128,
    pub debt_value: Uint128,
    pub ltv: Option<Decimal>
}
```

| Key           | Type    | Description                                                             |
| ------------- | ------- | ----------------------------------------------------------------------- |
| `bond_amount` | Uint128 | Amount of primary pair liquidity tokens owned by this position          |
| `bond_value`  | Uint128 | Value of the position's asset, measured in the short asset              |
| `debt_amount` | Uint128 | Amount of secondary assets owed by this position                        |
| `debt_value`  | Uint    | Value of the position's debt, measured in the short asset               |
| `ltv`\*       | Decimal | The ratio of `debt_value` to `bond_value`; None if `bond_value` is zero |

\* = optional

### `Snapshot`

Every time the user invokes `update_position`, we record a snaphot of the position. This snapshot does not have any impact on the contract's normal functioning. Rather it is used by the frontend to calculate PnL. Once we have the infrastructure for calculating PnL off-chain available, we will migrate the contract to delete this.&#x20;

```rust
#[derive(Default, Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct Snapshot {
    pub time: u64,
    pub height: u64,
    pub position: PositionUnchecked,
    pub health: Health
}
```

| Key        | Type | Description                         |
| ---------- | ---- | ----------------------------------- |
| `time`     | u64  |                                     |
| `height`   | u64  |                                     |
| `position` |      | Info of individual users' positions |
| `health`   |      | Info of individual users' positions |

### `PositionsResponseItem`

```rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct PositionsResponseItem {
    pub user: String,
    pub position: PositionUnchecked
}
```

| Key        |        |   |
| ---------- | ------ | - |
| `user`     | String |   |
| `position` |        |   |

## Enums

### `Action`

Defines a list of actions that users can perform on their positions.&#x20;

```rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum Action {
    Deposit(AssetUnchecked), 
    Borrow {
        amount: Uint128
    }, 
    Repay {
        amount: Uint128
    },
    Bond {
        slippage_tolerance: Option<Decimal>
    },
    Unbond {
        bond_units_to_reduce: Uint128
    }, 
    Swap {
        offer_amount: Uint128,
        max_spread: Option<Decimal>
    }
}
```

| Function  | Description                                                                                                                      | Keys/Types                                                                                          |
| --------- | -------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `Deposit` | Deposit asset of specified type and amount                                                                                       |                                                                                                     |
| `Borrow`  | Borrow secondary asset of specified amount from Red Bank                                                                         | <ul><li><code>amount</code>: Uint 128</li></ul>                                                     |
| `Repay`   | Repay secondary asset of specified amount to Red Bank                                                                            | <ul><li><code>amount</code>: Uint 128</li></ul>                                                     |
| `Bond`    | Provide all unlocked primary and secondary asset to Astroport pair, and bond the received liquidity tokens to the staking pool   | <ul><li><code>slippage\_tolerance</code>\* : Decimal</li></ul>                                      |
| `Unbond`  | Burn a specified amount bond units, unbond liquidity tokens of corresponding amount from the staking pool and withdraw liquidity | <ul><li><code>bond\_units\_to\_reduce</code>: Uint 128</li></ul>                                    |
| `Swap`    | Swap a specified amount of unlocked primary asset to the secondary asset                                                         | <ul><li><code>offer\_amount</code> : Uint128</li><li><code>max\_spread</code>\* : Decimal</li></ul> |

\* = optional

### `CallbackMsg`

Since CallbackMsg are always sent by the contract itself, we assume all types are already validated and don't do additional checks. E.g. user addresses are Addr instead of String.&#x20;

```rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum CallbackMsg {
    ProvideLiquidity {
        user_addr: Option<Addr>,
        slippage_tolerance: Option<Decimal>
    }, 
    WithdrawLiquidity {
        user_addr: Addr
    }, 
    Bond {
        user_addr: Option<Addr>
    }, 
    Unbond {
        user_addr: Addr,
        bond_units_to_reduce: Uint128
    }, 
    Borrow {
        user_addr: Addr,
        borrow_amount: Uint128
    }, 
    Repay{
        user_addr: Addr,
        repay_amount: Option<Uint128>
    }, 
    Swap {
        user_addr: Option<Addr>,
        offer_asset_info: AssetInfo,
        offer_amount: Option<Uint128>,
        max_spread: Option<Decimal>
    }, 
    Balance {
        max_spread: Option<Decimal>
    }, 
    Cover {
        user_addr: Addr
    },
    Refund {
        user_addr: Addr,
        recipient_addr: Addr,
        percentage: Decimal
    }, 
    AssertHealth {
        user_addr: Addr
    }, 
    ClearBadDebt {
        user_addr: Addr
    }, 
    PurgeStorage {
        user_addr: Addr
    }, 
    Snapshot {
        user_addr: Addr
    }
}
```

| Function             | Description                                                                                                                                                                                                | Keys/Types                                                                                                                                                                                  |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `provide_liquidity`  | Provides unlocked primary & secondary assets to the AMM pool, receive share tokens; Reduce the user's unlocked primary & secondary asset amounts to zero; Increase the user's unlocked share token amount  | <ul><li><code>user\_addr</code>\* : String</li><li><code>slippage\_tolerance</code>\* : Decimal</li></ul>                                                                                   |
| `withdraw_liquidity` | Burns the user's unlocked share tokens, receive primary & secondary assets; Reduce the user's unlocked share token amount to zero; Increase the user's unlocked primary & secondary asset amounts          | <ul><li><code>user\_addr</code>: String</li></ul>                                                                                                                                           |
| `bond`               | Bonds share tokens to the staking contract; Reduce the user's unlocked share token amount to zero; Increase the user's bond units                                                                          | <ul><li><code>user\_addr</code>\* :  String</li></ul>                                                                                                                                       |
| `unbond`             | Unbonds share tokens from the staking contract; Reduce the user's bond units; Increase the user's unlocked share token amount                                                                              | <ul><li><code>user\_addr</code>: Addr</li><li><code>bond\_units\_to\_reduce</code>: Uint128</li></ul>                                                                                       |
| `borrow`             | Borrows specified amount of secondary asset from Red Bank; Increase the user's debt units; Increase the user's unlocked secondary asset amount                                                             | <ul><li><code>user\_addr</code>: Addr</li><li><code>borrow\_amount</code>: Uint128</li></ul>                                                                                                |
| `repay`              | Repays specified amount of secondary asset to Red Bank; Reduce the user's debt units; Reduce the user's unlocked secondary asset amount.                                                                   | <ul><li><code>user\_addr</code>: String</li><li><code>repay\_amount</code>\*: Uint128</li></ul>                                                                                             |
| `swap`               | Swaps a specified amount of primary asset to secondary asset; Reduce the user's unlocked primary asset amount; Increase the user's unlocked secondary asset amount;                                        | <ul><li><code>user\_addr</code>*: String</li><li><code>offer\_asset\_info</code>: String</li><li><code>offer\_amount</code>*: Uint128</li><li><code>max\_spread</code>\*: Decimal</li></ul> |
| `balance`            | Swaps the primary and secondary assets currently held by the contract as pending rewards, such that the two assets have the same value and can be reinvested. Only used during the `Harvest` function call | `max_spread`\*: Decimal                                                                                                                                                                     |
| `cover`              | Sells an appropriate amount of a user's unlocked primary asset, such that the user has enough unlocked secondary asset to fully pay off debt. Only used during the `Liquidate` function call               | <ul><li><code>user\_addr</code>: String</li></ul>                                                                                                                                           |
| `refund`             | Sends a percentage of a user's unlocked primary & seoncdary asset to a recipient; default to the user if unspecified. Reduce the user's primary & secondary asset amounts                                  | <ul><li><code>user\_addr</code>: String</li><li><code>recipient\_addr</code>: String</li><li><code>percentage</code>: Decimal</li></ul>                                                     |
| `assert_health`      | Calculates a user's current LTV. If below the maximum LTV, emits a `position_updated` event; if above the maximum LTV, throw an error                                                                      | <ul><li><code>user\_addr</code>: String</li></ul>                                                                                                                                           |
| `clear_bad_debt`     | Check whether the user still has an outstanding debt. If no, do nothing. If yes, waive the debt from the user's position, and emit a `bad_debt` event                                                      | <ul><li><code>user\_addr</code>: String</li></ul>                                                                                                                                           |
| `purge_storage`      | Remove the user's position from contract storage if it is empty. Invoked at the end of `update_position` and `liquidate` callback chains                                                                   | <ul><li><code>user\_addr</code>: String</li></ul>                                                                                                                                           |
| `snapshot`           | See the comment on struct `Snapshot`. This callback should be removed at some point after launch when our tx indexing infrastructure is ready                                                              | <ul><li><code>user\_addr</code>: String</li></ul>                                                                                                                                           |

\* = optional
