Skip to main content

How to Deploy a Solver Contract

Solver execution logic must be held in a smart contract that will be called by Atlas during the transaction execution. Solvers must pay their bids before the end of their execution.

1. Requirements

The solver's contract MUST define the following function:

Atlas callback function
function atlasSolverCall(
address solverOpFrom,
address executionEnvironment,
address bidToken,
uint256 bidAmount,
bytes calldata solverOpData,
bytes calldata forwardedData
) external payable

This function will be called by Atlas during the transaction execution. Here is the breakdown of the parameters.

  1. solverOpFrom: the from field of the solver operation being executed (for safety checks).
  2. executionEnvironment: the execution environment is a unique contract generated for the user/dAppControl pair. The bid has to be paid to this address.
  3. bidToken: the bid token. address(0) refers to ETH.
  4. bidAmount: the bid amount to be paid to the execution environment.
  5. solverOpData: the data passed by the solver in the solver operation's data field.
  6. forwardedData: the data returned by previous execution steps (pre-ops and user operation) if enabled by the dApp.

Before the end of atlasSolverCall execution, the solver MUST:

  • Pay bidAmount to the executionEnvironment address in bidToken currency, or face revert.
  • Pay its gas consumption, by calling the Atlas reconcile function.
warning

The atlasSolverCall should ensure the caller is the Atlas contract.

2. Easy Integration

Solvers can inherit their contract from the official Atlas SolverBase contract. This contract defines the atlasSolverCall function, handles safety checks, bid payments, and gas liability payments, so the solver can focus on its custom execution logic only.

info

Atlas must be imported in your project.

Inheriting from SolverBase
pragma solidity ^0.8.22;

import {SolverBase} from "@atlas/solver/SolverBase.sol";

contract DemoSolver is SolverBase {
/*
* @notice Constructor
* @param weth_ The address of the WETH token
* @param atlas_ The address of Atlas
*/
constructor(address weth_, address atlas_) SolverBase(weth_, atlas_, msg.sender) {}

function myMevFunction(address myParam1, uint256 myParam2) external {
// Solver MEV logic goes here

// At the end of execution, profit should be held in this same contract
// The `payBids` modifier in `SolverBase` will take care of paying what is owed
}
}

Once deployed, the contract address will need to be referenced in the solver operation's solver field. Additionally, the solver operation's data field will need to be the encoded myMevFunction call.

How to compute solverOperation.data
address myParam1 = address(0x01);
uint256 myParam2 = 999;

bytes calldata solverOperationData = abi.encodeCall(DemoSolver.myMevFunction, (myParam1, myParam2));