Contract 01ace3aab3f4d6c3e3fff59ac943e274ea4502a711106988b6e625adffc34369

← Back to Index 📥 Download WASM

Meta

cliver 28.0.0#300aaf69ab100536678bdb641428b06f06b318ea
rssdkver 22.0.11#34f7f53ae31e0fd02aab436a9872e79fa671ca02
rsver 1.98.1

Instances

  • CBNKERYAG7VZNBH2V3TF5JBXLD3MXLVQW5GG4AO445EUDCPKP4D2DDP2
  • CCAUC2KH6WDIZI2Q4QAXMA2SRKVLRBHFGEYPQYVFWTEDGSO3WCH3CNT4
  • CDGWQLZOTQO4WFVB7ELUNC24YSJBXF3MGBR5VWGP4ZGEM3O4IHZ4NL52

Interface

Refreshes the cached USDC value of the adapter's Blend position to include yield accrued since the last call. Permissionless: anyone can call it, and it should be called (by the vault or a keeper) before any total_assets() read that will inform a deposit or withdrawal price, since total_assets() itself only returns the cached value rather than querying Blend live on every call.

Reads the adapter's current bToken balance from Blend's own ledger (get_positions) rather than self-tracking it, so there is no risk of drift between the stored total and Blend's actual accounting.

fn accrue(env: soroban_sdk::Env) -> Result<(), ContractError>

Called by the vault after transferring amount USDC to this adapter. Supplies the USDC to the Blend lending pool as collateral and returns the real bTokens credited, measured from Blend's own ledger rather than assumed 1:1, so the vault's adapter-share accounting (ADPT_SH) tracks genuine, appreciating shares instead of raw principal (#486).

fn deposit(env: soroban_sdk::Env, amount: i128) -> i128

Refreshes the cached total_assets to include yield accrued since the last call, satisfying the shared YieldAdapterInterface contract. Currently just calls accrue(), which remains a public, permissionless entry point in its own right.

Panics on failure rather than returning a Result: the shared adapter interface's refresh() has no error return, so propagating accrue()'s Result would mean changing that interface's ABI across both adapters and the vault's calls into them. Panicking here instead of silently discarding the error preserves this function's pre-existing fail-loud behaviour (accrue()'s storage read used to be a bare unwrap(), which panicked directly) rather than downgrading a real failure into a silent no-op success.

fn refresh(env: soroban_sdk::Env)

Returns the Blend pool this adapter supplies to.

fn get_pool(env: soroban_sdk::Env) -> soroban_sdk::Address

Called by the vault to redeem shares bTokens from the Blend pool. Blend's own withdraw request is denominated in underlying USDC, not bTokens, so shares is converted using the current b_rate before submitting. Returns the USDC amount actually delivered to recipient, measured directly rather than assumed to equal the request (#489).

fn withdraw(
    env: soroban_sdk::Env,
    shares: i128,
    recipient: soroban_sdk::Address,
) -> i128

Retained so the ABI of adapters already deployed from earlier WASM is unchanged, and so an old adapter can still be initialized by hand.

On any adapter deployed from this WASM it is unreachable: __constructor has already set VAULT_KEY, so every call returns AlreadyInitialized. That is the intended behaviour, not a leftover. An attacker calling this against a freshly deployed adapter is rejected instead of served.

fn initialize(
    env: soroban_sdk::Env,
    vault: soroban_sdk::Address,
    pool: soroban_sdk::Address,
    usdc: soroban_sdk::Address,
) -> Result<(), ContractError>

Returns "blend", identifying which protocol this adapter wraps.

fn get_protocol(env: soroban_sdk::Env) -> soroban_sdk::Symbol

Returns the cached USDC value of the adapter's Blend position. Reflects yield only as of the last accrue() call; call accrue() first for a value that includes interest accrued since then.

fn total_assets(env: soroban_sdk::Env) -> i128

Returns the adapter's current bToken share balance, read directly from Blend's ledger rather than self-tracked.

fn total_shares(env: soroban_sdk::Env) -> i128

Links the adapter to its vault, Blend pool, and USDC token.

Runs inside the CreateContract host operation that deploys this adapter, in the same transaction, so the adapter is never observable on-ledger in an uninitialized state.

This is what closes the front-running window in #505. initialize() below has no authorization check by design (there is no deployer identity in storage yet to check against), so for as long as deploy and initialize were two separate transactions, anyone watching the ledger could land initialize() first with their own address as vault, becoming the only party able to move funds through the adapter. Adding an auth check to initialize() would not have helped: it would only prove the racer controls the address they chose to pass in. Removing the intervening ledger is the fix.

fn __constructor(
    env: soroban_sdk::Env,
    vault: soroban_sdk::Address,
    pool: soroban_sdk::Address,
    usdc: soroban_sdk::Address,
)

Imports

WebAssembly Text (WAT) ▶