Skip to content

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

IOrionStrategist Template

A self-contained template for deploying and automating IOrionStrategist contracts against the Orion Finance protocol.

Clone this repo, fill in a .env, and you're ready to deploy or run automated rebalancing.

Strategist contracts

This template deploys the following strategists from protocol-plugins (sourced directly via npm - no local copies):

Key Contract Strategy
tvl KBestTvlWeightedAverage Top-K assets by TVL, weighted proportionally to TVL
apy-equal KBestApyStrategist (EqualWeighted) Top-K assets by APY, equal weights
apy-weighted KBestApyStrategist (ApyWeighted) Top-K assets by APY, weights ∝ APY

Prerequisites

  • Node.js ≥ 24
  • npm

Quick start

git clone https://github.com/OrionFinanceAI/IOrionStrategist-template.git
cd IOrionStrategist-template
npm install
cp .env.example .env
# Edit .env with your RPC URLs, PRIVATE_KEY, and SEPOLIA_ORION_CONFIG_ADDRESS / MAINNET_ORION_CONFIG_ADDRESS
npm run compile

Deploy contracts

# Deploy all three strategist variants
npx hardhat run scripts/deploy.ts --network sepolia

# Or via npm
npm run deploy:sepolia
npm run deploy:mainnet

# Deploy a single contract
DEPLOY_CONTRACTS=tvl npx hardhat run scripts/deploy.ts --network sepolia

# Deploy a subset
DEPLOY_CONTRACTS=apy-equal,apy-weighted npx hardhat run scripts/deploy.ts --network sepolia

A deployment summary is written to deployments/<network>-<timestamp>.json (gitignored).

Environment variables

Variable Required Default Description
PRIVATE_KEY Yes - Deployer key; becomes strategist owner
SEPOLIA_RPC_URL For Sepolia - Sepolia JSON-RPC endpoint
MAINNET_RPC_URL For mainnet - Mainnet JSON-RPC endpoint
SEPOLIA_ORION_CONFIG_ADDRESS Yes if --network is sepolia / hardhat / localhost - OrionConfig contract
MAINNET_ORION_CONFIG_ADDRESS Yes if --network mainnet - OrionConfig contract
VAULT_ADDRESS No - If set, vault manager (PRIVATE_KEY) calls updateStrategist() on this vault. Requires DEPLOY_CONTRACTS to name exactly one strategist
STRATEGIST_K No 10 Top-K assets to select (1–65535)
DEPLOY_CONTRACTS No tvl,apy-equal,apy-weighted Comma-separated contracts to deploy
SKIP_VERIFY No - Set 1 to skip printing verify commands
ETHERSCAN_API_KEY No - Needed to run hardhat verify after deployment

Deployment output

{
  "network": "sepolia",
  "timestamp": "2026-05-21T12:00:00.000Z",
  "deployer": "0x...",
  "orionConfig": "0x...",
  "k": 10,
  "vault": null,
  "tvl": "0x...",
  "apy-equal": "0x...",
  "apy-weighted": "0x..."
}

Link a strategist to a vault

Each strategist must be linked to exactly one transparent vault. setVault() on the strategist is only callable by the vault itself; the vault manager triggers that by calling updateStrategist(). Linking is one-time and irreversible on the strategist.

Automatic - set VAULT_ADDRESS and deploy exactly one contract (DEPLOY_CONTRACTS=tvl). The deployer (PRIVATE_KEY) must be that vault's manager. The script calls updateStrategist() on the vault.

Manual - call updateStrategist() on the vault as its manager:

const vault = await ethers.getContractAt("OrionTransparentVault", "0x<VAULT_ADDR>");
await vault.updateStrategist("0x<STRATEGIST_ADDR>");

Verify on Etherscan

After deployment, the script prints the exact commands to verify each contract:

To verify on Etherscan, run:
  npx hardhat verify --network sepolia 0x<TVL_ADDR> <owner> <config> <k>
  ...

Verification publishes the source code to Etherscan so anyone can audit the logic and interact with the contract directly via the Etherscan UI. Requires ETHERSCAN_API_KEY in .env.


Run rebalancing manually

Provide one vault address or a comma-separated list. The script reads the strategist() on each vault, verifies it implements IOrionStrategist (ERC-165), and calls submitIntent() as the PRIVATE_KEY signer (the strategist owner).

