Deposits
Each deposit routes through a Smart Routing Address and returns a Quote. This applies to same-chain and cross-chain deposits. The route is same-chain when srcChainId === destChainId. You do not select the route yourself.
Protocol facades
Each facade binds its protocol. The server maps the protocol to an adapter. The adapter builds the deposit calls and verifies the target on-chain before it quotes. Example: you pass a Morpho-Blue market where a 4626 vault is expected. The call fails immediately with a typed error. No funds move.
sr.aave.deposit(params) // no `into` - the pool follows from token + destChainId
sr.morpho.deposit(params) // `into` required
sr.fluid.deposit(params) // `into` required
sr.yearn.deposit(params) // `into` required
sr.erc4626.deposit(params) // unbranded ERC-4626 vault by id/addressParameters
Each deposit takes this core shape. Facades narrow it. Aave drops into. Morpho, Fluid, and Yearn require it.
type DepositParams = {
owner: Address // funds + signs + receives shares + gets refunds (one role)
amount: number | string // display units; the server scales by decimals (string math, no float)
token: TokenSymbol | Address // symbol → canonical per-chain address; address to disambiguate (USDC.e)
srcChainId: number // the chain the user funds from
destChainId?: number // the execution chain; equal to srcChainId ⇒ same-chain (no bridge).
// optional when `into` is a Vault (derived from vault.chainId);
// required for Aave or a string id/address `into`
into?: string | Vault // multi-vault only: vault id/address, or a Vault from listVaults()
slippage?: number // bps, default 100 (= 1%)
}owneris one role: funder, signer, shares receiver, and refund recipient. There is no separatebeneficiary.amountis in display units."100"means 100 USDC. Use astringfor very large values or values with more than 15 significant figures.tokenaccepts a symbol or an address.TOKENScontainsUSDC | USDT | DAI | WETH | WBTC | EURC | NATIVE. A symbol resolves to the canonical per-chain address. Pass a raw address for a variant (USDC.e) or an arbitrary token.slippageis an integer in bps.50means 0.5%. The server enforces the real floor. The quote'sswapMinOutputis an estimate.
Chain discovery into deposits with into
When into is a Vault object from listVaults(), you can omit destChainId. The vault contains its own chainId:
const { vaults } = await sr.listVaults({ asset: TOKENS.USDC, chains: [42161] });
await sr.morpho.deposit({
owner,
amount: "100",
token: TOKENS.USDC,
srcChainId: 8453,
into: vaults[0], // destChainId derived = vault.chainId
});Aave
Aave has one pool for each chain. The token and destChainId identify the target:
await sr.aave.deposit({
owner,
amount: "100",
token: TOKENS.USDC,
srcChainId: 8453, // Base
destChainId: 42161, // Arbitrum
slippage: 50, // 0.5%
});The owner receives the canonical aToken position.
into is optional for Aave. Omit it to supply the reserve of the funding token. Pass an Aave listing from listVaults({ protocol: 'aave' }) to select a different reserve. The funding token then routes into that reserve.
Generic deposits with depositIntoVault
Use depositIntoVault for a vault that has no facade. This includes ERC-4626 vaults that ZeroDev does not list. No facade binds the protocol here, so you must pass it:
await sr.depositIntoVault({
owner,
amount: "100",
token: TOKENS.USDC,
srcChainId: 42161,
destChainId: 42161,
into: "0xVAULT",
protocol: "erc4626", // required - 'aave' | 'morpho' | 'fluid' | 'yearn' | 'erc4626'
});The server rejects an unknown protocol with UNKNOWN_PROTOCOL. Use a facade when one exists.
Failure behavior
A destination action can revert after the bridge. In that case the funds stay in the SRA. ZeroDev does not hold the funds. Only the owner can recover them, with getWithdrawCalls. See Tracking Status.