Docs / vault contract

Under the shell.

Rust vault on NEAR (near-sdk). Share-based accounting, whitelisted strategies, a keeper role for the swarm, capped performance fee, NEP-297 events on every movement.

STATUS: UNAUDITED · TESTNET FIRST · APP OPENS WITH THE VAULT

Follow the build ↗
// near_beetle::vault
#[payable] deposit()                 // NEAR → shares
withdraw(shares)                     // shares → NEAR

// keeper: the swarm
deploy(strategy_id, amount)
recall(strategy_id, amount)
#[payable] harvest(strategy_id, reward_amount)
rebalance()

// views
get_share_price()  get_strategies()
preview_deposit(amount)

Interface

Every call,
by role.

All amounts are yoctoNEAR, passed as strings.
1 NEAR = 1024 yoctoNEAR.

User

anyone
deposit()
Payable. Mints shares for the attached NEAR, net of first-deposit storage. Returns the shares minted.
withdraw(shares)
Burns shares and pays NEAR from idle liquidity. Works while paused.

Keeper

keeper or owner
deploy(strategy_id, amount)
Idle → strategy, up to the strategy’s allocation cap.
recall(strategy_id, amount)
Strategy → idle. Works while paused.
harvest(strategy_id, reward_amount)
Payable. Reports yield; in the prototype, exactly reward_amount must be attached. Returns the fee shares minted.
rebalance()
Recalls excess, then deploys idle to targets. Returns the list of moves.

Owner

attach 1 yoctoNEAR
add_strategy(account_id, target_bps)
Whitelists a strategy. Returns its id.
update_strategy(strategy_id, target_bps?, enabled?)
Changes the target and/or the enabled flag. Moves no funds by itself.
remove_strategy(strategy_id)
Only when the strategy balance is zero.
set_performance_fee(bps)
At most 2,000 bps.
set_keeper · set_fee_recipient · set_owner
Reassign the roles.
pause() · unpause()
Pause blocks deposit, deploy and rebalance.

Views

read-only
get_config()
Roles, fee, pause flag, totals, minimum deposit.
get_strategies() · get_strategy(id)
Account, target, enabled, balance, lifetime harvested.
get_user_shares(account_id) · get_user_assets(account_id)
A user’s shares, and what they are worth in NEAR now.
get_share_price()
yoctoNEAR per 1024 shares. Starts at 1024.
total_assets() · total_shares() · idle_assets()
Vault totals.
preview_deposit(amount) · preview_withdraw(shares)
What a deposit would mint, what a withdrawal would pay.
storage_cost_per_account()
Upper bound of the first-deposit storage cost.

Key rules

How the vault behaves.

  • Share mathshares = assets * (S + 1) / (A + 1) and the inverse for withdrawals, both rounded down, computed with 256-bit intermediates. First depositor gets 1:1.
  • Inflation-attack guardA virtual share/asset offset of 1, a minimum net deposit of 0.01 NEAR, and internal accounting of idle assets: plain transfers to the contract don’t change the share price.
  • StrategiesAt most 20. The sum of target_bps over enabled strategies is at most 10,000. 10000 − sum(target_bps) stays idle as the withdrawal buffer.
  • HarvestThe reward compounds into the strategy balance. The performance fee, at most 2,000 bps, is minted as shares worth exactly the fee.
  • PauseBlocks deposit, deploy, rebalance. withdraw, recall and harvest still work.
  • WithdrawalsPaid from idle liquidity only; otherwise they fail with Insufficient idle liquidity. A failed transfer restores the burned shares.
  • StorageAn account’s first deposit pays for its own share entry, about 0.001 NEAR. The entry is kept at zero after a full withdrawal, with no storage refund.
  • Prototype scopeStrategy integrations are simulated with internal accounting. No NEAR leaves the vault on deploy, and yield is what the keeper reports and attaches.

Events

Every movement
leaves a trail.

The vault logs a NEP-297 event for each state-changing call, under the near_beetle standard, version 1.0.0.

Seven events: deposit, withdraw, withdraw_refunded, deploy, recall, harvest, rebalance.

// log line emitted by harvest
EVENT_JSON:{
  "standard": "near_beetle",
  "version": "1.0.0",
  "event": "harvest",
  "data": [{
    "strategy_id": 0,
    "reward": "…",
    "fee_assets": "…",
    "fee_shares": "…",
    "fee_recipient": "…",
    "share_price": "…"
  }]
}

Build & test

Run it
yourself.

The toolchain is pinned to Rust 1.86.0 with near-sdk 5.27; newer compilers can emit wasm features the NEAR runtime rejects.

cargo near optimises the wasm and embeds the ABI. Plain cargo build works too.

UNAUDITED · DO NOT USE WITH REAL FUNDS · TESTNET ONLY

# build
cargo install cargo-near
cargo near build non-reproducible-wasm
# → target/near/near_beetle_vault.wasm

# test
cargo test
# init call: new
{
  "owner_id": "you.testnet",
  "keeper_id": "keeper.testnet",
  "fee_recipient": "you.testnet",
  "performance_fee_bps": 1000
}

Back to / protocol

One vault. One swarm.

Continue ↗