Source Code
Overview
HYPE Balance
HYPE Value
$0.00Latest 1 from a total of 1 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Set Atlas | 22069354 | 41 days ago | IN | 0 HYPE | 0.00000877 |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Simulator
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 18 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol";
import { Math } from "openzeppelin-contracts/contracts/utils/math/Math.sol";
import "../types/SolverOperation.sol";
import "../types/UserOperation.sol";
import "../types/DAppOperation.sol";
import "../types/ConfigTypes.sol";
import "../types/ValidCalls.sol";
import "../types/EscrowTypes.sol";
import { AtlasErrors } from "../types/AtlasErrors.sol";
import { AtlasConstants } from "../types/AtlasConstants.sol";
import { AccountingMath } from "../libraries/AccountingMath.sol";
import { GasAccLib } from "../libraries/GasAccLib.sol";
import { CallBits } from "../libraries/CallBits.sol";
import { Result } from "../interfaces/ISimulator.sol";
import { IAtlas } from "../interfaces/IAtlas.sol";
import { IDAppControl } from "../interfaces/IDAppControl.sol";
contract Simulator is AtlasErrors, AtlasConstants {
using CallBits for uint32;
using AccountingMath for uint256;
using GasAccLib for SolverOperation[];
// The approx gas used between the minGasLeft check and the Atlas metacall() from this Simulator contract.
uint256 internal constant _ERROR_CATCHER_GAS_BUFFER = 10_000;
// The approx gas used between the `simUserOperation()` or `simSolverCall()` entrypoint functions in this Simulator
// contract, and the minGasLeft check.
uint256 internal constant _SIM_ENTRYPOINT_GAS_BUFFER = 50_000;
// An approximation of (64 / 63) ^ 2. This is the scaling to apply to a min amount of gas, such that after 2
// external calls where only 63/64 of the gas is forwarded, there is still that original intended amount of gas
// left. Used in _errorCatcher() below.
uint256 internal constant _MIN_GAS_SCALING_FACTOR = 10_320; // 10_320 out of 10_000 = 1.032
uint256 internal constant _SCALE = AccountingMath._SCALE; // 10_000 = 100%
address public immutable deployer;
address public atlas;
event DeployerWithdrawal(address indexed to, uint256 amount);
constructor() {
deployer = msg.sender;
}
/// @notice Returns an estimation of the gas limit for a metacall, given the supplied UserOperation and array of
/// SolverOperations. This is the gas limit that the bundler should use when executing the metacall.
/// @param userOp The UserOperation of the metacall.
/// @param solverOps The array of SolverOperations of the metacall.
/// @return The estimated gas limit for the metacall.
function estimateMetacallGasLimit(
UserOperation calldata userOp,
SolverOperation[] memory solverOps
)
public
view
returns (uint256)
{
(uint256 metacallCalldataGas, uint256 metacallExecutionGas) = _estimateMetacallGasLimit(userOp, solverOps);
return metacallCalldataGas + metacallExecutionGas;
}
/// @notice Internal function to estimate the calldata and execution gas for a metacall.
function _estimateMetacallGasLimit(
UserOperation calldata userOp,
SolverOperation[] memory solverOps
)
internal
view
returns (uint256 metacallCalldataGas, uint256 metacallExecutionGas)
{
DAppConfig memory dConfig = IDAppControl(userOp.control).getDAppConfig(userOp);
address l2GasCalculator = IAtlas(atlas).L2_GAS_CALCULATOR();
uint256 nonSolverCalldataLength =
userOp.data.length + USER_OP_STATIC_LENGTH + DAPP_OP_LENGTH + _EXTRA_CALLDATA_LENGTH;
uint256 solverOpsLen = solverOps.length;
uint256 solverDataLenSum; // Calculated as sum of solverOps[i].data.length below
uint256 allSolversExecutionGas; // Calculated as sum of solverOps[i].gas below
for (uint256 i = 0; i < solverOpsLen; ++i) {
// Sum calldata length of all solverOp.data fields in the array
solverDataLenSum += solverOps[i].data.length;
// Sum all solverOp.gas values in the array, each with a ceiling of dConfig.solverGasLimit
allSolversExecutionGas += Math.min(solverOps[i].gas, dConfig.solverGasLimit);
}
// metacallCalldataGas is first item in return tuple
metacallCalldataGas = GasAccLib.calldataGas(
solverDataLenSum + (_SOLVER_OP_STATIC_LENGTH * solverOpsLen), l2GasCalculator
) + GasAccLib.metacallCalldataGas(nonSolverCalldataLength, l2GasCalculator);
// metacallExecutionGas is second item in return tuple
metacallExecutionGas = _BASE_TX_GAS_USED + _PRE_EXECUTE_METACALL_GAS + _POST_SETTLE_METACALL_GAS + userOp.gas
+ dConfig.dappGasLimit + allSolversExecutionGas + (_EXECUTE_SOLVER_OVERHEAD * solverOpsLen);
// If exPostBids = true, add extra execution gas to account for bid-finding.
if (dConfig.callConfig.exPostBids()) {
metacallExecutionGas +=
solverOpsLen * (_BID_FIND_OVERHEAD + _EXECUTE_SOLVER_OVERHEAD) + allSolversExecutionGas;
}
}
/// @notice Returns an estimation of the max amount (in native token) a winning solver could be charged, given the
/// supplied UserOperation and SolverOperation, assuming the Atlas and Bundler surcharge rates do not change, and
/// assuming the supplied solverOp wins.
/// @param userOp The UserOperation of the metacall.
/// @param solverOp The SolverOperation of the solver whose charge is being estimated.
/// @return The estimated max gas charge in native token units.
function estimateMaxSolverWinGasCharge(
UserOperation calldata userOp,
SolverOperation calldata solverOp
)
external
view
returns (uint256)
{
DAppConfig memory dConfig = IDAppControl(userOp.control).getDAppConfig(userOp);
uint256 bundlerSurchargeRate = userOp.bundlerSurchargeRate;
uint256 atlasSurchargeRate = IAtlas(atlas).getAtlasSurchargeRate();
uint256 totalGas;
if (dConfig.callConfig.multipleSuccessfulSolvers()) {
// If multipleSuccessfulSolvers = true, each solver only pays for their own gas usage.
// Calculate solver gas obligation as if expecting a solver fault in handleSolverFailAccounting()
uint256 _calldataGas =
GasAccLib.solverOpCalldataGas(solverOp.data.length, IAtlas(atlas).L2_GAS_CALCULATOR());
// Use solver's gas limit since we can't know actual execution gas beforehand
totalGas = _calldataGas + solverOp.gas + _SOLVER_FAULT_OFFSET;
} else {
// If multipleSuccessfulSolvers = false, the winning solver pays for their own gas + the non-solver gas.
// In exPostBid mode, solvers do not pay for calldata gas, and these calldata gas vars will be excluded.
// In normal bid mode, solvers each pay for their own solverOp calldata gas, and the winning solver pays for
// the other non-solver calldata gas as well. In this calculation, there's only 1 solverOp so no need to
// subtract calldata of other solverOps as they aren't any.
uint256 metacallCalldataLength = (_SOLVER_OP_STATIC_LENGTH + solverOp.data.length)
+ (USER_OP_STATIC_LENGTH + userOp.data.length) + DAPP_OP_LENGTH + _EXTRA_CALLDATA_LENGTH;
uint256 metacallCalldataGas =
GasAccLib.metacallCalldataGas(metacallCalldataLength, IAtlas(atlas).L2_GAS_CALCULATOR());
uint256 metacallExecutionGas = _BASE_TX_GAS_USED + _PRE_EXECUTE_METACALL_GAS + _POST_SETTLE_METACALL_GAS
+ userOp.gas + userOp.dappGasLimit + solverOp.gas;
totalGas = metacallExecutionGas;
// Only add calldata costs if NOT in exPostBids mode
if (!dConfig.callConfig.exPostBids()) {
totalGas += metacallCalldataGas;
}
}
// NOTE: In exPostBids mode, the bid-finding solverOp execution gas is written off. So no need to add here.
return (totalGas * solverOp.maxFeePerGas).withSurcharge(bundlerSurchargeRate + atlasSurchargeRate);
}
function simUserOperation(UserOperation calldata userOp)
external
payable
returns (bool success, Result simResult, uint256)
{
if (userOp.value > address(this).balance) revert SimulatorBalanceTooLow();
SolverOperation[] memory solverOps = new SolverOperation[](0);
DAppOperation memory dAppOp;
dAppOp.to = atlas;
dAppOp.control = userOp.control;
(uint256 metacallCalldataGas, uint256 metacallExecutionGas) = _estimateMetacallGasLimit(userOp, solverOps);
(Result result, uint256 validCallsResult) =
_errorCatcher(userOp, solverOps, dAppOp, metacallExecutionGas, metacallCalldataGas);
success = uint8(result) > uint8(Result.UserOpSimFail);
if (success) validCallsResult = uint256(ValidCallsResult.Valid);
if (msg.value != 0) SafeTransferLib.safeTransferETH(msg.sender, msg.value);
return (success, result, validCallsResult);
}
function simSolverCall(
UserOperation calldata userOp,
SolverOperation calldata solverOp,
DAppOperation calldata dAppOp
)
external
payable
returns (bool success, Result simResult, uint256)
{
if (userOp.value > address(this).balance) revert SimulatorBalanceTooLow();
SolverOperation[] memory solverOps = new SolverOperation[](1);
solverOps[0] = solverOp;
(uint256 metacallCalldataGas, uint256 metacallExecutionGas) = _estimateMetacallGasLimit(userOp, solverOps);
(Result result, uint256 solverOutcomeResult) =
_errorCatcher(userOp, solverOps, dAppOp, metacallExecutionGas, metacallCalldataGas);
success = result == Result.SimulationPassed;
if (success) solverOutcomeResult = 0; // discard additional error uint if solver stage was successful
if (msg.value != 0) SafeTransferLib.safeTransferETH(msg.sender, msg.value);
return (success, result, solverOutcomeResult);
}
function simSolverCalls(
UserOperation calldata userOp,
SolverOperation[] calldata solverOps,
DAppOperation calldata dAppOp
)
external
payable
returns (bool success, Result simResult, uint256)
{
if (userOp.value > address(this).balance) revert SimulatorBalanceTooLow();
if (solverOps.length == 0) {
// Returns number out of usual range of SolverOutcome enum to indicate no solverOps
return (false, Result.Unknown, uint256(type(SolverOutcome).max) + 1);
}
(uint256 metacallCalldataGas, uint256 metacallExecutionGas) = _estimateMetacallGasLimit(userOp, solverOps);
(Result result, uint256 solverOutcomeResult) =
_errorCatcher(userOp, solverOps, dAppOp, metacallExecutionGas, metacallCalldataGas);
success = result == Result.SimulationPassed;
if (success) solverOutcomeResult = 0; // discard additional error uint if solver stage was successful
if (msg.value != 0) SafeTransferLib.safeTransferETH(msg.sender, msg.value);
return (success, result, solverOutcomeResult);
}
function _errorCatcher(
UserOperation memory userOp,
SolverOperation[] memory solverOps,
DAppOperation memory dAppOp,
uint256 metacallExecutionGas,
uint256 metacallCalldataGas
)
internal
returns (Result result, uint256 additionalErrorCode)
{
// Similar to how any calldata gas has already been deducted by this point in a simulator view call, the initial
// 21_000 gas (_BASE_TX_GAS_USED) has also already been deducted. As such, we can deduct that from the execution
// gas we actually need to forward to Atlas.
uint256 adjMetacallExecutionGas = metacallExecutionGas - _BASE_TX_GAS_USED;
// Calculate the minimum gas left at this point, given that the Atlas `metacall()` should start with
// approximately `metacallExecutionGas`, and that there are still 2x external calls to be made before that
// point:
// - First in the `metacallSimulation()` call below.
// - Second when the `metacallSimulation()` function calls `metacall()` in Atlas.
//
// For each external call, a max of 63/64 of the gas left is forwarded.
// Therefore we should have at least [metacallExecutionGas * (64/63) ^ 2] at this point to ensure there will be
// enough gas at the start of the `metacall()`
uint256 minGasLeft = adjMetacallExecutionGas * _MIN_GAS_SCALING_FACTOR / _SCALE + _ERROR_CATCHER_GAS_BUFFER;
uint256 gasLeft = gasleft();
// NOTE: Set gas limit to the max supported by your RPC's `eth_call` when calling Simulator from an offchain
// source if you experience the revert below. Only the expected execution gas will be forwarded to Atlas.
if (gasLeft < minGasLeft) {
revert InsufficientGasForMetacallSimulation(
gasLeft, // The gas left at this point that was insufficient to pass the check
metacallExecutionGas + metacallCalldataGas, // Suggested gas limit for a real metacall
_SIM_ENTRYPOINT_GAS_BUFFER + _BASE_TX_GAS_USED + minGasLeft + metacallCalldataGas // Suggested min gas
// limit for a sim call.
);
}
try this.metacallSimulation{ value: userOp.value }(userOp, solverOps, dAppOp, adjMetacallExecutionGas) {
revert Unreachable();
} catch (bytes memory revertData) {
bytes4 errorSwitch = bytes4(revertData);
if (errorSwitch == VerificationSimFail.selector) {
// revertData in form [bytes4, uint256] but reverts on abi.decode
// This decodes the uint256 error code portion of the revertData
uint256 validCallsResult;
assembly {
let dataLocation := add(revertData, 0x20)
validCallsResult := mload(add(dataLocation, sub(mload(revertData), 32)))
}
result = Result.VerificationSimFail;
additionalErrorCode = validCallsResult;
} else if (errorSwitch == PreOpsSimFail.selector) {
result = Result.PreOpsSimFail;
} else if (errorSwitch == UserOpSimFail.selector) {
result = Result.UserOpSimFail;
} else if (errorSwitch == SolverSimFail.selector) {
// Expects revertData in form [bytes4, uint256]
uint256 solverOutcomeResult;
assembly {
let dataLocation := add(revertData, 0x20)
solverOutcomeResult := mload(add(dataLocation, sub(mload(revertData), 32)))
}
result = Result.SolverSimFail;
additionalErrorCode = solverOutcomeResult;
} else if (errorSwitch == AllocateValueSimFail.selector) {
result = Result.AllocateValueSimFail;
} else if (errorSwitch == SimulationPassed.selector) {
result = Result.SimulationPassed;
} else {
result = Result.Unknown;
}
return (result, additionalErrorCode);
}
}
function metacallSimulation(
UserOperation calldata userOp,
SolverOperation[] calldata solverOps,
DAppOperation calldata dAppOp,
uint256 adjMetacallExecutionGas
)
external
payable
{
if (msg.sender != address(this)) revert InvalidEntryFunction();
// In real Atlas metacalls, when the caller is an EOA, it should include the suggested calldata gas in the gas
// limit. However, in as this is a Simulator call, that calldata gas has already been deducted in the initial
// `simUserOperation()` or `simSolverCall()` call. Simmilarly, the initial 21k base tx gas has also already been
// deducted by this point. As such, we set the metacall gas limit here to just the suggested execution gas, with
// the initial gas deduction already made in `_errorCatcher()` above.
bool auctionWon = IAtlas(atlas).metacall{ value: msg.value, gas: adjMetacallExecutionGas }(
userOp, solverOps, dAppOp, address(0)
);
// If multipleSuccessfulSolvers = true, metacall always returns auctionWon = false, even if there were some
// successful solvers. So we always revert with SimulationPassed here if multipleSuccessfulSolvers = true.
if (!auctionWon && !userOp.callConfig.multipleSuccessfulSolvers()) {
revert NoAuctionWinner(); // should be unreachable
}
revert SimulationPassed();
}
// ---------------------------------------------------- //
// Deployer Functions //
// ---------------------------------------------------- //
function setAtlas(address _atlas) external {
if (msg.sender != deployer) revert Unauthorized();
atlas = _atlas;
}
function withdrawETH(address to) external {
if (msg.sender != deployer) revert Unauthorized();
uint256 _balance = address(this).balance;
SafeTransferLib.safeTransferETH(to, _balance);
emit DeployerWithdrawal(to, _balance);
}
receive() external payable { }
fallback() external payable { }
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @author Permit2 operations from (https://github.com/Uniswap/permit2/blob/main/src/libraries/Permit2Lib.sol)
///
/// @dev Note:
/// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection.
/// - For ERC20s, this implementation won't check that a token has code,
/// responsibility is delegated to the caller.
library SafeTransferLib {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The ETH transfer has failed.
error ETHTransferFailed();
/// @dev The ERC20 `transferFrom` has failed.
error TransferFromFailed();
/// @dev The ERC20 `transfer` has failed.
error TransferFailed();
/// @dev The ERC20 `approve` has failed.
error ApproveFailed();
/// @dev The Permit2 operation has failed.
error Permit2Failed();
/// @dev The Permit2 amount must be less than `2**160 - 1`.
error Permit2AmountOverflow();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes.
uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300;
/// @dev Suggested gas stipend for contract receiving ETH to perform a few
/// storage reads and writes, but low enough to prevent griefing.
uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000;
/// @dev The unique EIP-712 domain domain separator for the DAI token contract.
bytes32 internal constant DAI_DOMAIN_SEPARATOR =
0xdbb8cf42e1ecb028be3f3dbc922e1d878b963f411dc388ced501601c60f7c6f7;
/// @dev The address for the WETH9 contract on Ethereum mainnet.
address internal constant WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
/// @dev The canonical Permit2 address.
/// [Github](https://github.com/Uniswap/permit2)
/// [Etherscan](https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3)
address internal constant PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ETH OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants.
//
// The regular variants:
// - Forwards all remaining gas to the target.
// - Reverts if the target reverts.
// - Reverts if the current contract has insufficient balance.
//
// The force variants:
// - Forwards with an optional gas stipend
// (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases).
// - If the target reverts, or if the gas stipend is exhausted,
// creates a temporary contract to force send the ETH via `SELFDESTRUCT`.
// Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758.
// - Reverts if the current contract has insufficient balance.
//
// The try variants:
// - Forwards with a mandatory gas stipend.
// - Instead of reverting, returns whether the transfer succeeded.
/// @dev Sends `amount` (in wei) ETH to `to`.
function safeTransferETH(address to, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Sends all the ETH in the current contract to `to`.
function safeTransferAllETH(address to) internal {
/// @solidity memory-safe-assembly
assembly {
// Transfer all the ETH and check if it succeeded or not.
if iszero(call(gas(), to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {
/// @solidity memory-safe-assembly
assembly {
if lt(selfbalance(), amount) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
if iszero(call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, to) // Store the address in scratch space.
mstore8(0x0b, 0x73) // Opcode `PUSH20`.
mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
}
}
}
/// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`.
function forceSafeTransferAllETH(address to, uint256 gasStipend) internal {
/// @solidity memory-safe-assembly
assembly {
if iszero(call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, to) // Store the address in scratch space.
mstore8(0x0b, 0x73) // Opcode `PUSH20`.
mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
}
}
}
/// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`.
function forceSafeTransferETH(address to, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
if lt(selfbalance(), amount) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, to) // Store the address in scratch space.
mstore8(0x0b, 0x73) // Opcode `PUSH20`.
mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
}
}
}
/// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`.
function forceSafeTransferAllETH(address to) internal {
/// @solidity memory-safe-assembly
assembly {
// forgefmt: disable-next-item
if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, to) // Store the address in scratch space.
mstore8(0x0b, 0x73) // Opcode `PUSH20`.
mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
}
}
}
/// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)
internal
returns (bool success)
{
/// @solidity memory-safe-assembly
assembly {
success := call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)
}
}
/// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`.
function trySafeTransferAllETH(address to, uint256 gasStipend)
internal
returns (bool success)
{
/// @solidity memory-safe-assembly
assembly {
success := call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERC20 OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
/// Reverts upon failure.
///
/// The `from` account must have at least `amount` approved for
/// the current contract to manage.
function safeTransferFrom(address token, address from, address to, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, amount) // Store the `amount` argument.
mstore(0x40, to) // Store the `to` argument.
mstore(0x2c, shl(96, from)) // Store the `from` argument.
mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.
// Perform the transfer, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
)
) {
mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
revert(0x1c, 0x04)
}
mstore(0x60, 0) // Restore the zero slot to zero.
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
///
/// The `from` account must have at least `amount` approved for the current contract to manage.
function trySafeTransferFrom(address token, address from, address to, uint256 amount)
internal
returns (bool success)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, amount) // Store the `amount` argument.
mstore(0x40, to) // Store the `to` argument.
mstore(0x2c, shl(96, from)) // Store the `from` argument.
mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.
success :=
and( // The arguments of `and` are evaluated from right to left.
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
)
mstore(0x60, 0) // Restore the zero slot to zero.
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Sends all of ERC20 `token` from `from` to `to`.
/// Reverts upon failure.
///
/// The `from` account must have their entire balance approved for the current contract to manage.
function safeTransferAllFrom(address token, address from, address to)
internal
returns (uint256 amount)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x40, to) // Store the `to` argument.
mstore(0x2c, shl(96, from)) // Store the `from` argument.
mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
// Read the balance, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
gt(returndatasize(), 0x1f), // At least 32 bytes returned.
staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)
)
) {
mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
revert(0x1c, 0x04)
}
mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`.
amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it.
// Perform the transfer, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
)
) {
mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
revert(0x1c, 0x04)
}
mstore(0x60, 0) // Restore the zero slot to zero.
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.
/// Reverts upon failure.
function safeTransfer(address token, address to, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
mstore(0x14, to) // Store the `to` argument.
mstore(0x34, amount) // Store the `amount` argument.
mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
// Perform the transfer, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
)
) {
mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
revert(0x1c, 0x04)
}
mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
}
}
/// @dev Sends all of ERC20 `token` from the current contract to `to`.
/// Reverts upon failure.
function safeTransferAll(address token, address to) internal returns (uint256 amount) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.
mstore(0x20, address()) // Store the address of the current contract.
// Read the balance, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
gt(returndatasize(), 0x1f), // At least 32 bytes returned.
staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)
)
) {
mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
revert(0x1c, 0x04)
}
mstore(0x14, to) // Store the `to` argument.
amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it.
mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
// Perform the transfer, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
)
) {
mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
revert(0x1c, 0x04)
}
mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
}
}
/// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
/// Reverts upon failure.
function safeApprove(address token, address to, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
mstore(0x14, to) // Store the `to` argument.
mstore(0x34, amount) // Store the `amount` argument.
mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
// Perform the approval, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
)
) {
mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
revert(0x1c, 0x04)
}
mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
}
}
/// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
/// If the initial attempt to approve fails, attempts to reset the approved amount to zero,
/// then retries the approval again (some tokens, e.g. USDT, requires this).
/// Reverts upon failure.
function safeApproveWithRetry(address token, address to, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
mstore(0x14, to) // Store the `to` argument.
mstore(0x34, amount) // Store the `amount` argument.
mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
// Perform the approval, retrying upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
)
) {
mstore(0x34, 0) // Store 0 for the `amount`.
mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
pop(call(gas(), token, 0, 0x10, 0x44, codesize(), 0x00)) // Reset the approval.
mstore(0x34, amount) // Store back the original `amount`.
// Retry the approval, reverting upon failure.
if iszero(
and(
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
)
) {
mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
revert(0x1c, 0x04)
}
}
mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
}
}
/// @dev Returns the amount of ERC20 `token` owned by `account`.
/// Returns zero if the `token` does not exist.
function balanceOf(address token, address account) internal view returns (uint256 amount) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x14, account) // Store the `account` argument.
mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
amount :=
mul( // The arguments of `mul` are evaluated from right to left.
mload(0x20),
and( // The arguments of `and` are evaluated from right to left.
gt(returndatasize(), 0x1f), // At least 32 bytes returned.
staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)
)
)
}
}
/// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
/// If the initial attempt fails, try to use Permit2 to transfer the token.
/// Reverts upon failure.
///
/// The `from` account must have at least `amount` approved for the current contract to manage.
function safeTransferFrom2(address token, address from, address to, uint256 amount) internal {
if (!trySafeTransferFrom(token, from, to, amount)) {
permit2TransferFrom(token, from, to, amount);
}
}
/// @dev Sends `amount` of ERC20 `token` from `from` to `to` via Permit2.
/// Reverts upon failure.
function permit2TransferFrom(address token, address from, address to, uint256 amount)
internal
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(add(m, 0x74), shr(96, shl(96, token)))
mstore(add(m, 0x54), amount)
mstore(add(m, 0x34), to)
mstore(add(m, 0x20), shl(96, from))
// `transferFrom(address,address,uint160,address)`.
mstore(m, 0x36c78516000000000000000000000000)
let p := PERMIT2
let exists := eq(chainid(), 1)
if iszero(exists) { exists := iszero(iszero(extcodesize(p))) }
if iszero(and(call(gas(), p, 0, add(m, 0x10), 0x84, codesize(), 0x00), exists)) {
mstore(0x00, 0x7939f4248757f0fd) // `TransferFromFailed()` or `Permit2AmountOverflow()`.
revert(add(0x18, shl(2, iszero(iszero(shr(160, amount))))), 0x04)
}
}
}
/// @dev Permit a user to spend a given amount of
/// another user's tokens via native EIP-2612 permit if possible, falling
/// back to Permit2 if native permit fails or is not implemented on the token.
function permit2(
address token,
address owner,
address spender,
uint256 amount,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
for {} shl(96, xor(token, WETH9)) {} {
mstore(0x00, 0x3644e515) // `DOMAIN_SEPARATOR()`.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
lt(iszero(mload(0x00)), eq(returndatasize(), 0x20)), // Returns 1 non-zero word.
// Gas stipend to limit gas burn for tokens that don't refund gas when
// an non-existing function is called. 5K should be enough for a SLOAD.
staticcall(5000, token, 0x1c, 0x04, 0x00, 0x20)
)
) { break }
// After here, we can be sure that token is a contract.
let m := mload(0x40)
mstore(add(m, 0x34), spender)
mstore(add(m, 0x20), shl(96, owner))
mstore(add(m, 0x74), deadline)
if eq(mload(0x00), DAI_DOMAIN_SEPARATOR) {
mstore(0x14, owner)
mstore(0x00, 0x7ecebe00000000000000000000000000) // `nonces(address)`.
mstore(add(m, 0x94), staticcall(gas(), token, 0x10, 0x24, add(m, 0x54), 0x20))
mstore(m, 0x8fcbaf0c000000000000000000000000) // `IDAIPermit.permit`.
// `nonces` is already at `add(m, 0x54)`.
// `1` is already stored at `add(m, 0x94)`.
mstore(add(m, 0xb4), and(0xff, v))
mstore(add(m, 0xd4), r)
mstore(add(m, 0xf4), s)
success := call(gas(), token, 0, add(m, 0x10), 0x104, codesize(), 0x00)
break
}
mstore(m, 0xd505accf000000000000000000000000) // `IERC20Permit.permit`.
mstore(add(m, 0x54), amount)
mstore(add(m, 0x94), and(0xff, v))
mstore(add(m, 0xb4), r)
mstore(add(m, 0xd4), s)
success := call(gas(), token, 0, add(m, 0x10), 0xe4, codesize(), 0x00)
break
}
}
if (!success) simplePermit2(token, owner, spender, amount, deadline, v, r, s);
}
/// @dev Simple permit on the Permit2 contract.
function simplePermit2(
address token,
address owner,
address spender,
uint256 amount,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, 0x927da105) // `allowance(address,address,address)`.
{
let addressMask := shr(96, not(0))
mstore(add(m, 0x20), and(addressMask, owner))
mstore(add(m, 0x40), and(addressMask, token))
mstore(add(m, 0x60), and(addressMask, spender))
mstore(add(m, 0xc0), and(addressMask, spender))
}
let p := mul(PERMIT2, iszero(shr(160, amount)))
if iszero(
and( // The arguments of `and` are evaluated from right to left.
gt(returndatasize(), 0x5f), // Returns 3 words: `amount`, `expiration`, `nonce`.
staticcall(gas(), p, add(m, 0x1c), 0x64, add(m, 0x60), 0x60)
)
) {
mstore(0x00, 0x6b836e6b8757f0fd) // `Permit2Failed()` or `Permit2AmountOverflow()`.
revert(add(0x18, shl(2, iszero(p))), 0x04)
}
mstore(m, 0x2b67b570) // `Permit2.permit` (PermitSingle variant).
// `owner` is already `add(m, 0x20)`.
// `token` is already at `add(m, 0x40)`.
mstore(add(m, 0x60), amount)
mstore(add(m, 0x80), 0xffffffffffff) // `expiration = type(uint48).max`.
// `nonce` is already at `add(m, 0xa0)`.
// `spender` is already at `add(m, 0xc0)`.
mstore(add(m, 0xe0), deadline)
mstore(add(m, 0x100), 0x100) // `signature` offset.
mstore(add(m, 0x120), 0x41) // `signature` length.
mstore(add(m, 0x140), r)
mstore(add(m, 0x160), s)
mstore(add(m, 0x180), shl(248, v))
if iszero(call(gas(), p, 0, add(m, 0x1c), 0x184, codesize(), 0x00)) {
mstore(0x00, 0x6b836e6b) // `Permit2Failed()`.
revert(0x1c, 0x04)
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Muldiv operation overflow.
*/
error MathOverflowedMulDiv();
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
return a / b;
}
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0 = x * y; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
if (denominator <= prod1) {
revert MathOverflowedMulDiv();
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
// works in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
bytes32 constant SOLVER_TYPEHASH = keccak256(
"SolverOperation(address from,address to,uint256 value,uint256 gas,uint256 maxFeePerGas,uint256 deadline,address solver,address control,bytes32 userOpHash,address bidToken,uint256 bidAmount,bytes data)"
);
// NOTE: The calldata length of this SolverOperation struct is 608 bytes when the `data` field is excluded. This value
// is stored in the `_SOLVER_OP_STATIC_LENGTH` constant in AtlasConstants.sol and must be kept up-to-date with any
// changes to this struct.
struct SolverOperation {
address from; // Solver address
address to; // Atlas address
uint256 value; // Amount of ETH required for the solver operation (used in `value` field of the solver call)
uint256 gas; // Gas limit for the solver operation
uint256 maxFeePerGas; // maxFeePerGas solver is willing to pay. This goes to validator, not dApp or user
uint256 deadline; // block.number deadline for the solver operation
address solver; // Nested "to" address (used in `to` field of the solver call)
address control; // DAppControl address
bytes32 userOpHash; // hash of User's Operation, for verification of user's tx (if not matched, solver wont be
// charged for gas)
address bidToken; // address(0) for ETH
uint256 bidAmount; // Amount of bidToken that the solver bids
bytes data; // Solver op calldata (used in `data` field of the solver call)
bytes signature; // Solver operation signature signed by SolverOperation.from
}//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
// Default UserOperation typehash
bytes32 constant USER_TYPEHASH_DEFAULT = keccak256(
"UserOperation(address from,address to,uint256 value,uint256 gas,uint256 maxFeePerGas,uint256 nonce,uint256 deadline,address dapp,address control,uint32 callConfig,uint32 dappGasLimit,uint32 solverGasLimit,uint24 bundlerSurchargeRate,address sessionKey,bytes data)"
);
// Trusted UserOperation typehash
// NOTE: This is explicitly for the 'trustedOpHash' configuration option meant so that solvers can submit
// SolverOperations
// prior to seeing the UserOperation or its hash. In this scenario, the Solvers should trust the signer of the
// UserOperation.
bytes32 constant USER_TYPEHASH_TRUSTED = keccak256(
"UserOperation(address from,address to,address dapp,address control,uint32 callConfig,uint32 dappGasLimit,uint32 solverGasLimit,uint24 bundlerSurchargeRate,address sessionKey)"
);
// Length of UserOperation in hex chars, assuming empty signature field, excluding the dynamic userOp.data field.
uint256 constant USER_OP_STATIC_LENGTH = 608;
struct UserOperation {
address from; // User address
address to; // Atlas address
uint256 value; // Amount of ETH required for the user operation (used in `value` field of the user call)
uint256 gas; // Gas limit for the user operation
uint256 maxFeePerGas; // Max fee per gas for the user operation
uint256 nonce; // Atlas nonce of the user operation available in the AtlasVerification contract
uint256 deadline; // block.number deadline for the user operation
address dapp; // Nested "to" for user's call (used in `to` field of the user call)
address control; // Address of the DAppControl contract
uint32 callConfig; // Call configuration expected by user, refer to `src/contracts/types/ConfigTypes.sol`
uint32 dappGasLimit; // Gas limit set by the DAppControl for preOps and allocateValue hook execution
uint32 solverGasLimit; // Gas limit set by the DAppControl for solverOp execution
uint24 bundlerSurchargeRate; // Bundler surcharge rate, set by the DAppControl
address sessionKey; // Address of the temporary session key which is used to sign the DappOperation
bytes data; // User operation calldata (used in `data` field of the user call)
bytes signature; // User operation signature signed by UserOperation.from
}//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
bytes32 constant DAPP_TYPEHASH = keccak256(
"DAppOperation(address from,address to,uint256 nonce,uint256 deadline,address control,address bundler,bytes32 userOpHash,bytes32 callChainHash)"
);
// Length of DAppOperation in hex chars, assuming empty signature field
uint256 constant DAPP_OP_LENGTH = 352;
struct DAppOperation {
address from; // signer of the DAppOperation
address to; // Atlas address
uint256 nonce; // Atlas nonce of the DAppOperation available in the AtlasVerification contract
uint256 deadline; // block.number deadline for the DAppOperation
address control; // DAppControl address
address bundler; // Signer of the atlas tx (msg.sender)
bytes32 userOpHash; // keccak256 of userOp.to, userOp.data
bytes32 callChainHash; // keccak256 of the solvers' txs
bytes signature; // DAppOperation signed by DAppOperation.from
}//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
struct DAppConfig {
address to; // Address of the DAppControl contract
uint32 callConfig; // Configuration
address bidToken; // address(0) for ETH
uint32 solverGasLimit; // Max gas limit for solverOp (including preSolver and postSolver) execution
uint32 dappGasLimit; // Max shared gas limit for preOps and allocateValue hook execution
uint128 bundlerSurchargeRate; // Bundler surcharge rate
}
struct CallConfig {
// userNoncesSequential: The userOp nonce must be the next sequential nonce for that user’s address in Atlas’
// nonce system. If false, the userOp nonces are allowed to be non-sequential (unordered), as long as they are
// unique.
bool userNoncesSequential;
// dappNoncesSequential: The dappOp nonce must be the next sequential nonce for that dApp signer’s address in
// Atlas’ nonce system. If false, the dappOp nonce is not checked, as the dAppOp is tied to its userOp's nonce via
// the callChainHash.
bool dappNoncesSequential;
// requirePreOps: The preOps hook is executed before the userOp is executed. If false, the preOps hook is skipped.
// the dapp control should check the validity of the user operation (whether its dapps can support userOp.dapp and
// userOp.data) in the preOps hook.
bool requirePreOps;
// trackPreOpsReturnData: The return data from the preOps hook is passed to the next call phase. If false preOps
// return data is discarded. If both trackPreOpsReturnData and trackUserReturnData are true, they are concatenated.
bool trackPreOpsReturnData;
// trackUserReturnData: The return data from the userOp call is passed to the next call phase. If false userOp
// return data is discarded. If both trackPreOpsReturnData and trackUserReturnData are true, they are concatenated.
bool trackUserReturnData;
// delegateUser: The userOp call is made using delegatecall from the Execution Environment. If false, userOp is
// called using call.
bool delegateUser;
// requirePreSolver: The preSolver hook is executed before the solverOp is executed. If false, the preSolver hook is
// skipped.
bool requirePreSolver;
// requirePostSolver: The postSolver hook is executed after the solverOp is executed. If false, the postSolver hook
// is skipped.
bool requirePostSolver;
// zeroSolvers: Allow the metacall to proceed even if there are no solverOps. The solverOps do not necessarily need
// to be successful, but at least 1 must exist.
bool zeroSolvers;
// reuseUserOp: If true, the metacall will revert if unsuccessful so as not to store nonce data, so the userOp can
// be reused.
bool reuseUserOp;
// userAuctioneer: The user is allowed to be the auctioneer (the signer of the dAppOp). More than one auctioneer
// option can be set to true for the same DAppControl.
bool userAuctioneer;
// solverAuctioneer: The solver is allowed to be the auctioneer (the signer of the dAppOp). If the solver is the
// auctioneer then their solverOp must be the only one. More than one auctioneer option can be set to true for the
// same DAppControl.
bool solverAuctioneer;
// unknownAuctioneer: Anyone is allowed to be the auctioneer - dAppOp.from must be the signer of the dAppOp, but the
// usual signatory[] checks are skipped. More than one auctioneer option can be set to true for the same
// DAppControl.
bool unknownAuctioneer;
// verifyCallChainHash: Check that the dAppOp callChainHash matches the actual callChainHash as calculated in
// AtlasVerification.
bool verifyCallChainHash;
// forwardReturnData: The return data from previous steps is included as calldata in the call from the Execution
// Environment to the solver contract. If false, return data is not passed to the solver contract.
bool forwardReturnData;
// requireFulfillment: If true, a winning solver must be found, otherwise the metacall will fail.
bool requireFulfillment;
// trustedOpHash: If true, the userOpHash excludes some userOp inputs such as `value`, `gas`, `maxFeePerGas`,
// `nonce`, `deadline`, and `data`, implying solvers trust changes made to these parts of the userOp after signing
// their associated solverOps.
bool trustedOpHash;
// invertBidValue: If true, the solver with the lowest successful bid wins.
bool invertBidValue;
// exPostBids: Bids are found on-chain using `_getBidAmount` in Atlas, and solverOp.bidAmount is used as the max
// bid. If solverOp.bidAmount is 0, then there is no max bid limit for that solver.
bool exPostBids;
// multipleSolvers: If true, the metacall will proceed even if a solver successfully pays their bid, and will be
// charged in gas as if it was reverted. If false, the auction ends after the first successful solver.
bool multipleSuccessfulSolvers;
// checkMetacallGasLimit: If true, the execution gas measured by `gasleft()` at the start of the metacall is
// verified to be in line with the expected gas limit, based on the userOp, solverOps, and dAppOp.
bool checkMetacallGasLimit;
}
enum CallConfigIndex {
UserNoncesSequential,
DAppNoncesSequential,
RequirePreOps,
TrackPreOpsReturnData,
TrackUserReturnData,
DelegateUser,
RequirePreSolver,
RequirePostSolver,
ZeroSolvers,
ReuseUserOp,
UserAuctioneer,
SolverAuctioneer,
UnknownAuctioneer,
// Default = DAppAuctioneer
VerifyCallChainHash,
ForwardReturnData,
RequireFulfillment,
TrustedOpHash,
InvertBidValue,
ExPostBids,
MultipleSuccessfulSolvers,
CheckMetacallGasLimit
}//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
/// @title ValidCallsResult
/// @notice Enum for ValidCallsResult
/// @dev A single ValidCallsResult is returned by `validateCalls` in AtlasVerification
enum ValidCallsResult {
Valid,
// Results below this line will cause metacall to revert
UserFromInvalid,
UserSignatureInvalid,
DAppSignatureInvalid,
UserNonceInvalid,
InvalidDAppNonce,
UnknownAuctioneerNotAllowed,
InvalidAuctioneer,
InvalidBundler,
// Results above this line will cause metacall to revert
InvertBidValueCannotBeExPostBids, // Threshold value (included in the revert range), any new reverting values should
// be included above this line
// Results below this line will cause metacall to gracefully return
GasPriceHigherThanMax,
TxValueLowerThanCallValue,
TooManySolverOps,
UserDeadlineReached,
DAppDeadlineReached,
ExecutionEnvEmpty,
NoSolverOp,
InvalidSequence,
OpHashMismatch,
DeadlineMismatch,
InvalidControl,
InvalidSolverGasLimit,
InvalidCallConfig,
CallConfigMismatch,
DAppToInvalid,
UserToInvalid,
ControlMismatch,
InvalidCallChainHash,
DAppNotEnabled,
BothUserAndDAppNoncesCannotBeSequential,
MetacallGasLimitTooLow,
MetacallGasLimitTooHigh,
DAppGasLimitMismatch,
SolverGasLimitMismatch,
BundlerSurchargeRateMismatch,
ExPostBidsAndMultipleSuccessfulSolversNotSupportedTogether,
InvertsBidValueAndMultipleSuccessfulSolversNotSupportedTogether,
NeedSolversForMultipleSuccessfulSolvers,
SolverCannotBeAuctioneerForMultipleSuccessfulSolvers,
CannotRequireFulfillmentForMultipleSuccessfulSolvers
}//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
// bonded = total - unbonding
struct EscrowAccountBalance {
uint112 balance;
uint112 unbonding;
}
struct EscrowAccountAccessData {
uint112 bonded;
uint32 lastAccessedBlock;
uint24 auctionWins;
uint24 auctionFails;
uint64 totalGasValueUsed; // The cumulative ETH value spent on gas in metacalls. Measured in gwei.
}
// Additional struct to avoid Stack Too Deep while tracking variables related to the solver call.
struct SolverTracker {
uint256 bidAmount;
uint256 floor;
uint256 ceiling;
bool etherIsBidToken;
bool invertsBidValue;
}
/// @title SolverOutcome
/// @notice Enum for SolverOutcome
/// @dev Multiple SolverOutcomes can be used to represent the outcome of a solver call
/// @dev Typical usage looks like solverOutcome = (1 << SolverOutcome.InvalidSignature) | (1 <<
/// SolverOutcome.InvalidUserHash) to indicate SolverOutcome.InvalidSignature and SolverOutcome.InvalidUserHash
enum SolverOutcome {
// No Refund (relay error or hostile user)
InvalidSignature,
InvalidUserHash,
DeadlinePassedAlt,
GasPriceBelowUsersAlt,
InvalidTo,
UserOutOfGas,
AlteredControl,
AltOpHashMismatch,
// Partial Refund but no execution
DeadlinePassed,
GasPriceOverCap,
InvalidSolver,
InvalidBidToken,
PerBlockLimit, // solvers can only send one tx per block
// if they sent two we wouldn't be able to flag builder censorship
InsufficientEscrow,
GasPriceBelowUsers,
CallValueTooHigh,
PreSolverFailed,
// execution, with Full Refund
SolverOpReverted,
PostSolverFailed,
BidNotPaid,
InvertedBidExceedsCeiling,
BalanceNotReconciled,
CallbackNotCalled,
EVMError
}//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
// aderyn-fp-next-line(unused-import)
import { ValidCallsResult } from "./ValidCalls.sol";
contract AtlasErrors {
// Simulator
error SimulatorBalanceTooLow();
error Unauthorized();
error Unreachable();
error NoAuctionWinner();
error InvalidEntryFunction();
error SimulationPassed();
error UserNotFulfilled();
error BidFindSuccessful(uint256 bidAmount);
error InvalidSolver();
error BidNotPaid();
error InvertedBidExceedsCeiling();
error BalanceNotReconciled();
error SolverOpReverted();
error AlteredControl();
error InvalidEntry();
error CallbackNotCalled();
error PreSolverFailed();
error PostSolverFailed();
error InsufficientEscrow();
error VerificationSimFail(ValidCallsResult);
error PreOpsSimFail();
error UserOpSimFail();
error SolverSimFail(uint256 solverOutcomeResult); // uint param is result returned in `verifySolverOp`
error AllocateValueSimFail();
error ValidCalls(ValidCallsResult);
error InsufficientGasForMetacallSimulation(uint256 gasLeft, uint256 estimatedMetacallGas, uint256 suggestedSimGas);
// Execution Environment
error InvalidTo();
error PreOpsDelegatecallFail();
error UserOpValueExceedsBalance();
error UserWrapperDelegatecallFail();
error UserWrapperCallFail();
error AllocateValueDelegatecallFail();
error NotEnvironmentOwner();
error ExecutionEnvironmentBalanceTooLow();
// Atlas
error PreOpsFail();
error UserOpFail();
error AllocateValueFail();
error InvalidAccess();
// Escrow
error InvalidEscrowDuration();
error DAppGasLimitReached();
// AtlETH
error EscrowLockActive();
error InsufficientBalanceForDeduction(uint256 balance, uint256 requested);
// DAppIntegration
error OnlyGovernance();
error SignatoryActive();
error InvalidCaller();
error DAppNotEnabled();
error AtlasLockActive();
// Permit69
error InvalidEnvironment();
error EnvironmentMismatch();
error InvalidLockState();
// GasAccounting
error InvalidExecutionEnvironment(address correctEnvironment);
error InsufficientAtlETHBalance(uint256 actual, uint256 needed);
error BorrowsNotRepaid(uint256 borrows, uint256 repays);
error AssignDeficitTooLarge(uint256 deficit, uint256 bundlerRefund);
// SafetyLocks
error AlreadyInitialized();
// Storage
error SurchargeRateTooHigh();
// DAppControl
error BothUserAndDAppNoncesCannotBeSequential();
error BothPreOpsAndUserReturnDataCannotBeTracked();
error InvalidControl();
error NoDelegatecall();
error MustBeDelegatecalled();
error OnlyAtlas();
error WrongPhase();
error InsufficientLocalFunds();
error NotImplemented();
error InvertBidValueCannotBeExPostBids();
}//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import "./ValidCalls.sol";
import { GasAccLib } from "../libraries/GasAccLib.sol";
// NOTE: Internal constants that are defined but not used in the logic of a smart contract, will NOT be included in the
// bytecode of the smart contract when compiled. However, public constants will be included in every inheriting contract
// as they are part of the ABI. As such, only internal constants are defined in this shared contract.
contract AtlasConstants {
// ------------------------------------------------------- //
// ATLAS CONSTANTS //
// ------------------------------------------------------- //
// Atlas constants
uint256 internal constant _GAS_VALUE_DECIMALS_TO_DROP = 1e9; // measured in gwei
uint256 internal constant _UNLOCKED = 0;
// Atlas constants used in `_bidFindingIteration()`
uint256 internal constant _BITS_FOR_INDEX = 16;
uint256 internal constant _FIRST_16_BITS_TRUE_MASK = uint256(0xFFFF);
// Escrow constants
uint256 internal constant _VALIDATION_GAS_LIMIT = 500_000;
uint256 internal constant _GRACEFUL_RETURN_GAS_OFFSET = 40_000;
// Gas Accounting constants
uint256 internal constant _GAS_PER_CALLDATA_BYTE = GasAccLib._GAS_PER_CALLDATA_BYTE;
// Calldata bytes charged at half the upper rate of 16 gas per byte (i.e. charged at 8 gas per byte), for both zero
// and non-zero bytes of calldata.
uint256 internal constant _BASE_TX_GAS_USED = 21_000;
uint256 internal constant _PRE_EXECUTE_METACALL_GAS = 150_000; // Approx gas used from start of metacall to the
// `execute()` function call, including EE deployment cost. For gas limit estimation purposes.
uint256 internal constant _POST_SETTLE_METACALL_GAS = 70_000; // Approx gas used from the gasleft() measurement
// taken at the start of `_settle()`. For full metacall gas reimbursement purposes.
uint256 internal constant _EXECUTE_SOLVER_OVERHEAD = 45_000; // Approx upper bound gas used by each
// `_executeSolverOperation()` call, excluding the `_solverOpWrapper()` gas. For gas limit estimation purposes.
uint256 internal constant _SOLVER_OP_STATIC_LENGTH = GasAccLib._SOLVER_OP_STATIC_LENGTH; // SolverOperation calldata
// length excluding solverOp.data
uint256 internal constant _BUNDLER_FAULT_OFFSET = 4500; // Extra gas to write off if solverOp failure is bundler
// fault in `_handleSolverFailAccounting()`. Value is worst-case gas measured for bundler fault.
uint256 internal constant _SOLVER_FAULT_OFFSET = 28_800; // Extra gas to charge solver if solverOp failure is solver
// fault in `_handleSolverFailAccounting()`. Value is worst-case gas measured for solver fault.
uint256 internal constant _EXTRA_CALLDATA_LENGTH = 238; // incl. gasRefundBeneficiary address and dynamic offset
// calldata
// First 160 bits of _solverLock are the address of the current solver.
// The 161st bit represents whether the solver has called back via `reconcile`.
// The 162nd bit represents whether the solver's outstanding debt has been repaid via `reconcile`.
uint256 internal constant _SOLVER_CALLED_BACK_MASK = 1 << 161;
uint256 internal constant _SOLVER_FULFILLED_MASK = 1 << 162;
// Used to set Lock phase without changing the activeEnvironment or callConfig.
uint256 internal constant _LOCK_PHASE_MASK =
uint256(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00);
// ValidCalls error threshold before which the metacall reverts, and after which it returns gracefully to store
// nonces as used.
uint8 internal constant _GRACEFUL_RETURN_THRESHOLD = uint8(ValidCallsResult.InvertBidValueCannotBeExPostBids) + 1;
// ------------------------------------------------------- //
// ATLAS VERIFICATION CONSTANTS //
// ------------------------------------------------------- //
uint8 internal constant _MAX_SOLVERS = type(uint8).max - 1;
uint256 internal constant _BID_FIND_OVERHEAD = 5000; // Overhead gas for the logic required to execute and sort each
// solverOp in `_bidFindingIteration()`
// Params below are used to calculate the tolerated max diff between actual gasleft and expected gasleft, in the
// `_getAndVerifyGasLimits()` function. This tolerance is mostly for calldata gas cost differences.
uint256 internal constant _UPPER_BASE_EXEC_GAS_TOLERANCE = 20_000;
uint256 internal constant _LOWER_BASE_EXEC_GAS_TOLERANCE = 60_000;
uint256 internal constant _TOLERANCE_PER_SOLVER = 33_000;
}//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
library AccountingMath {
uint256 internal constant _MAX_BUNDLER_REFUND_RATE = 8000; // out of 10_000 = 80%
uint256 internal constant _SCALE = 10_000; // 10_000 / 10_000 = 100%
function withSurcharge(uint256 amount, uint256 surchargeRate) internal pure returns (uint256 adjustedAmount) {
adjustedAmount = amount * (_SCALE + surchargeRate) / _SCALE;
}
function withoutSurcharge(uint256 amount, uint256 surchargeRate) internal pure returns (uint256 unadjustedAmount) {
unadjustedAmount = amount * _SCALE / (_SCALE + surchargeRate);
}
function withSurcharges(
uint256 amount,
uint256 atlasSurchargeRate,
uint256 bundlerSurchargeRate
)
internal
pure
returns (uint256 adjustedAmount)
{
adjustedAmount = amount * (_SCALE + atlasSurchargeRate + bundlerSurchargeRate) / _SCALE;
}
// gets the Atlas surcharge from an unadjusted amount
function getSurcharge(
uint256 unadjustedAmount,
uint256 surchargeRate
)
internal
pure
returns (uint256 surchargeAmount)
{
surchargeAmount = unadjustedAmount * surchargeRate / _SCALE;
}
// NOTE: This max should only be applied when there are no winning solvers.
// Set to 80% of the metacall gas cost, because the remaining 20% can be collected through storage refunds.
function maxBundlerRefund(uint256 metacallGasCost) internal pure returns (uint256 maxRefund) {
maxRefund = metacallGasCost * _MAX_BUNDLER_REFUND_RATE / _SCALE;
}
}//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import { SafeCast } from "openzeppelin-contracts/contracts/utils/math/SafeCast.sol";
import { AccountingMath } from "./AccountingMath.sol";
import { IL2GasCalculator } from "../interfaces/IL2GasCalculator.sol";
// All GasLedger vars are measured in units of gas.
// All GasLedger vars also include calldata and execution gas components.
// remainingMaxGas and unreachedSolverGas measure max gas limits (C + E).
// writeoffsGas and solverFaultFailureGas measure actual gas used (C + E).
// Only stores base gas values. Does not include the surcharges or gasprice components.
// type(uint40).max ~= 1.09 x 10^12, plenty even for gigagas (10^9) blocks
struct GasLedger {
uint40 remainingMaxGas; // Measured at start, decreased by solverOp gas limits when reached
uint40 writeoffsGas; // Gas used for solverOps but written off due to bundler fault
uint40 solverFaultFailureGas; // Gas used by solverOps that failed due to solver fault
uint40 unreachedSolverGas; // Sum of gas limits of solverOps not yet reached in the current metacall
uint40 maxApprovedGasSpend; // Max gas units approved by current solver to be spent from their bonded atlETH
uint24 atlasSurchargeRate; // Scale is 10_000 (100%) --> max atlas surcharge rate ~= 167.77x or 16777%
uint24 bundlerSurchargeRate; // Scale is 10_000 (100%) --> max bundler surcharge rate ~= 167.77x or 16777%
// NOTE: 8 bits unused.
}
// All BorrowsLedger vars are measured in units of native token (wei).
struct BorrowsLedger {
uint128 borrows; // Total native token value borrowed in the current metacall
uint128 repays; // Total native token value repaid in the current metacall
}
library GasAccLib {
using AccountingMath for uint256;
using SafeCast for uint256;
uint256 internal constant _SOLVER_OP_STATIC_LENGTH = 608;
uint256 internal constant _GAS_PER_CALLDATA_BYTE = 8; // Half of the upper 16 gas per non-zero byte, applied to all
// calldata bytes.
function pack(GasLedger memory gasLedger) internal pure returns (uint256) {
return uint256(gasLedger.remainingMaxGas) | (uint256(gasLedger.writeoffsGas) << 40)
| (uint256(gasLedger.solverFaultFailureGas) << 80) | (uint256(gasLedger.unreachedSolverGas) << 120)
| (uint256(gasLedger.maxApprovedGasSpend) << 160) | (uint256(gasLedger.atlasSurchargeRate) << 200)
| (uint256(gasLedger.bundlerSurchargeRate) << 224);
}
function pack(BorrowsLedger memory borrowsLedger) internal pure returns (uint256) {
return uint256(borrowsLedger.borrows) | (uint256(borrowsLedger.repays) << 128);
}
function toGasLedger(uint256 gasLedgerPacked) internal pure returns (GasLedger memory) {
return GasLedger({
remainingMaxGas: uint40(gasLedgerPacked),
writeoffsGas: uint40(gasLedgerPacked >> 40),
solverFaultFailureGas: uint40(gasLedgerPacked >> 80),
unreachedSolverGas: uint40(gasLedgerPacked >> 120),
maxApprovedGasSpend: uint40(gasLedgerPacked >> 160),
atlasSurchargeRate: uint24(gasLedgerPacked >> 200),
bundlerSurchargeRate: uint24(gasLedgerPacked >> 224)
});
}
function toBorrowsLedger(uint256 borrowsLedgerPacked) internal pure returns (BorrowsLedger memory) {
return BorrowsLedger({ borrows: uint128(borrowsLedgerPacked), repays: uint128(borrowsLedgerPacked >> 128) });
}
function netRepayments(BorrowsLedger memory bL) internal pure returns (int256) {
return uint256(bL.repays).toInt256() - uint256(bL.borrows).toInt256();
}
// Returns the max gas liability (in native token units) for the current solver.
// `remainingMaxGas` is max gas limit as measured at start of metacall, with the gas limit of each solverOp
// subtracted at the end of its execution.
// `unreachedSolverGas` is the sum of solverOp gas limits not yet reached, with gas limit of current solverOp
// subtracted at the start of its execution, before bonded balance check.
// Thus `remainingMaxGas - unreachedSolverGas` is the max gas the current solver might need to pay for if they win,
// including dApp hook gas limits and userOp gas limit.
function solverGasLiability(GasLedger memory gL) internal view returns (uint256) {
return uint256(gL.remainingMaxGas - gL.unreachedSolverGas).withSurcharge(
uint256(gL.atlasSurchargeRate + gL.bundlerSurchargeRate)
) * tx.gasprice;
}
// Returns the sum of the Atlas and bundler surcharge rates.
// Scale of the returned value is 10_000 (100%).
function totalSurchargeRate(GasLedger memory gL) internal pure returns (uint256) {
return uint256(gL.atlasSurchargeRate + gL.bundlerSurchargeRate);
}
function solverOpCalldataGas(uint256 calldataLength, address l2GasCalculator) internal view returns (uint256 gas) {
if (l2GasCalculator == address(0)) {
// Default to using mainnet gas calculations
// _SOLVER_OP_STATIC_LENGTH = SolverOperation calldata length excluding solverOp.data
gas = (calldataLength + _SOLVER_OP_STATIC_LENGTH) * _GAS_PER_CALLDATA_BYTE;
} else {
gas = IL2GasCalculator(l2GasCalculator).getCalldataGas(calldataLength + _SOLVER_OP_STATIC_LENGTH);
}
}
function calldataGas(uint256 calldataLength, address l2GasCalculator) internal view returns (uint256 gas) {
if (l2GasCalculator == address(0)) {
// Default to using mainnet gas calculations
gas = calldataLength * _GAS_PER_CALLDATA_BYTE;
} else {
gas = IL2GasCalculator(l2GasCalculator).getCalldataGas(calldataLength);
}
}
function metacallCalldataGas(
uint256 msgDataLength,
address l2GasCalculator
)
internal
view
returns (uint256 calldataGas)
{
if (l2GasCalculator == address(0)) {
calldataGas = msgDataLength * _GAS_PER_CALLDATA_BYTE;
} else {
calldataGas = IL2GasCalculator(l2GasCalculator).initialGasUsed(msgDataLength);
}
}
}//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import { IDAppControl } from "../interfaces/IDAppControl.sol";
import "../types/ConfigTypes.sol";
library CallBits {
uint32 internal constant _ONE = uint32(1);
function buildCallConfig(address control) internal view returns (uint32 callConfig) {
callConfig = IDAppControl(control).CALL_CONFIG();
}
function encodeCallConfig(CallConfig memory callConfig) internal pure returns (uint32 encodedCallConfig) {
if (callConfig.userNoncesSequential) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.UserNoncesSequential);
}
if (callConfig.dappNoncesSequential) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.DAppNoncesSequential);
}
if (callConfig.requirePreOps) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.RequirePreOps);
}
if (callConfig.trackPreOpsReturnData) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.TrackPreOpsReturnData);
}
if (callConfig.trackUserReturnData) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.TrackUserReturnData);
}
if (callConfig.delegateUser) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.DelegateUser);
}
if (callConfig.requirePreSolver) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.RequirePreSolver);
}
if (callConfig.requirePostSolver) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.RequirePostSolver);
}
if (callConfig.zeroSolvers) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.ZeroSolvers);
}
if (callConfig.reuseUserOp) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.ReuseUserOp);
}
if (callConfig.userAuctioneer) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.UserAuctioneer);
}
if (callConfig.solverAuctioneer) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.SolverAuctioneer);
}
if (callConfig.unknownAuctioneer) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.UnknownAuctioneer);
}
if (callConfig.verifyCallChainHash) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.VerifyCallChainHash);
}
if (callConfig.forwardReturnData) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.ForwardReturnData);
}
if (callConfig.requireFulfillment) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.RequireFulfillment);
}
if (callConfig.trustedOpHash) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.TrustedOpHash);
}
if (callConfig.invertBidValue) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.InvertBidValue);
}
if (callConfig.exPostBids) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.ExPostBids);
}
if (callConfig.multipleSuccessfulSolvers) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.MultipleSuccessfulSolvers);
}
if (callConfig.checkMetacallGasLimit) {
encodedCallConfig ^= _ONE << uint32(CallConfigIndex.CheckMetacallGasLimit);
}
}
function decodeCallConfig(uint32 encodedCallConfig) internal pure returns (CallConfig memory callConfig) {
callConfig.userNoncesSequential = needsSequentialUserNonces(encodedCallConfig);
callConfig.dappNoncesSequential = needsSequentialDAppNonces(encodedCallConfig);
callConfig.requirePreOps = needsPreOpsCall(encodedCallConfig);
callConfig.trackPreOpsReturnData = needsPreOpsReturnData(encodedCallConfig);
callConfig.trackUserReturnData = needsUserReturnData(encodedCallConfig);
callConfig.delegateUser = needsDelegateUser(encodedCallConfig);
callConfig.requirePreSolver = needsPreSolverCall(encodedCallConfig);
callConfig.requirePostSolver = needsPostSolverCall(encodedCallConfig);
callConfig.zeroSolvers = allowsZeroSolvers(encodedCallConfig);
callConfig.reuseUserOp = allowsReuseUserOps(encodedCallConfig);
callConfig.userAuctioneer = allowsUserAuctioneer(encodedCallConfig);
callConfig.solverAuctioneer = allowsSolverAuctioneer(encodedCallConfig);
callConfig.unknownAuctioneer = allowsUnknownAuctioneer(encodedCallConfig);
callConfig.verifyCallChainHash = verifyCallChainHash(encodedCallConfig);
callConfig.forwardReturnData = forwardReturnData(encodedCallConfig);
callConfig.requireFulfillment = needsFulfillment(encodedCallConfig);
callConfig.trustedOpHash = allowsTrustedOpHash(encodedCallConfig);
callConfig.invertBidValue = invertsBidValue(encodedCallConfig);
callConfig.exPostBids = exPostBids(encodedCallConfig);
callConfig.multipleSuccessfulSolvers = multipleSuccessfulSolvers(encodedCallConfig);
callConfig.checkMetacallGasLimit = checkMetacallGasLimit(encodedCallConfig);
}
function needsSequentialUserNonces(uint32 callConfig) internal pure returns (bool sequential) {
sequential = callConfig & (1 << uint32(CallConfigIndex.UserNoncesSequential)) != 0;
}
function needsSequentialDAppNonces(uint32 callConfig) internal pure returns (bool sequential) {
sequential = callConfig & (1 << uint32(CallConfigIndex.DAppNoncesSequential)) != 0;
}
function needsPreOpsCall(uint32 callConfig) internal pure returns (bool needsPreOps) {
needsPreOps = callConfig & (1 << uint32(CallConfigIndex.RequirePreOps)) != 0;
}
function needsPreOpsReturnData(uint32 callConfig) internal pure returns (bool needsReturnData) {
needsReturnData = callConfig & (1 << uint32(CallConfigIndex.TrackPreOpsReturnData)) != 0;
}
function needsUserReturnData(uint32 callConfig) internal pure returns (bool needsReturnData) {
needsReturnData = callConfig & (1 << uint32(CallConfigIndex.TrackUserReturnData)) != 0;
}
function needsDelegateUser(uint32 callConfig) internal pure returns (bool delegateUser) {
delegateUser = callConfig & (1 << uint32(CallConfigIndex.DelegateUser)) != 0;
}
function needsPreSolverCall(uint32 callConfig) internal pure returns (bool needsPreSolver) {
needsPreSolver = callConfig & (1 << uint32(CallConfigIndex.RequirePreSolver)) != 0;
}
function needsPostSolverCall(uint32 callConfig) internal pure returns (bool needsPostSolver) {
needsPostSolver = callConfig & (1 << uint32(CallConfigIndex.RequirePostSolver)) != 0;
}
function allowsZeroSolvers(uint32 callConfig) internal pure returns (bool zeroSolvers) {
zeroSolvers = callConfig & (1 << uint32(CallConfigIndex.ZeroSolvers)) != 0;
}
function allowsReuseUserOps(uint32 callConfig) internal pure returns (bool reuseUserOp) {
reuseUserOp = callConfig & (1 << uint32(CallConfigIndex.ReuseUserOp)) != 0;
}
function allowsUserAuctioneer(uint32 callConfig) internal pure returns (bool userAuctioneer) {
userAuctioneer = callConfig & (1 << uint32(CallConfigIndex.UserAuctioneer)) != 0;
}
function allowsSolverAuctioneer(uint32 callConfig) internal pure returns (bool userAuctioneer) {
userAuctioneer = callConfig & (1 << uint32(CallConfigIndex.SolverAuctioneer)) != 0;
}
function allowsUnknownAuctioneer(uint32 callConfig) internal pure returns (bool unknownAuctioneer) {
unknownAuctioneer = callConfig & (1 << uint32(CallConfigIndex.UnknownAuctioneer)) != 0;
}
function verifyCallChainHash(uint32 callConfig) internal pure returns (bool verify) {
verify = callConfig & (1 << uint32(CallConfigIndex.VerifyCallChainHash)) != 0;
}
function forwardReturnData(uint32 callConfig) internal pure returns (bool) {
return callConfig & (1 << uint32(CallConfigIndex.ForwardReturnData)) != 0;
}
function needsFulfillment(uint32 callConfig) internal pure returns (bool) {
return callConfig & (1 << uint32(CallConfigIndex.RequireFulfillment)) != 0;
}
function allowsTrustedOpHash(uint32 callConfig) internal pure returns (bool) {
return callConfig & (1 << uint32(CallConfigIndex.TrustedOpHash)) != 0;
}
function invertsBidValue(uint32 callConfig) internal pure returns (bool) {
return callConfig & (1 << uint32(CallConfigIndex.InvertBidValue)) != 0;
}
function exPostBids(uint32 callConfig) internal pure returns (bool) {
return callConfig & (1 << uint32(CallConfigIndex.ExPostBids)) != 0;
}
function multipleSuccessfulSolvers(uint32 callConfig) internal pure returns (bool) {
return (callConfig & (1 << uint32(CallConfigIndex.MultipleSuccessfulSolvers))) != 0;
}
function checkMetacallGasLimit(uint32 callConfig) internal pure returns (bool) {
return (callConfig & (1 << uint32(CallConfigIndex.CheckMetacallGasLimit))) != 0;
}
}//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import "../types/SolverOperation.sol";
import "../types/UserOperation.sol";
import "../types/DAppOperation.sol";
enum Result {
Unknown,
VerificationSimFail,
PreOpsSimFail,
UserOpSimFail,
SolverSimFail,
AllocateValueSimFail,
SimulationPassed
}
interface ISimulator {
function estimateMetacallGasLimit(
UserOperation calldata userOp,
SolverOperation[] calldata solverOps
)
external
view
returns (uint256);
function simUserOperation(UserOperation calldata userOp)
external
payable
returns (bool success, Result simResult, uint256);
function simSolverCall(
UserOperation calldata userOp,
SolverOperation calldata solverOp,
DAppOperation calldata verification
)
external
payable
returns (bool success, Result simResult, uint256);
function simSolverCalls(
UserOperation calldata userOp,
SolverOperation[] calldata solverOps,
DAppOperation calldata verification
)
external
payable
returns (bool success, Result simResult, uint256);
}//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import "../types/SolverOperation.sol";
import "../types/UserOperation.sol";
import "../types/DAppOperation.sol";
interface IAtlas {
// Atlas.sol
function metacall(
UserOperation calldata userOp,
SolverOperation[] calldata solverOps,
DAppOperation calldata dAppOp,
address gasRefundBeneficiary
)
external
payable
returns (bool auctionWon);
// Factory.sol
function createExecutionEnvironment(
address user,
address control
)
external
returns (address executionEnvironment);
function getExecutionEnvironment(
address user,
address control
)
external
view
returns (address executionEnvironment, uint32 callConfig, bool exists);
// AtlETH.sol
function balanceOf(address account) external view returns (uint256);
function balanceOfBonded(address account) external view returns (uint256);
function balanceOfUnbonding(address account) external view returns (uint256);
function accountLastActiveBlock(address account) external view returns (uint256);
function unbondingCompleteBlock(address account) external view returns (uint256);
function deposit() external payable;
function withdraw(uint256 amount) external;
function bond(uint256 amount) external;
function depositAndBond(uint256 amountToBond) external payable;
function unbond(uint256 amount) external;
function redeem(uint256 amount) external;
function withdrawSurcharge() external;
function transferSurchargeRecipient(address newRecipient) external;
function becomeSurchargeRecipient() external;
function setSurchargeRates(uint128 newAtlasRate, uint128 newBundlerRate) external;
// Permit69.sol
function transferUserERC20(
address token,
address destination,
uint256 amount,
address user,
address control
)
external;
function transferDAppERC20(
address token,
address destination,
uint256 amount,
address user,
address control
)
external;
// GasAccounting.sol
function contribute() external payable;
function borrow(uint256 amount) external payable;
function shortfall() external view returns (uint256 gasLiability, uint256 borrowLiability);
function reconcile(uint256 maxApprovedGasSpend) external payable returns (uint256 owed);
// SafetyLocks.sol
function isUnlocked() external view returns (bool);
// Storage.sol
function VERIFICATION() external view returns (address);
function SIMULATOR() external view returns (address);
function L2_GAS_CALCULATOR() external view returns (address);
function ESCROW_DURATION() external view returns (uint256);
function solverLockData() external view returns (address currentSolver, bool calledBack, bool fulfilled);
function totalSupply() external view returns (uint256);
function bondedTotalSupply() external view returns (uint256);
function accessData(address account)
external
view
returns (
uint112 bonded,
uint32 lastAccessedBlock,
uint24 auctionWins,
uint24 auctionFails,
uint64 totalGasValueUsed
);
function solverOpHashes(bytes32 opHash) external view returns (bool);
function lock() external view returns (address activeEnvironment, uint32 callConfig, uint8 phase);
function solverLock() external view returns (uint256);
function cumulativeSurcharge() external view returns (uint256);
function surchargeRecipient() external view returns (address);
function pendingSurchargeRecipient() external view returns (address);
function getAtlasSurchargeRate() external view returns (uint256);
}//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import "../types/UserOperation.sol";
import "../types/SolverOperation.sol";
import "../types/ConfigTypes.sol";
interface IDAppControl {
function preOpsCall(UserOperation calldata userOp) external payable returns (bytes memory);
function preSolverCall(SolverOperation calldata solverOp, bytes calldata returnData) external payable;
function postSolverCall(SolverOperation calldata solverOp, bytes calldata returnData) external payable;
function allocateValueCall(bool solved, address bidToken, uint256 bidAmount, bytes calldata data) external;
function getDAppConfig(UserOperation calldata userOp) external view returns (DAppConfig memory dConfig);
function getCallConfig() external view returns (CallConfig memory callConfig);
function CALL_CONFIG() external view returns (uint32);
function getSolverGasLimit() external view returns (uint32);
function getDAppGasLimit() external view returns (uint32);
function getBundlerSurchargeRate() external view returns (uint24);
function getBidFormat(UserOperation calldata userOp) external view returns (address bidToken);
function getBidValue(SolverOperation calldata solverOp) external view returns (uint256);
function getDAppSignatory() external view returns (address governanceAddress);
function requireSequentialUserNonces() external view returns (bool isSequential);
function requireSequentialDAppNonces() external view returns (bool isSequential);
function userDelegated() external view returns (bool delegated);
function transferGovernance(address newGovernance) external;
function acceptGovernance() external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.20;
/**
* @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeCast {
/**
* @dev Value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
/**
* @dev An int value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedIntToUint(int256 value);
/**
* @dev Value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
/**
* @dev An uint value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedUintToInt(uint256 value);
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toUint248(uint256 value) internal pure returns (uint248) {
if (value > type(uint248).max) {
revert SafeCastOverflowedUintDowncast(248, value);
}
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toUint240(uint256 value) internal pure returns (uint240) {
if (value > type(uint240).max) {
revert SafeCastOverflowedUintDowncast(240, value);
}
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toUint232(uint256 value) internal pure returns (uint232) {
if (value > type(uint232).max) {
revert SafeCastOverflowedUintDowncast(232, value);
}
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
if (value > type(uint224).max) {
revert SafeCastOverflowedUintDowncast(224, value);
}
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toUint216(uint256 value) internal pure returns (uint216) {
if (value > type(uint216).max) {
revert SafeCastOverflowedUintDowncast(216, value);
}
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toUint208(uint256 value) internal pure returns (uint208) {
if (value > type(uint208).max) {
revert SafeCastOverflowedUintDowncast(208, value);
}
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toUint200(uint256 value) internal pure returns (uint200) {
if (value > type(uint200).max) {
revert SafeCastOverflowedUintDowncast(200, value);
}
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toUint192(uint256 value) internal pure returns (uint192) {
if (value > type(uint192).max) {
revert SafeCastOverflowedUintDowncast(192, value);
}
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toUint184(uint256 value) internal pure returns (uint184) {
if (value > type(uint184).max) {
revert SafeCastOverflowedUintDowncast(184, value);
}
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toUint176(uint256 value) internal pure returns (uint176) {
if (value > type(uint176).max) {
revert SafeCastOverflowedUintDowncast(176, value);
}
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toUint168(uint256 value) internal pure returns (uint168) {
if (value > type(uint168).max) {
revert SafeCastOverflowedUintDowncast(168, value);
}
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toUint160(uint256 value) internal pure returns (uint160) {
if (value > type(uint160).max) {
revert SafeCastOverflowedUintDowncast(160, value);
}
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toUint152(uint256 value) internal pure returns (uint152) {
if (value > type(uint152).max) {
revert SafeCastOverflowedUintDowncast(152, value);
}
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toUint144(uint256 value) internal pure returns (uint144) {
if (value > type(uint144).max) {
revert SafeCastOverflowedUintDowncast(144, value);
}
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toUint136(uint256 value) internal pure returns (uint136) {
if (value > type(uint136).max) {
revert SafeCastOverflowedUintDowncast(136, value);
}
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
if (value > type(uint128).max) {
revert SafeCastOverflowedUintDowncast(128, value);
}
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toUint120(uint256 value) internal pure returns (uint120) {
if (value > type(uint120).max) {
revert SafeCastOverflowedUintDowncast(120, value);
}
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toUint112(uint256 value) internal pure returns (uint112) {
if (value > type(uint112).max) {
revert SafeCastOverflowedUintDowncast(112, value);
}
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toUint104(uint256 value) internal pure returns (uint104) {
if (value > type(uint104).max) {
revert SafeCastOverflowedUintDowncast(104, value);
}
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
if (value > type(uint96).max) {
revert SafeCastOverflowedUintDowncast(96, value);
}
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toUint88(uint256 value) internal pure returns (uint88) {
if (value > type(uint88).max) {
revert SafeCastOverflowedUintDowncast(88, value);
}
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toUint80(uint256 value) internal pure returns (uint80) {
if (value > type(uint80).max) {
revert SafeCastOverflowedUintDowncast(80, value);
}
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toUint72(uint256 value) internal pure returns (uint72) {
if (value > type(uint72).max) {
revert SafeCastOverflowedUintDowncast(72, value);
}
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
if (value > type(uint64).max) {
revert SafeCastOverflowedUintDowncast(64, value);
}
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toUint56(uint256 value) internal pure returns (uint56) {
if (value > type(uint56).max) {
revert SafeCastOverflowedUintDowncast(56, value);
}
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toUint48(uint256 value) internal pure returns (uint48) {
if (value > type(uint48).max) {
revert SafeCastOverflowedUintDowncast(48, value);
}
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toUint40(uint256 value) internal pure returns (uint40) {
if (value > type(uint40).max) {
revert SafeCastOverflowedUintDowncast(40, value);
}
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
if (value > type(uint32).max) {
revert SafeCastOverflowedUintDowncast(32, value);
}
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toUint24(uint256 value) internal pure returns (uint24) {
if (value > type(uint24).max) {
revert SafeCastOverflowedUintDowncast(24, value);
}
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
if (value > type(uint16).max) {
revert SafeCastOverflowedUintDowncast(16, value);
}
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toUint8(uint256 value) internal pure returns (uint8) {
if (value > type(uint8).max) {
revert SafeCastOverflowedUintDowncast(8, value);
}
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
if (value < 0) {
revert SafeCastOverflowedIntToUint(value);
}
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(248, value);
}
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(240, value);
}
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(232, value);
}
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(224, value);
}
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(216, value);
}
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(208, value);
}
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(200, value);
}
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(192, value);
}
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(184, value);
}
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(176, value);
}
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(168, value);
}
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(160, value);
}
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(152, value);
}
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(144, value);
}
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(136, value);
}
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(128, value);
}
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(120, value);
}
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(112, value);
}
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(104, value);
}
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(96, value);
}
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(88, value);
}
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(80, value);
}
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(72, value);
}
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(64, value);
}
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(56, value);
}
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(48, value);
}
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(40, value);
}
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(32, value);
}
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(24, value);
}
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(16, value);
}
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(8, value);
}
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
if (value > uint256(type(int256).max)) {
revert SafeCastOverflowedUintToInt(value);
}
return int256(value);
}
}//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
interface IL2GasCalculator {
/// @notice Calculate the cost (in gas units) of calldata in ETH on a L2 with a different fee structure than mainnet
function getCalldataGas(uint256 calldataLength) external view returns (uint256 calldataGas);
/// @notice Gets the cost (in gas units) of initial gas used for a tx with a different calldata fee than mainnet
function initialGasUsed(uint256 calldataLength) external view returns (uint256 gasUsed);
}{
"remappings": [
"ds-test/=lib/forge-std/lib/ds-test/src/",
"eth-gas-reporter/=node_modules/eth-gas-reporter/",
"forge-std/=lib/forge-std/src/",
"hardhat/=node_modules/hardhat/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"solady/=lib/solady/src/",
"nitro-contracts/=lib/nitro-contracts/",
"@offchainlabs/upgrade-executor/=lib/nitro-contracts/node_modules/@offchainlabs/upgrade-executor/",
"@openzeppelin/=node_modules/@openzeppelin/",
"@uniswap/lib/=lib/nitro-contracts/node_modules/@uniswap/lib/contracts/",
"@uniswap/v2-core/=lib/nitro-contracts/node_modules/@uniswap/v2-core/contracts/",
"chainlink/=lib/chainlink/",
"erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
"redstone-oracles-monorepo/=lib/redstone-oracles-monorepo/",
"solmate/=lib/solmate/src/"
],
"optimizer": {
"enabled": true,
"runs": 18
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": true
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AllocateValueDelegatecallFail","type":"error"},{"inputs":[],"name":"AllocateValueFail","type":"error"},{"inputs":[],"name":"AllocateValueSimFail","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"AlteredControl","type":"error"},{"inputs":[{"internalType":"uint256","name":"deficit","type":"uint256"},{"internalType":"uint256","name":"bundlerRefund","type":"uint256"}],"name":"AssignDeficitTooLarge","type":"error"},{"inputs":[],"name":"AtlasLockActive","type":"error"},{"inputs":[],"name":"BalanceNotReconciled","type":"error"},{"inputs":[{"internalType":"uint256","name":"bidAmount","type":"uint256"}],"name":"BidFindSuccessful","type":"error"},{"inputs":[],"name":"BidNotPaid","type":"error"},{"inputs":[{"internalType":"uint256","name":"borrows","type":"uint256"},{"internalType":"uint256","name":"repays","type":"uint256"}],"name":"BorrowsNotRepaid","type":"error"},{"inputs":[],"name":"BothPreOpsAndUserReturnDataCannotBeTracked","type":"error"},{"inputs":[],"name":"BothUserAndDAppNoncesCannotBeSequential","type":"error"},{"inputs":[],"name":"CallbackNotCalled","type":"error"},{"inputs":[],"name":"DAppGasLimitReached","type":"error"},{"inputs":[],"name":"DAppNotEnabled","type":"error"},{"inputs":[],"name":"EnvironmentMismatch","type":"error"},{"inputs":[],"name":"EscrowLockActive","type":"error"},{"inputs":[],"name":"ExecutionEnvironmentBalanceTooLow","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"InsufficientAtlETHBalance","type":"error"},{"inputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"InsufficientBalanceForDeduction","type":"error"},{"inputs":[],"name":"InsufficientEscrow","type":"error"},{"inputs":[{"internalType":"uint256","name":"gasLeft","type":"uint256"},{"internalType":"uint256","name":"estimatedMetacallGas","type":"uint256"},{"internalType":"uint256","name":"suggestedSimGas","type":"uint256"}],"name":"InsufficientGasForMetacallSimulation","type":"error"},{"inputs":[],"name":"InsufficientLocalFunds","type":"error"},{"inputs":[],"name":"InvalidAccess","type":"error"},{"inputs":[],"name":"InvalidCaller","type":"error"},{"inputs":[],"name":"InvalidControl","type":"error"},{"inputs":[],"name":"InvalidEntry","type":"error"},{"inputs":[],"name":"InvalidEntryFunction","type":"error"},{"inputs":[],"name":"InvalidEnvironment","type":"error"},{"inputs":[],"name":"InvalidEscrowDuration","type":"error"},{"inputs":[{"internalType":"address","name":"correctEnvironment","type":"address"}],"name":"InvalidExecutionEnvironment","type":"error"},{"inputs":[],"name":"InvalidLockState","type":"error"},{"inputs":[],"name":"InvalidSolver","type":"error"},{"inputs":[],"name":"InvalidTo","type":"error"},{"inputs":[],"name":"InvertBidValueCannotBeExPostBids","type":"error"},{"inputs":[],"name":"InvertedBidExceedsCeiling","type":"error"},{"inputs":[],"name":"MustBeDelegatecalled","type":"error"},{"inputs":[],"name":"NoAuctionWinner","type":"error"},{"inputs":[],"name":"NoDelegatecall","type":"error"},{"inputs":[],"name":"NotEnvironmentOwner","type":"error"},{"inputs":[],"name":"NotImplemented","type":"error"},{"inputs":[],"name":"OnlyAtlas","type":"error"},{"inputs":[],"name":"OnlyGovernance","type":"error"},{"inputs":[],"name":"PostSolverFailed","type":"error"},{"inputs":[],"name":"PreOpsDelegatecallFail","type":"error"},{"inputs":[],"name":"PreOpsFail","type":"error"},{"inputs":[],"name":"PreOpsSimFail","type":"error"},{"inputs":[],"name":"PreSolverFailed","type":"error"},{"inputs":[],"name":"SignatoryActive","type":"error"},{"inputs":[],"name":"SimulationPassed","type":"error"},{"inputs":[],"name":"SimulatorBalanceTooLow","type":"error"},{"inputs":[],"name":"SolverOpReverted","type":"error"},{"inputs":[{"internalType":"uint256","name":"solverOutcomeResult","type":"uint256"}],"name":"SolverSimFail","type":"error"},{"inputs":[],"name":"SurchargeRateTooHigh","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"Unreachable","type":"error"},{"inputs":[],"name":"UserNotFulfilled","type":"error"},{"inputs":[],"name":"UserOpFail","type":"error"},{"inputs":[],"name":"UserOpSimFail","type":"error"},{"inputs":[],"name":"UserOpValueExceedsBalance","type":"error"},{"inputs":[],"name":"UserWrapperCallFail","type":"error"},{"inputs":[],"name":"UserWrapperDelegatecallFail","type":"error"},{"inputs":[{"internalType":"enum ValidCallsResult","name":"","type":"uint8"}],"name":"ValidCalls","type":"error"},{"inputs":[{"internalType":"enum ValidCallsResult","name":"","type":"uint8"}],"name":"VerificationSimFail","type":"error"},{"inputs":[],"name":"WrongPhase","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DeployerWithdrawal","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"atlas","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deployer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"dapp","type":"address"},{"internalType":"address","name":"control","type":"address"},{"internalType":"uint32","name":"callConfig","type":"uint32"},{"internalType":"uint32","name":"dappGasLimit","type":"uint32"},{"internalType":"uint32","name":"solverGasLimit","type":"uint32"},{"internalType":"uint24","name":"bundlerSurchargeRate","type":"uint24"},{"internalType":"address","name":"sessionKey","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UserOperation","name":"userOp","type":"tuple"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"solver","type":"address"},{"internalType":"address","name":"control","type":"address"},{"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"internalType":"address","name":"bidToken","type":"address"},{"internalType":"uint256","name":"bidAmount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SolverOperation","name":"solverOp","type":"tuple"}],"name":"estimateMaxSolverWinGasCharge","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"dapp","type":"address"},{"internalType":"address","name":"control","type":"address"},{"internalType":"uint32","name":"callConfig","type":"uint32"},{"internalType":"uint32","name":"dappGasLimit","type":"uint32"},{"internalType":"uint32","name":"solverGasLimit","type":"uint32"},{"internalType":"uint24","name":"bundlerSurchargeRate","type":"uint24"},{"internalType":"address","name":"sessionKey","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UserOperation","name":"userOp","type":"tuple"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"solver","type":"address"},{"internalType":"address","name":"control","type":"address"},{"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"internalType":"address","name":"bidToken","type":"address"},{"internalType":"uint256","name":"bidAmount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SolverOperation[]","name":"solverOps","type":"tuple[]"}],"name":"estimateMetacallGasLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"dapp","type":"address"},{"internalType":"address","name":"control","type":"address"},{"internalType":"uint32","name":"callConfig","type":"uint32"},{"internalType":"uint32","name":"dappGasLimit","type":"uint32"},{"internalType":"uint32","name":"solverGasLimit","type":"uint32"},{"internalType":"uint24","name":"bundlerSurchargeRate","type":"uint24"},{"internalType":"address","name":"sessionKey","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UserOperation","name":"userOp","type":"tuple"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"solver","type":"address"},{"internalType":"address","name":"control","type":"address"},{"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"internalType":"address","name":"bidToken","type":"address"},{"internalType":"uint256","name":"bidAmount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SolverOperation[]","name":"solverOps","type":"tuple[]"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"control","type":"address"},{"internalType":"address","name":"bundler","type":"address"},{"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"internalType":"bytes32","name":"callChainHash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct DAppOperation","name":"dAppOp","type":"tuple"},{"internalType":"uint256","name":"adjMetacallExecutionGas","type":"uint256"}],"name":"metacallSimulation","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_atlas","type":"address"}],"name":"setAtlas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"dapp","type":"address"},{"internalType":"address","name":"control","type":"address"},{"internalType":"uint32","name":"callConfig","type":"uint32"},{"internalType":"uint32","name":"dappGasLimit","type":"uint32"},{"internalType":"uint32","name":"solverGasLimit","type":"uint32"},{"internalType":"uint24","name":"bundlerSurchargeRate","type":"uint24"},{"internalType":"address","name":"sessionKey","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UserOperation","name":"userOp","type":"tuple"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"solver","type":"address"},{"internalType":"address","name":"control","type":"address"},{"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"internalType":"address","name":"bidToken","type":"address"},{"internalType":"uint256","name":"bidAmount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SolverOperation","name":"solverOp","type":"tuple"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"control","type":"address"},{"internalType":"address","name":"bundler","type":"address"},{"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"internalType":"bytes32","name":"callChainHash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct DAppOperation","name":"dAppOp","type":"tuple"}],"name":"simSolverCall","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"enum Result","name":"simResult","type":"uint8"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"dapp","type":"address"},{"internalType":"address","name":"control","type":"address"},{"internalType":"uint32","name":"callConfig","type":"uint32"},{"internalType":"uint32","name":"dappGasLimit","type":"uint32"},{"internalType":"uint32","name":"solverGasLimit","type":"uint32"},{"internalType":"uint24","name":"bundlerSurchargeRate","type":"uint24"},{"internalType":"address","name":"sessionKey","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UserOperation","name":"userOp","type":"tuple"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"solver","type":"address"},{"internalType":"address","name":"control","type":"address"},{"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"internalType":"address","name":"bidToken","type":"address"},{"internalType":"uint256","name":"bidAmount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SolverOperation[]","name":"solverOps","type":"tuple[]"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"control","type":"address"},{"internalType":"address","name":"bundler","type":"address"},{"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"internalType":"bytes32","name":"callChainHash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct DAppOperation","name":"dAppOp","type":"tuple"}],"name":"simSolverCalls","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"enum Result","name":"simResult","type":"uint8"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"dapp","type":"address"},{"internalType":"address","name":"control","type":"address"},{"internalType":"uint32","name":"callConfig","type":"uint32"},{"internalType":"uint32","name":"dappGasLimit","type":"uint32"},{"internalType":"uint32","name":"solverGasLimit","type":"uint32"},{"internalType":"uint24","name":"bundlerSurchargeRate","type":"uint24"},{"internalType":"address","name":"sessionKey","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UserOperation","name":"userOp","type":"tuple"}],"name":"simUserOperation","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"enum Result","name":"simResult","type":"uint8"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60a080604052346030573360805261203c90816100358239608051818181610133015281816102ce015261099c0152f35b5f80fdfe60806040526004361015610010575b005b5f3560e01c8063127f1b7d146100af578063133bff36146100aa5780635dd362cd146100a5578063690d8320146100a057806388f719bf1461009b578063b2e3aac114610096578063b6a777c114610091578063b759598a1461008c578063d5f39488146100875763fb3ae8de0361000e576109cb565b610987565b610895565b61079d565b610633565b6105b6565b6102af565b610223565b610114565b6100cf565b5f9103126100be57565b5f80fd5b6001600160a01b03169052565b346100be575f3660031901126100be575f546040516001600160a01b039091168152602090f35b6001600160a01b038116036100be57565b3590610112826100f6565b565b346100be5760203660031901126100be57600435610131816100f6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610182575f80546001600160a01b0319166001600160a01b0392909216919091179055005b6282b42960e81b5f5260045ffd5b90816102009103126100be5790565b9181601f840112156100be578235916001600160401b0383116100be576020808501948460051b0101116100be57565b90816101209103126100be5790565b634e487b7160e01b5f52602160045260245ffd5b600711156101fc57565b6101de565b9015158152606081019392919060078210156101fc5760409160208201520152565b60603660031901126100be576004356001600160401b0381116100be5761024e903690600401610190565b6024356001600160401b0381116100be5761026d90369060040161019f565b9091604435916001600160401b0383116100be576102ab9361029661029c9436906004016101cf565b92610fa5565b60409391935193849384610201565b0390f35b346100be5760203660031901126100be576004356102cc816100f6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610182577f79937dd50eabc51ec0ce6597abf279889ffbe60563a346e7d16826a5e9954b3f6020479261032b8482611eb7565b6040519384526001600160a01b031692a2005b634e487b7160e01b5f52604160045260245ffd5b6101a081019081106001600160401b0382111761036e57604052565b61033e565b60c081019081106001600160401b0382111761036e57604052565b90601f801991011681019081106001600160401b0382111761036e57604052565b604051906101126101a08361038e565b604051906101126102008361038e565b604051906101126101208361038e565b6001600160401b03811161036e5760051b60200190565b6001600160401b03811161036e57601f01601f191660200190565b81601f820112156100be57803590610428826103f6565b92610436604051948561038e565b828452602083830101116100be57815f926020809301838601378301015290565b9190916101a0818403126100be5761046d6103af565b9261047782610107565b845261048560208301610107565b602085015260408201356040850152606082013560608501526080820135608085015260a082013560a08501526104be60c08301610107565b60c08501526104cf60e08301610107565b60e08501526101008201356101008501526104ed6101208301610107565b6101208501526101408201356101408501526101608201356001600160401b0381116100be578161051f918401610411565b6101608501526101808201356001600160401b0381116100be576105439201610411565b610180830152565b929190610557816103df565b93610565604051958661038e565b602085838152019160051b8101918383116100be5781905b83821061058b575050505050565b81356001600160401b0381116100be576020916105ab8784938701610457565b81520191019061057d565b346100be5760403660031901126100be576004356001600160401b0381116100be576105e6903690600401610190565b6024356001600160401b0381116100be57366023820112156100be576102ab9161061d61062392369060248160040135910161054b565b90611036565b6040519081529081906020820190565b60803660031901126100be576004356001600160401b0381116100be5761065e903690600401610190565b6024356001600160401b0381116100be5761067d90369060040161019f565b906044356001600160401b0381116100be5761069d9036906004016101cf565b6064359130330361078e575f546106f29460209490916106d3906106c7906001600160a01b031681565b6001600160a01b031690565b9260405196879586948593634317ca0160e01b85528b600486016112c9565b03923491f1908115610789575f9161075a575b50159081610731575b506107225763d7817dcb60e01b5f5260045ffd5b6334d8364360e21b5f5260045ffd5b61075491506107466101206107509201611460565b6208000016151590565b1590565b5f61070e565b61077c915060203d602011610782575b610774818361038e565b81019061104c565b5f610705565b503d61076a565b611455565b63b749f31960e01b5f5260045ffd5b60203660031901126100be576004356001600160401b0381116100be576107c8903690600401610190565b60408101354710610877576108349061082f6107e261146a565b6107ea6115b3565b5f546001600160a01b031660208201529061081b61080b6101008601611607565b6001600160a01b03166080840152565b61082581856117a0565b9390943690610dce565b611d25565b61083d826101f2565b600360ff8316119081610870575b6102ab9034610861575b60405193849384610201565b61086b3433611eb7565b610855565b505f61084b565b634febe21360e11b5f5260045ffd5b90816101a09103126100be5790565b60603660031901126100be576004356001600160401b0381116100be576108c0903690600401610190565b6024356001600160401b0381116100be576108df903690600401610886565b906044356001600160401b0381116100be576108ff9036906004016101cf565b91604082013547106108775761095f926109519161092661091e61150d565b913690610457565b61092f82611611565b5261093981611611565b5061095961094782866117a0565b9490953690610dce565b923690610f02565b91611d25565b610968826101f2565b600682149081610870576102ab90346108615760405193849384610201565b346100be575f3660031901126100be576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346100be5760403660031901126100be576004356001600160401b0381116100be576109fb903690600401610190565b6024356001600160401b0381116100be57610a1a903690600401610886565b610a2d6106c76106c76101008501611607565b60c0604051809263e514a79d60e01b82528180610a4d88600483016116de565b03915afa908115610789575f91610cde575b50610a78610a7061018085016116ef565b62ffffff1690565b5f54909190610a91906106c7906001600160a01b031681565b604051635b651b0560e01b81529091602082600481865afa918215610789575f92610cac575b50602001610acc610746825163ffffffff1690565b15610b8457508394506020610ae76101606004960187611708565b604051635cd6ef6760e01b815296909487925082905afa918215610789576102ab956080610b3d610b38610b2d610b4d97610b47966106239b5f92610b53575b50611f41565b606085013590610d90565b610d63565b915b01359061178d565b92610d90565b90611fa8565b610b7691925060203d602011610b7d575b610b6e818361038e565b81019061173a565b905f610b27565b503d610b64565b6004906020610bcb610bc6610bc1610baa610ba36101608c018c611708565b9050610d21565b610bbb610ba36101c08e018e611708565b90610d90565b610d36565b610d45565b9460405193848092635cd6ef6760e01b82525afa958615610789576102ab97610c69610750610c5f610c54610c49610c156106239d610b4d9c610b479b5f92610c8b575b50611ed3565b95610bbb610c40610140610c39610c2e62029bf8610d53565b606086013590610d90565b9301611460565b63ffffffff1690565b606087013590610d90565b955163ffffffff1690565b6204000016151590565b610c77575b50608090610b3f565b610c849060809293610d90565b9190610c6e565b610ca591925060203d602011610b7d57610b6e818361038e565b905f610c0f565b6020919250610cd090823d8411610cd7575b610cc8818361038e565b8101906116f9565b9190610ab7565b503d610cbe565b610d00915060c03d60c011610d06575b610cf8818361038e565b81019061165a565b5f610a5f565b503d610cee565b634e487b7160e01b5f52601160045260245ffd5b61026001908161026011610d3157565b610d0d565b906101608201809211610d3157565b9060ee8201809211610d3157565b90620111708201809211610d3157565b906170808201809211610d3157565b906102608201809211610d3157565b906127108201809211610d3157565b91908201809211610d3157565b63ffffffff8116036100be57565b359061011282610d9d565b62ffffff8116036100be57565b359061011282610db6565b919091610200818403126100be57610de46103bf565b92610dee82610107565b8452610dfc60208301610107565b602085015260408201356040850152606082013560608501526080820135608085015260a082013560a085015260c082013560c0850152610e3f60e08301610107565b60e0850152610e516101008301610107565b610100850152610e646101208301610dab565b610120850152610e776101408301610dab565b610140850152610e8a6101608301610dab565b610160850152610e9d6101808301610dc3565b610180850152610eb06101a08301610107565b6101a08501526101c08201356001600160401b0381116100be5781610ed6918401610411565b6101c08501526101e08201356001600160401b0381116100be57610efa9201610411565b6101e0830152565b919091610120818403126100be57610f186103cf565b92610f2282610107565b8452610f3060208301610107565b60208501526040820135604085015260608201356060850152610f5560808301610107565b6080850152610f6660a08301610107565b60a085015260c082013560c085015260e082013560e08501526101008201356001600160401b0381116100be57610f9d9201610411565b610100830152565b916040830135471061087757801561102957610ff393610959610feb610fe394610fd9610fd336878461054b565b886117a0565b9690973690610dce565b94369161054b565b913690610f02565b9091610ffe836101f2565b6006831480611021575b3461101257929190565b61101c3433611eb7565b929190565b5f9250611008565b505050505f905f90601890565b90611040916117a0565b8101809111610d315790565b908160209103126100be575180151581036100be5790565b9035601e19823603018112156100be5701602081359101916001600160401b0382116100be5781360383136100be57565b908060209392818452848401375f828201840152601f01601f1916010190565b61121f916110cb816110c684610107565b6100c2565b6110e46110da60208401610107565b60208301906100c2565b60408201356040820152606082013560608201526080820135608082015260a082013560a082015260c082013560c082015261112f61112560e08401610107565b60e08301906100c2565b61114a61113f6101008401610107565b6101008301906100c2565b61116861115a6101208401610dab565b63ffffffff16610120830152565b6111866111786101408401610dab565b63ffffffff16610140830152565b6111a46111966101608401610dab565b63ffffffff16610160830152565b6111c16111b46101808401610dc3565b62ffffff16610180830152565b6111dc6111d16101a08401610107565b6101a08301906100c2565b6112106112046111f06101c0850185611064565b6102006101c0860152610200850191611095565b926101e0810190611064565b916101e0818503910152611095565b90565b906101206112b861121f9361123a846110c683610107565b61125361124960208301610107565b60208601906100c2565b604081013560408501526060810135606085015261128061127660808301610107565b60808601906100c2565b61129961128f60a08301610107565b60a08601906100c2565b60c081013560c085015260e081013560e0850152610100810190611064565b919092816101008201520191611095565b949391906112df906080875260808701906110b5565b8581036020870152838152602081019360208160051b83010194835f9161019e1982360301945b848410611333575050505050505061132b826060928661011295036040880152611222565b93015f6100c2565b90919293949597601f198282030183528835878112156100be5760206114446001938783940190611367816110c684610107565b61137e611375858401610107565b858301906100c2565b60408201356040820152606082013560608201526080820135608082015260a082013560a08201526113bf6113b560c08401610107565b60c08301906100c2565b6113ce61112560e08401610107565b6101008201356101008201526113f56113ea6101208401610107565b6101208301906100c2565b610140820135610140820152611435611429611415610160850185611064565b6101a06101608601526101a0850191611095565b92610180810190611064565b91610180818503910152611095565b9a0193019401929195949390611306565b6040513d5f823e3d90fd5b3561121f81610d9d565b6114735f6103df565b90611481604051928361038e565b5f825281601f196114915f6103df565b01905f5b8281106114a157505050565b6020906040516114b081610352565b5f81525f838201525f60408201525f60608201525f60808201525f60a08201525f60c08201525f60e08201525f6101008201525f6101208201525f6101408201526060610160820152606061018082015282828501015201611495565b61151760016103df565b90611525604051928361038e565b6001825281601f1961153760016103df565b01905f5b82811061154757505050565b60209060405161155681610352565b5f81525f838201525f60408201525f60608201525f60808201525f60a08201525f60c08201525f60e08201525f6101008201525f6101208201525f610140820152606061016082015260606101808201528282850101520161153b565b6040519061012082018281106001600160401b0382111761036e576040526060610100835f81525f60208201525f60408201525f838201525f60808201525f60a08201525f60c08201525f60e08201520152565b3561121f816100f6565b80511561161e5760200190565b634e487b7160e01b5f52603260045260245ffd5b805182101561161e5760209160051b010190565b51906001600160801b03821682036100be57565b908160c09103126100be576116d660a06040519261167784610373565b8051611682816100f6565b8452602081015161169281610d9d565b602085015260408101516116a5816100f6565b604085015260608101516116b881610d9d565b606085015260808101516116cb81610d9d565b608085015201611646565b60a082015290565b90602061121f9281815201906110b5565b3561121f81610db6565b908160209103126100be575190565b903590601e19813603018212156100be57018035906001600160401b0382116100be576020019181360383136100be57565b908160209103126100be575161121f816100f6565b90816102600291610260830403610d3157565b908161afc8029161afc8830403610d3157565b906128508202918083046128501490151715610d3157565b81810292918115918404141715610d3157565b916117b46106c76106c76101008601611607565b9160c0604051809463e514a79d60e01b825281806117d589600483016116de565b03915afa928315610789575f93611985575b505f54600490602090611804906106c7906001600160a01b031681565b604051635cd6ef6760e01b815292839182905afa908115610789575f91611966575b50611845610bc6610bc161183e6101c0890189611708565b9050610d72565b908251915f5f945f905b8886831061190e5750505090828593926118688661174f565b61187191610d90565b9061187b91611fda565b9161188591611ed3565b61188e91610d90565b9561189b62029bf8610d53565b90606001356118a991610d90565b608086015163ffffffff1663ffffffff166118c391610d90565b906118cd91610d90565b6118d682611762565b6118df91610d90565b6020949094015162040000166118f3575050565b61121f929391611909610bbb9261c3509061178d565b610d90565b8297610bbb61195e92611958610c406060806119496119428b9c6101606119388d9e60019e611632565b5101515190610d90565b9b8b611632565b51015193015163ffffffff1690565b90611fc8565b96019061184f565b61197f915060203d602011610b7d57610b6e818361038e565b5f611826565b61199f91935060c03d60c011610d0657610cf8818361038e565b915f6117e7565b61520719810191908211610d3157565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b9080602083519182815201916020808360051b8301019401925f915b838310611a0557505050505090565b9091929394602080611ae4600193601f19868203018752895190611a2a8183516100c2565b611a3a84830151858301906100c2565b60408201516040820152606082015160608201526080820151608082015260a082015160a0820152611a7460c083015160c08301906100c2565b611a8660e083015160e08301906100c2565b610100820151610100820152611aa66101208301516101208301906100c2565b610140820151610140820152610180611ad26101608401516101a06101608501526101a08401906119b6565b920151906101808184039101526119b6565b970193019301919392906119f6565b9061012061010061121f93611b098482516100c2565b611b1b602082015160208601906100c2565b6040810151604085015260608101516060850152611b41608082015160808601906100c2565b611b5360a082015160a08601906100c2565b60c081015160c085015260e081015160e08501520151918161010082015201906119b6565b949392611ca6606093611c98611cb49460808a52611b9a60808b0182516100c2565b611bac602082015160a08c01906100c2565b604081015160c08b01528681015160e08b015260808101516101008b015260a08101516101208b015260c08101516101408b0152611bf360e08201516101608c01906100c2565b611c076101008201516101808c01906100c2565b61012081015163ffffffff166101a08b015261014081015163ffffffff166101c08b015261016081015163ffffffff166101e08b015261018081015162ffffff166102008b0152611c626101a08201516102208c01906100c2565b6101e0611c838b6102006102406101c08601519201526102808d01906119b6565b9101518a8203607f19016102608c01526119b6565b9088820360208a01526119da565b908682036040880152611af3565b930152565b3d15611ce3573d90611cca826103f6565b91611cd8604051938461038e565b82523d5f602084013e565b606090565b80516020909101516001600160e01b0319811692919060048210611d0a575050565b6001600160e01b031960049290920360031b82901b16169150565b9190949392945f95611d36816119a6565b94611d53611d4e611d4688611775565b612710900490565b610d81565b905a92828410611e795750505050604083015190303b156100be575f93611d906040519687958694859463b2e3aac160e01b865260048601611b78565b0391305af19081611e5f575b50611e5057611da9611cb9565b6001600160e01b0319611dbb82611ce8565b16634e47c97160e01b8103611dd65750805101516001925090565b635933e62b60e11b8103611dec57505060029190565b63bdc56ad160e01b8103611e0257505060039190565b9192909163e49c0b2560e01b8103611e1f57505080510151600491565b9092915063a695d44360e01b8103611e38575060059190565b63d7817dcb60e01b03611e4b5760069190565b5f9190565b63039f249b60e61b5f5260045ffd5b80611e6d5f611e739361038e565b806100b4565b5f611d9c565b611eb4945090611909611e8f82611e9994610d90565b9362011558610d90565b6311e12adf60e01b5f52600492909252602452604452606490565b5ffd5b5f80809338935af115611ec657565b63b12d13eb5f526004601cfd5b906001600160a01b031680611ef957508060031b9080820460081490151715610d315790565b906020906024604051809481936336d2da6b60e21b835260048301525afa908115610789575f91611f28575090565b61121f915060203d602011610cd757610cc8818361038e565b6001600160a01b039091169081611f7257611f5c9150610d72565b8060031b9080820460081490151715610d315790565b611f7d602091610d72565b60246040518094819363577ad82160e11b835260048301525afa908115610789575f91611f28575090565b9061271001908161271011610d315761271091611fc49161178d565b0490565b9080821015611fd5575090565b905090565b906001600160a01b03168061200057508060031b9080820460081490151715610d315790565b9060209060246040518094819363577ad82160e11b835260048301525afa908115610789575f91611f2857509056fea164736f6c634300081c000a
Deployed Bytecode
0x60806040526004361015610010575b005b5f3560e01c8063127f1b7d146100af578063133bff36146100aa5780635dd362cd146100a5578063690d8320146100a057806388f719bf1461009b578063b2e3aac114610096578063b6a777c114610091578063b759598a1461008c578063d5f39488146100875763fb3ae8de0361000e576109cb565b610987565b610895565b61079d565b610633565b6105b6565b6102af565b610223565b610114565b6100cf565b5f9103126100be57565b5f80fd5b6001600160a01b03169052565b346100be575f3660031901126100be575f546040516001600160a01b039091168152602090f35b6001600160a01b038116036100be57565b3590610112826100f6565b565b346100be5760203660031901126100be57600435610131816100f6565b7f00000000000000000000000078c5d8df575098a97a3bd1f8dcceb22d71f3a4746001600160a01b03163303610182575f80546001600160a01b0319166001600160a01b0392909216919091179055005b6282b42960e81b5f5260045ffd5b90816102009103126100be5790565b9181601f840112156100be578235916001600160401b0383116100be576020808501948460051b0101116100be57565b90816101209103126100be5790565b634e487b7160e01b5f52602160045260245ffd5b600711156101fc57565b6101de565b9015158152606081019392919060078210156101fc5760409160208201520152565b60603660031901126100be576004356001600160401b0381116100be5761024e903690600401610190565b6024356001600160401b0381116100be5761026d90369060040161019f565b9091604435916001600160401b0383116100be576102ab9361029661029c9436906004016101cf565b92610fa5565b60409391935193849384610201565b0390f35b346100be5760203660031901126100be576004356102cc816100f6565b7f00000000000000000000000078c5d8df575098a97a3bd1f8dcceb22d71f3a4746001600160a01b03163303610182577f79937dd50eabc51ec0ce6597abf279889ffbe60563a346e7d16826a5e9954b3f6020479261032b8482611eb7565b6040519384526001600160a01b031692a2005b634e487b7160e01b5f52604160045260245ffd5b6101a081019081106001600160401b0382111761036e57604052565b61033e565b60c081019081106001600160401b0382111761036e57604052565b90601f801991011681019081106001600160401b0382111761036e57604052565b604051906101126101a08361038e565b604051906101126102008361038e565b604051906101126101208361038e565b6001600160401b03811161036e5760051b60200190565b6001600160401b03811161036e57601f01601f191660200190565b81601f820112156100be57803590610428826103f6565b92610436604051948561038e565b828452602083830101116100be57815f926020809301838601378301015290565b9190916101a0818403126100be5761046d6103af565b9261047782610107565b845261048560208301610107565b602085015260408201356040850152606082013560608501526080820135608085015260a082013560a08501526104be60c08301610107565b60c08501526104cf60e08301610107565b60e08501526101008201356101008501526104ed6101208301610107565b6101208501526101408201356101408501526101608201356001600160401b0381116100be578161051f918401610411565b6101608501526101808201356001600160401b0381116100be576105439201610411565b610180830152565b929190610557816103df565b93610565604051958661038e565b602085838152019160051b8101918383116100be5781905b83821061058b575050505050565b81356001600160401b0381116100be576020916105ab8784938701610457565b81520191019061057d565b346100be5760403660031901126100be576004356001600160401b0381116100be576105e6903690600401610190565b6024356001600160401b0381116100be57366023820112156100be576102ab9161061d61062392369060248160040135910161054b565b90611036565b6040519081529081906020820190565b60803660031901126100be576004356001600160401b0381116100be5761065e903690600401610190565b6024356001600160401b0381116100be5761067d90369060040161019f565b906044356001600160401b0381116100be5761069d9036906004016101cf565b6064359130330361078e575f546106f29460209490916106d3906106c7906001600160a01b031681565b6001600160a01b031690565b9260405196879586948593634317ca0160e01b85528b600486016112c9565b03923491f1908115610789575f9161075a575b50159081610731575b506107225763d7817dcb60e01b5f5260045ffd5b6334d8364360e21b5f5260045ffd5b61075491506107466101206107509201611460565b6208000016151590565b1590565b5f61070e565b61077c915060203d602011610782575b610774818361038e565b81019061104c565b5f610705565b503d61076a565b611455565b63b749f31960e01b5f5260045ffd5b60203660031901126100be576004356001600160401b0381116100be576107c8903690600401610190565b60408101354710610877576108349061082f6107e261146a565b6107ea6115b3565b5f546001600160a01b031660208201529061081b61080b6101008601611607565b6001600160a01b03166080840152565b61082581856117a0565b9390943690610dce565b611d25565b61083d826101f2565b600360ff8316119081610870575b6102ab9034610861575b60405193849384610201565b61086b3433611eb7565b610855565b505f61084b565b634febe21360e11b5f5260045ffd5b90816101a09103126100be5790565b60603660031901126100be576004356001600160401b0381116100be576108c0903690600401610190565b6024356001600160401b0381116100be576108df903690600401610886565b906044356001600160401b0381116100be576108ff9036906004016101cf565b91604082013547106108775761095f926109519161092661091e61150d565b913690610457565b61092f82611611565b5261093981611611565b5061095961094782866117a0565b9490953690610dce565b923690610f02565b91611d25565b610968826101f2565b600682149081610870576102ab90346108615760405193849384610201565b346100be575f3660031901126100be576040517f00000000000000000000000078c5d8df575098a97a3bd1f8dcceb22d71f3a4746001600160a01b03168152602090f35b346100be5760403660031901126100be576004356001600160401b0381116100be576109fb903690600401610190565b6024356001600160401b0381116100be57610a1a903690600401610886565b610a2d6106c76106c76101008501611607565b60c0604051809263e514a79d60e01b82528180610a4d88600483016116de565b03915afa908115610789575f91610cde575b50610a78610a7061018085016116ef565b62ffffff1690565b5f54909190610a91906106c7906001600160a01b031681565b604051635b651b0560e01b81529091602082600481865afa918215610789575f92610cac575b50602001610acc610746825163ffffffff1690565b15610b8457508394506020610ae76101606004960187611708565b604051635cd6ef6760e01b815296909487925082905afa918215610789576102ab956080610b3d610b38610b2d610b4d97610b47966106239b5f92610b53575b50611f41565b606085013590610d90565b610d63565b915b01359061178d565b92610d90565b90611fa8565b610b7691925060203d602011610b7d575b610b6e818361038e565b81019061173a565b905f610b27565b503d610b64565b6004906020610bcb610bc6610bc1610baa610ba36101608c018c611708565b9050610d21565b610bbb610ba36101c08e018e611708565b90610d90565b610d36565b610d45565b9460405193848092635cd6ef6760e01b82525afa958615610789576102ab97610c69610750610c5f610c54610c49610c156106239d610b4d9c610b479b5f92610c8b575b50611ed3565b95610bbb610c40610140610c39610c2e62029bf8610d53565b606086013590610d90565b9301611460565b63ffffffff1690565b606087013590610d90565b955163ffffffff1690565b6204000016151590565b610c77575b50608090610b3f565b610c849060809293610d90565b9190610c6e565b610ca591925060203d602011610b7d57610b6e818361038e565b905f610c0f565b6020919250610cd090823d8411610cd7575b610cc8818361038e565b8101906116f9565b9190610ab7565b503d610cbe565b610d00915060c03d60c011610d06575b610cf8818361038e565b81019061165a565b5f610a5f565b503d610cee565b634e487b7160e01b5f52601160045260245ffd5b61026001908161026011610d3157565b610d0d565b906101608201809211610d3157565b9060ee8201809211610d3157565b90620111708201809211610d3157565b906170808201809211610d3157565b906102608201809211610d3157565b906127108201809211610d3157565b91908201809211610d3157565b63ffffffff8116036100be57565b359061011282610d9d565b62ffffff8116036100be57565b359061011282610db6565b919091610200818403126100be57610de46103bf565b92610dee82610107565b8452610dfc60208301610107565b602085015260408201356040850152606082013560608501526080820135608085015260a082013560a085015260c082013560c0850152610e3f60e08301610107565b60e0850152610e516101008301610107565b610100850152610e646101208301610dab565b610120850152610e776101408301610dab565b610140850152610e8a6101608301610dab565b610160850152610e9d6101808301610dc3565b610180850152610eb06101a08301610107565b6101a08501526101c08201356001600160401b0381116100be5781610ed6918401610411565b6101c08501526101e08201356001600160401b0381116100be57610efa9201610411565b6101e0830152565b919091610120818403126100be57610f186103cf565b92610f2282610107565b8452610f3060208301610107565b60208501526040820135604085015260608201356060850152610f5560808301610107565b6080850152610f6660a08301610107565b60a085015260c082013560c085015260e082013560e08501526101008201356001600160401b0381116100be57610f9d9201610411565b610100830152565b916040830135471061087757801561102957610ff393610959610feb610fe394610fd9610fd336878461054b565b886117a0565b9690973690610dce565b94369161054b565b913690610f02565b9091610ffe836101f2565b6006831480611021575b3461101257929190565b61101c3433611eb7565b929190565b5f9250611008565b505050505f905f90601890565b90611040916117a0565b8101809111610d315790565b908160209103126100be575180151581036100be5790565b9035601e19823603018112156100be5701602081359101916001600160401b0382116100be5781360383136100be57565b908060209392818452848401375f828201840152601f01601f1916010190565b61121f916110cb816110c684610107565b6100c2565b6110e46110da60208401610107565b60208301906100c2565b60408201356040820152606082013560608201526080820135608082015260a082013560a082015260c082013560c082015261112f61112560e08401610107565b60e08301906100c2565b61114a61113f6101008401610107565b6101008301906100c2565b61116861115a6101208401610dab565b63ffffffff16610120830152565b6111866111786101408401610dab565b63ffffffff16610140830152565b6111a46111966101608401610dab565b63ffffffff16610160830152565b6111c16111b46101808401610dc3565b62ffffff16610180830152565b6111dc6111d16101a08401610107565b6101a08301906100c2565b6112106112046111f06101c0850185611064565b6102006101c0860152610200850191611095565b926101e0810190611064565b916101e0818503910152611095565b90565b906101206112b861121f9361123a846110c683610107565b61125361124960208301610107565b60208601906100c2565b604081013560408501526060810135606085015261128061127660808301610107565b60808601906100c2565b61129961128f60a08301610107565b60a08601906100c2565b60c081013560c085015260e081013560e0850152610100810190611064565b919092816101008201520191611095565b949391906112df906080875260808701906110b5565b8581036020870152838152602081019360208160051b83010194835f9161019e1982360301945b848410611333575050505050505061132b826060928661011295036040880152611222565b93015f6100c2565b90919293949597601f198282030183528835878112156100be5760206114446001938783940190611367816110c684610107565b61137e611375858401610107565b858301906100c2565b60408201356040820152606082013560608201526080820135608082015260a082013560a08201526113bf6113b560c08401610107565b60c08301906100c2565b6113ce61112560e08401610107565b6101008201356101008201526113f56113ea6101208401610107565b6101208301906100c2565b610140820135610140820152611435611429611415610160850185611064565b6101a06101608601526101a0850191611095565b92610180810190611064565b91610180818503910152611095565b9a0193019401929195949390611306565b6040513d5f823e3d90fd5b3561121f81610d9d565b6114735f6103df565b90611481604051928361038e565b5f825281601f196114915f6103df565b01905f5b8281106114a157505050565b6020906040516114b081610352565b5f81525f838201525f60408201525f60608201525f60808201525f60a08201525f60c08201525f60e08201525f6101008201525f6101208201525f6101408201526060610160820152606061018082015282828501015201611495565b61151760016103df565b90611525604051928361038e565b6001825281601f1961153760016103df565b01905f5b82811061154757505050565b60209060405161155681610352565b5f81525f838201525f60408201525f60608201525f60808201525f60a08201525f60c08201525f60e08201525f6101008201525f6101208201525f610140820152606061016082015260606101808201528282850101520161153b565b6040519061012082018281106001600160401b0382111761036e576040526060610100835f81525f60208201525f60408201525f838201525f60808201525f60a08201525f60c08201525f60e08201520152565b3561121f816100f6565b80511561161e5760200190565b634e487b7160e01b5f52603260045260245ffd5b805182101561161e5760209160051b010190565b51906001600160801b03821682036100be57565b908160c09103126100be576116d660a06040519261167784610373565b8051611682816100f6565b8452602081015161169281610d9d565b602085015260408101516116a5816100f6565b604085015260608101516116b881610d9d565b606085015260808101516116cb81610d9d565b608085015201611646565b60a082015290565b90602061121f9281815201906110b5565b3561121f81610db6565b908160209103126100be575190565b903590601e19813603018212156100be57018035906001600160401b0382116100be576020019181360383136100be57565b908160209103126100be575161121f816100f6565b90816102600291610260830403610d3157565b908161afc8029161afc8830403610d3157565b906128508202918083046128501490151715610d3157565b81810292918115918404141715610d3157565b916117b46106c76106c76101008601611607565b9160c0604051809463e514a79d60e01b825281806117d589600483016116de565b03915afa928315610789575f93611985575b505f54600490602090611804906106c7906001600160a01b031681565b604051635cd6ef6760e01b815292839182905afa908115610789575f91611966575b50611845610bc6610bc161183e6101c0890189611708565b9050610d72565b908251915f5f945f905b8886831061190e5750505090828593926118688661174f565b61187191610d90565b9061187b91611fda565b9161188591611ed3565b61188e91610d90565b9561189b62029bf8610d53565b90606001356118a991610d90565b608086015163ffffffff1663ffffffff166118c391610d90565b906118cd91610d90565b6118d682611762565b6118df91610d90565b6020949094015162040000166118f3575050565b61121f929391611909610bbb9261c3509061178d565b610d90565b8297610bbb61195e92611958610c406060806119496119428b9c6101606119388d9e60019e611632565b5101515190610d90565b9b8b611632565b51015193015163ffffffff1690565b90611fc8565b96019061184f565b61197f915060203d602011610b7d57610b6e818361038e565b5f611826565b61199f91935060c03d60c011610d0657610cf8818361038e565b915f6117e7565b61520719810191908211610d3157565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b9080602083519182815201916020808360051b8301019401925f915b838310611a0557505050505090565b9091929394602080611ae4600193601f19868203018752895190611a2a8183516100c2565b611a3a84830151858301906100c2565b60408201516040820152606082015160608201526080820151608082015260a082015160a0820152611a7460c083015160c08301906100c2565b611a8660e083015160e08301906100c2565b610100820151610100820152611aa66101208301516101208301906100c2565b610140820151610140820152610180611ad26101608401516101a06101608501526101a08401906119b6565b920151906101808184039101526119b6565b970193019301919392906119f6565b9061012061010061121f93611b098482516100c2565b611b1b602082015160208601906100c2565b6040810151604085015260608101516060850152611b41608082015160808601906100c2565b611b5360a082015160a08601906100c2565b60c081015160c085015260e081015160e08501520151918161010082015201906119b6565b949392611ca6606093611c98611cb49460808a52611b9a60808b0182516100c2565b611bac602082015160a08c01906100c2565b604081015160c08b01528681015160e08b015260808101516101008b015260a08101516101208b015260c08101516101408b0152611bf360e08201516101608c01906100c2565b611c076101008201516101808c01906100c2565b61012081015163ffffffff166101a08b015261014081015163ffffffff166101c08b015261016081015163ffffffff166101e08b015261018081015162ffffff166102008b0152611c626101a08201516102208c01906100c2565b6101e0611c838b6102006102406101c08601519201526102808d01906119b6565b9101518a8203607f19016102608c01526119b6565b9088820360208a01526119da565b908682036040880152611af3565b930152565b3d15611ce3573d90611cca826103f6565b91611cd8604051938461038e565b82523d5f602084013e565b606090565b80516020909101516001600160e01b0319811692919060048210611d0a575050565b6001600160e01b031960049290920360031b82901b16169150565b9190949392945f95611d36816119a6565b94611d53611d4e611d4688611775565b612710900490565b610d81565b905a92828410611e795750505050604083015190303b156100be575f93611d906040519687958694859463b2e3aac160e01b865260048601611b78565b0391305af19081611e5f575b50611e5057611da9611cb9565b6001600160e01b0319611dbb82611ce8565b16634e47c97160e01b8103611dd65750805101516001925090565b635933e62b60e11b8103611dec57505060029190565b63bdc56ad160e01b8103611e0257505060039190565b9192909163e49c0b2560e01b8103611e1f57505080510151600491565b9092915063a695d44360e01b8103611e38575060059190565b63d7817dcb60e01b03611e4b5760069190565b5f9190565b63039f249b60e61b5f5260045ffd5b80611e6d5f611e739361038e565b806100b4565b5f611d9c565b611eb4945090611909611e8f82611e9994610d90565b9362011558610d90565b6311e12adf60e01b5f52600492909252602452604452606490565b5ffd5b5f80809338935af115611ec657565b63b12d13eb5f526004601cfd5b906001600160a01b031680611ef957508060031b9080820460081490151715610d315790565b906020906024604051809481936336d2da6b60e21b835260048301525afa908115610789575f91611f28575090565b61121f915060203d602011610cd757610cc8818361038e565b6001600160a01b039091169081611f7257611f5c9150610d72565b8060031b9080820460081490151715610d315790565b611f7d602091610d72565b60246040518094819363577ad82160e11b835260048301525afa908115610789575f91611f28575090565b9061271001908161271011610d315761271091611fc49161178d565b0490565b9080821015611fd5575090565b905090565b906001600160a01b03168061200057508060031b9080820460081490151715610d315790565b9060209060246040518094819363577ad82160e11b835260048301525afa908115610789575f91611f2857509056fea164736f6c634300081c000a
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$70.17
Net Worth in HYPE
Token Allocations
ETH
100.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| UNI | 100.00% | $2,970.29 | 0.0236 | $70.17 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.