migrate_from_blend moves a Blend V2 position to XOXNO in one transaction. The controller repays Blend debt, withdraws collateral and non-collateral supply, deposits the withdrawn assets as XOXNO collateral, and runs a final health check before persisting state.
Entrypoint
| Parameter | Semantics |
|---|---|
caller | Must authorize the call. Owns the Blend position and the resulting XOXNO account. |
account_id | 0 creates a fresh account; non-zero merges into an existing account owned by caller. |
blend_pool | Target Blend pool. Must pass is_blend_pool_approved or the call reverts with #42 BlendPoolNotApproved. |
collateral_assets | Blend collateral tokens to withdraw. Each uses WithdrawCollateral with i128::MAX internally. |
supply_assets | Blend non-collateral supply to withdraw. Each uses Withdraw with i128::MAX. Deposited as XOXNO collateral. |
debt_caps | Per debt asset, the maximum the controller may borrow to repay Blend. Must be ≥ actual Blend debt. |
{collateral_assets, supply_assets, debt_caps} must be non-empty.
Atomic flow
The entire flow runs inside one controller call. Any revert rolls back all Blend and XOXNO state changes.Debt sourcing
Migration does not use the flash-loan receiver pattern. It uses an internal zero-fee strategy borrow:| Mechanism | flash_loan | Migration borrow |
|---|---|---|
| Entrypoint | controller.flash_loan | open_migration_borrow inside migrate_from_blend |
| Pool call | pool.flash_loan → receiver callback | pool.create_strategy |
| Fee | Configured bps | 0 |
| Debt outcome | Repaid in same callback | Permanent debt on the migrated account |
| Receiver contract | Required | None |
| Solvency check | At callback end | At strategy_finalize |
Refund reconciliation
debt_caps are upper bounds, not exact debt amounts. When Blend repays less than the cap, Blend refunds the surplus to the controller. reconcile_debt_refunds detects the refund via balance delta and calls repay_debt_from_controller. The migrated XOXNO debt equals the actual Blend debt, not the cap.
Looped positions
When the same token is both collateral and debt (for example USDC collateral plus USDC debt), the controller uses a two-phase submit:- Phase 1 — repay debt with an isolated balance snapshot so refunds do not alias with withdrawals.
- Phase 2 — withdraw collateral and supply with a fresh snapshot.
collateral_assets and debt_caps. Duplicate debt entries in debt_caps revert with #AssetsAreTheSame.
Blend request types
| Request | Constant | Amount | Purpose |
|---|---|---|---|
| Repay | REQ_REPAY = 5 | cap from debt_caps | Clear Blend debt |
| WithdrawCollateral | REQ_WITHDRAW_COLLATERAL = 3 | i128::MAX | Sweep all collateral |
| Withdraw | REQ_WITHDRAW = 1 | i128::MAX | Sweep non-collateral supply |
Authorization
| Leg | Who authorizes |
|---|---|
migrate_from_blend | caller.require_auth() |
Blend submit(from=caller) | Caller in the transaction auth tree (per phase) |
transfer(controller → blend_pool, cap) | Controller authorize_as_current_contract before repay submit |
Reentry guard
guarded_submit sets FlashLoanOngoing during Blend calls. Mutating controller entrypoints reject reentry while the guard is set (#400 FlashLoanOngoing).
Governance
Blend pools are allow-listed through governance:configs/blend_pools.json. Query approval with is_blend_pool_approved(blend_pool).
Events
Failure modes
| Condition | Error |
|---|---|
Empty collateral_assets, supply_assets, and debt_caps | #InvalidPayments |
Unapproved blend_pool | #42 BlendPoolNotApproved |
Duplicate debt asset in debt_caps | #AssetsAreTheSame |
debt_cap below actual Blend debt | Blend health check revert (atomic rollback) |
| End state fails health / LTV / min collateral | #InsufficientCollateral at finalize |
| Caller does not own target account | Ownership mismatch |
Example invoke
debt_cap to at least the actual Blend debt for that asset. Use get_account_positions and Blend views to size caps before invoking.
Next
Strategies
Multiply, swap debt, swap collateral, and repay-with-collateral flows.
Flash loans
The flash-loan receiver pattern — distinct from migration’s zero-fee borrow.
Accounts and risk
Account model, health factor, and spoke constraints after migration.
Controller ABI
Full
migrate_from_blend signature and related admin entrypoints.
