SolverBase
The SolverBase
contract serves as a foundational component for Solvers within the Atlas Protocol. It ensures the safe execution of solver operations, handles escrow reconciliation, and manages bid payments. This contract is designed to work seamlessly with DAppControl
contracts that have the invertBidValue
flag set to false
. For DAppControl
contracts with invertBidValue
set to true
, use the SolverBaseInvertBid
contract instead.
Inheritance
- Interfaces:
- Libraries:
SafeTransferLib
from SoladyIERC20
from OpenZeppelin
State Variables
Variable | Type | Visibility | Description |
---|---|---|---|
WETH_ADDRESS | address | public | Immutable address of the Wrapped ETH (WETH) contract. |
_owner | address | internal | Immutable address of the contract owner. |
_atlas | address | internal | Immutable address of the deployed Atlas protocol. |
Errors
Error Name | Description |
---|---|
SolverCallUnsuccessful | Thrown when the solver operation execution fails. |
InvalidEntry | Thrown when an unauthorized entry point is detected. |
InvalidCaller | Thrown when the caller is not the designated owner. |
Constructor
constructor(address weth, address atlas, address owner)
Description
Initializes the SolverBase
contract by setting the WETH address, Atlas protocol address, and the contract owner.
Parameters
Name | Type | Description |
---|---|---|
weth | address | Address of the Wrapped ETH (WETH) contract. |
atlas | address | Address of the deployed Atlas protocol. |
owner | address | Address of the contract owner. |
External Functions
atlasSolverCall
function atlasSolverCall(
address solverOpFrom,
address executionEnvironment,
address bidToken,
uint256 bidAmount,
bytes calldata solverOpData,
bytes calldata
)
external
payable
virtual
safetyFirst(executionEnvironment, solverOpFrom)
payBids(executionEnvironment, bidToken, bidAmount)
{
(bool success,) = address(this).call{ value: msg.value }(solverOpData);
if (!success) revert SolverCallUnsuccessful();
}
Description
Executes a solver operation within the Atlas Protocol. This function performs safety checks, executes the solver operation, and handles bid payments.
Parameters
Name | Type | Description |
---|---|---|
solverOpFrom | address | Address initiating the solver operation. |
executionEnvironment | address | Address of the execution environment for the solver operation. |
bidToken | address | Address of the token used for bidding. Use address(0) for ETH. |
bidAmount | uint256 | Amount of the bid in the specified bidToken . |
solverOpData | bytes calldata | Encoded data for the solver operation execution. |
_unused | bytes calldata | Reserved for future use (currently unused). |
Return Values
This function does not return any values directly but may emit events or revert on failure.
Requirements
- The caller must be the Atlas protocol contract.
- The
solverOpFrom
must be the designated owner. - The contract must have enough Ether to process the simulation.
Behavior
- Safety Checks: Ensures that the caller is authorized and that the operation originates from the correct owner.
- Solver Operation Execution: Executes the solver operation using a low-level
call
. - Bid Payment: After execution, pays the bid to the specified execution environment, either in ETH or ERC20 tokens.
Reverts
SolverCallUnsuccessful
if the solver operation execution fails.InvalidEntry
if the caller is not the Atlas protocol.InvalidCaller
if thesolverOpFrom
is not the designated owner.
Modifiers
safetyFirst
modifier safetyFirst(address executionEnvironment, address solverOpFrom)
Description
Performs safety checks before and after the execution of a solver operation.
Parameters
Name | Type | Description |
---|---|---|
executionEnvironment | address | Address of the execution environment. |
solverOpFrom | address | Address initiating the solver operation. |
Behavior
-
Pre-Execution Checks:
- Verifies that the caller is the Atlas protocol contract.
- Ensures that the operation originates from the designated owner.
-
Post-Execution Reconciliation:
- Calculates any shortfall between the sent Ether (
msg.value
) and the protocol's shortfall requirement. - Withdraws the necessary Ether from WETH if the contract's balance is insufficient.
- Calls the
reconcile
function on the Atlas protocol to handle the shortfall.
- Calculates any shortfall between the sent Ether (
Reverts
InvalidEntry
if the caller is not the Atlas protocol.InvalidCaller
if thesolverOpFrom
is not the designated owner.
payBids
modifier payBids(address executionEnvironment, address bidToken, uint256 bidAmount)
Description
Handles the payment of bids after the execution of a solver operation.
Parameters
Name | Type | Description |
---|---|---|
executionEnvironment | address | Address to receive the bid payment. |
bidToken | address | Address of the token used for bidding. Use address(0) for ETH. |
bidAmount | uint256 | Amount of the bid to be paid. |
Behavior
- Post-Execution Bid Payment:
- If
bidToken
isaddress(0)
, pays the bid amount in ETH.- Withdraws the required Ether from WETH if the contract's balance is insufficient.
- Transfers Ether to the
executionEnvironment
.
- If
bidToken
is an ERC20 token, transfers the bid amount to theexecutionEnvironment
usingSafeTransferLib
.
- If
Reverts
- Reverts if the contract does not have enough Ether or ERC20 tokens to cover the bid amount.
Internal Functions
_transferETH
function _transferETH(address to, uint256 amount) internal
Description
Transfers a specified amount of Ether to a given address.
Parameters
Name | Type | Description |
---|---|---|
to | address | Recipient address. |
amount | uint256 | Amount of Ether to transfer. |
Behavior
- Uses
SafeTransferLib
to safely transfer Ether to the specified address.
Reverts
- Reverts if the Ether transfer fails.
_transferERC20
function _transferERC20(address token, address to, uint256 amount) internal
Description
Transfers a specified amount of ERC20 tokens to a given address.
Parameters
Name | Type | Description |
---|---|---|
token | address | ERC20 token contract address. |
to | address | Recipient address. |
amount | uint256 | Amount of tokens to transfer. |
Behavior
- Uses
SafeTransferLib
to safely transfer ERC20 tokens to the specified address.
Reverts
- Reverts if the token transfer fails.
Error Handling
The SolverBase
contract utilizes custom errors to handle various failure scenarios efficiently:
Error Name | Description |
---|---|
SolverCallUnsuccessful | Thrown when the solver operation execution fails. |
InvalidEntry | Thrown when an unauthorized entry point is detected. |
InvalidCaller | Thrown when the caller is not the designated owner. |
Usage Examples
Deploying the SolverBase Contract
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.25;
import { SolverBase } from "./SolverBase.sol";
contract MySolver is SolverBase {
constructor(address weth, address atlas, address owner)
SolverBase(weth, atlas, owner)
{
// Additional initialization if necessary
}
// Implement additional solver-specific logic if needed
}
Executing a Solver Operation
// Assume `solver` is an instance of SolverBase deployed at address `solverAddress`
// and `atlas` is the deployed Atlas protocol contract.
UserOperation memory userOp = UserOperation({
// Initialize user operation parameters
});
SolverOperation memory solverOp = SolverOperation({
// Initialize solver operation parameters
});
DAppOperation memory dAppOp = DAppOperation({
// Initialize DApp operation parameters
});
// Execute the solver call
(bool success, Result memory simResult, uint256 errorCode) = solver.atlasSolverCall{ value: msg.value }(
userOp.from,
executionEnvironment,
bidToken,
bidAmount,
abi.encodeWithSignature("executeSolver(bytes)", solverOpData),
""
);
// Handle the result
require(success, "Solver operation failed");
Security Considerations
-
Access Control:
Ensure that only authorized entities (e.g., the Atlas protocol contract) can invoke theatlasSolverCall
function. ThesafetyFirst
modifier enforces this by checking the caller and the originator of the solver operation. -
Reentrancy Protection:
The contract uses low-levelcall
to execute solver operations. Ensure that the called functions are not vulnerable to reentrancy attacks. Consider using the Checks-Effects-Interactions pattern or Reentrancy Guards if extending functionality. -
Handling ETH and ERC20 Transfers:
UtilizeSafeTransferLib
to handle token transfers securely, preventing common pitfalls like missing return values or failing transfers. -
Error Handling:
Implement comprehensive error handling to revert transactions in case of failures, ensuring that the contract's state remains consistent.
Best Practices
-
Thorough Testing:
Rigorously test all solver operations to handle expected and edge-case scenarios, ensuring the contract behaves as intended under various conditions. -
Security Audits:
Conduct comprehensive security audits to identify and mitigate potential vulnerabilities, especially since the contract handles funds and critical operations. -
Clear Documentation:
Maintain detailed documentation for each function and modifier, explaining their purpose and usage to facilitate future maintenance and onboarding. -
Upgradeability Considerations:
If the contract is intended to be upgradeable, implement proper upgrade mechanisms and storage patterns to prevent storage collisions and ensure seamless upgrades. -
Event Emission:
Although theSolverBase
contract does not emit custom events, consider emitting events in extended contracts to facilitate easier tracking and monitoring of solver operations.
Conclusion
The SolverBase
contract provides a robust and secure foundation for implementing solver operations within the Atlas Protocol. By ensuring safety checks, managing bid payments, and handling escrow reconciliation, it enables seamless integration of solver functionalities with decentralized applications. Adhering to best practices and thorough testing will further enhance the contract's reliability and security within the ecosystem.