# Single vault
VAULT_ADDRESS=0xAAA... npx hardhat run scripts/update-intents.ts --network sepolia

# Multiple vaults
VAULT_ADDRESS=0xAAA...,0xBBB...,0xCCC... npx hardhat run scripts/update-intents.ts --network sepolia

# Or via npm
npm run update-intents:sepolia
npm run update-intents:mainnet

Dry-run (no transactions, all vaults still resolved and checked):

DRY_RUN=1 VAULT_ADDRESS=0xAAA...,0xBBB... npx hardhat run scripts/update-intents.ts --network sepolia

Exit code is 1 on any failure - including vault read errors (e.g. strategist() reverts or the strategist fails the ERC-165 check) as well as failed submitIntent() calls - useful for cron/ECS alerting.

Environment variables

Variable Required Default Description
PRIVATE_KEY Yes - Strategist owner key
VAULT_ADDRESS Yes - Vault address or comma-separated list of vault addresses
ORION_STRATEGIST_INTERFACE_ID No - Override ERC-165 check to a specific bytes4
DRY_RUN No - Set 1 to log only - no transactions sent

Automated rebalancing

Option A - Cron job

# Preview the crontab line
bash infra/cron/setup.sh

# Or install it automatically (runs every 4 hours)
NETWORK=mainnet bash infra/cron/setup.sh --install

Logs are written to logs/iorion-strategist-template.log in the repo root (see infra/cron/setup.sh).

Option B - AWS ECS (Fargate + EventBridge)

  1. Build and push the image (tag with the commit SHA - CI uses the same strategy)

    GIT_SHA=$(git rev-parse --short HEAD)
    docker build -f infra/ecs/Dockerfile -t <ECR_REPO_URI>:${GIT_SHA} .
    docker push <ECR_REPO_URI>:${GIT_SHA}
  2. Store secrets in AWS Secrets Manager

    aws secretsmanager create-secret --name orion/PRIVATE_KEY     --secret-string '0x...'
    aws secretsmanager create-secret --name orion/MAINNET_RPC_URL --secret-string 'https://...'
    aws secretsmanager create-secret --name orion/VAULT_ADDRESS    --secret-string '0xAAA...,0xBBB...'
    aws secretsmanager create-secret --name orion/MAINNET_ORION_CONFIG_ADDRESS --secret-string '0x...'
  3. Register the task - fill in the <PLACEHOLDERS> in infra/ecs/task-definition.json, then:

    aws ecs register-task-definition --cli-input-json file://infra/ecs/task-definition.json
  4. Schedule with EventBridge - see the _comment block in infra/ecs/task-definition.json for the full aws events put-rule command. The default schedule is every 4 hours (cron(0 */4 * * ? *)).


Keeping contracts up to date

Contract source lives in the public OrionFinanceAI/protocol-plugins repo. The package is pinned to a git SHA in package.json. npm update will not move that pin - change the SHA, then reinstall:

# Edit the @orion-finance/plugins commit SHA in package.json, then:
npm install
npm run compile

Writing a custom strategist

To deploy your own strategist, implement IOrionStrategist:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.34;

import "@orion-finance/protocol/contracts/interfaces/IOrionStrategist.sol";
import "@orion-finance/protocol/contracts/interfaces/IOrionTransparentVault.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";

contract MyStrategist is IOrionStrategist, ERC165 {
    address private _vault;

    function setVault(address vault_) external {
        require(_vault == address(0), "already linked");
        require(msg.sender == vault_, "not authorized");
        _vault = vault_;
    }

    function submitIntent() external {
        IOrionTransparentVault.IntentPosition[] memory intent = _buildIntent();
        IOrionTransparentVault(_vault).submitIntent(intent);
    }

    function supportsInterface(bytes4 id) public view override(ERC165, IERC165) returns (bool) {
        return id == type(IOrionStrategist).interfaceId || super.supportsInterface(id);
    }

    function _buildIntent() internal view returns (IOrionTransparentVault.IntentPosition[] memory) {
        // your allocation logic here
    }
}
  1. Place the contract under contracts/ in this repo.

  2. Add contracts/ as a source in hardhat.config.ts:

    paths: { sources: "./contracts" }
  3. Add a deploy step in scripts/deploy.ts.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages