DocumentationOpen App
On this pageCalls and their targets

Build a custom multicall

A multicall executes an ordered list of Credit Account actions in one transaction. Use it when you want to choose the individual steps instead of using a prepared operation from Manage or following a delayed operation's intent.

Calls and their targets

Each MultiCall entry contains:

FieldMeaning
targetCredit Facade for account actions, or an adapter allowed by this Credit Manager for protocol interactions
callDataEncoded function and arguments for that target

Use SDK helpers to encode account actions and the router to generate supported conversion paths. Encode adapter calls directly only for operations the router does not cover; do not substitute a protocol contract or token address as the target. The batch executes in order and reverts if a call or required account check fails.

Available actions

Credit Facade actions

These are the supported Credit Facade multicall entries for V3.1. Their target is the account's Credit Facade. Token amounts use integer base units, not human-readable decimals: 1_000_000n represents 1 token with 6 decimals. In TypeScript, use bigint for amounts, quotas, and bitmasks. MAX_UINT256 below means 2^256 - 1.

Debt changes must respect market limits and cannot be repeated in the same block for an account. Full repayment requires all quotas to be disabled. Opening, closing, liquidation, and bot-driven batches have additional permissions; this guide uses an owner-driven update of an existing account.

These are entries inside the batch. Functions such as multicall, openCreditAccount, and closeCreditAccount are transaction entry points, not calls to nest inside it.

ActionArguments and behavior
addCollateral

Transfer approved tokens from the caller into the Credit Account. The caller must approve the Credit Manager.

  • token (address): ERC-20 token to add
  • amount (uint256): Positive amount in the token's base units
addCollateralWithPermit

Add collateral using an EIP-2612 permit. The caller signs the permit with the Credit Manager as spender and the funding amount as value.

  • token (address): ERC-20 token to add
  • amount (uint256): Positive amount in the token's base units
  • deadline (uint256): Permit expiry: Unix timestamp in seconds
  • v (uint8): Signature recovery component
  • r (bytes32): Signature r component
  • s (bytes32): Signature s component
increaseDebt

Borrow underlying into the Credit Account.

  • amount (uint256): Amount to borrow in underlying base units
decreaseDebt

Repay using underlying already held by the Credit Account.

  • amount (uint256): Amount to repay in underlying base units

An amount covering the total debt requests full repayment. Use MAX_UINT256 for full repayment; the Credit Account still needs sufficient underlying to fund it.

withdrawCollateral

Transfer collateral from the Credit Account to a recipient.

  • token (address): Collateral token to withdraw
  • amount (uint256): Amount in token base units; MAX_UINT256 for the full balance
  • to (address): Recipient

For a supported phantom token, withdrawal redeems it and sends its deposited token to the recipient.

updateQuota

Increase, reduce, or disable a collateral token's quota.

  • token (address): Collateral token; cannot be the underlying
  • quotaChange (int96): Signed change in underlying base units
  • minQuota (uint96): Minimum acceptable resulting quota in underlying base units

A positive change increases quota; a negative change reduces it. Use -2^95 to disable the quota and 0 as the minimum. The call reverts if the resulting quota is below minQuota.

setBotPermissions

Set or revoke a bot's access to the Credit Account.

  • bot (address): Bot contract
  • permissions (uint192): Permission bitmask; 0 revokes access

Combine permission bits with bitwise OR:

  • Add collateral: 1n << 0n
  • Increase debt: 1n << 1n
  • Decrease debt: 1n << 2n
  • Withdraw collateral: 1n << 5n
  • Update quota: 1n << 6n
  • Call adapters: 1n << 16n

A nonzero grant must exactly match the bot's requiredPermissions(). Other bits are rejected, including the set-bot-permissions bit (1n << 8n).

onDemandPriceUpdates

Submit price updates. This call must be first in the batch. executeCaUpdate supplies the required updates.

  • updates (PriceUpdate[]): List of feed updates

Each update contains:

  • priceFeed (address): Price feed to update
  • data (bytes): Feed-specific encoded update payload
storeExpectedBalances

Record minimum balances to check after subsequent operations.

  • balanceDeltas (BalanceDelta[]): List of minimum balance changes

Each delta contains:

  • token (address): Token whose balance will be checked
  • amount (int256): Signed minimum change in token base units

The stored floor is the balance at this call plus the delta. A positive delta requires a gain, a negative delta permits a bounded spend, and zero requires the starting balance to be preserved. For example, 100 starting units with a delta of −30 sets a floor of 70. The floor cannot be negative.

Call compareBalances before storing another set of expectations. The ABI field is named amount, not minBalanceDelta.

compareBalances

No arguments. Check that current balances are at least the stored floors, then clear the expectations. Reverts if no expectations were stored.

Outstanding expectations are checked automatically at the end of the batch.

setFullCheckParams

Configure the final collateral check. Unavailable during closure or liquidation.

  • collateralHints (uint256[]): Ordered token masks to check first; [] for no hints
  • minHealthFactor (uint16): Minimum health factor in basis points

Each hint is an individual, single-bit collateral token mask from the Credit Manager. Token addresses, combined masks, and the underlying mask are not valid.

For the health factor, 10000 means 1.0 and 12000 means 1.2. Values below 10000 revert.

Adapter actions

Adapter actions depend on the integrations enabled for the selected Credit Manager. Common categories include:

