# 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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ocean.fi/protocol-architecture/04-protocol-architecture/strategy-modules.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
