Skip to main content
Composer deploys a small set of contracts on every supported EVM chain. Your wallet sends the compiled transaction to your per-user proxy (or, on the proxy’s first use, to the ProxyFactory, which deploys the proxy and runs the flow atomically). The proxy delegatecalls the VM — the shared logic contract — so the flow executes in your proxy’s own balance and storage context. The remaining contracts support arithmetic and invariant checks during execution.
ContractRole
VirtualMachineShared logic that executes a compiled Flow. Each proxy delegatecalls the VM — it is not the transactionRequest.to.
ProxyFactoryDeterministically derives each signer’s per-signer execution proxy, and is the transactionRequest.to on the proxy’s first use (deployAndExecute). See Account model.
ArithmeticProcessorEvaluates core.* arithmetic instructions during execution.
InvariantCheckerEnforces guard assertions baked into the calldata.
FlashloanRegistryResolves flashloan providers for the flashloan materialiser.
LiFiFlashloanAdapterInitiates flashloans and routes the provider callback so lifi.flashloanRepay can settle each leg.
Verify before you hardcode. The most reliable source is the POST /compose response itself: userProxy is your per-user proxy, and transactionRequest.to is that same proxy once it’s deployed (or the ProxyFactory on first use). These always match the deployment that produced your calldata. Treat the tables below as a convenience snapshot.

Canonical (production)

Served from https://composer.li.quest. These addresses are the same on every supported chain.
ContractAddress
VirtualMachine0xb57Ce43Be47DF611C98EB0943e5D36EBDb36cc6D
ProxyFactory0xe174D02351656a883f6626497C86684e849efB35
InvariantChecker0xe17006F4DfE8Aa2bf80589E497ad98D470f66fef
ArithmeticProcessor0x46C2c852E6FEfaF173dFe49457f0Fe61Dc3F587a
FlashloanRegistryNot in production — ETHGlobal preview only
LiFiFlashloanAdapterNot in production — ETHGlobal preview only
Flashloans are not yet deployed to production; the FlashloanRegistry and LiFiFlashloanAdapter contracts exist only in the ETHGlobal preview deployment below.

ETHGlobal hackathon

Unaudited preview. The ETHGlobal hackathon deployment, and any contract surface that exists only there (flashloans included), is an unaudited preview intended for the hackathon and experimentation only. Do not point production applications at these addresses or route significant value through them. Use the canonical production deployment (composer.li.quest) for anything handling real money.
A separate deployment is used for the ETHGlobal hackathon. Point the SDK at the hackathon host:
const sdk = createComposeSdk({
  baseUrl: 'https://ethglobal-composer.li.quest',
  apiKey: process.env.LIFI_API_KEY,
});
ContractAddress
VirtualMachine0x6Db1F048B899ADb75728A5976F871AF1426A9443
ProxyFactory0xA0cA0957fa87d3Ed7243d8dfd442979fa5A0dd7a
InvariantChecker0xd31Ede9fD78d0f6Aa61c5De13849164c3874b8fd
ArithmeticProcessor0x5506E9fbf8168Ef6aEe346ED2Aa5412dD98554cD
FlashloanRegistry0x5032441C17A58D247e605f928c23De0BB011A7B9
LiFiFlashloanAdapter0x2dD49Bd2E4afC5b48877fD1a598b0dA59e39e692

Addresses from the compile response

You rarely need to hardcode anything: every POST /compose response carries the two addresses an integration actually touches, and they always match the deployment (canonical or hackathon) that produced the calldata.
const result = await builder.compile({ signer, inputs, sweepTo });

result.transactionRequest.to; // your execution proxy (the ProxyFactory on first use)
result.userProxy;             // your per-signer execution proxy address
The remaining contracts (arithmetic processor, invariant checker, flashloan registry, adapter) are wired in by the compiler during lowering and don’t need to be referenced from integration code.