Use this file to discover all available pages before exploring further.
Solver context (also called relayer context) is a critical component that allows solvers to pass settlement-specific data to adapters. This guide explains how context works and how to use it with different adapters.
Solver context is arbitrary bytes data that solvers append to adapter calls to configure settlement behavior. Each adapter defines its own context format based on its specific requirements.Key Characteristics:
Solver-specific configuration data passed to adapters
Format varies by adapter implementation
Extracted efficiently using assembly in AdapterBase.sol:137-144
Does not increase gas costs significantly due to calldata efficiency
The SameChainAdapter expects the simplest context format - just a recipient address.Format:
abi.encodePacked(address tokenInRecipient)
Implementation from SameChainAdapter.sol:115-120:
function _tokenInRecipient() internal pure returns (address tokenInRecipient) { (uint256 relayerContextLength, bytes calldata relayerContext) = _loadRelayerContext(); require(relayerContextLength == 20, InvalidRelayerContext()); // The first 20 bytes are the tokenIn recipient address return address(bytes20(relayerContext[:20]));}
Usage Example:
// Solver wants input tokens sent to their addressaddress solverAddress = 0x742d35Cc6634C0532925a3b844Bc454e4438f44e;bytes memory solverContext = abi.encodePacked(solverAddress);// Call router with this contextrouter.routeFill(solverContext, adapterCalldata);
In Settlement Flow (from SameChainAdapter.sol:233-244):
The MultiCallAdapter also uses a simple address-only context.Format:
abi.encodePacked(address tokenInRecipient)
Implementation from MultiCallAdapter.sol:42-47:
function _tokenInRecipient() internal pure returns (address) { (uint256 relayerContextLength, bytes calldata relayerContext) = _loadRelayerContext(); require(relayerContextLength == 20, InvalidRelayerContext()); // The first 20 bytes are the tokenIn recipient address return address(bytes20(relayerContext[:20]));}
The IntentExecutorAdapter doesn’t consume any solver context.From IntentExecutorAdapter.sol:227-229:
function ADAPTER_TAG() external pure override returns (bytes12) { return Constants.DEFAULT_ADAPTER_TAG.setSkipRelayerContext();}
Adapters that skip relayer context have special tags that tell the Router not to consume a context entry for them. This is important for batch operations.Usage Example:
// No context needed for IntentExecutorbytes[] memory contexts = new bytes[](0);bytes[] memory calldatas = new bytes[](1);calldatas[0] = abi.encodeWithSelector( IIntentExecutorAdapter.handleFill_intentExecutor_handleCompactTargetOps.selector, executorCalldata);// Empty contexts arrayrouter.optimized_routeFill921336808( contexts, // Empty abi.encode(calldatas), atomicSig);
The Router validates context consumption at the end of batch execution:From RouterLogic.sol:288-292:
// Ensure all provided solver contexts were consumed// This prevents accidentally providing too many contextsrequire(relayerContextsLength == relayerContextIndex, IRouter.LengthMismatch());
If you provide the wrong number of contexts, you’ll get a LengthMismatch error.