> ## Documentation Index
> Fetch the complete documentation index at: https://docs.defindex.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Introduction

## What is a strategy?

A strategy is a set of **steps** to execute an investment in one or several protocols: holding an asset, farming and auto-compounding rewards, leveraged lending, leveraged farming.

A vault does not know any of those steps. It hands assets to a strategy and asks what they are worth now. Everything protocol-specific lives behind [the strategy trait](#the-strategy-trait), which is why a new strategy can be added without touching the vault.

For a worked example, see [Blend Autocompound Strategy](/strategy-developers/blend-autocompound-strategy).

## The Strategy Trait

A strategy implements [`DeFindexStrategyTrait`](https://github.com/defindex-io/stellar-contracts/blob/main/strategies/core/src/lib.rs). Six methods, and any vault can allocate to your contract.

```toml theme={null}
[dependencies]
defindex-strategy-core = "0.2.0"
```

### The six methods

| Method          | Signature                                                                                        |
| --------------- | ------------------------------------------------------------------------------------------------ |
| `__constructor` | `fn __constructor(env: Env, asset: Address, init_args: Vec<Val>)`                                |
| `asset`         | `fn asset(env: Env) -> Result<Address, StrategyError>`                                           |
| `deposit`       | `fn deposit(env: Env, amount: i128, from: Address) -> Result<i128, StrategyError>`               |
| `withdraw`      | `fn withdraw(env: Env, amount: i128, from: Address, to: Address) -> Result<i128, StrategyError>` |
| `harvest`       | `fn harvest(env: Env, from: Address, data: Option<Bytes>) -> Result<(), StrategyError>`          |
| `balance`       | `fn balance(env: Env, from: Address) -> Result<i128, StrategyError>`                             |

`from` is always the vault.

* **`__constructor`**: the underlying asset plus `init_args`, a free-form `Vec<Val>` whose shape you define. Pool addresses, routers, thresholds, the keeper. Validate here.
* **`deposit`** and **`withdraw`**: return the vault's balance *after* the operation, not the amount moved. `from.require_auth()` first.
* **`balance`**: the vault's position at the live protocol rate. Do not cache the rate.

> **The one rule that matters.** `deposit`, `withdraw` and `balance` return **underlying asset**, never internal shares or protocol receipt tokens. The vault prices its dfTokens off that number, so a strategy that returns bTokens gives every user of the vault a wrong share price.

**`harvest`** is every active action the position needs: claiming and compounding rewards, adjusting a leverage ratio, rebalancing a drifting position, rolling an expiring one. Deposit and withdraw are driven by the vault; harvest is driven by nobody, which is why it needs a keeper. `data` is an optional opaque blob, by convention a big-endian `i128` minimum amount out so a harvest that swaps cannot be sandwiched. With nothing to do, return `Ok(())` rather than failing.

### Authorization

Address-based, through `require_auth()`. The trait defines no roles, but you need one: the **keeper**, the address allowed to call `harvest`. Store it yourself, check it twice, and allow rotation signed by the current keeper.

```rust theme={null}
let keeper = storage::get_keeper(&e)?;
keeper.require_auth();
if from != keeper {
    return Err(StrategyError::NotAuthorized);
}
```

Every call your strategy makes on its own behalf needs `env.authorize_as_current_contract()` with the matching sub-invocations. Exercise that with real auth in at least one test, not only `mock_all_auths()`.

### Events

Emit the ones from [`defindex_strategy_core::event`](https://github.com/defindex-io/stellar-contracts/blob/main/strategies/core/src/event.rs). Indexers, the API and the APY charts read them, so a silent strategy is invisible in the product even when it works.

```rust theme={null}
pub struct DepositEvent  { pub amount: i128, pub from: Address }
pub struct WithdrawEvent { pub amount: i128, pub from: Address }
pub struct HarvestEvent  { pub amount: i128, pub from: Address, pub price_per_share: i128 }
```

`price_per_share` is what DeFindex computes your APY from. See [Strategies APY](#strategies-apy).

### Errors

Return [`StrategyError`](https://github.com/defindex-io/stellar-contracts/blob/main/strategies/core/src/error.rs) rather than panicking: `NotInitialized` (401), `InvalidArgument` (411), `InsufficientBalance` (412), `InvalidSharesMinted` (416), `OnlyPositiveAmountAllowed` (417), `NotAuthorized` (418).

### Share accounting

Several vaults can use one strategy at once, so track shares per vault and convert to underlying on the way out. ERC-4626, with the upstream rate refreshed on every touch.

* **Rounding direction.** In the protocol's favour on the way in, the user's disfavour on the way out. The other way round leaks value one stroop at a time.
* **The inflation attack.** The first depositor can donate assets so later deposits round to zero shares. Burn a small fixed amount of shares on the first deposit, permanently.

### Before you ship

* `deposit`, `withdraw` and `balance` return underlying, at the live rate.
* `from.require_auth()` on deposit and withdraw, keeper check on harvest.
* All three events emitted, with a real `price_per_share`.
* First-deposit inflation guard in place.
* Rounding tested in both directions.

Build to `wasm32v1-none`, optimize with `stellar contract optimize`, and test against the upstream protocol deployed locally rather than a mock of it. The [Blend Autocompound Strategy](/strategy-developers/blend-autocompound-strategy) does all of the above, and its [tests](https://github.com/defindex-io/stellar-contracts/tree/main/strategies/blend/src/test/blend) cover the inflation and rounding attacks explicitly.

## Strategies APY

Every strategy earns differently, so DeFindex does not try to model lending rates, emission schedules and reward prices per protocol. It reads one number off the `HarvestEvent`: the **price per share**.

```rust theme={null}
pub struct HarvestEvent {
    pub amount: i128,
    pub from: Address,
    pub price_per_share: i128,
}
```

Depositors receive shares. As the strategy earns, each share is worth more underlying. Track that one value over time and the APY falls out, whatever the strategy does inside.

Comparing the price per share now against its value $\Delta t$ days ago:

$$
\text{ROI} = \frac{\text{PPS}_\text{now}}{\text{PPS}_\text{then}} - 1
$$

$$
\text{APY} = \left(1 + \text{ROI} \right)^{\left(\frac{365.2425}{\Delta t}\right)} - 1
$$

`365.2425` is the average length of a year, leap years included.

**Example.** A price per share of `1.10` today against `1.00` thirty days ago is an ROI of `0.10`, which annualizes to $(1.10)^{365.2425/30} - 1 \approx 113.8\%$.

This is why [the trait](#the-strategy-trait) insists on emitting `HarvestEvent` with a real `price_per_share`. A strategy that does not is invisible to the APY charts, the API and the indexer.
