> For the complete documentation index, see [llms.txt](https://docs.ocean.fi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ocean.fi/protocol-architecture/04-protocol-architecture/strategy-modules.md).

# Strategy Modules

## Overview

Ocean Finance implements a modular strategy architecture through specialized handler contracts built on a standardized abstract base. Each handler manages interactions with external yield protocols, allowing the protocol to diversify yield sources while maintaining security, operational efficiency, and consistent interfaces.

## Handler Architecture

![Handler Architecture](/files/FL5qwnhy8DlGT1XOHltL)

## BaseHandler Abstract Contract

**Contract**: `BaseHandler.sol`\
**Purpose**: Provides standardized interface and common functionality for all strategy handlers

### Core Interface

```solidity
abstract contract BaseHandler is IBaseHandler {
    IAddressProvider public addressProvider;
    
    constructor(IAddressProvider addressProvider_) {
        addressProvider = addressProvider_;
    }
    
    // Standard asset management interface
    function receiveAsset(address asset_, uint256 amount_) external virtual;
    function claimAsset(address to_, address asset_, uint256 amount_) external virtual;
    
    // Access control modifiers
    modifier onlyStrategyAllocator() {
        require(msg.sender == addressProvider.strategyAllocator(), "Not strategy allocator");
        _;
    }
    
    modifier validAddress(address address_) {
        require(address_ != address(0), "Invalid address");
        _;
    }
    
    modifier validAmount(uint256 amount_) {
        require(amount_ > 0, "Invalid amount");
        _;
    }
}
```

### Standardized Features

* **Unified Access Control**: All handlers use `onlyStrategyAllocator` modifier
* **Common Asset Interface**: Standardized `receiveAsset` and `claimAsset` functions
* **Address Resolution**: Centralized address management via `AddressProvider`
* **Input Validation**: Common validation modifiers for addresses and amounts
* **Event Standardization**: Consistent event patterns through `IBaseHandlerEvents`

### Implementation Requirements

All concrete handlers must:

1. **Inherit from BaseHandler**: `contract MyHandler is BaseHandler, IMyHandler`
2. **Implement Core Methods**: Override `receiveAsset` and `claimAsset`
3. **Use Standardized Modifiers**: Apply access control and validation consistently
4. **Follow Event Patterns**: Emit standardized events for tracking

### Handler Inheritance Hierarchy

![Handler Inheritance Hierarchy](/files/u7ErhhsbmUhBrx4Zdb47)

```
IBaseHandler <|-- BaseHandler
IBaseHandlerEvents <|-- BaseHandler
BaseHandler <|-- EthenaHandler
BaseHandler <|-- SkyHandler
BaseHandler <|-- NestHandler

class IEthenaHandler {
    <<interface>>
}
class ISkyHandler {
    <<interface>>
}
class INestHandler {
    <<interface>>
}

IEthenaHandler <|-- EthenaHandler
ISkyHandler <|-- SkyHandler
INestHandler <|-- NestHandler
```

````

## EthenaHandler

**Contract**: `EthenaHandler.sol`  
**Inherits**: `BaseHandler`, `IEthenaHandler`  
**Purpose**: Manages interactions with Ethena Protocol for USDe and sUSDe

### Implementation
```solidity
contract EthenaHandler is BaseHandler, IEthenaHandler {
    constructor(IAddressProvider addressProvider_) 
        BaseHandler(addressProvider_) {}
        
    function receiveAsset(address asset_, uint256 amount_) 
        external override onlyStrategyAllocator validAmount(amount_) {
        // Standardized asset receipt implementation
    }
}
````

### Core Operations

#### Staking USDe

```solidity
function stakeUSDe(uint256 amount_, uint256 minShares_) 
    external onlyStrategyAllocator validAmount(amount_) {
    // Stakes USDe for sUSDe to earn delta-neutral yield
    IStakedUSDe(sUSDe).deposit(amount_, address(this));
}
```

#### Cooldown Management

```solidity
function cooldownAssets(uint256 assets_) 
    external onlyStrategyAllocator validAmount(assets_) returns (uint256 shares) {
    // Initiates Ethena cooldown for sUSDe unstaking
    return IStakedUSDe(sUSDe).cooldownAssets(assets_);
}

function cooldownShares(uint256 shares_) 
    external onlyStrategyAllocator validAmount(shares_) returns (uint256 assets) {
    // Alternative cooldown initiation by shares
    return IStakedUSDe(sUSDe).cooldownShares(shares_);
}
```

#### Unstaking Operations

```solidity
function unstakeUSDe(address receiver_) 
    external onlyStrategyAllocator validAddress(receiver_) returns (uint256 assets) {
    // Claims assets after cooldown period expires
    return IStakedUSDe(sUSDe).unstake(receiver_);
}

function withdrawUSDe(uint256 assets_, address receiver_) 
    external onlyStrategyAllocator validAmount(assets_) validAddress(receiver_) 
    returns (uint256 shares) {
    // Direct withdrawal if cooldown is disabled
    return IStakedUSDe(sUSDe).withdraw(assets_, receiver_, address(this));
}

function redeemUSDe(uint256 shares_, address receiver_) 
    external onlyStrategyAllocator validAmount(shares_) validAddress(receiver_) 
    returns (uint256 assets) {
    // Direct redemption if cooldown is disabled  
    return IStakedUSDe(sUSDe).redeem(shares_, receiver_, address(this));
}
```

### Asset Management

```solidity
function transferAsset(address asset, address to, uint256 amount) external onlyAdmin {
    // Emergency asset transfer capability
    IERC20(asset).safeTransfer(to, amount);
}

function approveAsset(address asset, address spender, uint256 amount) external onlyService {
    // Manage approvals for protocol interactions
    IERC20(asset).forceApprove(spender, amount);
}
```

### Key Features

* **Delta-Neutral Yield**: Ethena's sUSDe provides yield without directional crypto exposure
* **Cooldown Management**: Handles Ethena's unstaking cooldown periods
* **Flexible Withdrawals**: Supports both cooldown and direct withdrawal modes
* **Balance Tracking**: Maintains accurate asset accounting

## SkyHandler

**Contract**: `SkyHandler.sol`\
**Inherits**: `BaseHandler`, `ISkyHandler`\
**Purpose**: Manages interactions with Sky Protocol for USDS and sUSDS

### Implementation

```solidity
contract SkyHandler is BaseHandler, ISkyHandler {
    constructor(IAddressProvider addressProvider_) 
        BaseHandler(addressProvider_) {}
        
    function receiveAsset(address asset_, uint256 amount_) 
        external override onlyStrategyAllocator validAmount(amount_) {
        // Standardized asset receipt with optional auto-staking
    }
}
```

### Core Operations

#### Staking USDS

```solidity
function stakeUsds(uint256 amount_) 
    external onlyStrategyAllocator validAmount(amount_) {
    // Stakes USDS for sUSDS to earn Sky rewards
    ISavingsUsds(sUSDS).deposit(amount_, address(this));
}
```

#### Unstaking Operations

```solidity
function withdrawUsds(uint256 assets_, address receiver_) 
    external onlyStrategyAllocator validAmount(assets_) validAddress(receiver_) 
    returns (uint256 shares) {
    // Withdraw specific amount of USDS
    return ISavingsUsds(sUSDS).withdraw(assets_, receiver_, address(this));
}

function redeemUsds(uint256 shares_, address receiver_) 
    external onlyStrategyAllocator validAmount(shares_) validAddress(receiver_) 
    returns (uint256 assets) {
    // Redeem specific shares for USDS
    return ISavingsUsds(sUSDS).redeem(shares_, receiver_, address(this));
}
```

#### PSM Swapping

```solidity
function swapUsdcToUsds(uint256 amountIn_) 
    external onlyStrategyAllocator validAmount(amountIn_) returns (uint256 amountOut) {
    // Convert USDC to USDS via PSM
    amountOut = IPsm(psm).sellGem(address(this), amountIn_);
}

function swapUsdsToUsdc(uint256 amountIn_) 
    external onlyStrategyAllocator validAmount(amountIn_) returns (uint256 amountOut) {
    // Convert USDS to USDC via PSM  
    amountOut = IPsm(psm).buyGem(address(this), amountIn_);
}
```

### Balance Tracking

```solidity
function getUsdsBalance() external view returns (uint256) {
    // Get USDS balance including staked positions
    return IERC20(usds).balanceOf(address(this)) + 
           ISavingsUsds(sUSDS).maxWithdraw(address(this));
}

function getSUsdsBalance() external view returns (uint256) {
    // Get sUSDS share balance
    return IERC20(sUSDS).balanceOf(address(this));
}
```

### Key Features

* **Sky Yield**: Earns yield through Sky Protocol's savings rate
* **PSM Integration**: Efficient USDC/USDS swapping via Peg Stability Module
* **ERC4626 Compliance**: Standard vault interface for staking operations
* **Balance Aggregation**: Comprehensive balance tracking across staked/unstaked positions

## NestHandler

**Contract**: `NestHandler.sol`\
**Inherits**: `BaseHandler`, `INestHandler`\
**Purpose**: Manages deposits and withdrawals from Nest Protocol vaults

### Implementation

```solidity
contract NestHandler is BaseHandler, INestHandler {
    using EnumerableSet for EnumerableSet.AddressSet;
    
    constructor(IAddressProvider addressProvider_) 
        BaseHandler(addressProvider_) {}
        
    function receiveAsset(address asset_, uint256 amount_) 
        external override onlyStrategyAllocator validAmount(amount_) {
        // Standardized asset receipt with vault management
    }
}
```

### Core Operations

#### Vault Deposits

```solidity
function deposit(
    address teller_,
    address vault_, 
    uint256 amount_,
    uint256 minimumMint_
) external onlyStrategyAllocator validAddress(teller_) validAddress(vault_) 
    validAmount(amount_) returns (uint256 shares) {
    // Deposit assets into Nest vault via Teller
    shares = ITeller(teller_).deposit(vault_, asset, amount_, minimumMint_);
}
```

#### Atomic Withdrawals

```solidity
function withdraw(
    address atomicQueue_,
    address vault_,
    uint256 shares_,
    address receiver_
) external onlyStrategyAllocator validAddress(atomicQueue_) validAddress(vault_) 
    validAmount(shares_) validAddress(receiver_) returns (uint256 assets) {
    // Create atomic withdrawal request
    assets = IAtomicQueue(atomicQueue_).updateAtomicRequest(
        vault_, shares_, receiver_, address(this)
    );
}
```

### Teller Management

```solidity
function addValidTeller(address teller) external onlyAdmin {
    // Add authorized teller for deposits
    validTellers.add(teller);
}

function removeValidTeller(address teller) external onlyAdmin {
    // Remove teller authorization
    validTellers.remove(teller);
}

function isValidTeller(address teller) external view returns (bool) {
    // Check if teller is authorized
    return validTellers.contains(teller);
}
```

### Balance Tracking

```solidity
function getVaultBalance(address vault) external view returns (uint256) {
    // Get balance in specific Nest vault
    return IERC20(vault).balanceOf(address(this));
}

function getTotalBalance() external view returns (uint256 total) {
    // Aggregate balance across all vaults
    uint256 length = validVaults.length();
    for (uint256 i = 0; i < length; i++) {
        total += IERC20(validVaults.at(i)).balanceOf(address(this));
    }
}
```

### Key Features

* **Multi-Vault Support**: Can interact with multiple Nest vaults simultaneously
* **Teller Validation**: Only authorized tellers can be used for deposits
* **Atomic Withdrawals**: Efficient withdrawal mechanism via AtomicQueue
* **Vault Enumeration**: Tracks and manages multiple vault positions

## Handler Security Model

### Standardized Access Control

All handlers inherit consistent access control from BaseHandler:

```solidity
// Primary access control - only StrategyAllocator can execute operations
modifier onlyStrategyAllocator() {
    require(msg.sender == addressProvider.strategyAllocator(), "Not strategy allocator");
    _;
}

// Input validation modifiers
modifier validAddress(address address_) {
    require(address_ != address(0), "Invalid address");
    _;
}

modifier validAmount(uint256 amount_) {
    require(amount_ > 0, "Invalid amount");
    _;
}
```

### Operation Validation

* **Asset Verification**: All operations validate asset addresses
* **Amount Validation**: Prevent zero-amount operations
* **Slippage Protection**: Minimum output amounts where applicable
* **Reentrancy Guards**: Protect against reentrancy attacks

### Emergency Functions

```solidity
function emergencyWithdraw(address asset, uint256 amount) external onlyAdmin {
    // Emergency asset recovery
    IERC20(asset).safeTransfer(msg.sender, amount);
}

function pause() external onlyAdmin {
    // Pause handler operations
    _pause();
}
```

## Strategy Execution Flow

![Strategy Execution Flow](/files/F1i6nCpzYF1vUNCU6W0R)

## BaseHandler Standardization Benefits

![BaseHandler Standardization Benefits](/files/x2aKyc8S7pdNVIGNWkrD)

## Handler Integration Pattern

### 1. Whitelisting

* Handlers must be whitelisted in StrategyAllocator
* Only SERVICE\_ROLE can execute handler operations
* Admin can add/remove handlers as needed

### 2. Asset Flow

```
User Collateral → MintingManager → StrategyAllocator → Handler → External Protocol
```

### 3. Yield Flow

```
External Protocol → Handler → StrategyAllocator → YieldDistributor → Users/Stakers
```

### 4. Reporting

* Handlers report balances to StrategyAllocator
* Real-time position tracking across all strategies
* Automated rebalancing based on performance metrics

## Handler Development Guide

### Creating New Handlers

With the BaseHandler architecture, developing new handlers follows a standardized pattern:

#### 1. Contract Structure

```solidity
contract NewProtocolHandler is BaseHandler, INewProtocolHandler {
    constructor(IAddressProvider addressProvider_) 
        BaseHandler(addressProvider_) {}
    
    // Required implementations
    function receiveAsset(address asset_, uint256 amount_) 
        external override onlyStrategyAllocator validAmount(amount_) {
        // Handle incoming assets
    }
    
    function claimAsset(address to_, address asset_, uint256 amount_) 
        external override onlyStrategyAllocator validAddress(to_) validAmount(amount_) {
        // Handle outgoing assets
    }
    
    // Protocol-specific functions
    function protocolSpecificOperation(uint256 amount_) 
        external onlyStrategyAllocator validAmount(amount_) {
        // Custom protocol interactions
    }
}
```

#### 2. Implementation Requirements

1. **Inherit BaseHandler**: All handlers must extend `BaseHandler`
2. **Implement Required Methods**: Override `receiveAsset` and `claimAsset`
3. **Use Standard Modifiers**: Apply `onlyStrategyAllocator`, `validAddress`, `validAmount`
4. **Follow Naming Conventions**: Use underscore suffix for parameters (`amount_`, `to_`)
5. **Emit Standard Events**: Use `IBaseHandlerEvents` for consistency

#### 3. Integration Checklist

* [ ] Contract inherits from BaseHandler
* [ ] Required methods implemented
* [ ] All external functions use proper access control
* [ ] Input validation applied consistently
* [ ] Protocol-specific interface defined
* [ ] Comprehensive unit tests written
* [ ] Integration tests with StrategyAllocator
* [ ] Security audit completed
* [ ] Documentation updated

### Supported Protocol Types

* **Staking Protocols**: For yield-bearing token strategies
* **Lending Protocols**: For supply-side yield generation
* **AMM Protocols**: For liquidity provision strategies
* **Vault Protocols**: For complex multi-strategy yield
* **Bridge Protocols**: For cross-chain yield opportunities

The BaseHandler architecture ensures that Ocean Finance can efficiently integrate with new protocols while maintaining security, consistency, and operational efficiency across all yield strategies.
