FungibleVault
wrappers, and fee vaults. Read first:
Supply and borrow,
Withdraw and repay,
Interest and revenue.
A reference DeFindexStrategyTrait adapter maps each DeFindex vault to one
controller supply account. Share accounting lives in the DeFindex vault
contract; the strategy holds only a vault-to-account mapping. See
DeFindex strategy for the trait API,
deposit/withdraw flows, and verification checklist.
The position model
Supply positions are not tokens. The controller stores them per account (account_id: u64), keyed by asset, as scaled shares (scaled_amount = amount / supply_index, RAY = 27 decimals). Your contract is the account owner;
the underlying value is scaled × supply_index, and the supply index grows as
borrowers pay interest. There is no share token to hold, no emissions token to
claim, and no harvest step — interest compounds into the index automatically.
Three integration properties make a clean two-call loop:
- Views accrue to now.
get_collateral_amount(account_id, hub_asset)returns the current underlying balance with interest simulated to the ledger timestamp — no keeper dependency, and the same fixed-point math the pool persists on the next mutation. What a view reports is what a deposit or withdrawal in the same transaction applies. - Balance views read no oracle.
get_collateral_amount,get_borrow_amount, andget_market_indexstay callable through any oracle outage, so yourbalance()never bricks downstream accounting. - Rounding always favours the pool, never you. A supply mints shares floor-rounded; a partial withdrawal burns them ceil-rounded. Both directions cost you a sub-unit rather than the pool. Do not replicate the formulas — re-read the view after the call and use what it reports.
The core loop
One strategy instance per asset; your contract iscaller everywhere.
Authorize
When your contract callssupply, the controller runs exactly one nested token
call: transfer(your_contract → pool, amount). Pre-authorize it with
authorize_as_current_contract — no allowances, no other entries:
withdraw needs no auth entry: tokens flow from the pool toward the recipient.
Your contract’s own require_auth as caller is satisfied by invoker
authorization. Resolve the pool address once at deploy time from
get_pool_address().
Size limits before acting
A withdrawal can revert on pool cash (#112), the market’s max-utilization cap
(#127), or the account’s LTV/HF gates (only if you also borrow). A deposit can
revert on the spoke supply cap (#311) or the position limit (#109).
Lifecycle rules
- Account deletion on full close. Withdrawing the last position deletes the
account. Reset your stored
account_idto0; supplying with a stale id raises#24 AccountNotFound. Views degrade gracefully for missing accounts (0, empty maps,i128::MAXhealth factor). - Min borrow collateral. While the vault account carries debt, LTV-weighted
collateral must stay above the instance-level
MinBorrowCollateralUsdfloor (get_min_borrow_collateral_usd, default$5 WAD). - Pause. The protocol circuit breaker blocks
supply, but notwithdraw— a paused protocol still lets solvent users exit.repay,renew_account, andrecapitalizealso stay available. Apausedspoke-asset flag is stricter: it blocks that asset’s exits too. - Oracle posture. Every mutating flow needs a complete, valid price snapshot and fails closed otherwise — there is no lenient risk-decreasing path. Balance reporting is oracle-free.
- Storage rent. Account keys auto-extend on every touch: when their
remaining life drops below 30 days, a read or write pushes it back to 120
days. A position nobody touches gets no such renewal, so call
renew_account(caller, account_id)periodically. It works while paused. Archived entries are restorable withRestoreFootprint, not lost. - Third parties can supply into your account, but only narrowly. A caller who is neither owner nor delegate may add only to hub assets the account already holds a supply position in, so it cannot consume your supply-position slots. Within that constraint your protocol balance is monotone-up from external action — relevant for share-price accounting; use a first-deposit inflation guard as the reference strategy does.
- Your account is an NFT.
account_idis the position-NFTtoken_id, and whoever holds that token is the owner the controller checks. Your contract must hold it. Transferring it transfers the whole position.
Verify
Verify your flows against the same cases the reference strategy covers: deposit/balance/withdraw round trips, third-party payout, interest accrual without index maintenance, and the account-recreation path after a full exit.Next
Controller ABI
Exact signatures for supply, withdraw, and every view used here.
Interest and revenue
How the supply index accrues the yield your vault reports.
DeFindex strategy
The reference vault adapter: one account per vault, trait API, and test
harness.
Accounts and risk
Account metadata, position limits, and spoke rules.
Errors
Every error code your integration can surface.

