Skip to main content
core.call is one of many ops the Composer supports. It has a dedicated page here because it’s worth explaining in depth — for the complete, live list of every op, see the Op Catalog.
core.call is the escape hatch for any on-chain function that is not already wrapped by a higher-level op. It encodes an ABI call against target using a human-readable functionSignature, optionally spending a bound resource (via resource) and granting inline approvals. If the signature declares a uint256 return (returns (uint256)), the return value is exposed on .result as a typed handle; a signature with no return clause exposes no .result. core.call and core.rawCall currently support only a single uint256 return, or none — other return types are rejected at compile time. Prefer lifi.swap or lifi.zap when they fit; they route through audited protocol edges. Reach for core.call only when you need a direct contract interaction (vault redeem, reward claim, custom entrypoint). For pre-encoded calldata, see core.rawCall; for read-only calls, see core.staticCall. Both live in the Op Catalog.

Example

Redeem ERC-4626 vault shares back to the underlying token:
const redeemResult = builder.core.call('redeem', {
  resource: builder.inputs.shares,
  bind: {
    shares: builder.inputs.shares,
    receiver: builder.context.executionAddress,
    owner: builder.context.executionAddress,
  },
  config: {
    target: VAULT,
    functionSignature:
      'function redeem(uint256 shares, address receiver, address owner) returns (uint256)',
    approvals: [{ spender: VAULT }],
  },
});

// Graduate the uint256 return value into a tracked resource.
builder.core.asResource('underlying', {
  bind: { handle: redeemResult.result },
  config: { resource: resources.erc20(USDC, 1) },
});
See callContract.ts for a full end-to-end example including inline approvals and ValueCall for payable functions.