ActionExamples
SwapExchange tokens through an allowed DEX adapter
Deposit or mintConvert tokens into vault shares or a position token
Withdraw or redeemConvert shares or position tokens back into assets
Add or remove liquidityEnter or exit a liquidity pool
Stake or unstakeEnter or exit a supported staking position
Claim rewardsCollect rewards from a supported position
Request redemptionStart a delayed operation
Claim redemptionCollect proceeds through the integration's claim adapter
Integration-specific operationsFor example, receive a Midas greenlisting or transfer a redeemer where permitted

There is no single fixed list of adapter methods across all markets. For supported conversions, the router assembles the adapter chain for you. Use the selected suite's creditManager.adapters and each adapter's ABI to identify its supported calls. A method's presence does not remove its permissions or integration-specific requirements.

Select the account

Start with the connected sdk, owner, and position from Manage.

TypeScript
import type { MultiCall } from "@gearbox-protocol/sdk/onchain"; const chainId = position.chainId; const chain = sdk.onchain.chain(chainId); const account = await chain.accounts.getCreditAccountData(position.creditAccount); if (!account) throw new Error("Credit Account not found"); const suite = chain.marketRegister.findCreditManager(account.creditManager); const facade = suite.creditFacade;

Assemble the calls

For example, repay part of a loan with wallet funds: add underlying → repay. Here, repayAmount is a positive bigint in the pool underlying's base units. This example uses an ordinary ERC-20 underlying; RWA markets may require additional wrapping or factory-specific steps.

TypeScript
if (repayAmount <= 0n) throw new Error("Repayment must be positive"); const calls: MultiCall[] = [ ...facade.prepareAddCollateral([ { token: account.underlying, balance: repayAmount }, ], {}), facade.prepareChangeDebt(repayAmount, true), // true means decrease debt ];

Approve the funding amount to the SDK-resolved spender before execution, as described in Repay. Partial repayment must leave debt above the market minimum. These helpers encode calls; they do not calculate an affordable amount or validate the operation.

For other batches, order the steps by their dependencies:

  • Claim → convert → repay → withdraw: claim before spending its proceeds.
  • Quotas: include required quota updates when changing collateral; the transaction builder does not derive them for you.
  • Swap limits: preserve the route's minimum outputs and balance checks.
  • Final state: leave sufficient eligible collateral for the remaining debt. A claimed token may need conversion before its value counts toward HF.

Generate adapter calls with the router

The router is an onchain contract that builds a conversion path using the adapters available in the relevant Credit Manager. It returns the ordered adapter calls needed to execute that path.

Use chain.routerFor(account) to find a conversion path through the market's supported integrations. This is a read-only quote: it returns ordered route.calls to insert into your batch, not a router transaction to send.

As an alternative to the wallet-funded example above, convert collateral → repay. Here, tokenIn differs from the underlying, inputBalance is its available balance when the route executes, and swapAmount is the portion to convert. Amounts are bigint base units; slippage is in basis points (100 means 1%).

TypeScript
if (swapAmount <= 0n || swapAmount > inputBalance) { throw new Error("Invalid conversion amount"); } const route = await chain.routerFor(account).findManyToOnePath({ creditAccount: account, creditManager: suite.creditManager, expectedBalances: [{ token: tokenIn, balance: inputBalance }], leftoverBalances: [{ token: tokenIn, balance: inputBalance - swapAmount }], target: account.underlying, slippage, }); if (repayAmount <= 0n || repayAmount > route.minAmount) { throw new Error("Repayment exceeds the route's minimum output"); } const calls: MultiCall[] = [ ...route.calls, facade.prepareChangeDebt(repayAmount, true), ];

Preserve the returned sequence and its slippage and balance checks. route.amount is the quoted output; route.minAmount is the slippage-adjusted minimum. The example caps repayment at that minimum and must still satisfy debt, quota, and health checks. Build and preview the complete batch below.

Routing needSDK method
Convert a single token's full balancefindOneTokenPath
Convert selected balances while retaining explicit amountsfindManyToOnePath with expectedBalances and leftoverBalances
Convert collateral and borrowed funds when openingfindOpenStrategyPath
Convert assets to underlying for closingfindBestClosePath; use the Close guide for the complete operation

For a claim → convert batch, quote with the balances expected after the claim, including any pre-existing input-token balance, and place the claim before route.calls. Do not reuse a quote made before settlement. A route only supplies the conversion leg; add the required claim, debt, quota, and withdrawal actions yourself. If no route is available, the batch is not ready to execute.

Build the transaction

TypeScript
const tx = await chain.accounts.executeCaUpdate(account, calls);

Despite its name, executeCaUpdate only builds a transaction. It prepends required price updates and chooses the Credit Facade or applicable RWA factory as the transaction destination. It does not sign, send, or invent missing calls.

Continue with chainId, tx, and owner at Preview and check. Use that page's transaction payload instructions for signing and execution.

Include a delayed claim

For a fresh claimable entry from Monitor settlement, the claim entry is:

TypeScript
const claimCall: MultiCall = { target: claimable.claimCall.to, callData: claimable.claimCall.callData, };

Place this entry before the calls that use its proceeds, replacing the repayment example's funding step as appropriate. The claim does not execute the recorded intent. Add your chosen conversion, repayment, quota, or withdrawal calls so the complete batch passes the final health check. For expected-balance checks around a claim, use chain.accounts.assembleClaimDelayedCalls(...) with the lower-level withdrawal data; the raw entry above does not add those checks.

Source