Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Latest 25 from a total of 50,742 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Fill | 23811565 | 2 mins ago | IN | 0 ETH | 0.00003131 | ||||
| Deposit | 23811563 | 2 mins ago | IN | 0 ETH | 0.00002832 | ||||
| Deposit Native | 23811519 | 11 mins ago | IN | 0.002 ETH | 0.00041873 | ||||
| Fill | 23811517 | 11 mins ago | IN | 0 ETH | 0.00002547 | ||||
| Fill | 23811480 | 19 mins ago | IN | 0 ETH | 0.00005229 | ||||
| Deposit Native | 23811476 | 19 mins ago | IN | 0.0011 ETH | 0.00001848 | ||||
| Deposit Native | 23811446 | 25 mins ago | IN | 0.0012 ETH | 0.00002569 | ||||
| Fill | 23811446 | 25 mins ago | IN | 0 ETH | 0.00005599 | ||||
| Deposit Native | 23811438 | 27 mins ago | IN | 0.01 ETH | 0.00002609 | ||||
| Deposit | 23811438 | 27 mins ago | IN | 0 ETH | 0.00010862 | ||||
| Deposit | 23811421 | 30 mins ago | IN | 0 ETH | 0.00004745 | ||||
| Deposit | 23811397 | 35 mins ago | IN | 0 ETH | 0.00004824 | ||||
| Fill | 23811355 | 44 mins ago | IN | 0 ETH | 0.00001166 | ||||
| Fill | 23811353 | 44 mins ago | IN | 0 ETH | 0.00002501 | ||||
| Fill | 23811337 | 47 mins ago | IN | 0 ETH | 0.00002655 | ||||
| Fill | 23811328 | 49 mins ago | IN | 0 ETH | 0.00002445 | ||||
| Fill | 23811324 | 50 mins ago | IN | 0 ETH | 0.0000264 | ||||
| Fill | 23811299 | 55 mins ago | IN | 0 ETH | 0.00003531 | ||||
| Fill | 23811290 | 57 mins ago | IN | 0 ETH | 0.00004376 | ||||
| Fill | 23811261 | 1 hr ago | IN | 0 ETH | 0.00002142 | ||||
| Fill | 23811253 | 1 hr ago | IN | 0 ETH | 0.00001787 | ||||
| Fill | 23811242 | 1 hr ago | IN | 0 ETH | 0.00001679 | ||||
| Fill | 23811239 | 1 hr ago | IN | 0 ETH | 0.00002007 | ||||
| Fill | 23811211 | 1 hr ago | IN | 0 ETH | 0.00002604 | ||||
| Fill | 23811208 | 1 hr ago | IN | 0 ETH | 0.00001546 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
To
|
|||
|---|---|---|---|---|---|---|---|
| Transfer | 23811565 | 2 mins ago | 0.00017613 ETH | ||||
| Transfer | 23811565 | 2 mins ago | 0.07974102 ETH | ||||
| Transfer | 23811565 | 2 mins ago | 0.07991716 ETH | ||||
| Transfer | 23811480 | 19 mins ago | 0.00000277 ETH | ||||
| Transfer | 23811480 | 19 mins ago | 0.0274822 ETH | ||||
| Transfer | 23811480 | 19 mins ago | 0.02748497 ETH | ||||
| Transfer | 23811451 | 24 mins ago | 0.0012 ETH | ||||
| Transfer | 23811446 | 25 mins ago | 0.00104816 ETH | ||||
| Transfer | 23811446 | 25 mins ago | 0.29823344 ETH | ||||
| Transfer | 23811446 | 25 mins ago | 0.29928161 ETH | ||||
| Transfer | 23811353 | 44 mins ago | 0.00006548 ETH | ||||
| Transfer | 23811353 | 44 mins ago | 0.09134601 ETH | ||||
| Transfer | 23811353 | 44 mins ago | 0.09141149 ETH | ||||
| Transfer | 23811337 | 47 mins ago | 0.00006611 ETH | ||||
| Transfer | 23811337 | 47 mins ago | 0.0676441 ETH | ||||
| Transfer | 23811337 | 47 mins ago | 0.06771022 ETH | ||||
| Transfer | 23811328 | 49 mins ago | 0.00000209 ETH | ||||
| Transfer | 23811328 | 49 mins ago | 0.00284105 ETH | ||||
| Transfer | 23811328 | 49 mins ago | 0.00284314 ETH | ||||
| Transfer | 23811324 | 50 mins ago | 0.0000935 ETH | ||||
| Transfer | 23811324 | 50 mins ago | 0.08210186 ETH | ||||
| Transfer | 23811324 | 50 mins ago | 0.08219536 ETH | ||||
| Transfer | 23811299 | 55 mins ago | 0.00000059 ETH | ||||
| Transfer | 23811299 | 55 mins ago | 0.00245645 ETH | ||||
| Transfer | 23811299 | 55 mins ago | 0.00245705 ETH |
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Aori
Compiler Version
v0.8.28+commit.7893614a
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import { OApp, Origin, MessagingFee, MessagingReceipt } from "@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { Pausable } from "@openzeppelin/contracts/utils/Pausable.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { EIP712 } from "solady/src/utils/EIP712.sol";
import { ECDSA } from "solady/src/utils/ECDSA.sol";
import { IAori } from "./IAori.sol";
import "./AoriUtils.sol";
/** @@@@@@@@@@@@
@@ @@@@@@ @@@@@
@@ @@@@@ @@@@@
@@@
@@@@
@@@@@
@@@@@
@@@@@@@@@ @@@@ @@@@@@@@@@ @@@@@@ @@@@@@@ @@@@@
@@@@ @@ @@@@ @@@@ @@@@@@@ @@@@ @@ @@@ @@@@
@@@@ @ @@@@ @@@@ @@@@@@ @@@@ @@ @@@@
@@@@@ @@@@@@ @@@@@ @@@@@@ @@@@ @ @@@@
@@@@@ @@@@ @@@@@ @ @ @@@@@ @@@@ @@@@
@@@@@ @@@@ @@@@@@ @@@@@@ @@@@@ @@@@ @@@@
@@@@@ @@@@@ @@@@@@ @ @ @@@@@ @@@@ @@@@
@@@@@ @@@@ @@@@@ @@@@ @@@@ @@@@
@@@@ @@@@@@ @@@@@@ @@@@ @@@@ @@@@
@@@@ @@@@ @@@@@@ @@@@@ @@@ @@@@ @@@@ @@
@@@@@@@@@ @@@@@ @@@@@@@@@@@ @@@@ @@@@@
*/
/**
* @title Aori
* @dev version 0.3.1
* @notice Aori is a trust-minimized omnichain intent settlement protocol.
* Connecting users and solvers from any chain to any chain,
* facilitating peer to peer exchange from any token to any token.
*/
contract Aori is IAori, OApp, ReentrancyGuard, Pausable, EIP712 {
using PayloadPackUtils for bytes32[];
using PayloadUnpackUtils for bytes;
using PayloadSizeUtils for uint8;
using HookUtils for SrcHook;
using HookUtils for DstHook;
using SafeERC20 for IERC20;
using BalanceUtils for Balance;
using ValidationUtils for IAori.Order;
using NativeTokenUtils for address;
constructor(
address _endpoint, // LayerZero endpoint address
address _owner, // Contract owner address
uint32 _eid, // Endpoint ID for this chain
uint16 _maxFillsPerSettle // Maximum number of fills per settlement
) OApp(_endpoint, _owner) Ownable(_owner) EIP712() {
ENDPOINT_ID = _eid;
MAX_FILLS_PER_SETTLE = _maxFillsPerSettle;
require(_owner != address(0), "Set owner");
isSupportedChain[_eid] = true;
}
/**
* @notice Allows the contract to receive native tokens
* @dev Required for native token operations including hook interactions
*/
receive() external payable {
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* SRC STATE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// Unique identifier for this endpoint in the LayerZero network
uint32 public immutable ENDPOINT_ID;
// Tracks locked and unlocked balances for each user and token
mapping(address => mapping(address => Balance)) private balances;
// Stores orders by their unique hash
mapping(bytes32 => Order) public orders;
// Tracks supported chains by their endpoint IDs
mapping(uint32 => bool) public isSupportedChain;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* DST STATE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// Maximum number of fills that can be included in a single settlement
uint16 public immutable MAX_FILLS_PER_SETTLE;
// Tracks the current status of each order
mapping(bytes32 => IAori.OrderStatus) public orderStatus;
// Tracks whitelisted hook addresses for token conversion
mapping(address => bool) public isAllowedHook;
// Tracks whitelisted solver addresses
mapping(address => bool) public isAllowedSolver;
// Maps source endpoint and maker to an array of order hashes filled by a filler
mapping(uint32 => mapping(address => bytes32[])) public srcEidToFillerFills;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* OWNER FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @notice Pauses all contract operations
* @dev Only callable by the contract owner
*/
function pause() external onlyOwner {
_pause();
}
/**
* @notice Unpauses all contract operations
* @dev Only callable by the contract owner
*/
function unpause() external onlyOwner {
_unpause();
}
/**
* @notice Adds a hook address to the whitelist
* @param hook The address of the hook to whitelist
* @dev Only callable by the contract owner
*/
function addAllowedHook(address hook) external onlyOwner {
isAllowedHook[hook] = true;
}
/**
* @notice Removes a hook address from the whitelist
* @param hook The address of the hook to remove
* @dev Only callable by the contract owner
*/
function removeAllowedHook(address hook) external onlyOwner {
isAllowedHook[hook] = false;
}
/**
* @notice Adds a solver address to the whitelist
* @param solver The address of the solver to whitelist
* @dev Only callable by the contract owner
*/
function addAllowedSolver(address solver) external onlyOwner {
isAllowedSolver[solver] = true;
}
/**
* @notice Removes a solver address from the whitelist
* @param solver The address of the solver to remove
* @dev Only callable by the contract owner
*/
function removeAllowedSolver(address solver) external onlyOwner {
isAllowedSolver[solver] = false;
}
/**
* @notice Adds a single chain to the supported chains list
* @param eid The endpoint ID of the chain to add
* @dev Only callable by the contract owner
*/
function addSupportedChain(uint32 eid) external onlyOwner {
isSupportedChain[eid] = true;
emit ChainSupported(eid);
}
/**
* @notice Adds multiple chains to the supported chains list
* @param eids Array of endpoint IDs of the chains to add
* @return results Array of booleans indicating which EIDs were successfully added
* @dev Only callable by the contract owner
*/
function addSupportedChains(uint32[] calldata eids) external onlyOwner returns (bool[] memory results) {
uint256 length = eids.length;
results = new bool[](length);
for (uint256 i = 0; i < length; i++) {
isSupportedChain[eids[i]] = true;
emit ChainSupported(eids[i]);
results[i] = true;
}
return results;
}
/**
* @notice Removes a supported chain by its endpoint ID
* @param eid The endpoint ID of the chain to remove
* @dev Only callable by the contract owner
*/
function removeSupportedChain(uint32 eid) external onlyOwner {
isSupportedChain[eid] = false;
emit ChainRemoved(eid);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EMERGENCY FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @notice Emergency function to cancel an order, bypassing normal restrictions
* @dev Only callable by the contract owner. Always transfers tokens to maintain accounting consistency.
* WARNING: This bypasses normal validation and should only be used in emergency situations.
* @param orderId The hash of the order to cancel
* @param recipient The address to send tokens to (can be different from offerer)
*/
function emergencyCancel(bytes32 orderId, address recipient) external onlyOwner {
require(orderStatus[orderId] == IAori.OrderStatus.Active, "Can only cancel active orders");
require(recipient != address(0), "Invalid recipient address");
Order memory order = orders[orderId];
require(order.srcEid == ENDPOINT_ID, "Emergency cancel only allowed on source chain");
address tokenAddress = order.inputToken;
uint128 amountToReturn = order.inputAmount;
// Validate sufficient balance
tokenAddress.validateSufficientBalance(amountToReturn);
orderStatus[orderId] = IAori.OrderStatus.Cancelled;
bool success = balances[order.offerer][tokenAddress].decreaseLockedNoRevert(amountToReturn);
require(success, "Failed to decrease locked balance");
// Transfer tokens to recipient
tokenAddress.safeTransfer(recipient, amountToReturn);
emit Cancel(orderId);
emit Withdraw(recipient, tokenAddress, amountToReturn);
}
/**
* @notice Emergency function to extract tokens or ether from the contract
* @dev Only callable by the contract owner. Does not update user balances - use for direct contract withdrawals.
* @param token The token address to withdraw
* @param amount The amount of tokens to withdraw
*/
function emergencyWithdraw(address token, uint256 amount) external onlyOwner {
uint256 etherBalance = address(this).balance;
if (etherBalance > 0) {
(bool success, ) = payable(owner()).call{ value: etherBalance }("");
require(success, "Ether withdrawal failed");
}
if (amount > 0) {
token.safeTransfer(owner(), amount);
}
}
/**
* @notice Emergency function to extract tokens from a specific user's balance while maintaining accounting consistency
* @dev Only callable by the contract owner. Updates user balances to maintain internal accounting state.
* @param token The token address to withdraw
* @param amount The amount of tokens to withdraw
* @param user The user address whose balance to withdraw from
* @param isLocked Whether to withdraw from locked (true) or unlocked (false) balance
* @param recipient The address to send the withdrawn tokens to
*/
function emergencyWithdraw(
address token,
uint256 amount,
address user,
bool isLocked,
address recipient
) external onlyOwner {
require(amount > 0, "Amount must be greater than zero");
require(user != address(0), "Invalid user address");
require(recipient != address(0), "Invalid recipient address");
if (isLocked) {
bool success = balances[user][token].decreaseLockedNoRevert(uint128(amount));
require(success, "Failed to decrease locked balance");
} else {
uint256 unlockedBalance = balances[user][token].unlocked;
require(unlockedBalance >= amount, "Insufficient unlocked balance");
balances[user][token].unlocked = uint128(unlockedBalance - amount);
}
// Validate sufficient balance and transfer
token.validateSufficientBalance(amount);
token.safeTransfer(recipient, amount);
emit Withdraw(user, token, amount);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MODIFIERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @notice Modifier to ensure the caller is a whitelisted solver
* @dev Only allows whitelisted solvers to proceed
*/
modifier onlySolver() {
require(isAllowedSolver[msg.sender], "Invalid solver");
_;
}
/**
* @notice Modifier to ensure the caller is a whitelisted hook address
* @dev Only allows whitelisted hook addresses to proceed
* @param hookAddress The address of the hook to check
*/
modifier allowedHookAddress(address hookAddress) {
require(isAllowedHook[hookAddress], "Invalid hook address");
_;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* DEPOSIT */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @notice Deposits tokens to the contract without a hook call
* @dev Takes tokens from offerer (not the caller) via transferFrom after signature verification
* @param order The order details
* @param signature The user's EIP712 signature over the order
*/
function deposit(
Order calldata order,
bytes calldata signature
) external nonReentrant whenNotPaused onlySolver {
require(!order.inputToken.isNativeToken(), "Use depositNative for native tokens");
bytes32 orderId = order.validateDeposit(
signature,
_hashOrder712(order),
ENDPOINT_ID,
this.orderStatus,
this.isSupportedChain
);
IERC20(order.inputToken).safeTransferFrom(order.offerer, address(this), order.inputAmount);
_postDeposit(order.inputToken, order.inputAmount, order, orderId);
}
/**
* @notice Deposits tokens to the contract with a hook call for token conversion
* @dev Executes a hook call for token conversion before deposit processing.
* For single-chain swaps, immediately settles and transfers tokens to recipient.
* For cross-chain swaps, locks converted tokens for later settlement.
* @param order The order details
* @param signature The user's EIP712 signature over the order
* @param hook The pre-hook configuration for token conversion
*/
function deposit(
Order calldata order,
bytes calldata signature,
SrcHook calldata hook
) external nonReentrant whenNotPaused onlySolver {
require(!order.inputToken.isNativeToken(), "Use depositNative for native tokens");
require(hook.isSome(), "Missing hook");
bytes32 orderId = order.validateDeposit(
signature,
_hashOrder712(order),
ENDPOINT_ID,
this.orderStatus,
this.isSupportedChain
);
// Execute hook to convert input tokens to preferred/output tokens
(uint256 amountReceived, address tokenReceived) =
_executeSrcHook(order, hook);
emit SrcHookExecuted(orderId, tokenReceived, amountReceived);
if (order.isSingleChainSwap()) {
// Single-chain: immediate settlement (tokens already transferred to recipient)
orders[orderId] = order;
orderStatus[orderId] = IAori.OrderStatus.Settled;
emit Settle(orderId);
} else {
// Cross-chain: lock converted tokens for later settlement
_postDeposit(tokenReceived, amountReceived, order, orderId);
}
}
/**
* @notice Executes a source hook to convert input tokens and handle distribution
* @dev Sends input tokens to hook, executes conversion, and handles token distribution.
* For single-chain swaps: converts to output token and immediately distributes.
* For cross-chain swaps: converts to preferred token for later cross-chain transfer.
* @param order The order details
* @param hook The source hook configuration
* @return amountReceived The amount of tokens received from the hook
* @return tokenReceived The token address that was received
*/
function _executeSrcHook(
Order calldata order,
SrcHook calldata hook
) internal allowedHookAddress(hook.hookAddress) returns (
uint256 amountReceived,
address tokenReceived
) {
// Send input tokens to hook for conversion
IERC20(order.inputToken).safeTransferFrom(
order.offerer,
hook.hookAddress,
order.inputAmount
);
if (order.isSingleChainSwap()) {
// Single-chain: convert to final output token and distribute immediately
amountReceived = ExecutionUtils.observeBalChg(
hook.hookAddress,
hook.instructions,
order.outputToken
);
require(amountReceived >= order.outputAmount, "Insufficient output from hook");
tokenReceived = order.outputToken;
// Distribute tokens: exact amount to recipient, surplus to solver
order.outputToken.safeTransfer(order.recipient, order.outputAmount);
uint256 surplus = amountReceived - order.outputAmount;
if (surplus > 0) {
order.outputToken.safeTransfer(msg.sender, surplus);
}
} else {
// Cross-chain: convert to preferred token for cross-chain transfer
amountReceived = ExecutionUtils.observeBalChg(
hook.hookAddress,
hook.instructions,
hook.preferredToken
);
require(amountReceived >= hook.minPreferedTokenAmountOut, "Insufficient output from hook");
tokenReceived = hook.preferredToken;
}
}
/**
* @notice Posts a deposit and updates the order status
* @param depositToken The token address to deposit
* @param depositAmount The amount of tokens to deposit
* @param order The order details
* @param orderId The unique identifier for the order
*/
function _postDeposit(
address depositToken,
uint256 depositAmount,
Order calldata order,
bytes32 orderId
) internal {
balances[order.offerer][depositToken].lock(SafeCast.toUint128(depositAmount));
orderStatus[orderId] = IAori.OrderStatus.Active;
orders[orderId] = order;
orders[orderId].inputToken = depositToken;
orders[orderId].inputAmount = SafeCast.toUint128(depositAmount);
emit Deposit(orderId, order);
}
/**
* @notice Deposits native tokens to the contract without a hook call
* @dev User calls this directly and sends their own ETH via msg.value.
* @param order The order details (must specify NATIVE_TOKEN as inputToken)
*/
function depositNative(
Order calldata order
) external payable nonReentrant whenNotPaused {
require(order.inputToken.isNativeToken(), "Order must specify native token");
require(msg.value == order.inputAmount, "Incorrect native amount");
require(msg.sender == order.offerer, "Only offerer can deposit native tokens");
// Calculate order ID and validate uniqueness
bytes32 orderId = hash(order);
require(orderStatus[orderId] == IAori.OrderStatus.Unknown, "Order already exists");
require(isSupportedChain[order.dstEid], "Destination chain not supported");
require(order.srcEid == ENDPOINT_ID, "Chain mismatch");
// Use validation utility for common order parameter checks
ValidationUtils.validateCommonOrderParams(order);
_postDeposit(order.inputToken, order.inputAmount, order, orderId);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* FILL */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @notice Fills an order by transferring output tokens from the filler to recipient
* @dev For single-chain orders: settles immediately with internal balance transfers.
* For cross-chain orders: marks as filled and queues for later settlement.
* @param order The order details to fill
*/
function fill(Order calldata order) external payable nonReentrant whenNotPaused onlySolver {
bytes32 orderId = order.validateFill(
ENDPOINT_ID,
this.orderStatus
);
// Validate payment method matches output token type
if (order.outputToken.isNativeToken()) {
require(msg.value == order.outputAmount, "Incorrect native amount sent");
} else {
require(msg.value == 0, "No native tokens should be sent for ERC20 fills");
}
// Update contract state
if (order.isSingleChainSwap()) {
_settleSingleChainSwap(orderId, order, msg.sender);
} else {
_postFill(orderId, order);
}
// Transfer tokens to recipient
if (order.outputToken.isNativeToken()) {
order.outputToken.safeTransfer(order.recipient, order.outputAmount);
} else {
IERC20(order.outputToken).safeTransferFrom(msg.sender, order.recipient, order.outputAmount);
}
}
/**
* @notice Fills an order by converting preferred tokens to output tokens via hook
* @dev Uses a hook contract to convert solver's preferred tokens into the required output tokens.
* Any surplus from the conversion is returned to the solver.
* @param order The order details to fill
* @param hook The hook configuration for token conversion
*/
function fill(
Order calldata order,
IAori.DstHook calldata hook
) external payable nonReentrant whenNotPaused onlySolver {
bytes32 orderId = order.validateFill(
ENDPOINT_ID,
this.orderStatus
);
// Execute hook to convert preferred tokens to output tokens
uint256 amountReceived = _executeDstHook(order, hook);
emit DstHookExecuted(orderId, hook.preferredToken, amountReceived);
uint256 surplus = amountReceived - order.outputAmount;
// Update contract state
if (order.isSingleChainSwap()) {
_settleSingleChainSwap(orderId, order, msg.sender);
} else {
_postFill(orderId, order);
}
// Transfer tokens: exact amount to recipient, surplus to solver
order.outputToken.safeTransfer(order.recipient, order.outputAmount);
if (surplus > 0) {
order.outputToken.safeTransfer(msg.sender, surplus);
}
}
/**
* @notice Executes a destination hook and handles token conversion
* @param order The order details
* @param hook The destination hook configuration
* @return balChg The balance change observed from the hook execution
*/
function _executeDstHook(
Order calldata order,
IAori.DstHook calldata hook
) internal allowedHookAddress(hook.hookAddress) returns (uint256 balChg) {
if (hook.preferedDstInputAmount > 0) {
if (hook.preferredToken.isNativeToken()) {
require(msg.value == hook.preferedDstInputAmount, "Incorrect native amount for preferred token");
(bool success, ) = payable(hook.hookAddress).call{value: hook.preferedDstInputAmount}("");
require(success, "Native transfer to hook failed");
} else {
// ERC20 token input - no native tokens should be sent
require(msg.value == 0, "No native tokens should be sent for ERC20 preferred token");
IERC20(hook.preferredToken).safeTransferFrom(
msg.sender,
hook.hookAddress,
hook.preferedDstInputAmount
);
}
} else {
// Hook expects no input tokens - ensure no ETH was mistakenly sent
require(msg.value == 0, "No native tokens expected");
}
balChg = ExecutionUtils.observeBalChg(
hook.hookAddress,
hook.instructions,
order.outputToken
);
require(balChg >= order.outputAmount, "Hook must provide at least the expected output amount");
}
/**
* @notice Processes an order after successful filling
* @param orderId The unique identifier for the order
* @param order The order details that were filled
*/
function _postFill(bytes32 orderId, Order calldata order) internal {
orderStatus[orderId] = IAori.OrderStatus.Filled;
srcEidToFillerFills[order.srcEid][msg.sender].push(orderId);
emit Fill(orderId, order);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* SETTLE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @notice Settles filled orders by batching order hashes into a payload and sending through LayerZero
* @dev Requires ETH to be sent for LayerZero fees
* @param srcEid The source endpoint ID
* @param filler The filler address
* @param extraOptions Additional LayerZero options
*/
function settle(
uint32 srcEid,
address filler,
bytes calldata extraOptions
) external payable nonReentrant whenNotPaused onlySolver {
bytes32[] storage arr = srcEidToFillerFills[srcEid][filler];
uint256 arrLength = arr.length;
require(arrLength > 0, "No orders provided");
uint16 fillCount = uint16(
arrLength < MAX_FILLS_PER_SETTLE ? arrLength : MAX_FILLS_PER_SETTLE
);
bytes memory payload = arr.packSettlement(filler, fillCount);
MessagingReceipt memory receipt = _lzSend(srcEid, payload, extraOptions, MessagingFee(msg.value, 0), payable(msg.sender));
emit SettleSent(srcEid, filler, payload, receipt.guid, receipt.nonce, receipt.fee.nativeFee);
}
/**
* @notice Settles a single order by transferring tokens from offerer to filler
* @dev Moves tokens from offerer's locked balance to filler's unlocked balance.
* Uses cache-and-restore pattern to ensure true atomicity - if any step fails,
* all balance changes are reverted to prevent accounting inconsistencies.
* @param orderId The hash of the order to settle
* @param filler The filler address who will receive the tokens
*/
function _settleOrder(bytes32 orderId, address filler) internal {
if (orderStatus[orderId] != IAori.OrderStatus.Active) {
return; // Skip non-active orders
}
Order memory order = orders[orderId];
// Cache original balances for potential rollback
Balance memory offererBalanceCache = balances[order.offerer][order.inputToken];
Balance memory fillerBalanceCache = balances[filler][order.inputToken];
// Attempt atomic balance transfer
bool successLock = balances[order.offerer][order.inputToken].decreaseLockedNoRevert(
order.inputAmount
);
bool successUnlock = balances[filler][order.inputToken].increaseUnlockedNoRevert(
order.inputAmount
);
// If either operation failed, restore original balances to maintain atomicity
if (!successLock || !successUnlock) {
balances[order.offerer][order.inputToken] = offererBalanceCache;
balances[filler][order.inputToken] = fillerBalanceCache;
return; // Exit with no state changes
}
orderStatus[orderId] = IAori.OrderStatus.Settled;
emit Settle(orderId);
}
/**
* @notice Handles settlement of filled orders
* @param payload The settlement payload containing order hashes and filler information
* @param senderEid The source endpoint ID
* @dev Skips orders that were filled on the wrong chain and emits an event
*/
function _handleSettlement(bytes calldata payload, uint32 senderEid) internal {
payload.validateSettlementLen();
(address filler, uint16 fillCount) = payload.unpackSettlementHeader();
payload.validateSettlementLen(fillCount);
for (uint256 i = 0; i < fillCount; ++i) {
bytes32 orderId = payload.unpackSettlementBodyAt(i);
Order memory order = orders[orderId];
if (order.dstEid != senderEid) {
emit settlementFailed(
orderId,
order.dstEid,
senderEid,
"Eid mismatch"
);
continue;
}
_settleOrder(orderId, filler);
}
}
/**
* @notice Handles settlement of same-chain swaps with immediate token transfer
* @dev Performs atomic settlement within the same transaction for same-chain orders.
* Moves tokens from offerer's locked balance to solver's unlocked balance.
* Includes comprehensive validation to ensure balance consistency.
* @param orderId The unique identifier for the order
* @param order The order details
* @param solver The address of the solver who filled the order
*/
function _settleSingleChainSwap(
bytes32 orderId,
Order memory order,
address solver
) internal {
// Capture initial state for validation
uint128 initialOffererLocked = balances[order.offerer][order.inputToken].locked;
uint128 initialSolverUnlocked = balances[solver][order.inputToken].unlocked;
// Atomic balance transfer: locked → unlocked
if (balances[order.offerer][order.inputToken].locked >= order.inputAmount) {
bool successLock = balances[order.offerer][order.inputToken].decreaseLockedNoRevert(
order.inputAmount
);
bool successUnlock = balances[solver][order.inputToken].increaseUnlockedNoRevert(
order.inputAmount
);
require(successLock && successUnlock, "Balance operation failed");
}
// Verify the transfer was executed correctly
uint128 finalOffererLocked = balances[order.offerer][order.inputToken].locked;
uint128 finalSolverUnlocked = balances[solver][order.inputToken].unlocked;
balances[order.offerer][order.inputToken].validateBalanceTransferOrRevert(
initialOffererLocked,
finalOffererLocked,
initialSolverUnlocked,
finalSolverUnlocked,
order.inputAmount
);
orderStatus[orderId] = IAori.OrderStatus.Settled;
emit Settle(orderId);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CANCEL */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @notice Allows cancellation of single-chain orders from the source chain
* @dev Cross-chain orders must be cancelled from the destination chain to prevent race conditions.
* Cancellation is permitted for:
* 1. Whitelisted solvers (for any active single-chain order)
* 2. Order offerers (for their own expired single-chain orders)
* @param orderId The hash of the order to cancel
*/
function cancel(bytes32 orderId) external nonReentrant whenNotPaused {
Order memory order = orders[orderId];
order.validateSourceChainCancel(
orderId,
ENDPOINT_ID,
this.orderStatus,
msg.sender,
this.isAllowedSolver
);
_cancel(orderId);
}
/**
* @notice Cancels a cross-chain order from the destination chain by sending a cancellation message to the source chain
* @dev This is the required method for cancelling cross-chain orders to prevent race conditions with settlement.
* Requires ETH to be sent for LayerZero fees. Cancellation is permitted for:
* 1. Whitelisted solvers (anytime before settlement)
* 2. Order offerers (after expiry)
* 3. Order recipients (after expiry)
* @param orderId The hash of the order to cancel
* @param orderToCancel The order details to cancel
* @param extraOptions Additional LayerZero options
*/
function cancel(
bytes32 orderId,
Order calldata orderToCancel,
bytes calldata extraOptions
) external payable nonReentrant whenNotPaused {
require(hash(orderToCancel) == orderId, "Submitted order data doesn't match orderId");
orderToCancel.validateCancel(
orderId,
ENDPOINT_ID,
this.orderStatus,
msg.sender,
this.isAllowedSolver
);
orderStatus[orderId] = IAori.OrderStatus.Cancelled;
bytes memory payload = PayloadPackUtils.packCancellation(orderId);
MessagingReceipt memory receipt = __lzSend(orderToCancel.srcEid, payload, extraOptions);
emit CancelSent(orderId, receipt.guid, receipt.nonce, receipt.fee.nativeFee);
}
/**
* @notice Internal function to cancel an order and return tokens to offerer
* @dev Updates order status, decreases locked balance, and transfers tokens back.
* @param orderId The hash of the order to cancel
*/
function _cancel(bytes32 orderId) internal {
require(orderStatus[orderId] == IAori.OrderStatus.Active, "Can only cancel active orders");
Order memory order = orders[orderId];
uint128 amountToReturn = order.inputAmount;
address tokenAddress = order.inputToken;
address recipient = order.offerer;
// Validate contract has sufficient tokens
tokenAddress.validateSufficientBalance(amountToReturn);
// Update state first
orderStatus[orderId] = IAori.OrderStatus.Cancelled;
bool success = balances[recipient][tokenAddress].decreaseLockedNoRevert(amountToReturn);
require(success, "Failed to decrease locked balance");
// Transfer tokens back to offerer
tokenAddress.safeTransfer(recipient, amountToReturn);
emit Cancel(orderId);
}
/**
* @notice Handles cancellation payload from source chain
* @param payload The cancellation payload containing the order hash
*/
function _handleCancellation(bytes calldata payload) internal {
payload.validateCancellationLen();
bytes32 orderId = payload.unpackCancellation();
_cancel(orderId);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* WITHDRAW */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @notice Allows users to withdraw their unlocked token balances
* @dev Only unlocked balances can be withdrawn. Locked balances are reserved for active orders.
* @param token The token address to withdraw
* @param amount The amount to withdraw (use 0 to withdraw full balance)
*/
function withdraw(address token, uint256 amount) external nonReentrant whenNotPaused {
address holder = msg.sender;
uint256 unlockedBalance = balances[holder][token].unlocked;
require(unlockedBalance > 0, "Non-zero balance required");
// Default to full balance if amount is 0
if (amount == 0) {
amount = unlockedBalance;
} else {
require(unlockedBalance >= amount, "Insufficient unlocked balance");
}
token.validateSufficientBalance(amount);
// Update balance
balances[holder][token].unlocked = uint128(unlockedBalance - amount);
// Transfer tokens to user
token.safeTransfer(holder, amount);
emit Withdraw(holder, token, amount);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* LAYERZERO FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @notice Sends a message through LayerZero
* @dev Captures and returns the MessagingReceipt for event emission
* @param eId The destination endpoint ID
* @param payload The message payload
* @param extraOptions Additional options
* @return receipt The messaging receipt containing transaction details (guid, nonce, fee)
*/
function __lzSend(
uint32 eId,
bytes memory payload,
bytes calldata extraOptions
) internal returns (MessagingReceipt memory receipt) {
return _lzSend(eId, payload, extraOptions, MessagingFee(msg.value, 0), payable(msg.sender));
}
/**
* @notice Handles incoming LayerZero messages for order settlement and cancellation
* @dev Processes settlement and cancellation payloads
* @param payload The message payload containing order hashes and filler information
*/
function _lzReceive(
Origin calldata origin,
bytes32,
bytes calldata payload,
address,
bytes calldata
) internal override whenNotPaused {
require(payload.length > 0, "Empty payload");
// Pass the sender chain's endpoint ID
_recvPayload(payload, origin.srcEid);
}
/**
* @notice Processes incoming LayerZero messages based on the payload type
* @param payload The message payload containing order hashes and filler information
*/
function _recvPayload(bytes calldata payload, uint32 srcEid) internal {
PayloadType msgType = payload.getType();
if (msgType == PayloadType.Cancellation) {
_handleCancellation(payload);
} else if (msgType == PayloadType.Settlement) {
_handleSettlement(payload, srcEid);
} else {
revert("Unsupported payload type");
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EIP-712/HASHING HELPER FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Returns the domain name and version for EIP712.
*/
function _domainNameAndVersion()
internal
pure
override
returns (string memory name, string memory version)
{
return ("Aori", "0.3.1");
}
/**
* @dev EIP712 typehash for order struct
*/
bytes32 private constant _ORDER_TYPEHASH =
keccak256(
"Order(uint128 inputAmount,uint128 outputAmount,address inputToken,address outputToken,uint32 startTime,uint32 endTime,uint32 srcEid,uint32 dstEid,address offerer,address recipient)"
);
/**
* @dev Returns the EIP712 digest for the given order
* @param order The order details
* @return The computed digest
*/
function _hashOrder712(Order calldata order) internal view returns (bytes32) {
return
_hashTypedDataSansChainId(
keccak256(
abi.encode(
_ORDER_TYPEHASH,
order.inputAmount,
order.outputAmount,
order.inputToken,
order.outputToken,
order.startTime,
order.endTime,
order.srcEid,
order.dstEid,
order.offerer,
order.recipient
)
)
);
}
/**
* @notice Computes the hash of an order
* @param order The order to hash
* @return The computed hash
*/
function hash(IAori.Order calldata order) public pure returns (bytes32) {
return keccak256(abi.encode(order));
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* VIEW FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @notice Returns the locked balance for a user and token
* @param offerer The user address
* @param token The token address
* @return The locked balance amount
*/
function getLockedBalances(address offerer, address token) external view returns (uint256) {
return balances[offerer][token].locked;
}
/**
* @notice Returns the unlocked balance for a user and token
* @param offerer The user address
* @param token The token address
* @return The unlocked balance amount
*/
function getUnlockedBalances(address offerer, address token) external view returns (uint256) {
return balances[offerer][token].unlocked;
}
/**
* @notice Returns a fee quote for sending a message through LayerZero
* @param _dstEid Destination endpoint ID
* @param _msgType Message type (0 for settlement, 1 for cancellation)
* @param _options Execution options
* @param _payInLzToken Whether to pay fee in LayerZero token
* @param _srcEid Source endpoint ID (for settle operations)
* @param _filler Filler address (for settle operations)
* @return fee The messaging fee in native currency
*/
function quote(
uint32 _dstEid,
uint8 _msgType,
bytes calldata _options,
bool _payInLzToken,
uint32 _srcEid,
address _filler
) public view returns (uint256 fee) {
// Calculate payload size using the library function
uint256 fillsLength = srcEidToFillerFills[_srcEid][_filler].length;
uint256 payloadSize = PayloadSizeUtils.calculatePayloadSize(
_msgType,
fillsLength,
MAX_FILLS_PER_SETTLE
);
// Get the quote from LayerZero
MessagingFee memory messagingFee = _quote(
_dstEid,
new bytes(payloadSize),
_options,
_payInLzToken
);
return messagingFee.nativeFee;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import { IMessageLibManager } from "./IMessageLibManager.sol";
import { IMessagingComposer } from "./IMessagingComposer.sol";
import { IMessagingChannel } from "./IMessagingChannel.sol";
import { IMessagingContext } from "./IMessagingContext.sol";
struct MessagingParams {
uint32 dstEid;
bytes32 receiver;
bytes message;
bytes options;
bool payInLzToken;
}
struct MessagingReceipt {
bytes32 guid;
uint64 nonce;
MessagingFee fee;
}
struct MessagingFee {
uint256 nativeFee;
uint256 lzTokenFee;
}
struct Origin {
uint32 srcEid;
bytes32 sender;
uint64 nonce;
}
interface ILayerZeroEndpointV2 is IMessageLibManager, IMessagingComposer, IMessagingChannel, IMessagingContext {
event PacketSent(bytes encodedPayload, bytes options, address sendLibrary);
event PacketVerified(Origin origin, address receiver, bytes32 payloadHash);
event PacketDelivered(Origin origin, address receiver);
event LzReceiveAlert(
address indexed receiver,
address indexed executor,
Origin origin,
bytes32 guid,
uint256 gas,
uint256 value,
bytes message,
bytes extraData,
bytes reason
);
event LzTokenSet(address token);
event DelegateSet(address sender, address delegate);
function quote(MessagingParams calldata _params, address _sender) external view returns (MessagingFee memory);
function send(
MessagingParams calldata _params,
address _refundAddress
) external payable returns (MessagingReceipt memory);
function verify(Origin calldata _origin, address _receiver, bytes32 _payloadHash) external;
function verifiable(Origin calldata _origin, address _receiver) external view returns (bool);
function initializable(Origin calldata _origin, address _receiver) external view returns (bool);
function lzReceive(
Origin calldata _origin,
address _receiver,
bytes32 _guid,
bytes calldata _message,
bytes calldata _extraData
) external payable;
// oapp can burn messages partially by calling this function with its own business logic if messages are verified in order
function clear(address _oapp, Origin calldata _origin, bytes32 _guid, bytes calldata _message) external;
function setLzToken(address _lzToken) external;
function lzToken() external view returns (address);
function nativeToken() external view returns (address);
function setDelegate(address _delegate) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import { Origin } from "./ILayerZeroEndpointV2.sol";
interface ILayerZeroReceiver {
function allowInitializePath(Origin calldata _origin) external view returns (bool);
function nextNonce(uint32 _eid, bytes32 _sender) external view returns (uint64);
function lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
struct SetConfigParam {
uint32 eid;
uint32 configType;
bytes config;
}
interface IMessageLibManager {
struct Timeout {
address lib;
uint256 expiry;
}
event LibraryRegistered(address newLib);
event DefaultSendLibrarySet(uint32 eid, address newLib);
event DefaultReceiveLibrarySet(uint32 eid, address newLib);
event DefaultReceiveLibraryTimeoutSet(uint32 eid, address oldLib, uint256 expiry);
event SendLibrarySet(address sender, uint32 eid, address newLib);
event ReceiveLibrarySet(address receiver, uint32 eid, address newLib);
event ReceiveLibraryTimeoutSet(address receiver, uint32 eid, address oldLib, uint256 timeout);
function registerLibrary(address _lib) external;
function isRegisteredLibrary(address _lib) external view returns (bool);
function getRegisteredLibraries() external view returns (address[] memory);
function setDefaultSendLibrary(uint32 _eid, address _newLib) external;
function defaultSendLibrary(uint32 _eid) external view returns (address);
function setDefaultReceiveLibrary(uint32 _eid, address _newLib, uint256 _gracePeriod) external;
function defaultReceiveLibrary(uint32 _eid) external view returns (address);
function setDefaultReceiveLibraryTimeout(uint32 _eid, address _lib, uint256 _expiry) external;
function defaultReceiveLibraryTimeout(uint32 _eid) external view returns (address lib, uint256 expiry);
function isSupportedEid(uint32 _eid) external view returns (bool);
function isValidReceiveLibrary(address _receiver, uint32 _eid, address _lib) external view returns (bool);
/// ------------------- OApp interfaces -------------------
function setSendLibrary(address _oapp, uint32 _eid, address _newLib) external;
function getSendLibrary(address _sender, uint32 _eid) external view returns (address lib);
function isDefaultSendLibrary(address _sender, uint32 _eid) external view returns (bool);
function setReceiveLibrary(address _oapp, uint32 _eid, address _newLib, uint256 _gracePeriod) external;
function getReceiveLibrary(address _receiver, uint32 _eid) external view returns (address lib, bool isDefault);
function setReceiveLibraryTimeout(address _oapp, uint32 _eid, address _lib, uint256 _expiry) external;
function receiveLibraryTimeout(address _receiver, uint32 _eid) external view returns (address lib, uint256 expiry);
function setConfig(address _oapp, address _lib, SetConfigParam[] calldata _params) external;
function getConfig(
address _oapp,
address _lib,
uint32 _eid,
uint32 _configType
) external view returns (bytes memory config);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IMessagingChannel {
event InboundNonceSkipped(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce);
event PacketNilified(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);
event PacketBurnt(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);
function eid() external view returns (uint32);
// this is an emergency function if a message cannot be verified for some reasons
// required to provide _nextNonce to avoid race condition
function skip(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce) external;
function nilify(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;
function burn(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;
function nextGuid(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (bytes32);
function inboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);
function outboundNonce(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (uint64);
function inboundPayloadHash(
address _receiver,
uint32 _srcEid,
bytes32 _sender,
uint64 _nonce
) external view returns (bytes32);
function lazyInboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IMessagingComposer {
event ComposeSent(address from, address to, bytes32 guid, uint16 index, bytes message);
event ComposeDelivered(address from, address to, bytes32 guid, uint16 index);
event LzComposeAlert(
address indexed from,
address indexed to,
address indexed executor,
bytes32 guid,
uint16 index,
uint256 gas,
uint256 value,
bytes message,
bytes extraData,
bytes reason
);
function composeQueue(
address _from,
address _to,
bytes32 _guid,
uint16 _index
) external view returns (bytes32 messageHash);
function sendCompose(address _to, bytes32 _guid, uint16 _index, bytes calldata _message) external;
function lzCompose(
address _from,
address _to,
bytes32 _guid,
uint16 _index,
bytes calldata _message,
bytes calldata _extraData
) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IMessagingContext {
function isSendingMessage() external view returns (bool);
function getSendContext() external view returns (uint32 dstEid, address sender);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// @dev Import the 'MessagingFee' and 'MessagingReceipt' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import
import { OAppSender, MessagingFee, MessagingReceipt } from "./OAppSender.sol";
// @dev Import the 'Origin' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import
import { OAppReceiver, Origin } from "./OAppReceiver.sol";
import { OAppCore } from "./OAppCore.sol";
/**
* @title OApp
* @dev Abstract contract serving as the base for OApp implementation, combining OAppSender and OAppReceiver functionality.
*/
abstract contract OApp is OAppSender, OAppReceiver {
/**
* @dev Constructor to initialize the OApp with the provided endpoint and owner.
* @param _endpoint The address of the LOCAL LayerZero endpoint.
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
*/
constructor(address _endpoint, address _delegate) OAppCore(_endpoint, _delegate) {}
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol implementation.
* @return receiverVersion The version of the OAppReceiver.sol implementation.
*/
function oAppVersion()
public
pure
virtual
override(OAppSender, OAppReceiver)
returns (uint64 senderVersion, uint64 receiverVersion)
{
return (SENDER_VERSION, RECEIVER_VERSION);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IOAppCore, ILayerZeroEndpointV2 } from "./interfaces/IOAppCore.sol";
/**
* @title OAppCore
* @dev Abstract contract implementing the IOAppCore interface with basic OApp configurations.
*/
abstract contract OAppCore is IOAppCore, Ownable {
// The LayerZero endpoint associated with the given OApp
ILayerZeroEndpointV2 public immutable endpoint;
// Mapping to store peers associated with corresponding endpoints
mapping(uint32 eid => bytes32 peer) public peers;
/**
* @dev Constructor to initialize the OAppCore with the provided endpoint and delegate.
* @param _endpoint The address of the LOCAL Layer Zero endpoint.
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
*
* @dev The delegate typically should be set as the owner of the contract.
*/
constructor(address _endpoint, address _delegate) {
endpoint = ILayerZeroEndpointV2(_endpoint);
if (_delegate == address(0)) revert InvalidDelegate();
endpoint.setDelegate(_delegate);
}
/**
* @notice Sets the peer address (OApp instance) for a corresponding endpoint.
* @param _eid The endpoint ID.
* @param _peer The address of the peer to be associated with the corresponding endpoint.
*
* @dev Only the owner/admin of the OApp can call this function.
* @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.
* @dev Set this to bytes32(0) to remove the peer address.
* @dev Peer is a bytes32 to accommodate non-evm chains.
*/
function setPeer(uint32 _eid, bytes32 _peer) public virtual onlyOwner {
_setPeer(_eid, _peer);
}
/**
* @notice Sets the peer address (OApp instance) for a corresponding endpoint.
* @param _eid The endpoint ID.
* @param _peer The address of the peer to be associated with the corresponding endpoint.
*
* @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.
* @dev Set this to bytes32(0) to remove the peer address.
* @dev Peer is a bytes32 to accommodate non-evm chains.
*/
function _setPeer(uint32 _eid, bytes32 _peer) internal virtual {
peers[_eid] = _peer;
emit PeerSet(_eid, _peer);
}
/**
* @notice Internal function to get the peer address associated with a specific endpoint; reverts if NOT set.
* ie. the peer is set to bytes32(0).
* @param _eid The endpoint ID.
* @return peer The address of the peer associated with the specified endpoint.
*/
function _getPeerOrRevert(uint32 _eid) internal view virtual returns (bytes32) {
bytes32 peer = peers[_eid];
if (peer == bytes32(0)) revert NoPeer(_eid);
return peer;
}
/**
* @notice Sets the delegate address for the OApp.
* @param _delegate The address of the delegate to be set.
*
* @dev Only the owner/admin of the OApp can call this function.
* @dev Provides the ability for a delegate to set configs, on behalf of the OApp, directly on the Endpoint contract.
*/
function setDelegate(address _delegate) public onlyOwner {
endpoint.setDelegate(_delegate);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { IOAppReceiver, Origin } from "./interfaces/IOAppReceiver.sol";
import { OAppCore } from "./OAppCore.sol";
/**
* @title OAppReceiver
* @dev Abstract contract implementing the ILayerZeroReceiver interface and extending OAppCore for OApp receivers.
*/
abstract contract OAppReceiver is IOAppReceiver, OAppCore {
// Custom error message for when the caller is not the registered endpoint/
error OnlyEndpoint(address addr);
// @dev The version of the OAppReceiver implementation.
// @dev Version is bumped when changes are made to this contract.
uint64 internal constant RECEIVER_VERSION = 2;
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol contract.
* @return receiverVersion The version of the OAppReceiver.sol contract.
*
* @dev Providing 0 as the default for OAppSender version. Indicates that the OAppSender is not implemented.
* ie. this is a RECEIVE only OApp.
* @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions.
*/
function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {
return (0, RECEIVER_VERSION);
}
/**
* @notice Indicates whether an address is an approved composeMsg sender to the Endpoint.
* @dev _origin The origin information containing the source endpoint and sender address.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address on the src chain.
* - nonce: The nonce of the message.
* @dev _message The lzReceive payload.
* @param _sender The sender address.
* @return isSender Is a valid sender.
*
* @dev Applications can optionally choose to implement separate composeMsg senders that are NOT the bridging layer.
* @dev The default sender IS the OAppReceiver implementer.
*/
function isComposeMsgSender(
Origin calldata /*_origin*/,
bytes calldata /*_message*/,
address _sender
) public view virtual returns (bool) {
return _sender == address(this);
}
/**
* @notice Checks if the path initialization is allowed based on the provided origin.
* @param origin The origin information containing the source endpoint and sender address.
* @return Whether the path has been initialized.
*
* @dev This indicates to the endpoint that the OApp has enabled msgs for this particular path to be received.
* @dev This defaults to assuming if a peer has been set, its initialized.
* Can be overridden by the OApp if there is other logic to determine this.
*/
function allowInitializePath(Origin calldata origin) public view virtual returns (bool) {
return peers[origin.srcEid] == origin.sender;
}
/**
* @notice Retrieves the next nonce for a given source endpoint and sender address.
* @dev _srcEid The source endpoint ID.
* @dev _sender The sender address.
* @return nonce The next nonce.
*
* @dev The path nonce starts from 1. If 0 is returned it means that there is NO nonce ordered enforcement.
* @dev Is required by the off-chain executor to determine the OApp expects msg execution is ordered.
* @dev This is also enforced by the OApp.
* @dev By default this is NOT enabled. ie. nextNonce is hardcoded to return 0.
*/
function nextNonce(uint32 /*_srcEid*/, bytes32 /*_sender*/) public view virtual returns (uint64 nonce) {
return 0;
}
/**
* @dev Entry point for receiving messages or packets from the endpoint.
* @param _origin The origin information containing the source endpoint and sender address.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address on the src chain.
* - nonce: The nonce of the message.
* @param _guid The unique identifier for the received LayerZero message.
* @param _message The payload of the received message.
* @param _executor The address of the executor for the received message.
* @param _extraData Additional arbitrary data provided by the corresponding executor.
*
* @dev Entry point for receiving msg/packet from the LayerZero endpoint.
*/
function lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) public payable virtual {
// Ensures that only the endpoint can attempt to lzReceive() messages to this OApp.
if (address(endpoint) != msg.sender) revert OnlyEndpoint(msg.sender);
// Ensure that the sender matches the expected peer for the source endpoint.
if (_getPeerOrRevert(_origin.srcEid) != _origin.sender) revert OnlyPeer(_origin.srcEid, _origin.sender);
// Call the internal OApp implementation of lzReceive.
_lzReceive(_origin, _guid, _message, _executor, _extraData);
}
/**
* @dev Internal function to implement lzReceive logic without needing to copy the basic parameter validation.
*/
function _lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) internal virtual;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { SafeERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { MessagingParams, MessagingFee, MessagingReceipt } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
import { OAppCore } from "./OAppCore.sol";
/**
* @title OAppSender
* @dev Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint.
*/
abstract contract OAppSender is OAppCore {
using SafeERC20 for IERC20;
// Custom error messages
error NotEnoughNative(uint256 msgValue);
error LzTokenUnavailable();
// @dev The version of the OAppSender implementation.
// @dev Version is bumped when changes are made to this contract.
uint64 internal constant SENDER_VERSION = 1;
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol contract.
* @return receiverVersion The version of the OAppReceiver.sol contract.
*
* @dev Providing 0 as the default for OAppReceiver version. Indicates that the OAppReceiver is not implemented.
* ie. this is a SEND only OApp.
* @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions
*/
function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {
return (SENDER_VERSION, 0);
}
/**
* @dev Internal function to interact with the LayerZero EndpointV2.quote() for fee calculation.
* @param _dstEid The destination endpoint ID.
* @param _message The message payload.
* @param _options Additional options for the message.
* @param _payInLzToken Flag indicating whether to pay the fee in LZ tokens.
* @return fee The calculated MessagingFee for the message.
* - nativeFee: The native fee for the message.
* - lzTokenFee: The LZ token fee for the message.
*/
function _quote(
uint32 _dstEid,
bytes memory _message,
bytes memory _options,
bool _payInLzToken
) internal view virtual returns (MessagingFee memory fee) {
return
endpoint.quote(
MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _payInLzToken),
address(this)
);
}
/**
* @dev Internal function to interact with the LayerZero EndpointV2.send() for sending a message.
* @param _dstEid The destination endpoint ID.
* @param _message The message payload.
* @param _options Additional options for the message.
* @param _fee The calculated LayerZero fee for the message.
* - nativeFee: The native fee.
* - lzTokenFee: The lzToken fee.
* @param _refundAddress The address to receive any excess fee values sent to the endpoint.
* @return receipt The receipt for the sent message.
* - guid: The unique identifier for the sent message.
* - nonce: The nonce of the sent message.
* - fee: The LayerZero fee incurred for the message.
*/
function _lzSend(
uint32 _dstEid,
bytes memory _message,
bytes memory _options,
MessagingFee memory _fee,
address _refundAddress
) internal virtual returns (MessagingReceipt memory receipt) {
// @dev Push corresponding fees to the endpoint, any excess is sent back to the _refundAddress from the endpoint.
uint256 messageValue = _payNative(_fee.nativeFee);
if (_fee.lzTokenFee > 0) _payLzToken(_fee.lzTokenFee);
return
// solhint-disable-next-line check-send-result
endpoint.send{ value: messageValue }(
MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _fee.lzTokenFee > 0),
_refundAddress
);
}
/**
* @dev Internal function to pay the native fee associated with the message.
* @param _nativeFee The native fee to be paid.
* @return nativeFee The amount of native currency paid.
*
* @dev If the OApp needs to initiate MULTIPLE LayerZero messages in a single transaction,
* this will need to be overridden because msg.value would contain multiple lzFees.
* @dev Should be overridden in the event the LayerZero endpoint requires a different native currency.
* @dev Some EVMs use an ERC20 as a method for paying transactions/gasFees.
* @dev The endpoint is EITHER/OR, ie. it will NOT support both types of native payment at a time.
*/
function _payNative(uint256 _nativeFee) internal virtual returns (uint256 nativeFee) {
if (msg.value != _nativeFee) revert NotEnoughNative(msg.value);
return _nativeFee;
}
/**
* @dev Internal function to pay the LZ token fee associated with the message.
* @param _lzTokenFee The LZ token fee to be paid.
*
* @dev If the caller is trying to pay in the specified lzToken, then the lzTokenFee is passed to the endpoint.
* @dev Any excess sent, is passed back to the specified _refundAddress in the _lzSend().
*/
function _payLzToken(uint256 _lzTokenFee) internal virtual {
// @dev Cannot cache the token because it is not immutable in the endpoint.
address lzToken = endpoint.lzToken();
if (lzToken == address(0)) revert LzTokenUnavailable();
// Pay LZ token fee by sending tokens to the endpoint.
IERC20(lzToken).safeTransferFrom(msg.sender, address(endpoint), _lzTokenFee);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { ILayerZeroEndpointV2 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
/**
* @title IOAppCore
*/
interface IOAppCore {
// Custom error messages
error OnlyPeer(uint32 eid, bytes32 sender);
error NoPeer(uint32 eid);
error InvalidEndpointCall();
error InvalidDelegate();
// Event emitted when a peer (OApp) is set for a corresponding endpoint
event PeerSet(uint32 eid, bytes32 peer);
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol contract.
* @return receiverVersion The version of the OAppReceiver.sol contract.
*/
function oAppVersion() external view returns (uint64 senderVersion, uint64 receiverVersion);
/**
* @notice Retrieves the LayerZero endpoint associated with the OApp.
* @return iEndpoint The LayerZero endpoint as an interface.
*/
function endpoint() external view returns (ILayerZeroEndpointV2 iEndpoint);
/**
* @notice Retrieves the peer (OApp) associated with a corresponding endpoint.
* @param _eid The endpoint ID.
* @return peer The peer address (OApp instance) associated with the corresponding endpoint.
*/
function peers(uint32 _eid) external view returns (bytes32 peer);
/**
* @notice Sets the peer address (OApp instance) for a corresponding endpoint.
* @param _eid The endpoint ID.
* @param _peer The address of the peer to be associated with the corresponding endpoint.
*/
function setPeer(uint32 _eid, bytes32 _peer) external;
/**
* @notice Sets the delegate address for the OApp Core.
* @param _delegate The address of the delegate to be set.
*/
function setDelegate(address _delegate) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { ILayerZeroReceiver, Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol";
interface IOAppReceiver is ILayerZeroReceiver {
/**
* @notice Indicates whether an address is an approved composeMsg sender to the Endpoint.
* @param _origin The origin information containing the source endpoint and sender address.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address on the src chain.
* - nonce: The nonce of the message.
* @param _message The lzReceive payload.
* @param _sender The sender address.
* @return isSender Is a valid sender.
*
* @dev Applications can optionally choose to implement a separate composeMsg sender that is NOT the bridging layer.
* @dev The default sender IS the OAppReceiver implementer.
*/
function isComposeMsgSender(
Origin calldata _origin,
bytes calldata _message,
address _sender
) external view returns (bool isSender);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
// bubble errors
if iszero(success) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
returnSize := returndatasize()
returnValue := mload(0)
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
bool success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
returnSize := returndatasize()
returnValue := mload(0)
}
return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
bool private _paused;
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
/**
* @dev The operation failed because the contract is paused.
*/
error EnforcedPause();
/**
* @dev The operation failed because the contract is not paused.
*/
error ExpectedPause();
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
if (paused()) {
revert EnforcedPause();
}
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
if (!paused()) {
revert ExpectedPause();
}
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
* consider using {ReentrancyGuardTransient} instead.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.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/bool 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);
}
/**
* @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
*/
function toUint(bool b) internal pure returns (uint256 u) {
assembly ("memory-safe") {
u := iszero(iszero(b))
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { ECDSA } from "solady/src/utils/ECDSA.sol";
import { IAori } from "./IAori.sol";
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* VALIDATION */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @notice Library for order validation functions
* @dev Provides reusable validation logic for orders across different contract functions
*/
library ValidationUtils {
/**
* @notice Validates basic order parameters that are common to all validation flows
* @dev Checks offerer, recipient, time bounds, amounts, and token addresses
* @param order The order to validate
*/
function validateCommonOrderParams(IAori.Order calldata order) internal view {
require(order.offerer != address(0), "Invalid offerer");
require(order.recipient != address(0), "Invalid recipient");
require(order.startTime < order.endTime, "Invalid end time");
require(order.startTime <= block.timestamp, "Order not started");
require(order.endTime > block.timestamp, "Order has expired");
require(order.inputAmount > 0, "Invalid input amount");
require(order.outputAmount > 0, "Invalid output amount");
require(order.inputToken != address(0) && order.outputToken != address(0), "Invalid token");
}
/**
* @notice Validates deposit parameters including signature verification
* @dev Performs comprehensive validation for deposit operations
* @param order The order to validate
* @param signature The EIP712 signature to verify
* @param digest The EIP712 type hash digest of the order
* @param endpointId The current chain's endpoint ID
* @param orderStatus The status mapping function to check order status
* @param isSupportedChain A function to check if the destination chain is supported
* @return orderId The calculated order hash
*/
function validateDeposit(
IAori.Order calldata order,
bytes calldata signature,
bytes32 digest,
uint32 endpointId,
function(bytes32) external view returns (IAori.OrderStatus) orderStatus,
function(uint32) external view returns (bool) isSupportedChain
) internal view returns (bytes32 orderId) {
orderId = keccak256(abi.encode(order));
require(orderStatus(orderId) == IAori.OrderStatus.Unknown, "Order already exists");
require(isSupportedChain(order.dstEid), "Destination chain not supported");
// Signature validation
address recovered = ECDSA.recover(digest, signature);
require(recovered == order.offerer, "InvalidSignature");
// Order parameter validation
validateCommonOrderParams(order);
require(order.srcEid == endpointId, "Chain mismatch");
}
/**
* @notice Validates fill parameters for both single-chain and cross-chain swaps
* @dev Performs comprehensive validation for fill operations
* @param order The order to validate
* @param endpointId The current chain's endpoint ID
* @param orderStatus The status mapping function to check order status
* @return orderId The calculated order hash
*/
function validateFill(
IAori.Order calldata order,
uint32 endpointId,
function(bytes32) external view returns (IAori.OrderStatus) orderStatus
) internal view returns (bytes32 orderId) {
// Order parameter validation
validateCommonOrderParams(order);
require(order.dstEid == endpointId, "Chain mismatch");
orderId = keccak256(abi.encode(order));
// Different validation based on whether it's a single-chain or cross-chain swap
if (order.srcEid == order.dstEid) {
// For single-chain swaps, the order should already be Active
require(orderStatus(orderId) == IAori.OrderStatus.Active, "Order not active");
} else {
// For cross-chain swaps, the order should be Unknown on the destination chain
require(orderStatus(orderId) == IAori.OrderStatus.Unknown, "Order not active");
}
}
/**
* @notice Validates the cancellation of a cross-chain order from the destination chain
* @dev Allows whitelisted solvers (anytime), offerers (after expiry), and recipients (after expiry) to cancel
* @param order The order details to cancel
* @param orderId The hash of the order to cancel
* @param endpointId The current chain's endpoint ID
* @param orderStatus The status mapping function to check order status
* @param sender The address of the transaction sender
* @param isAllowedSolver A function to check if an address is a whitelisted solver
*/
function validateCancel(
IAori.Order calldata order,
bytes32 orderId,
uint32 endpointId,
function(bytes32) external view returns (IAori.OrderStatus) orderStatus,
address sender,
function(address) external view returns (bool) isAllowedSolver
) internal view {
require(order.dstEid == endpointId, "Not on destination chain");
require(orderStatus(orderId) == IAori.OrderStatus.Unknown, "Order not active");
require(
(isAllowedSolver(sender)) ||
(sender == order.offerer && block.timestamp > order.endTime) ||
(sender == order.recipient && block.timestamp > order.endTime),
"Only whitelisted solver, offerer, or recipient (after expiry) can cancel"
);
}
/**
* @notice Validates cancellation of an order on the source chain
* @dev Only allows cancellation of single-chain orders or by solver (with expiry restriction for cross-chain)
* @param order The order details to cancel
* @param orderId The hash of the order to cancel
* @param endpointId The current chain's endpoint ID
* @param orderStatus The function to check order status
* @param sender The transaction sender address
* @param isAllowedSolver The function to check if an address is a whitelisted solver
*/
function validateSourceChainCancel(
IAori.Order memory order,
bytes32 orderId,
uint32 endpointId,
function(bytes32) external view returns (IAori.OrderStatus) orderStatus,
address sender,
function(address) external view returns (bool) isAllowedSolver
) internal view {
// Verify we're on the source chain
require(order.srcEid == endpointId, "Not on source chain");
// Verify order exists and is active
require(orderStatus(orderId) == IAori.OrderStatus.Active, "Order not active");
// Cross-chain orders cannot be cancelled from the source chain to prevent race conditions
// with settlement messages. Use emergencyCancel for emergency situations.
require(order.srcEid == order.dstEid, "Cross-chain orders must be cancelled from destination chain");
// For single-chain orders: solver can always cancel, offerer can cancel after expiry
require(
isAllowedSolver(sender) ||
(sender == order.offerer && block.timestamp > order.endTime),
"Only solver or offerer (after expiry) can cancel"
);
}
/**
* @notice Checks if an order is a single-chain swap
* @param order The order to check
* @return True if the order is a single-chain swap
*/
function isSingleChainSwap(IAori.Order calldata order) internal pure returns (bool) {
return order.srcEid == order.dstEid;
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* BALANCE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @notice Balance struct for tracking locked and unlocked token amounts
* @dev Uses uint128 for both values to pack them into a single storage slot
*/
struct Balance {
uint128 locked; // Tokens locked in active orders
uint128 unlocked; // Tokens available for withdrawal
}
using BalanceUtils for Balance global;
/**
* @notice Utility library for managing token balances
* @dev Provides functions for locking, unlocking, and managing token balances
* with optimized storage operations
*/
library BalanceUtils {
/**
* @notice Locks a specified amount of tokens
* @dev Increases the locked balance by the specified amount
* @param balance The Balance struct reference
* @param amount The amount to lock
*/
function lock(Balance storage balance, uint128 amount) internal {
balance.locked += amount;
}
/**
* @notice Unlocks a specified amount of tokens from locked to unlocked state
* @dev Decreases locked balance and increases unlocked balance
* @param balance The Balance struct reference
* @param amount The amount to unlock
*/
function unlock(Balance storage balance, uint128 amount) internal {
(uint128 locked, uint128 unlocked) = balance.loadBalance();
require(locked >= amount, "Insufficient locked balance");
unchecked {
locked -= amount;
}
unlocked += amount;
balance.storeBalance(locked, unlocked);
}
/**
* @notice Decreases locked balance without reverting on underflow
* @dev Safe version that returns false instead of reverting on underflow
* @param balance The Balance struct reference
* @param amount The amount to decrease
* @return success Whether the operation was successful
*/
function decreaseLockedNoRevert(
Balance storage balance,
uint128 amount
) internal returns (bool success) {
uint128 locked = balance.locked;
unchecked {
uint128 newLocked = locked - amount;
if (newLocked > locked) {
return false; // Underflow
}
balance.locked = newLocked;
}
return true;
}
/**
* @notice Increases unlocked balance without reverting on overflow
* @dev Safe version that returns false instead of reverting on overflow
* @param balance The Balance struct reference
* @param amount The amount to increase
* @return success Whether the operation was successful
*/
function increaseUnlockedNoRevert(
Balance storage balance,
uint128 amount
) internal returns (bool success) {
uint128 unlocked = balance.unlocked;
unchecked {
uint128 newUnlocked = unlocked + amount;
if (newUnlocked < unlocked) {
return false; // Overflow
}
balance.unlocked = newUnlocked;
}
return true;
}
/**
* @notice Unlocks all locked tokens into the unlocked balance
* @dev Moves the entire locked balance to unlocked
* @param balance The Balance struct reference
* @return amount The amount that was unlocked
*/
function unlockAll(Balance storage balance) internal returns (uint128 amount) {
(uint128 locked, uint128 unlocked) = balance.loadBalance();
amount = locked;
unlocked += amount;
locked = 0;
balance.storeBalance(locked, unlocked);
}
/**
* @notice Gets the unlocked balance amount
* @param balance The Balance struct reference
* @return The unlocked balance amount
*/
function getUnlocked(Balance storage balance) internal view returns (uint128) {
return balance.unlocked;
}
/**
* @notice Gets the locked balance amount
* @param balance The Balance struct reference
* @return The locked balance amount
*/
function getLocked(Balance storage balance) internal view returns (uint128) {
return balance.locked;
}
/**
* @notice Load balance values using optimized storage operations
* @dev Uses assembly to read both values in a single storage read
* @param balance The Balance struct reference
* @return locked The locked balance
* @return unlocked The unlocked balance
*/
function loadBalance(
Balance storage balance
) internal view returns (uint128 locked, uint128 unlocked) {
assembly {
let fullSlot := sload(balance.slot)
unlocked := shr(128, fullSlot)
locked := fullSlot
}
}
/**
* @notice Store balance values using optimized storage operations
* @dev Uses assembly to write both values in a single storage write
* @param balance The Balance struct reference
* @param locked The locked balance to store
* @param unlocked The unlocked balance to store
*/
function storeBalance(Balance storage balance, uint128 locked, uint128 unlocked) internal {
assembly {
sstore(balance.slot, or(shl(128, unlocked), locked))
}
}
/**
* @notice Validates a decrease in locked balance with a corresponding increase in unlocked balance
* @dev Verifies that the token accounting was performed correctly during transfer operations
* @param _balance The Balance struct reference (not used, but needed for extension method pattern)
* @param initialOffererLocked The offerer's initial locked balance
* @param finalOffererLocked The offerer's final locked balance
* @param initialSolverUnlocked The solver's initial unlocked balance
* @param finalSolverUnlocked The solver's final unlocked balance
* @param transferAmount The amount that should have been transferred
* @return success Whether the validation was successful
*/
function validateBalanceTransfer(
Balance storage _balance,
uint128 initialOffererLocked,
uint128 finalOffererLocked,
uint128 initialSolverUnlocked,
uint128 finalSolverUnlocked,
uint128 transferAmount
) internal pure returns (bool success) {
// Verify offerer's locked balance decreased by exactly the transfer amount
if (initialOffererLocked != finalOffererLocked + transferAmount) {
return false;
}
// Verify solver's unlocked balance increased by exactly the transfer amount
if (finalSolverUnlocked != initialSolverUnlocked + transferAmount) {
return false;
}
return true;
}
/**
* @notice Validates a decrease in locked balance with a corresponding increase in unlocked balance with revert
* @dev Same as validateBalanceTransfer but reverts with custom error messages if validation fails
* @param _balance The Balance struct reference (not used, but needed for extension method pattern)
* @param initialOffererLocked The offerer's initial locked balance
* @param finalOffererLocked The offerer's final locked balance
* @param initialSolverUnlocked The solver's initial unlocked balance
* @param finalSolverUnlocked The solver's final unlocked balance
* @param transferAmount The amount that should have been transferred
*/
function validateBalanceTransferOrRevert(
Balance storage _balance,
uint128 initialOffererLocked,
uint128 finalOffererLocked,
uint128 initialSolverUnlocked,
uint128 finalSolverUnlocked,
uint128 transferAmount
) internal pure {
// Verify offerer's locked balance decreased by exactly the transfer amount
require(
initialOffererLocked == finalOffererLocked + transferAmount,
"Inconsistent offerer balance"
);
// Verify solver's unlocked balance increased by exactly the transfer amount
require(
finalSolverUnlocked == initialSolverUnlocked + transferAmount,
"Inconsistent solver balance"
);
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EXECUTION */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @notice Library for executing external calls and observing token balance changes
* @dev Used for hook execution and token conversion operations
*/
library ExecutionUtils {
/**
* @notice Executes an external call and measures the resulting token balance change
* @dev Useful for hook operations that convert tokens
* @param target The target contract address to call
* @param data The calldata to send to the target
* @param observedToken The token address to observe balance changes for
* @return The balance change (positive if tokens increased, reverts if decreased)
*/
function observeBalChg(
address target,
bytes calldata data,
address observedToken
) internal returns (uint256) {
uint256 balBefore = NativeTokenUtils.balanceOf(observedToken, address(this));
(bool success, ) = target.call(data);
require(success, "Call failed");
uint256 balAfter = NativeTokenUtils.balanceOf(observedToken, address(this));
// Prevent underflow and provide clear error message
require(balAfter >= balBefore, "Hook decreased contract balance");
return balAfter - balBefore;
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* HOOKS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @notice Library for hook-related utility functions
* @dev Provides helper functions for working with SrcHook and DstHook structs
*/
library HookUtils {
/**
* @notice Checks if a SrcHook is defined (has a non-zero address)
* @param hook The SrcHook struct to check
* @return True if the hook has a non-zero address
*/
function isSome(IAori.SrcHook calldata hook) internal pure returns (bool) {
return hook.hookAddress != address(0);
}
/**
* @notice Checks if a DstHook is defined (has a non-zero address)
* @param hook The DstHook struct to check
* @return True if the hook has a non-zero address
*/
function isSome(IAori.DstHook calldata hook) internal pure returns (bool) {
return hook.hookAddress != address(0);
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PAYLOAD TYPES */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @notice Enum for different LayerZero message payload types
*/
enum PayloadType {
Settlement, // Settlement message with multiple order fills (0)
Cancellation // Cancellation message for a single order (1)
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PAYLOAD PACKING */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @notice Library for packing LayerZero message payloads
* @dev Provides functions to create properly formatted message payloads for cross-chain messaging
* that will work with the MessagingReceipt tracking in the contract
*/
library PayloadPackUtils {
/**
* @notice Packs a settlement payload with order hashes for LayerZero messaging
* @dev Creates a settlement payload and clears the filled orders from storage
* The message will return a MessagingReceipt that is included in the SettleSent event
* @param arr The array of order hashes to be packed
* @param filler The address of the filler
* @param takeSize The number of order hashes to take from the array
* @return The packed payload
*
* @notice The payload structure is as follows:
* Header
* - 1 byte: Message type (0)
* - 20 bytes: Filler address
* - 2 bytes: Fill count
* Body
* - Fill count * 32 bytes: Order hashes
*/
function packSettlement(
bytes32[] storage arr,
address filler,
uint16 takeSize
) internal returns (bytes memory) {
uint32 offset = 23;
bytes memory payload = new bytes(offset + takeSize * 32);
assembly {
let payloadPtr := add(payload, 32)
// Store msgType, filler and takeSize
mstore(payloadPtr, or(shl(88, filler), shl(72, takeSize)))
// Load array slot
mstore(0x00, arr.slot)
let base := keccak256(0x00, 32)
let arrLength := sload(arr.slot)
let min_i := sub(arrLength, takeSize)
let dataPtr := add(payloadPtr, offset)
// Store storage elements into memory and clear them
for {
let i := arrLength
} gt(i, min_i) {} {
i := sub(i, 1)
let elementSlot := add(base, i)
mstore(dataPtr, sload(elementSlot)) // Storage -> memory
sstore(elementSlot, 0) // Clear the slot
dataPtr := add(dataPtr, 32)
}
// Update the array length
sstore(arr.slot, min_i)
}
return payload;
}
/**
* @notice Packs a cancellation payload for LayerZero messaging
* @dev Creates a properly formatted cancellation message payload
* The message will return a MessagingReceipt that is included in the CancelSent event
* @param orderHash The hash of the order to cancel
* @return payload The packed cancellation payload
*/
function packCancellation(bytes32 orderHash) internal pure returns (bytes memory) {
uint8 msgType = uint8(PayloadType.Cancellation);
return abi.encodePacked(msgType, orderHash);
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PAYLOAD UNPACKING */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @notice Library for unpacking LayerZero message payloads
* @dev Provides functions to extract and validate data from received payloads
*/
library PayloadUnpackUtils {
/**
* @notice Validates the length of a cancellation payload
* @dev Ensures the payload is exactly 33 bytes (1 byte type + 32 bytes order hash)
* @param payload The payload to validate
*/
function validateCancellationLen(bytes calldata payload) internal pure {
require(payload.length == 33, "Invalid cancellation payload length");
}
/**
* @notice Unpacks an order hash from a cancellation payload
* @dev Extracts the 32-byte order hash, skipping the first byte (type)
* @param payload The cancellation payload to unpack
* @return orderHash The extracted order hash
*/
function unpackCancellation(bytes calldata payload) internal pure returns (bytes32 orderHash) {
assembly {
orderHash := calldataload(add(payload.offset, 1))
}
}
/**
* @notice Validates the minimum length of a settlement payload
* @dev Ensures the payload is at least 23 bytes (header size)
* @param payload The payload to validate
*/
function validateSettlementLen(bytes calldata payload) internal pure {
require(payload.length >= 23, "Payload too short for settlement");
}
/**
* @notice Validates the length of a settlement payload for a specific fill count
* @dev Ensures the payload matches the expected size based on fill count
* @param payload The payload to validate
* @param fillCount The number of fills in the payload
*/
function validateSettlementLen(bytes calldata payload, uint16 fillCount) internal pure {
require(
payload.length == 23 + uint256(fillCount) * 32,
"Invalid payload length for settlement"
);
}
/**
* @notice Gets the payload type from a message payload
* @dev Reads the first byte to determine the payload type
* @param payload The payload to check
* @return The payload type (Settlement or Cancellation)
*/
function getType(bytes calldata payload) internal pure returns (PayloadType) {
return PayloadType(uint8(payload[0]));
}
/**
* @notice Unpacks the header from a settlement payload
* @dev Extracts the filler address (20 bytes) and fill count (2 bytes)
* @param payload The settlement payload to unpack
* @return filler The filler address
* @return fillCount The number of fills in the payload
*/
function unpackSettlementHeader(
bytes calldata payload
) internal pure returns (address filler, uint16 fillCount) {
require(payload.length >= 23, "Invalid payload length");
assembly {
let word := calldataload(add(payload.offset, 1))
filler := shr(96, word)
}
fillCount = (uint16(uint8(payload[21])) << 8) | uint16(uint8(payload[22]));
}
/**
* @notice Unpacks an order hash from a specific position in the settlement payload body
* @dev Extracts the order hash at the specified index
* @param payload The settlement payload to unpack
* @param index The index of the order hash to extract
* @return orderHash The extracted order hash
*/
function unpackSettlementBodyAt(
bytes calldata payload,
uint256 index
) internal pure returns (bytes32 orderHash) {
require(payload.length >= 23, "Invalid payload length");
require(index < (payload.length - 23) / 32, "Index out of bounds");
assembly {
orderHash := calldataload(add(add(payload.offset, 23), mul(index, 32)))
}
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PAYLOAD SIZES */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @notice Calculates the size of a settlement payload based on fill count
* @dev 1 byte type + 20 bytes filler + 2 bytes count + (fillCount * 32 bytes order hash)
* @param fillCount The number of fills in the settlement
* @return The total payload size in bytes
*/
function settlementPayloadSize(uint256 fillCount) pure returns (uint256) {
return 1 + 20 + 2 + (fillCount * 32);
}
// Constant size of a cancellation payload: 1 byte type + 32 bytes order hash
uint256 constant CANCELLATION_PAYLOAD_SIZE = 33;
/**
* @notice Library for payload size calculations
* @dev Provides functions to calculate payload sizes for different message types
*/
library PayloadSizeUtils {
/**
* @notice Calculate payload size based on message type and other parameters
* @dev Used for fee estimation when sending messages via LayerZero
* @param msgType Message type (0 for settlement, 1 for cancellation)
* @param fillsLength Number of fills available for the filler
* @param maxFillsPerSettle Maximum fills allowed per settlement
* @return The calculated payload size in bytes
*/
function calculatePayloadSize(
uint8 msgType,
uint256 fillsLength,
uint16 maxFillsPerSettle
) internal pure returns (uint256) {
if (msgType == uint8(PayloadType.Cancellation)) {
return CANCELLATION_PAYLOAD_SIZE; // 1 byte type + 32 bytes order hash
} else if (msgType == uint8(PayloadType.Settlement)) {
// Get the number of fills (capped by maxFillsPerSettle)
uint16 fillCount = uint16(
fillsLength < maxFillsPerSettle ? fillsLength : maxFillsPerSettle
);
// Calculate settlement payload size
return settlementPayloadSize(fillCount);
} else {
revert("Invalid message type");
}
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* NATIVE TOKEN UTILS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// Native token address constant
address constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
/**
* @notice Library for native token operations
* @dev Provides utilities for handling native ETH alongside ERC20 tokens
*/
library NativeTokenUtils {
using SafeERC20 for IERC20;
/**
* @notice Checks if a token address represents native ETH
* @param token The token address to check
* @return True if the token is the native token address
*/
function isNativeToken(address token) internal pure returns (bool) {
return token == NATIVE_TOKEN;
}
/**
* @notice Safely transfers tokens (native or ERC20) to a recipient
* @param token The token address (use NATIVE_TOKEN for ETH)
* @param to The recipient address
* @param amount The amount to transfer
*/
function safeTransfer(address token, address to, uint256 amount) internal {
if (isNativeToken(token)) {
(bool success, ) = payable(to).call{value: amount}("");
require(success, "Native transfer failed");
} else {
IERC20(token).safeTransfer(to, amount);
}
}
/**
* @notice Gets the balance of a token for a specific address
* @param token The token address (use NATIVE_TOKEN for ETH)
* @param account The account to check balance for
* @return The token balance
*/
function balanceOf(address token, address account) internal view returns (uint256) {
if (isNativeToken(token)) {
return account.balance;
} else {
return IERC20(token).balanceOf(account);
}
}
/**
* @notice Validates that the contract has sufficient balance for a transfer
* @param token The token address (use NATIVE_TOKEN for ETH)
* @param amount The amount to validate
*/
function validateSufficientBalance(address token, uint256 amount) internal view {
if (isNativeToken(token)) {
require(address(this).balance >= amount, "Insufficient contract native balance");
} else {
require(IERC20(token).balanceOf(address(this)) >= amount, "Insufficient contract balance");
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
interface IAori {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STATUS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
enum OrderStatus {
Unknown, // Order not found
Active, // Order deposited but not filled
Filled, // Pending settlement
Cancelled, // Order cancelled
Settled // Order settled
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ORDER */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
struct Order {
uint128 inputAmount;
uint128 outputAmount;
address inputToken;
address outputToken;
uint32 startTime;
uint32 endTime;
uint32 srcEid;
uint32 dstEid;
address offerer;
address recipient;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* HOOKS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
struct SrcHook {
address hookAddress;
address preferredToken;
uint256 minPreferedTokenAmountOut;
bytes instructions;
}
struct DstHook {
address hookAddress;
address preferredToken;
bytes instructions;
uint256 preferedDstInputAmount;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* SRC EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
event Deposit(bytes32 indexed orderId, Order order);
event Cancel(bytes32 indexed orderId);
event Settle(bytes32 indexed orderId);
event Withdraw(address indexed holder, address indexed token, uint256 amount);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CHAIN MANAGEMENT EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
event ChainSupported(uint32 indexed eid);
event ChainRemoved(uint32 indexed eid);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* DST EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
event Fill(bytes32 indexed orderId, Order order);
/**
* @notice Emitted when an order is cancelled from the destination chain
* @dev Contains MessagingReceipt data for cross-chain tracking
* @param orderId The hash of the cancelled order
* @param guid The unique identifier of the LayerZero message
* @param nonce The nonce of the LayerZero message
* @param fee The fee paid for the LayerZero message
*/
event CancelSent(bytes32 indexed orderId, bytes32 guid, uint64 nonce, uint256 fee);
/**
* @notice Emitted when orders are settled from the destination chain
* @dev Contains MessagingReceipt data for cross-chain tracking
* @param srcEid The source endpoint ID
* @param filler The address of the filler
* @param payload The settlement payload
* @param guid The unique identifier of the LayerZero message
* @param nonce The nonce of the LayerZero message
* @param fee The fee paid for the LayerZero message
*/
event SettleSent(uint32 indexed srcEid, address indexed filler, bytes payload, bytes32 guid, uint64 nonce, uint256 fee);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* SRC FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
function deposit(Order calldata order, bytes calldata signature) external;
function deposit(
Order calldata order,
bytes calldata signature,
SrcHook calldata data
) external;
function depositNative(Order calldata order) external payable;
function withdraw(address token, uint256 amount) external;
function cancel(bytes32 orderId) external;
event settlementFailed(bytes32 indexed orderId, uint32 expectedEid, uint32 submittedEid, string reason);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* DST FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
function fill(Order calldata order) external payable;
function fill(Order calldata order, DstHook calldata hook) external payable;
function settle(uint32 srcEid, address filler, bytes calldata extraOptions) external payable;
function cancel(
bytes32 orderId,
Order calldata orderToCancel,
bytes calldata extraOptions
) external payable;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* UTILITY FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
function hash(Order calldata order) external pure returns (bytes32);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* VIEW FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
function getLockedBalances(address offerer, address token) external view returns (uint256);
function getUnlockedBalances(address offerer, address token) external view returns (uint256);
function quote(
uint32 _dstEid,
uint8 _msgType,
bytes calldata _options,
bool _payInLzToken,
uint32 _srcEid,
address _filler
) external view returns (uint256 fee);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* HOOK EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @notice Emitted when a source hook is executed during deposit
* @param orderId The hash of the order being processed
* @param preferredToken The token address that was received from the hook
* @param amountReceived The amount of tokens received from hook execution
*/
event SrcHookExecuted(bytes32 indexed orderId, address indexed preferredToken, uint256 amountReceived);
/**
* @notice Emitted when a destination hook is executed during fill
* @param orderId The hash of the order being processed
* @param preferredToken The token address that was converted by the hook
* @param amountReceived The amount of output tokens received from hook execution
*/
event DstHookExecuted(bytes32 indexed orderId, address indexed preferredToken, uint256 amountReceived);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Gas optimized ECDSA wrapper.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol)
///
/// @dev Note:
/// - The recovery functions use the ecrecover precompile (0x1).
/// - As of Solady version 0.0.68, the `recover` variants will revert upon recovery failure.
/// This is for more safety by default.
/// Use the `tryRecover` variants if you need to get the zero address back
/// upon recovery failure instead.
/// - As of Solady version 0.0.134, all `bytes signature` variants accept both
/// regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures.
/// See: https://eips.ethereum.org/EIPS/eip-2098
/// This is for calldata efficiency on smart accounts prevalent on L2s.
///
/// WARNING! Do NOT directly use signatures as unique identifiers:
/// - The recovery operations do NOT check if a signature is non-malleable.
/// - Use a nonce in the digest to prevent replay attacks on the same contract.
/// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts.
/// EIP-712 also enables readable signing of typed data for better user safety.
/// - If you need a unique hash from a signature, please use the `canonicalHash` functions.
library ECDSA {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The order of the secp256k1 elliptic curve.
uint256 internal constant N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141;
/// @dev `N/2 + 1`. Used for checking the malleability of the signature.
uint256 private constant _HALF_N_PLUS_1 =
0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The signature is invalid.
error InvalidSignature();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* RECOVERY OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
function recover(bytes32 hash, bytes memory signature) internal view returns (address result) {
/// @solidity memory-safe-assembly
assembly {
for { let m := mload(0x40) } 1 {
mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
revert(0x1c, 0x04)
} {
switch mload(signature)
case 64 {
let vs := mload(add(signature, 0x40))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
}
case 65 {
mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
mstore(0x60, mload(add(signature, 0x40))) // `s`.
}
default { continue }
mstore(0x00, hash)
mstore(0x40, mload(add(signature, 0x20))) // `r`.
result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if returndatasize() { break }
}
}
}
/// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
function recoverCalldata(bytes32 hash, bytes calldata signature)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
for { let m := mload(0x40) } 1 {
mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
revert(0x1c, 0x04)
} {
switch signature.length
case 64 {
let vs := calldataload(add(signature.offset, 0x20))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x40, calldataload(signature.offset)) // `r`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
}
case 65 {
mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.
}
default { continue }
mstore(0x00, hash)
result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if returndatasize() { break }
}
}
}
/// @dev Recovers the signer's address from a message digest `hash`,
/// and the EIP-2098 short form signature defined by `r` and `vs`.
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, hash)
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x40, r)
mstore(0x60, shr(1, shl(1, vs))) // `s`.
result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if iszero(returndatasize()) {
mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
revert(0x1c, 0x04)
}
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Recovers the signer's address from a message digest `hash`,
/// and the signature defined by `v`, `r`, `s`.
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, hash)
mstore(0x20, and(v, 0xff))
mstore(0x40, r)
mstore(0x60, s)
result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if iszero(returndatasize()) {
mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
revert(0x1c, 0x04)
}
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* TRY-RECOVER OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// WARNING!
// These functions will NOT revert upon recovery failure.
// Instead, they will return the zero address upon recovery failure.
// It is critical that the returned address is NEVER compared against
// a zero address (e.g. an uninitialized address variable).
/// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
function tryRecover(bytes32 hash, bytes memory signature)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
for { let m := mload(0x40) } 1 {} {
switch mload(signature)
case 64 {
let vs := mload(add(signature, 0x40))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
}
case 65 {
mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
mstore(0x60, mload(add(signature, 0x40))) // `s`.
}
default { break }
mstore(0x00, hash)
mstore(0x40, mload(add(signature, 0x20))) // `r`.
pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20))
mstore(0x60, 0) // Restore the zero slot.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
result := mload(xor(0x60, returndatasize()))
mstore(0x40, m) // Restore the free memory pointer.
break
}
}
}
/// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
function tryRecoverCalldata(bytes32 hash, bytes calldata signature)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
for { let m := mload(0x40) } 1 {} {
switch signature.length
case 64 {
let vs := calldataload(add(signature.offset, 0x20))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x40, calldataload(signature.offset)) // `r`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
}
case 65 {
mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.
}
default { break }
mstore(0x00, hash)
pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20))
mstore(0x60, 0) // Restore the zero slot.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
result := mload(xor(0x60, returndatasize()))
mstore(0x40, m) // Restore the free memory pointer.
break
}
}
}
/// @dev Recovers the signer's address from a message digest `hash`,
/// and the EIP-2098 short form signature defined by `r` and `vs`.
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, hash)
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x40, r)
mstore(0x60, shr(1, shl(1, vs))) // `s`.
pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20))
mstore(0x60, 0) // Restore the zero slot.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
result := mload(xor(0x60, returndatasize()))
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Recovers the signer's address from a message digest `hash`,
/// and the signature defined by `v`, `r`, `s`.
function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, hash)
mstore(0x20, and(v, 0xff))
mstore(0x40, r)
mstore(0x60, s)
pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20))
mstore(0x60, 0) // Restore the zero slot.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
result := mload(xor(0x60, returndatasize()))
mstore(0x40, m) // Restore the free memory pointer.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* HASHING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns an Ethereum Signed Message, created from a `hash`.
/// This produces a hash corresponding to the one signed with the
/// [`eth_sign`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign)
/// JSON-RPC method as part of EIP-191.
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x20, hash) // Store into scratch space for keccak256.
mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes.
result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`.
}
}
/// @dev Returns an Ethereum Signed Message, created from `s`.
/// This produces a hash corresponding to the one signed with the
/// [`eth_sign`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign)
/// JSON-RPC method as part of EIP-191.
/// Note: Supports lengths of `s` up to 999999 bytes.
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let sLength := mload(s)
let o := 0x20
mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded.
mstore(0x00, 0x00)
// Convert the `s.length` to ASCII decimal representation: `base10(s.length)`.
for { let temp := sLength } 1 {} {
o := sub(o, 1)
mstore8(o, add(48, mod(temp, 10)))
temp := div(temp, 10)
if iszero(temp) { break }
}
let n := sub(0x3a, o) // Header length: `26 + 32 - o`.
// Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes.
returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20))
mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header.
result := keccak256(add(s, sub(0x20, n)), add(n, sLength))
mstore(s, sLength) // Restore the length.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CANONICAL HASH FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// The following functions return the hash of the signature in its canonicalized format,
// which is the 65-byte `abi.encodePacked(r, s, uint8(v))`, where `v` is either 27 or 28.
// If `s` is greater than `N / 2` then it will be converted to `N - s`
// and the `v` value will be flipped.
// If the signature has an invalid length, or if `v` is invalid,
// a uniquely corrupt hash will be returned.
// These functions are useful for "poor-mans-VRF".
/// @dev Returns the canonical hash of `signature`.
function canonicalHash(bytes memory signature) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let l := mload(signature)
for {} 1 {} {
mstore(0x00, mload(add(signature, 0x20))) // `r`.
let s := mload(add(signature, 0x40))
let v := mload(add(signature, 0x41))
if eq(l, 64) {
v := add(shr(255, s), 27)
s := shr(1, shl(1, s))
}
if iszero(lt(s, _HALF_N_PLUS_1)) {
v := xor(v, 7)
s := sub(N, s)
}
mstore(0x21, v)
mstore(0x20, s)
result := keccak256(0x00, 0x41)
mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
break
}
// If the length is neither 64 nor 65, return a uniquely corrupted hash.
if iszero(lt(sub(l, 64), 2)) {
// `bytes4(keccak256("InvalidSignatureLength"))`.
result := xor(keccak256(add(signature, 0x20), l), 0xd62f1ab2)
}
}
}
/// @dev Returns the canonical hash of `signature`.
function canonicalHashCalldata(bytes calldata signature)
internal
pure
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
for {} 1 {} {
mstore(0x00, calldataload(signature.offset)) // `r`.
let s := calldataload(add(signature.offset, 0x20))
let v := calldataload(add(signature.offset, 0x21))
if eq(signature.length, 64) {
v := add(shr(255, s), 27)
s := shr(1, shl(1, s))
}
if iszero(lt(s, _HALF_N_PLUS_1)) {
v := xor(v, 7)
s := sub(N, s)
}
mstore(0x21, v)
mstore(0x20, s)
result := keccak256(0x00, 0x41)
mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
break
}
// If the length is neither 64 nor 65, return a uniquely corrupted hash.
if iszero(lt(sub(signature.length, 64), 2)) {
calldatacopy(mload(0x40), signature.offset, signature.length)
// `bytes4(keccak256("InvalidSignatureLength"))`.
result := xor(keccak256(mload(0x40), signature.length), 0xd62f1ab2)
}
}
}
/// @dev Returns the canonical hash of `signature`.
function canonicalHash(bytes32 r, bytes32 vs) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, r) // `r`.
let v := add(shr(255, vs), 27)
let s := shr(1, shl(1, vs))
mstore(0x21, v)
mstore(0x20, s)
result := keccak256(0x00, 0x41)
mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
}
}
/// @dev Returns the canonical hash of `signature`.
function canonicalHash(uint8 v, bytes32 r, bytes32 s) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, r) // `r`.
if iszero(lt(s, _HALF_N_PLUS_1)) {
v := xor(v, 7)
s := sub(N, s)
}
mstore(0x21, v)
mstore(0x20, s)
result := keccak256(0x00, 0x41)
mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EMPTY CALLDATA HELPERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns an empty calldata bytes.
function emptySignature() internal pure returns (bytes calldata signature) {
/// @solidity memory-safe-assembly
assembly {
signature.length := 0
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Contract for EIP-712 typed structured data hashing and signing.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EIP712.sol)
/// @author Modified from Solbase (https://github.com/Sol-DAO/solbase/blob/main/src/utils/EIP712.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/EIP712.sol)
///
/// @dev Note, this implementation:
/// - Uses `address(this)` for the `verifyingContract` field.
/// - Does NOT use the optional EIP-712 salt.
/// - Does NOT use any EIP-712 extensions.
/// This is for simplicity and to save gas.
/// If you need to customize, please fork / modify accordingly.
abstract contract EIP712 {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS AND IMMUTABLES */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`.
bytes32 internal constant _DOMAIN_TYPEHASH =
0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;
/// @dev `keccak256("EIP712Domain(string name,string version,address verifyingContract)")`.
/// This is only used in `_hashTypedDataSansChainId`.
bytes32 internal constant _DOMAIN_TYPEHASH_SANS_CHAIN_ID =
0x91ab3d17e3a50a9d89e63fd30b92be7f5336b03b287bb946787a83a9d62a2766;
/// @dev `keccak256("EIP712Domain(string name,string version)")`.
/// This is only used in `_hashTypedDataSansChainIdAndVerifyingContract`.
bytes32 internal constant _DOMAIN_TYPEHASH_SANS_CHAIN_ID_AND_VERIFYING_CONTRACT =
0xb03948446334eb9b2196d5eb166f69b9d49403eb4a12f36de8d3f9f3cb8e15c3;
/// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId)")`.
/// This is only used in `_hashTypedDataSansVerifyingContract`.
bytes32 internal constant _DOMAIN_TYPEHASH_SANS_VERIFYING_CONTRACT =
0xc2f8787176b8ac6bf7215b4adcc1e069bf4ab82d9ab1df05a57a91d425935b6e;
uint256 private immutable _cachedThis;
uint256 private immutable _cachedChainId;
bytes32 private immutable _cachedNameHash;
bytes32 private immutable _cachedVersionHash;
bytes32 private immutable _cachedDomainSeparator;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTRUCTOR */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Cache the hashes for cheaper runtime gas costs.
/// In the case of upgradeable contracts (i.e. proxies),
/// or if the chain id changes due to a hard fork,
/// the domain separator will be seamlessly calculated on-the-fly.
constructor() {
_cachedThis = uint256(uint160(address(this)));
_cachedChainId = block.chainid;
string memory name;
string memory version;
if (!_domainNameAndVersionMayChange()) (name, version) = _domainNameAndVersion();
bytes32 nameHash = _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(name));
bytes32 versionHash =
_domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(version));
_cachedNameHash = nameHash;
_cachedVersionHash = versionHash;
bytes32 separator;
if (!_domainNameAndVersionMayChange()) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Load the free memory pointer.
mstore(m, _DOMAIN_TYPEHASH)
mstore(add(m, 0x20), nameHash)
mstore(add(m, 0x40), versionHash)
mstore(add(m, 0x60), chainid())
mstore(add(m, 0x80), address())
separator := keccak256(m, 0xa0)
}
}
_cachedDomainSeparator = separator;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* FUNCTIONS TO OVERRIDE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Please override this function to return the domain name and version.
/// ```
/// function _domainNameAndVersion()
/// internal
/// pure
/// virtual
/// returns (string memory name, string memory version)
/// {
/// name = "Solady";
/// version = "1";
/// }
/// ```
///
/// Note: If the returned result may change after the contract has been deployed,
/// you must override `_domainNameAndVersionMayChange()` to return true.
function _domainNameAndVersion()
internal
view
virtual
returns (string memory name, string memory version);
/// @dev Returns if `_domainNameAndVersion()` may change
/// after the contract has been deployed (i.e. after the constructor).
/// Default: false.
function _domainNameAndVersionMayChange() internal pure virtual returns (bool result) {}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* HASHING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the EIP-712 domain separator.
function _domainSeparator() internal view virtual returns (bytes32 separator) {
if (_domainNameAndVersionMayChange()) {
separator = _buildDomainSeparator();
} else {
separator = _cachedDomainSeparator;
if (_cachedDomainSeparatorInvalidated()) separator = _buildDomainSeparator();
}
}
/// @dev Returns the hash of the fully encoded EIP-712 message for this domain,
/// given `structHash`, as defined in
/// https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct.
///
/// The hash can be used together with {ECDSA-recover} to obtain the signer of a message:
/// ```
/// bytes32 digest = _hashTypedData(keccak256(abi.encode(
/// keccak256("Mail(address to,string contents)"),
/// mailTo,
/// keccak256(bytes(mailContents))
/// )));
/// address signer = ECDSA.recover(digest, signature);
/// ```
function _hashTypedData(bytes32 structHash) internal view virtual returns (bytes32 digest) {
// We will use `digest` to store the domain separator to save a bit of gas.
if (_domainNameAndVersionMayChange()) {
digest = _buildDomainSeparator();
} else {
digest = _cachedDomainSeparator;
if (_cachedDomainSeparatorInvalidated()) digest = _buildDomainSeparator();
}
/// @solidity memory-safe-assembly
assembly {
// Compute the digest.
mstore(0x00, 0x1901000000000000) // Store "\x19\x01".
mstore(0x1a, digest) // Store the domain separator.
mstore(0x3a, structHash) // Store the struct hash.
digest := keccak256(0x18, 0x42)
// Restore the part of the free memory slot that was overwritten.
mstore(0x3a, 0)
}
}
/// @dev Variant of `_hashTypedData` that excludes the chain ID.
/// Included for the niche use case of cross-chain workflows.
function _hashTypedDataSansChainId(bytes32 structHash)
internal
view
virtual
returns (bytes32 digest)
{
(string memory name, string memory version) = _domainNameAndVersion();
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Load the free memory pointer.
mstore(0x00, _DOMAIN_TYPEHASH_SANS_CHAIN_ID)
mstore(0x20, keccak256(add(name, 0x20), mload(name)))
mstore(0x40, keccak256(add(version, 0x20), mload(version)))
mstore(0x60, address())
// Compute the digest.
mstore(0x20, keccak256(0x00, 0x80)) // Store the domain separator.
mstore(0x00, 0x1901) // Store "\x19\x01".
mstore(0x40, structHash) // Store the struct hash.
digest := keccak256(0x1e, 0x42)
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero pointer.
}
}
/// @dev Variant of `_hashTypedData` that excludes the chain ID and verifying contract.
/// Included for the niche use case of cross-chain and multi-verifier workflows.
function _hashTypedDataSansChainIdAndVerifyingContract(bytes32 structHash)
internal
view
virtual
returns (bytes32 digest)
{
(string memory name, string memory version) = _domainNameAndVersion();
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Load the free memory pointer.
mstore(0x00, _DOMAIN_TYPEHASH_SANS_CHAIN_ID_AND_VERIFYING_CONTRACT)
mstore(0x20, keccak256(add(name, 0x20), mload(name)))
mstore(0x40, keccak256(add(version, 0x20), mload(version)))
// Compute the digest.
mstore(0x20, keccak256(0x00, 0x60)) // Store the domain separator.
mstore(0x00, 0x1901) // Store "\x19\x01".
mstore(0x40, structHash) // Store the struct hash.
digest := keccak256(0x1e, 0x42)
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero pointer.
}
}
/// @dev Variant of `_hashTypedData` that excludes the chain ID and verifying contract.
/// Included for the niche use case of multi-verifier workflows.
function _hashTypedDataSansVerifyingContract(bytes32 structHash)
internal
view
virtual
returns (bytes32 digest)
{
(string memory name, string memory version) = _domainNameAndVersion();
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Load the free memory pointer.
mstore(0x00, _DOMAIN_TYPEHASH_SANS_VERIFYING_CONTRACT)
mstore(0x20, keccak256(add(name, 0x20), mload(name)))
mstore(0x40, keccak256(add(version, 0x20), mload(version)))
mstore(0x60, chainid())
// Compute the digest.
mstore(0x20, keccak256(0x00, 0x80)) // Store the domain separator.
mstore(0x00, 0x1901) // Store "\x19\x01".
mstore(0x40, structHash) // Store the struct hash.
digest := keccak256(0x1e, 0x42)
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero pointer.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EIP-5267 OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev See: https://eips.ethereum.org/EIPS/eip-5267
function eip712Domain()
public
view
virtual
returns (
bytes1 fields,
string memory name,
string memory version,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
)
{
fields = hex"0f"; // `0b01111`.
(name, version) = _domainNameAndVersion();
chainId = block.chainid;
verifyingContract = address(this);
salt = salt; // `bytes32(0)`.
extensions = extensions; // `new uint256[](0)`.
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PRIVATE HELPERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the EIP-712 domain separator.
function _buildDomainSeparator() private view returns (bytes32 separator) {
// We will use `separator` to store the name hash to save a bit of gas.
bytes32 versionHash;
if (_domainNameAndVersionMayChange()) {
(string memory name, string memory version) = _domainNameAndVersion();
separator = keccak256(bytes(name));
versionHash = keccak256(bytes(version));
} else {
separator = _cachedNameHash;
versionHash = _cachedVersionHash;
}
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Load the free memory pointer.
mstore(m, _DOMAIN_TYPEHASH)
mstore(add(m, 0x20), separator) // Name hash.
mstore(add(m, 0x40), versionHash)
mstore(add(m, 0x60), chainid())
mstore(add(m, 0x80), address())
separator := keccak256(m, 0xa0)
}
}
/// @dev Returns if the cached domain separator has been invalidated.
function _cachedDomainSeparatorInvalidated() private view returns (bool result) {
uint256 cachedChainId = _cachedChainId;
uint256 cachedThis = _cachedThis;
/// @solidity memory-safe-assembly
assembly {
result := iszero(and(eq(chainid(), cachedChainId), eq(address(), cachedThis)))
}
}
}{
"evmVersion": "paris",
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 100
},
"remappings": [],
"viaIR": true,
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_endpoint","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"uint16","name":"_maxFillsPerSettle","type":"uint16"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"InvalidDelegate","type":"error"},{"inputs":[],"name":"InvalidEndpointCall","type":"error"},{"inputs":[],"name":"LzTokenUnavailable","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"NoPeer","type":"error"},{"inputs":[{"internalType":"uint256","name":"msgValue","type":"uint256"}],"name":"NotEnoughNative","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"OnlyEndpoint","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"}],"name":"OnlyPeer","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orderId","type":"bytes32"}],"name":"Cancel","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orderId","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"nonce","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"CancelSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"eid","type":"uint32"}],"name":"ChainRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"eid","type":"uint32"}],"name":"ChainSupported","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orderId","type":"bytes32"},{"components":[{"internalType":"uint128","name":"inputAmount","type":"uint128"},{"internalType":"uint128","name":"outputAmount","type":"uint128"},{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"indexed":false,"internalType":"struct IAori.Order","name":"order","type":"tuple"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orderId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"preferredToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountReceived","type":"uint256"}],"name":"DstHookExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orderId","type":"bytes32"},{"components":[{"internalType":"uint128","name":"inputAmount","type":"uint128"},{"internalType":"uint128","name":"outputAmount","type":"uint128"},{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"indexed":false,"internalType":"struct IAori.Order","name":"order","type":"tuple"}],"name":"Fill","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"eid","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"peer","type":"bytes32"}],"name":"PeerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orderId","type":"bytes32"}],"name":"Settle","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"srcEid","type":"uint32"},{"indexed":true,"internalType":"address","name":"filler","type":"address"},{"indexed":false,"internalType":"bytes","name":"payload","type":"bytes"},{"indexed":false,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"nonce","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"SettleSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orderId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"preferredToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountReceived","type":"uint256"}],"name":"SrcHookExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"holder","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orderId","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"expectedEid","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"submittedEid","type":"uint32"},{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"settlementFailed","type":"event"},{"inputs":[],"name":"ENDPOINT_ID","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FILLS_PER_SETTLE","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"hook","type":"address"}],"name":"addAllowedHook","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"solver","type":"address"}],"name":"addAllowedSolver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"addSupportedChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32[]","name":"eids","type":"uint32[]"}],"name":"addSupportedChains","outputs":[{"internalType":"bool[]","name":"results","type":"bool[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"}],"name":"allowInitializePath","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderId","type":"bytes32"},{"components":[{"internalType":"uint128","name":"inputAmount","type":"uint128"},{"internalType":"uint128","name":"outputAmount","type":"uint128"},{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct IAori.Order","name":"orderToCancel","type":"tuple"},{"internalType":"bytes","name":"extraOptions","type":"bytes"}],"name":"cancel","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderId","type":"bytes32"}],"name":"cancel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"inputAmount","type":"uint128"},{"internalType":"uint128","name":"outputAmount","type":"uint128"},{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct IAori.Order","name":"order","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"components":[{"internalType":"address","name":"hookAddress","type":"address"},{"internalType":"address","name":"preferredToken","type":"address"},{"internalType":"uint256","name":"minPreferedTokenAmountOut","type":"uint256"},{"internalType":"bytes","name":"instructions","type":"bytes"}],"internalType":"struct IAori.SrcHook","name":"hook","type":"tuple"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"inputAmount","type":"uint128"},{"internalType":"uint128","name":"outputAmount","type":"uint128"},{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct IAori.Order","name":"order","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"inputAmount","type":"uint128"},{"internalType":"uint128","name":"outputAmount","type":"uint128"},{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct IAori.Order","name":"order","type":"tuple"}],"name":"depositNative","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderId","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"}],"name":"emergencyCancel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"bool","name":"isLocked","type":"bool"},{"internalType":"address","name":"recipient","type":"address"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"endpoint","outputs":[{"internalType":"contract ILayerZeroEndpointV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"inputAmount","type":"uint128"},{"internalType":"uint128","name":"outputAmount","type":"uint128"},{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct IAori.Order","name":"order","type":"tuple"}],"name":"fill","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"inputAmount","type":"uint128"},{"internalType":"uint128","name":"outputAmount","type":"uint128"},{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct IAori.Order","name":"order","type":"tuple"},{"components":[{"internalType":"address","name":"hookAddress","type":"address"},{"internalType":"address","name":"preferredToken","type":"address"},{"internalType":"bytes","name":"instructions","type":"bytes"},{"internalType":"uint256","name":"preferedDstInputAmount","type":"uint256"}],"internalType":"struct IAori.DstHook","name":"hook","type":"tuple"}],"name":"fill","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"token","type":"address"}],"name":"getLockedBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"token","type":"address"}],"name":"getUnlockedBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"inputAmount","type":"uint128"},{"internalType":"uint128","name":"outputAmount","type":"uint128"},{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct IAori.Order","name":"order","type":"tuple"}],"name":"hash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isAllowedHook","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isAllowedSolver","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"","type":"tuple"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"address","name":"_sender","type":"address"}],"name":"isComposeMsgSender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"isSupportedChain","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"_origin","type":"tuple"},{"internalType":"bytes32","name":"_guid","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"nextNonce","outputs":[{"internalType":"uint64","name":"nonce","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oAppVersion","outputs":[{"internalType":"uint64","name":"senderVersion","type":"uint64"},{"internalType":"uint64","name":"receiverVersion","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"orderStatus","outputs":[{"internalType":"enum IAori.OrderStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"orders","outputs":[{"internalType":"uint128","name":"inputAmount","type":"uint128"},{"internalType":"uint128","name":"outputAmount","type":"uint128"},{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"peers","outputs":[{"internalType":"bytes32","name":"peer","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstEid","type":"uint32"},{"internalType":"uint8","name":"_msgType","type":"uint8"},{"internalType":"bytes","name":"_options","type":"bytes"},{"internalType":"bool","name":"_payInLzToken","type":"bool"},{"internalType":"uint32","name":"_srcEid","type":"uint32"},{"internalType":"address","name":"_filler","type":"address"}],"name":"quote","outputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"hook","type":"address"}],"name":"removeAllowedHook","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"solver","type":"address"}],"name":"removeAllowedSolver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"removeSupportedChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_delegate","type":"address"}],"name":"setDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"setPeer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"address","name":"filler","type":"address"},{"internalType":"bytes","name":"extraOptions","type":"bytes"}],"name":"settle","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"srcEidToFillerFills","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
61018080604052346102a6576000608082615ca9803803809161002282856102ab565b8339810103126102a357610035826102e4565b91610042602082016102e4565b604082015163ffffffff8116928382036102a157606001519161ffff831683036102a1576001600160a01b0316801561028d5784546001600160a01b0319811682178655604051969082906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08880a36001600160a01b0316608081905290813b1561028957602487878094829463ca5eb5e160e01b845260048401525af194851561027e5760409561026a575b5060016002553060a0524660c05260a085519461011587876102ab565b60048652602086019563416f726960e01b875287519661013589896102ab565b60058852602088019164302e332e3160d81b835251902091965190208160e05280610100528751917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8352602083015287820152466060820152306080820152206101205261014052610160528152600660205220600160ff198254161790556040516159b090816102f9823960805181818161054001528181610fb801528181611cfd01528181612f9c015281816139050152615013015260a05181505060c05181505060e05181505061010051815050610120518150506101405181818161074d0152818161098d01528181610dfd015281816110cc015281816115390152818161170b015281816118be01528181611ca90152611ef30152610160518181816108ce01528181610c910152612f0a0152f35b84610277919592956102ab565b92386100f8565b6040513d86823e3d90fd5b8580fd5b631e4fbdf760e01b85526004859052602485fd5b845b80fd5b600080fd5b601f909101601f19168101906001600160401b038211908210176102ce57604052565b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036102a65756fe6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c806305ef94ba1461030b5780630c89a13d1461030657806313137d651461030157806317442b70146102fc5780631c0166aa146102f75780631e2c273e146102f25780632c85455b146102ed5780632cee9acd146102e85780632d7c615a146102e35780632dff692d146102de5780633400288b146102d9578063344ba6fd146102d45780633f4ba83a146102cf57806344ae20c3146102ca57806350964586146102c5578063555c3898146102c0578063595490c8146102bb57806359f429a4146102b65780635c975abb146102b15780635e280f11146102ac5780636b624fdb146102a7578063715018a6146102a25780637ce5e33e1461029d5780637d25a05e146102985780637de637341461029357806382413eac1461028e5780638456cb591461028957806384b0196e146102845780638da5cb5b1461027f57806395ccea671461027a578063983f7fd114610275578063996628a0146102705780639c3f1e901461026b578063a9a683ba14610266578063b410f12214610261578063b8f480c61461025c578063bb0b6a5314610257578063c15c4b3714610252578063c4d252f51461024d578063ca5eb5e114610248578063cd77488714610243578063e86dfbbf1461023e578063e898841f14610239578063edb25d8114610234578063f2fde38b1461022f578063f3fef3a31461022a5763ff7bd03d0361000e576121df565b6120f5565b612068565b61201f565b611e56565b611e0e565b611d80565b611cd3565b611b4e565b611ae6565b611aab565b611a3f565b6119d6565b611854565b61175d565b611647565b6114b0565b6113fd565b6113d4565b611333565b611298565b61123a565b6111f8565b6111d1565b611086565b61102d565b610fe7565b610fa2565b610f7f565b610f3f565b610ef6565b610d2e565b610cb5565b610c76565b610c0d565b610bcb565b610b5c565b610b24565b6109bb565b610970565b6107e5565b61079f565b61061d565b6105d7565b6104d4565b61040a565b61035b565b6001600160a01b0381160361032157565b600080fd5b359061033182610310565b565b60409060031901126103215760043561034b81610310565b9060243561035881610310565b90565b3461032157602061036b36610333565b6001600160a01b039182166000908152600484526040808220929093168152602091909152206001600160801b03905416604051908152f35b63ffffffff81160361032157565b3590610331826103a4565b6001600160a01b0316600090815260046020526040902090565b634e487b7160e01b600052603260045260246000fd5b80548210156104055760005260206000200190600090565b6103d7565b3461032157606036600319011261032157600435610427816103a4565b61046460243561043681610310565b63ffffffff6044359316600052600a60205260406000209060018060a01b0316600052602052604060002090565b8054821015610321576104929161047a916103ed565b90549060031b1c604051918291829190602083019252565b0390f35b606090600319011261032157600490565b9181601f84011215610321578235916001600160401b038311610321576020838186019501011161032157565b60e0366003190112610321576104e936610496565b6064356084356001600160401b0381116103215761050b9036906004016104a7565b60a4929192359061051b82610310565b60c4356001600160401b0381116103215761053a9036906004016104a7565b949093337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316036105c257863596610579886103a4565b610582886130fc565b97602082013580990361059a57506100199750613130565b63ffffffff816105aa8b936103a4565b63309afaf360e21b6000521660045260245260446000fd5b6391ac5e4f60e01b6000523360045260246000fd5b3461032157600036600319011261032157604080516001815260026020820152f35b61014090600319011261032157600490565b61014090602319011261032157602490565b61014036600319011261032157610795610636366105f9565b61063e613210565b610646613230565b604081019061068161067c61065a84612230565b6001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1490565b61223a565b6106a361069c61069083612297565b6001600160801b031690565b34146122a1565b6106c96106c26106b66101008401612230565b6001600160a01b031690565b33146122e7565b6107836106d582612c60565b926107066106f76106f0866000526007602052604060002090565b5460ff1690565b61070081610b15565b15612342565b6107366107316106f061071b60e08701612226565b63ffffffff166000526006602052604060002090565b612385565b61077561074560c08501612226565b63ffffffff807f0000000000000000000000000000000000000000000000000000000000000000169116146123d1565b61077e8361344d565b612230565b61078f61069083612297565b90613551565b6100196001600255565b34610321576020366003190112610321576004356107bc81610310565b6107c46136a2565b6001600160a01b03166000908152600960205260409020805460ff19169055005b6060366003190112610321576004356107fd816103a4565b60243561080981610310565b604435906001600160401b0382116103215763ffffffff7fd054cd999785d4c556d1f55b27cc59caba458cd5663063989d47725b970092329161095c6108566109279536906004016104a7565b610861969196613210565b610869613230565b33600052600960205261088360ff6040600020541661240e565b6109006108bb856108a48b63ffffffff16600052600a602052604060002090565b9060018060a01b0316600052602052604060002090565b8561ffff82546108cc81151561244b565b7f000000000000000000000000000000000000000000000000000000000000000082168082101561096957505b16916136e2565b9661092061090c6124fe565b913483526000602084015233933691612547565b888a613888565b805190604061094060208301516001600160401b031690565b910151519160405195869560018060a01b03169916978561257e565b0390a36100196001600255565b90506108f9565b3461032157600036600319011261032157602060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b8015150361032157565b346103215760a0366003190112610321576004356109d881610310565b6024359060008051602061595b833981519152610aae604435926109fb84610310565b610a948560643595610a0c876109b1565b8360843591610a1a83610310565b610a226136a2565b610a2d8415156125af565b6001600160a01b03811698610a438a15156125fa565b610a576001600160a01b038516151561263d565b15610ab357610a6f610a84926108a4610a7f936103bd565b6001600160801b03851690613979565b61271c565b610a8e8285613a73565b83613b0e565b6040519485526001600160a01b0316939081906020820190565b0390a3005b610af5826108a4610aef61069088610ade610690610ad7610afa9a6108a48b6103bd565b5460801c90565b610aea82821015612685565b6126e7565b936103bd565b6126f9565b610a84565b634e487b7160e01b600052602160045260246000fd5b60051115610b1f57565b610aff565b3461032157602036600319011261032157600435600052600760205260ff604060002054166040516005821015610b1f576020918152f35b34610321576040366003190112610321577f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b6040600435610b9c816103a4565b63ffffffff60243591610bad6136a2565b169081600052600160205280836000205582519182526020820152a1005b3461032157602036600319011261032157600435610be881610310565b60018060a01b03166000526008602052602060ff604060002054166040519015158152f35b3461032157600036600319011261032157610c266136a2565b60035460ff811615610c655760ff19166003557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b638dfc202b60e01b60005260046000fd5b3461032157600036600319011261032157602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346103215760203660031901126103215763ffffffff600435610cd7816103a4565b610cdf6136a2565b168060005260066020526040600020600160ff198254161790557fa7dbeb6ef5cb64125bfb03ac211f1aea3f639de95ceb37b16706d4f0735d1863600080a2005b908160809103126103215790565b346103215761018036600319011261032157610d49366105f9565b610144356001600160401b03811161032157610d699036906004016104a7565b90610164356001600160401b03811161032157610e2a91610d91610e23923690600401610d20565b93610d9a613210565b610da2613230565b336000526009602052610dbc60ff6040600020541661240e565b610ddc610dd7610dd3604089013561065a81610310565b1590565b612772565b610ded610de886613bd5565b6127ca565b610df686613bed565b91309230927f00000000000000000000000000000000000000000000000000000000000000009289613d8f565b9183613f4f565b604051828152909391906001600160a01b0385169084907f86d7c80bc9d060acd32be0a39bbd97538a0e7b1f748c30d4e87b186b1d3589bb90602090a3610e7082614138565b15610ee85750819250610e90610e95926000526005602052604060002090565b612805565b610eb9610eac826000526007602052604060002090565b805460ff19166004179055565b7fe82916be8cebf4000a0d08979cca286e4bfe07a019f19c0c930305aceacdcaf6600080a26100196001600255565b610ef193613551565b610795565b3461032157602036600319011261032157600435610f1381610310565b610f1b6136a2565b6001600160a01b03166000908152600960205260409020805460ff19166001179055005b346103215760203660031901126103215763ffffffff600435610f61816103a4565b166000526006602052602060ff604060002054166040519015158152f35b3461032157600036600319011261032157602060ff600354166040519015158152f35b34610321576000366003190112610321576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346103215760203660031901126103215760043561100481610310565b61100c6136a2565b6001600160a01b03166000908152600860205260409020805460ff19169055005b34610321576000366003190112610321576110466136a2565b600080546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b6101403660031901126103215761109c366105f9565b6110a4613210565b6110ac613230565b3360005260096020526110c660ff6040600020541661240e565b6110f1307f0000000000000000000000000000000000000000000000000000000000000000836141a0565b90606081019161110361065a84612230565b156111c25761112161111a61069060208501612297565b3414612a28565b8161112b81614138565b156111b457506111479033906111413685612a7f565b906143c0565b61115361065a83612230565b156111875761116461079592612230565b90611181610690602061117a6101208501612230565b9301612297565b91613b0e565b6111966106b6610ef193612230565b906111ac610690602061117a6101208501612230565b913390614613565b6111bd916142c8565b611147565b6111cc34156129c4565b611121565b34610321576040366003190112610321576111ed6004356103a4565b602060405160008152f35b346103215760203660031901126103215760043561121581610310565b60018060a01b03166000526009602052602060ff604060002054166040519015158152f35b346103215760a03660031901126103215761125436610496565b506064356001600160401b038111610321576112749036906004016104a7565b5050602060843561128481610310565b6040516001600160a01b0390911630148152f35b34610321576000366003190112610321576112b16136a2565b6112b9613230565b600160ff1960035416176003557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b919082519283825260005b84811061131e575050826000602080949584010152601f8019910116010190565b806020809284010151828286010152016112fd565b3461032157600036600319011261032157611373611381611352614657565b604092919251938493600f60f81b855260e0602086015260e08501906112f2565b9083820360408501526112f2565b466060830152306080830152600060a083015281810360c0830152602060605191828152019060809060005b8181106113bb575050500390f35b82518452859450602093840193909201916001016113ad565b34610321576000366003190112610321576000546040516001600160a01b039091168152602090f35b346103215760403660031901126103215760043561141a81610310565b6024356114256136a2565b478061144b575b508061143457005b60005461001992906001600160a01b031690613b0e565b60008080809360018060a01b038254165af1611465612b3e565b5015611471573861142c565b60405162461bcd60e51b8152602060048201526017602482015276115d1a195c881dda5d1a191c985dd85b0819985a5b1959604a1b6044820152606490fd5b610180366003190112610321576004356114c93661060b565b610164356001600160401b038111610321576114e99036906004016104a7565b6114f4929192613210565b6114fc613230565b8361150683612c60565b036115ef577f8168c9ac1d18802efe1afee0a6bf2de2b35d9f041a5b42a072b06252ba84fe509261159d9261155f3033307f00000000000000000000000000000000000000000000000000000000000000008a86614763565b611583611576876000526007602052604060002090565b805460ff19166003179055565b61159860c0611591886148ce565b9201612226565b6148f0565b80516115e260406115b860208501516001600160401b031690565b93015151604051938493846001600160401b03604092959493606083019683521660208201520152565b0390a26100196001600255565b60405162461bcd60e51b815260206004820152602a60248201527f5375626d6974746564206f72646572206461746120646f65736e2774206d617460448201526918da081bdc99195c925960b21b6064820152608490fd5b346103215761016036600319011261032157611662366105f9565b610144356001600160401b03811161032157610795916116896107839236906004016104a7565b611694939193613210565b61169c613230565b3360005260096020526116b660ff6040600020541661240e565b61077e60408401916117376117318435976116d089610310565b6001600160a01b038916936116fb73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee861415612772565b61170489613bed565b91309230927f0000000000000000000000000000000000000000000000000000000000000000928c613d8f565b96610310565b6101008501359061174782610310565b611755863561069081612286565b913091614613565b346103215760203660031901126103215760043560005260056020526040600020805461049260018060a01b036001840154166002840154936117a08560e01c90565b6003820154906117d460046117c563ffffffff85169460201c6001600160a01b031690565b9401546001600160a01b031690565b604080516001600160801b0389168152608098891c60208201526001600160a01b0396871691810191909152858916606082015260a089811c63ffffffff9081169983019990995260c0998a1c89169082015291871697820197909752941660e08501528116610100840152909216610120820152908190610140820190565b6101603660031901126103215761186a366105f9565b610144356001600160401b0381116103215761188a903690600401610d20565b90611893613210565b61189b613230565b3360005260096020526118b560ff6040600020541661240e565b61199f6118e3307f0000000000000000000000000000000000000000000000000000000000000000846141a0565b916118ee8482614928565b936001600160a01b039061190490602001612230565b16837fd6fb3db9629fef5e875e0d0138b2fb4ae60575aba13837c23c1c9a6aa1e35bac6040518061193a89829190602083019252565b0390a3611957602082019461195161069087612297565b906126e7565b928161196281614138565b156119c857506119789033906111413685612a7f565b606081019361118161069061199961012061199289612230565b9501612230565b92612297565b806119ae576100196001600255565b6119c1916119bc3391612230565b613b0e565b3880610795565b6119d1916142c8565b611978565b34610321576101403660031901126103215760206119fb6119f6366105f9565b612c60565b604051908152f35b602060408183019282815284518094520192019060005b818110611a275750505090565b82511515845260209384019390920191600101611a1a565b34610321576020366003190112610321576004356001600160401b0381116103215736602382011215610321578060040135906001600160401b038211610321573660248360051b8301011161032157610492916024611a9f9201612c89565b60405191829182611a03565b346103215760203660031901126103215763ffffffff600435611acd816103a4565b1660005260016020526020604060002054604051908152f35b346103215760203660031901126103215763ffffffff600435611b08816103a4565b611b106136a2565b16806000526006602052604060002060ff1981541690557f79df5d328757ca456e42d3dc087c02eedd4cf61d984a6aa526cfac31f1542dcd600080a2005b3461032157602036600319011261032157610795600435611b6d613210565b611b75613230565b806000526005602052611cce6040600020611ca0611c8f6004611b9661250d565b84546001600160801b0381168252909490611bc690611bb6905b60801c90565b6001600160801b03166020870152565b6001810154611be9906001600160a01b03165b6001600160a01b03166040870152565b60028101546001600160a01b0381166060870152611c3990611c2c9063ffffffff60a082901c16608089015263ffffffff60c082901c1660a08901525b60e01c90565b63ffffffff1660c0870152565b611c81611c706003830154611c61611c548263ffffffff1690565b63ffffffff1660e08a0152565b60201c6001600160a01b031690565b6001600160a01b0316610100870152565b01546001600160a01b031690565b6001600160a01b0316610120830152565b309033903090857f000000000000000000000000000000000000000000000000000000000000000091614d00565b614e41565b346103215760006020366003190112611d7d5780600435611cf381610310565b611cfb6136a2565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803b15611d795760405163ca5eb5e160e01b81526001600160a01b0390921660048301529091908290602490829084905af18015611d74578290611d665780f35b611d6f916124dd565b388180f35b612e85565b5050fd5b80fd5b346103215760c036600319011261032157600435611d9d816103a4565b6024359060ff8216820361032157604435906001600160401b0382116103215761049292611dd2611dfe9336906004016104a7565b60643591611ddf836109b1565b60843593611dec856103a4565b60a43595611df987610310565b612ec3565b6040519081529081906020820190565b34610321576020611e4a611e2136610333565b6001600160a01b0391821660009081526004855260408082209290931681526020919091522090565b5460801c604051908152f35b3461032157604036600319011261032157600435602435611e7681610310565b611e7e6136a2565b611e92826000526007602052604060002090565b5460ff16611e9f81610b15565b600114611eab90613006565b6001600160a01b03811690611ec182151561263d565b611ed5836000526005602052604060002090565b611ede90612d9b565b9260c0840151611ef19063ffffffff1690565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff169063ffffffff1614611f2990613052565b604084015184516001600160801b0316946001600160a01b039091169290859081908590611f578383613a73565b611f6b866000526007602052604060002090565b805460ff1916600317905561010001516001600160a01b0316611f8d906103bd565b6001600160a01b0390911660009081526020919091526040902090611fb191613979565b611fba9061271c565b611fc49184613b0e565b6040519182917fe8d9861dbc9c663ed3accd261bbe2fe01e0d3d9e5f51fa38523b265c7757a93a600080a26001600160801b039490941690526001600160a01b039092169160008051602061595b83398151915290602090a3005b346103215760203660031901126103215760043561203c81610310565b6120446136a2565b6001600160a01b03166000908152600860205260409020805460ff19166001179055005b346103215760203660031901126103215760043561208581610310565b61208d6136a2565b6001600160a01b031680156120df57600080546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b631e4fbdf760e01b600052600060045260246000fd5b346103215760403660031901126103215760043561211281610310565b60243561211d613210565b612125613230565b80336000526004602052612152610ad78460406000209060018060a01b0316600052602052604060002090565b9161215e8315156130b4565b806121c257505061218961217c6106908380945b610aea8288613a73565b610af5846108a4336103bd565b612194813384613b0e565b6040519081526001600160a01b0390911690339060008051602061595b83398151915290806020810161095c565b61069082846121da61217c9461218996971015612685565b612172565b346103215760603660031901126103215760206121fb36610496565b63ffffffff813561220b816103a4565b16600052600182528160406000205491013560405191148152f35b35610358816103a4565b3561035881610310565b1561224157565b60405162461bcd60e51b815260206004820152601f60248201527f4f72646572206d7573742073706563696679206e617469766520746f6b656e006044820152606490fd5b6001600160801b0381160361032157565b3561035881612286565b156122a857565b60405162461bcd60e51b8152602060048201526017602482015276125b98dbdc9c9958dd081b985d1a5d9948185b5bdd5b9d604a1b6044820152606490fd5b156122ee57565b60405162461bcd60e51b815260206004820152602660248201527f4f6e6c79206f6666657265722063616e206465706f736974206e617469766520604482015265746f6b656e7360d01b6064820152608490fd5b1561234957565b60405162461bcd60e51b81526020600482015260146024820152734f7264657220616c72656164792065786973747360601b6044820152606490fd5b1561238c57565b60405162461bcd60e51b815260206004820152601f60248201527f44657374696e6174696f6e20636861696e206e6f7420737570706f72746564006044820152606490fd5b156123d857565b60405162461bcd60e51b815260206004820152600e60248201526d086d0c2d2dc40dad2e6dac2e8c6d60931b6044820152606490fd5b1561241557565b60405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b7b63b32b960911b6044820152606490fd5b1561245257565b60405162461bcd60e51b8152602060048201526012602482015271139bc81bdc99195c9cc81c1c9bdd9a59195960721b6044820152606490fd5b634e487b7160e01b600052604160045260246000fd5b604081019081106001600160401b038211176124bd57604052565b61248c565b606081019081106001600160401b038211176124bd57604052565b90601f801991011681019081106001600160401b038211176124bd57604052565b604051906103316040836124dd565b60405190610331610140836124dd565b6040519061033160a0836124dd565b6001600160401b0381116124bd57601f01601f191660200190565b9291926125538261252c565b9161256160405193846124dd565b829481845281830111610321578281602093846000960137010152565b9060609295949361259f6001600160401b03926080855260808501906112f2565b9660208401521660408201520152565b156125b657565b606460405162461bcd60e51b815260206004820152602060248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152fd5b1561260157565b60405162461bcd60e51b8152602060048201526014602482015273496e76616c69642075736572206164647265737360601b6044820152606490fd5b1561264457565b60405162461bcd60e51b8152602060048201526019602482015278496e76616c696420726563697069656e74206164647265737360381b6044820152606490fd5b1561268c57565b60405162461bcd60e51b815260206004820152601d60248201527f496e73756666696369656e7420756e6c6f636b65642062616c616e63650000006044820152606490fd5b634e487b7160e01b600052601160045260246000fd5b919082039182116126f457565b6126d1565b80546001600160801b031660809290921b6001600160801b031916919091179055565b1561272357565b60405162461bcd60e51b815260206004820152602160248201527f4661696c656420746f206465637265617365206c6f636b65642062616c616e636044820152606560f81b6064820152608490fd5b1561277957565b60405162461bcd60e51b815260206004820152602360248201527f557365206465706f7369744e617469766520666f72206e617469766520746f6b604482015262656e7360e81b6064820152608490fd5b156127d157565b60405162461bcd60e51b815260206004820152600c60248201526b4d697373696e6720686f6f6b60a01b6044820152606490fd5b60046129a36101206103319461283961281d82612297565b86546001600160801b0319166001600160801b03909116178655565b61284e61284860208301612297565b866126f9565b61288061285d60408301612230565b6001870180546001600160a01b0319166001600160a01b03909216919091179055565b61293c600286016128b261289660608501612230565b82546001600160a01b0319166001600160a01b03909116178255565b6128e16128c160808501612226565b825463ffffffff60a01b191660a09190911b63ffffffff60a01b16178255565b6129106128f060a08501612226565b825463ffffffff60c01b191660c09190911b63ffffffff60c01b16178255565b61291c60c08401612226565b81546001600160e01b031660e09190911b6001600160e01b031916179055565b61299d6003860161296861295260e08501612226565b825463ffffffff191663ffffffff909116178255565b6129756101008401612230565b8154640100000000600160c01b03191660209190911b640100000000600160c01b0316179055565b01612230565b910180546001600160a01b0319166001600160a01b03909216919091179055565b156129cb57565b60405162461bcd60e51b815260206004820152602f60248201527f4e6f206e617469766520746f6b656e732073686f756c642062652073656e742060448201526e666f722045524332302066696c6c7360881b6064820152608490fd5b15612a2f57565b60405162461bcd60e51b815260206004820152601c60248201527f496e636f7272656374206e617469766520616d6f756e742073656e74000000006044820152606490fd5b359061033182612286565b91908261014091031261032157612b36610120612a9a61250d565b93612aa481612a74565b8552612ab260208201612a74565b6020860152612ac360408201610326565b6040860152612ad460608201610326565b6060860152612ae5608082016103b2565b6080860152612af660a082016103b2565b60a0860152612b0760c082016103b2565b60c0860152612b1860e082016103b2565b60e0860152612b2a6101008201610326565b61010086015201610326565b610120830152565b3d15612b69573d90612b4f8261252c565b91612b5d60405193846124dd565b82523d6000602084013e565b606090565b61033190929192610120612c5281610140840196612b9c85612b8f83612a74565b6001600160801b03169052565b612bab611bb660208301612a74565b612bba611bd960408301610326565b612bd9612bc960608301610326565b6001600160a01b03166060870152565b612bf5612be8608083016103b2565b63ffffffff166080870152565b612c11612c0460a083016103b2565b63ffffffff1660a0870152565b612c20611c2c60c083016103b2565b612c3c612c2f60e083016103b2565b63ffffffff1660e0870152565b612c4c611c706101008301610326565b01610326565b6001600160a01b0316910152565b604051612c8381612c75602082019485612b6e565b03601f1981018352826124dd565b51902090565b612c916136a2565b612c9a82612d60565b91612ca860405193846124dd565b808352601f19612cb782612d60565b0136602085013760005b818110612cce5750505090565b8063ffffffff612ce16001938587612d77565b35612ceb816103a4565b16600052600660205260406000208260ff19825416179055612d22612d19612d14838688612d77565b612226565b63ffffffff1690565b7fa7dbeb6ef5cb64125bfb03ac211f1aea3f639de95ceb37b16706d4f0735d1863600080a2612d5a612d548287612d87565b60019052565b01612cc1565b6001600160401b0381116124bd5760051b60200190565b91908110156104055760051b0190565b80518210156104055760209160051b010190565b90610331612e746004612dac61250d565b85546001600160801b0381168252909590612dda90612dca90611bb0565b6001600160801b03166020880152565b60018101546001600160a01b0316604087015260028101546001600160a01b0381166060880152612e3b90612e2e9063ffffffff60a082901c1660808a015263ffffffff60c082901c1660a08a0152611c26565b63ffffffff1660c0880152565b611c81612e636003830154611c61612e568263ffffffff1690565b63ffffffff1660e08b0152565b6001600160a01b0316610100880152565b6001600160a01b0316610120840152565b6040513d6000823e3d90fd5b90612e9b8261252c565b612ea860405191826124dd565b8281528092612eb9601f199161252c565b0190602036910137565b9391612f3c90612f34612f2f612f7d9694612f07612f989b63ffffffff60409c16600052600a6020528b6000209060018060a01b0316600052602052604060002090565b547f000000000000000000000000000000000000000000000000000000000000000091614f0e565b612e91565b923691612547565b90612f45613768565b50612f4f856130fc565b612f66612f5a61251d565b63ffffffff9097168752565b602086015285850152606084015215156080830152565b815180938192631bb8518b60e31b835230906004840161381a565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115611d7457600091612fd957505190565b612ffb915060403d604011612fff575b612ff381836124dd565b810190614f85565b5190565b503d612fe9565b1561300d57565b60405162461bcd60e51b815260206004820152601d60248201527f43616e206f6e6c792063616e63656c20616374697665206f72646572730000006044820152606490fd5b1561305957565b60405162461bcd60e51b815260206004820152602d60248201527f456d657267656e63792063616e63656c206f6e6c7920616c6c6f776564206f6e60448201526c1039b7bab931b29031b430b4b760991b6064820152608490fd5b156130bb57565b60405162461bcd60e51b8152602060048201526019602482015278139bdb8b5e995c9bc818985b185b98d9481c995c5d5a5c9959603a1b6044820152606490fd5b63ffffffff1680600052600160205260406000205490811561311c575090565b63f6ff4fb760e01b60005260045260246000fd5b9350509350915061313f613230565b81156131db573561314f816103a4565b61315982846153fa565b3560f81c6002811015610b1f5761316f816148c4565b6001810361318257505061033191615550565b61318e819392936148c4565b61319b5761033192615403565b60405162461bcd60e51b8152602060048201526018602482015277556e737570706f72746564207061796c6f6164207479706560401b6044820152606490fd5b60405162461bcd60e51b815260206004820152600d60248201526c115b5c1d1e481c185e5b1bd859609a1b6044820152606490fd5b600280541461321f5760028055565b633ee5aeb560e01b60005260046000fd5b60ff6003541661323c57565b63d93c066560e01b60005260046000fd5b1561325457565b60405162461bcd60e51b815260206004820152600f60248201526e24b73b30b634b21037b33332b932b960891b6044820152606490fd5b1561329257565b60405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b6044820152606490fd5b156132d257565b60405162461bcd60e51b815260206004820152601060248201526f496e76616c696420656e642074696d6560801b6044820152606490fd5b1561331157565b60405162461bcd60e51b815260206004820152601160248201527013dc99195c881b9bdd081cdd185c9d1959607a1b6044820152606490fd5b1561335157565b60405162461bcd60e51b815260206004820152601160248201527013dc99195c881a185cc8195e1c1a5c9959607a1b6044820152606490fd5b1561339157565b60405162461bcd60e51b8152602060048201526014602482015273125b9d985b1a59081a5b9c1d5d08185b5bdd5b9d60621b6044820152606490fd5b156133d457565b60405162461bcd60e51b8152602060048201526015602482015274125b9d985b1a59081bdd5d1c1d5d08185b5bdd5b9d605a1b6044820152606490fd5b1561341857565b60405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b2103a37b5b2b760991b6044820152606490fd5b610331906134716001600160a01b036134696101008401612230565b16151561324d565b61348b6134846106b66101208401612230565b151561328b565b6134e5608082016134d26134c36134a183612226565b92612d1460a087019463ffffffff6134bb612d1988612226565b9116106132cb565b63ffffffff429116111561330a565b6134df612d194292612226565b1161334a565b6135016001600160801b036134f983612297565b16151561338a565b61351a61351361069060208401612297565b15156133cd565b6135296106b660408301612230565b15159081613538575b50613411565b613549915060606106b69101612230565b151538613532565b9161369161365e61369d936136597f8e45fa612720ed3142e896a3a29c981f4ca01c25bca19c3a5c203398ee1bc3d79661010086013561359081610310565b6001600160a01b0390811660009081526004602090815260408083209385168352929052206135f2906135d56135c586614f99565b82546001600160801b0316614fcc565b81546001600160801b0319166001600160801b0391909116179055565b8860005260076020526040600020600160ff1982541617905561362386610e908b6000526005602052604060002090565b60016136398a6000526005602052604060002090565b0180546001600160a01b0319166001600160a01b03909216919091179055565b614f99565b613672866000526005602052604060002090565b80546001600160801b0319166001600160801b03909216919091179055565b60405191829182612b6e565b0390a2565b6000546001600160a01b031633036136b657565b63118cdaa760e01b6000523360045260246000fd5b63ffffffff166017019063ffffffff82116126f457565b908260051b621fffe061ffe08216911681036126f457612f2f612d1961370f6137149396949661ffff1690565b6136cb565b928160481b9060581b17602084015281600052602060002093825491820393603781015b838681111561375c57906000602092811901958119908a0101805483525501613738565b50509392915093505590565b60405190613775826124a2565b60006020838281520152565b6040519061378e826124c2565b81600081526000602082015260406137a4613768565b910152565b9190826040910312610321576040516137c1816124a2565b6020808294805184520151910152565b60808183031261032157604051916137e8836124c2565b8151835260208201516001600160401b0381168103610321576020840152613812916040016137a9565b604082015290565b906020909392936040835263ffffffff8151166040840152818101516060840152608061386e613858604084015160a08488015260e08701906112f2565b6060840151868203603f190160a08801526112f2565b910151151560c08401526001600160a01b03909416910152565b6138e560809492613901969461389c613781565b5060206138a98651614fe5565b95019182518061396a575b506138be856130fc565b92511515926138ce612f5a61251d565b602086015260408501526060840152151585830152565b6040518095819482936302637a4560e41b84526004840161381a565b03917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af1908115611d7457600091613941575090565b610358915060803d608011613963575b61395b81836124dd565b8101906137d1565b503d613951565b61397390615004565b386138b4565b805490916001600160801b039182169081039091169081116139b95781546001600160801b0319166001600160801b03909116179055600190565b600190565b5050600090565b90816020910312610321575190565b156139d657565b60405162461bcd60e51b815260206004820152601d60248201527f496e73756666696369656e7420636f6e74726163742062616c616e63650000006044820152606490fd5b15613a2257565b60405162461bcd60e51b8152602060048201526024808201527f496e73756666696369656e7420636f6e7472616374206e61746976652062616c604482015263616e636560e01b6064820152608490fd5b6001600160a01b03169073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8203613aa5576103319150471015613a1b565b6040516370a0823160e01b815230600482015291602090839060249082905afa8015611d745761033192600091613adf575b5010156139cf565b613b01915060203d602011613b07575b613af981836124dd565b8101906139c0565b38613ad7565b503d613aef565b6001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8103613b9557506000918291829182916001600160a01b03165af1613b4f612b3e565b5015613b5757565b60405162461bcd60e51b815260206004820152601660248201527513985d1a5d99481d1c985b9cd9995c8819985a5b195960521b6044820152606490fd5b60405163a9059cbb60e01b60208201526001600160a01b03909216602483015260448083019390935291815261033191613bd06064836124dd565b61537e565b35613bdf81610310565b6001600160a01b0316151590565b61035890803590613bfd82612286565b613d1b6020820135613c0e81612286565b612c75604084013593613c2085610310565b606081013590613c2f82610310565b613c3b60808201612226565b613c4760a08301612226565b613c5360c08401612226565b90613c6060e08501612226565b92613c7b610120613c746101008801612230565b9601612230565b956040519a8b9960208b019d8e7f16210483e9c961c9c307e53963eafad0795395f2fce68f0c9c294cca1ac5a06a81526001600160801b039182166020820152911660408201526001600160a01b039182166060820152918116608083015263ffffffff92831660a083015292821660c082015292811660e084015292909216610100820152918116610120830152919091166101408201526101600190565b5190206150bd565b90816020910312610321575160058110156103215790565b908160209103126103215751610358816109b1565b15613d5757565b60405162461bcd60e51b815260206004820152601060248201526f496e76616c69645369676e617475726560801b6044820152606490fd5b90613dd49392959796602060405181810190613daf81612c758885612b6e565b519020809a6040518080998194632dff692d60e01b8352600483019190602083019252565b03915afa908115611d7457613dfb602092613e3097600091613edf575b5061070081610b15565b613e0760e08501612226565b60405163167d0a6960e21b815263ffffffff909116600482015295869190829081906024820190565b03915afa918215611d7457613e97613e7663ffffffff9695613e7060c0956103319b613e69613ea6998c9b600091613eb0575b50612385565b3691612547565b9061512a565b613e866106b66101008501612230565b6001600160a01b0390911614613d50565b613ea08161344d565b01612226565b92169116146123d1565b613ed2915060203d602011613ed8575b613eca81836124dd565b810190613d3b565b38613e63565b503d613ec0565b613eff9150843d8611613f05575b613ef781836124dd565b810190613d23565b38613df1565b503d613eed565b15613f1357565b60405162461bcd60e51b8152602060048201526014602482015273496e76616c696420686f6f6b206164647265737360601b6044820152606490fd5b91908035613f5c81610310565b6001600160a01b0316600090815260086020526040902054613f809060ff16613f0c565b613fbb613f926106b660408601612230565b613f9f6101008601612230565b613fa884612230565b90613fb561069088612297565b92614613565b613fc483614138565b1561407d57613ff8613fe3613fd883612230565b9260608101906140ba565b606086019391613ff285612230565b926151b6565b906140576140516106906020870161401d61401561069083612297565b8710156140ec565b61404c61402986612230565b9861404061012061403989612230565b9201612230565b61118161069085612297565b612297565b836126e7565b80614063575b50509190565b61406f61407692612230565b3390613b0e565b388061405d565b915061035861408b83612230565b61077e60406140af6140a060608801886140ba565b602089019591613ff287612230565b9501358510156140ec565b903590601e198136030182121561032157018035906001600160401b0382116103215760200191813603831361032157565b156140f357565b60405162461bcd60e51b815260206004820152601d60248201527f496e73756666696369656e74206f75747075742066726f6d20686f6f6b0000006044820152606490fd5b63ffffffff8060e060c08401359361414f856103a4565b013561415a816103a4565b1691161490565b1561416857565b60405162461bcd60e51b815260206004820152601060248201526f4f72646572206e6f742061637469766560801b6044820152606490fd5b9291906141ac8461344d565b6141c360e085019163ffffffff80613ea685612226565b63ffffffff6141f9612d196141f360c060405160208101906141e981612c758d85612b6e565b5190209801612226565b93612226565b91160361426657604051632dff692d60e01b81526004810184905290602090829060249082905afa908115611d745761033191600191600091614247575b5061424181610b15565b14614161565b614260915060203d602011613f0557613ef781836124dd565b38614237565b604051632dff692d60e01b81526004810184905290602090829060249082905afa8015611d7457610331916000916142a9575b506142a381610b15565b15614161565b6142c2915060203d602011613f0557613ef781836124dd565b38614299565b908160005260076020526142e76040600020600260ff19825416179055565b63ffffffff60c08201356142fa816103a4565b166000908152600a60209081526040808320338452909152902080549091600160401b8210156124bd57614358827f7f80314442bfb82d1f9dfa4f96cbc84ae8fef158c7a93315024778ca3fc1671694600161369d950181556103ed565b81549060031b9086821b91600019901b191617905560405191829182612b6e565b1561438057565b60405162461bcd60e51b815260206004820152601860248201527710985b185b98d9481bdc195c985d1a5bdb8819985a5b195960421b6044820152606490fd5b610100820180519193916001600160a01b03166143dc906103bd565b604084810180516001600160a01b031660009081526020939093529120909390546001600160801b03169282614411826103bd565b86516001600160a01b03166000908152602091909152604090205460801c81519093908190889085906001600160a01b031661444c906103bd565b82516001600160a01b0316600090815260209190915260409020546001600160801b031683516001600160801b03166001600160801b031690600160801b600190031610156144d561451f610ad761450f61450961454f9f6144da6144d56145499d61453b9c6144e69b6144fc9561452d9c61458d575b505090516001600160a01b0316919050565b6103bd565b89516001600160a01b03165b60018060a01b0316600052602052604060002090565b546001600160801b031690565b9a6103bd565b86516001600160a01b03166144e6565b99516001600160a01b031690565b91516001600160a01b031690565b50516001600160801b031690565b936152a4565b614566610eac826000526007602052604060002090565b7fe82916be8cebf4000a0d08979cca286e4bfe07a019f19c0c930305aceacdcaf6600080a2565b614602926145f06145e26145f6936144e661452d6145dc6145ca6145ba6144d58d5160018060a01b031690565b85516001600160a01b03166144e6565b87516001600160801b03165b90613979565b976103bd565b91516001600160801b031690565b9061527e565b8161460b575b50614379565b8f8e908d6144c3565b9050386145fc565b6040516323b872dd60e01b60208201526001600160a01b03928316602482015292909116604483015260648083019390935291815261033191613bd06084836124dd565b604090815161466683826124dd565b6004815263416f726960e01b602082015291614684815191826124dd565b6005815264302e332e3160d81b602082015290565b156146a057565b60405162461bcd60e51b81526020600482015260186024820152772737ba1037b7103232b9ba34b730ba34b7b71031b430b4b760411b6044820152606490fd5b156146e757565b60405162461bcd60e51b815260206004820152604860248201527f4f6e6c792077686974656c697374656420736f6c7665722c206f66666572657260448201527f2c206f7220726563697069656e742028616674657220657870697279292063616064820152671b8818d85b98d95b60c21b608482015260a490fd5b929060209161478b6147ab9463ffffffff8061478160e08a01612226565b9216911614614699565b6040518080958194632dff692d60e01b8352600483019190602083019252565b03915afa8015611d74576147ca916000916142a957506142a381610b15565b604051631f798dcd60e21b81526001600160a01b038316600482015292602090849060249082905afa918215611d7457610331936000936148a3575b508215614863575b821561481c575b50506146e0565b90915061482f6106b66101208401612230565b6001600160a01b0390911614908161484a575b503880614815565b61485b915060a0612d199101612226565b421138614842565b91506148756106b66101008301612230565b6001600160a01b038316148061488c575b9161480e565b5061489c612d1960a08301612226565b4211614886565b6148bd91935060203d602011613ed857613eca81836124dd565b9138614806565b60021115610b1f57565b60405190600160f81b60208301526021820152602181526103586041826124dd565b6103589392916148fe613781565b506149226040519361490f856124a2565b3485526000602086015233953691612547565b91613888565b906149e461069060206149dd61035894803561494381610310565b6001600160a01b031660009081526008845260409020546149669060ff16613f0c565b60608101358015614a175783820161498061065a82612230565b156149ec575060008080808461499a6149b9963414614ad1565b6149a96106b66106b689612230565b5af16149b3612b3e565b50614b31565b6149d06149c582612230565b9160408101906140ba565b90613ff260608a01612230565b9401612297565b821015614b7d565b90614a016106b6614a129361077e3415614a63565b614a0a84612230565b903390614613565b6149b9565b50614a1234614a2257565b60405162461bcd60e51b8152602060048201526019602482015278139bc81b985d1a5d99481d1bdad95b9cc8195e1c1958dd1959603a1b6044820152606490fd5b15614a6a57565b60405162461bcd60e51b815260206004820152603960248201527f4e6f206e617469766520746f6b656e732073686f756c642062652073656e74206044820152783337b91022a921991810383932b332b93932b2103a37b5b2b760391b6064820152608490fd5b15614ad857565b60405162461bcd60e51b815260206004820152602b60248201527f496e636f7272656374206e617469766520616d6f756e7420666f72207072656660448201526a32b93932b2103a37b5b2b760a91b6064820152608490fd5b15614b3857565b60405162461bcd60e51b815260206004820152601e60248201527f4e6174697665207472616e7366657220746f20686f6f6b206661696c656400006044820152606490fd5b15614b8457565b60405162461bcd60e51b815260206004820152603560248201527f486f6f6b206d7573742070726f76696465206174206c656173742074686520656044820152741e1c1958dd1959081bdd5d1c1d5d08185b5bdd5b9d605a1b6064820152608490fd5b15614bee57565b60405162461bcd60e51b81526020600482015260136024820152722737ba1037b71039b7bab931b29031b430b4b760691b6044820152606490fd5b15614c3057565b60405162461bcd60e51b815260206004820152603b60248201527f43726f73732d636861696e206f7264657273206d7573742062652063616e636560448201527f6c6c65642066726f6d2064657374696e6174696f6e20636861696e00000000006064820152608490fd5b15614ca257565b60405162461bcd60e51b815260206004820152603060248201527f4f6e6c7920736f6c766572206f72206f6666657265722028616674657220657860448201526f1c1a5c9e4a4818d85b8818d85b98d95b60821b6064820152608490fd5b92614d2e9160209161478b60c087019563ffffffff80614d24895163ffffffff1690565b9216911614614be7565b03915afa918215611d7457614d576001614d8294614d6194600091614247575061424181610b15565b5163ffffffff1690565b63ffffffff614d7a612d1960e086015163ffffffff1690565b911614614c29565b604051631f798dcd60e21b81526001600160a01b038316600482015292602090849060249082905afa918215611d745761033193600093614e20575b508215614dcd575b5050614c9b565b61010082015191925090614de9906001600160a01b03166106b6565b6001600160a01b03909116149081614e04575b503880614dc6565b60a00151614e18915063ffffffff16612d19565b421138614dfc565b614e3a91935060203d602011613ed857613eca81836124dd565b9138614dbe565b806000526007602052614e67600160ff60406000205416614e6181610b15565b14613006565b614ee7614e86614e81836000526005602052604060002090565b612d9b565b80516040820151610100909201516001600160801b03909116916001600160a01b039182169116614eb78382613a73565b614ece611576866000526007602052604060002090565b6119bc610a7f84614ee2846108a4876103bd565b613979565b7fe8d9861dbc9c663ed3accd261bbe2fe01e0d3d9e5f51fa38523b265c7757a93a600080a2565b90919060ff1660018103614f2457505050602190565b614f49576103589161ffff91821680821015614f4257505b166153d9565b9050614f3c565b60405162461bcd60e51b8152602060048201526014602482015273496e76616c6964206d657373616765207479706560601b6044820152606490fd5b9060408282031261032157610358916137a9565b6001600160801b038111614fb3576001600160801b031690565b6306dfcc6560e41b600052608060045260245260446000fd5b6001600160801b0391821690821601919082116126f457565b803403614fef5790565b6304fb820960e51b6000523460045260246000fd5b60405163393f876560e21b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169190602081600481865afa908115611d7457600091615082575b506001600160a01b031691821561507157610331923390614613565b6329b99a9560e11b60005260046000fd5b90506020813d6020116150b5575b8161509d602093836124dd565b8101031261032157516150af81610310565b38615055565b3d9150615090565b906150c6614657565b604093919351937f91ab3d17e3a50a9d89e63fd30b92be7f5336b03b287bb946787a83a9d62a276660005260208151910120602052602081519101206040523060605260806000206020526119016000526040526042601e20916040526000606052565b919091604051928051806040146151945760411461515557505050505b638baa579f6000526004601cfd5b602091606082015160001a835260408201516060525b60005201516040526020600160806000825afa519160006060526040523d610331575050615147565b506020916040820151601b8160ff1c01845260018060ff1b031660605261516b565b6000919392908291826151c930876155b6565b96826040519384928337810182815203925af16151e4612b3e565b501561524b576151f59030906155b6565b9080821061520657610358916126e7565b60405162461bcd60e51b815260206004820152601f60248201527f486f6f6b2064656372656173656420636f6e74726163742062616c616e6365006044820152606490fd5b60405162461bcd60e51b815260206004820152600b60248201526a10d85b1b0819985a5b195960aa1b6044820152606490fd5b8054909160809190911c9081016001600160801b03169081106139b9576139b4916126f9565b92939192906001600160801b03906152bd908490614fcc565b166001600160801b0390911603615339576001600160801b03916152e19190614fcc565b166001600160801b03909116036152f457565b60405162461bcd60e51b815260206004820152601b60248201527f496e636f6e73697374656e7420736f6c7665722062616c616e636500000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601c60248201527f496e636f6e73697374656e74206f6666657265722062616c616e6365000000006044820152606490fd5b906000602091828151910182855af115612e85576000513d6153d057506001600160a01b0381163b155b6153af5750565b635274afe760e01b60009081526001600160a01b0391909116600452602490fd5b600114156153a8565b8060051b90808204602014901517156126f457601701806017116126f45790565b90156104055790565b9190916017831061550c576154188382615678565b9390916154268583836156bc565b60005b61ffff8616811061543c57505050505050565b60018161544d61ffff938686615741565b868861547660e061546b614e81866000526005602052604060002090565b015163ffffffff1690565b63ffffffff821663ffffffff82160361549c57505061549491615805565b019050615429565b7fbb563f7e333f32ed0571f8dc4913648b41737753db5df83c58657c6bfcc2ef569250615504604051928392839060a09263ffffffff809216835216602082015260606040820152600c60608201526b08ad2c840dad2e6dac2e8c6d60a31b60808201520190565b0390a2615494565b606460405162461bcd60e51b815260206004820152602060248201527f5061796c6f616420746f6f2073686f727420666f7220736574746c656d656e746044820152fd5b90602103615565576001610331910135614e41565b60405162461bcd60e51b815260206004820152602360248201527f496e76616c69642063616e63656c6c6174696f6e207061796c6f6164206c656e6044820152620cee8d60eb1b6064820152608490fd5b6001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81036155df57503190565b6040516370a0823160e01b81526001600160a01b039092166004830152602090829060249082905afa908115611d745760009161561a575090565b610358915060203d602011613b0757613af981836124dd565b1561563a57565b60405162461bcd60e51b8152602060048201526016602482015275092dcecc2d8d2c840e0c2f2d8dec2c840d8cadccee8d60531b6044820152606490fd5b9190916156886017841015615633565b600181013560601c928060151015610405576016101561040557601581013560f01c61ff00166016919091013560f81c1790565b5090621fffe061ffff82169160051b1690808204602014901517156126f45760170190816017116126f457036156ee57565b60405162461bcd60e51b815260206004820152602560248201527f496e76616c6964207061796c6f6164206c656e67746820666f7220736574746c604482015264195b595b9d60da1b6064820152608490fd5b9061574f6017821015615633565b60161981019081116126f45760051c8210156157715760179160051b01013590565b60405162461bcd60e51b8152602060048201526013602482015272496e646578206f7574206f6620626f756e647360681b6044820152606490fd5b906040516157b9816124a2565b91546001600160801b038116835260801c6020830152565b815181546001600160801b0319166001600160801b039190911617815561033191602001516001600160801b0316906126f9565b90600161581f6106f0846000526007602052604060002090565b61582881610b15565b0361595657615844614e81836000526005602052604060002090565b6101008101805191929091615861906001600160a01b03166103bd565b6040840180519093916158869161588191906001600160a01b03166144e6565b6157ac565b9061589661588161450f856103bd565b946158e36158d36158c36158b36144d5865160018060a01b031690565b88516001600160a01b03166144e6565b83516001600160801b03166145d6565b916145f06145e26144da886103bd565b901590811561594d575b5061590e575050505050614566610eac826000526007602052604060002090565b51610331955061594893926144e69261452d926144d591908790615938906001600160a01b031684565b87516001600160a01b03166144e6565b6157d1565b905015386158ed565b505056fe9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eba26469706673582212202463fc3c173b6a5cc2bef337128c18ef1cd9704d7eb70d9979f92d42aa4971ad64736f6c634300081c00330000000000000000000000001a44076050125825900e736c501f859c50fe728c000000000000000000000000941327e206b8d8cfe1014a8a95b05e1536dfd00d00000000000000000000000000000000000000000000000000000000000075950000000000000000000000000000000000000000000000000000000000000064
Deployed Bytecode
0x6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c806305ef94ba1461030b5780630c89a13d1461030657806313137d651461030157806317442b70146102fc5780631c0166aa146102f75780631e2c273e146102f25780632c85455b146102ed5780632cee9acd146102e85780632d7c615a146102e35780632dff692d146102de5780633400288b146102d9578063344ba6fd146102d45780633f4ba83a146102cf57806344ae20c3146102ca57806350964586146102c5578063555c3898146102c0578063595490c8146102bb57806359f429a4146102b65780635c975abb146102b15780635e280f11146102ac5780636b624fdb146102a7578063715018a6146102a25780637ce5e33e1461029d5780637d25a05e146102985780637de637341461029357806382413eac1461028e5780638456cb591461028957806384b0196e146102845780638da5cb5b1461027f57806395ccea671461027a578063983f7fd114610275578063996628a0146102705780639c3f1e901461026b578063a9a683ba14610266578063b410f12214610261578063b8f480c61461025c578063bb0b6a5314610257578063c15c4b3714610252578063c4d252f51461024d578063ca5eb5e114610248578063cd77488714610243578063e86dfbbf1461023e578063e898841f14610239578063edb25d8114610234578063f2fde38b1461022f578063f3fef3a31461022a5763ff7bd03d0361000e576121df565b6120f5565b612068565b61201f565b611e56565b611e0e565b611d80565b611cd3565b611b4e565b611ae6565b611aab565b611a3f565b6119d6565b611854565b61175d565b611647565b6114b0565b6113fd565b6113d4565b611333565b611298565b61123a565b6111f8565b6111d1565b611086565b61102d565b610fe7565b610fa2565b610f7f565b610f3f565b610ef6565b610d2e565b610cb5565b610c76565b610c0d565b610bcb565b610b5c565b610b24565b6109bb565b610970565b6107e5565b61079f565b61061d565b6105d7565b6104d4565b61040a565b61035b565b6001600160a01b0381160361032157565b600080fd5b359061033182610310565b565b60409060031901126103215760043561034b81610310565b9060243561035881610310565b90565b3461032157602061036b36610333565b6001600160a01b039182166000908152600484526040808220929093168152602091909152206001600160801b03905416604051908152f35b63ffffffff81160361032157565b3590610331826103a4565b6001600160a01b0316600090815260046020526040902090565b634e487b7160e01b600052603260045260246000fd5b80548210156104055760005260206000200190600090565b6103d7565b3461032157606036600319011261032157600435610427816103a4565b61046460243561043681610310565b63ffffffff6044359316600052600a60205260406000209060018060a01b0316600052602052604060002090565b8054821015610321576104929161047a916103ed565b90549060031b1c604051918291829190602083019252565b0390f35b606090600319011261032157600490565b9181601f84011215610321578235916001600160401b038311610321576020838186019501011161032157565b60e0366003190112610321576104e936610496565b6064356084356001600160401b0381116103215761050b9036906004016104a7565b60a4929192359061051b82610310565b60c4356001600160401b0381116103215761053a9036906004016104a7565b949093337f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b0316036105c257863596610579886103a4565b610582886130fc565b97602082013580990361059a57506100199750613130565b63ffffffff816105aa8b936103a4565b63309afaf360e21b6000521660045260245260446000fd5b6391ac5e4f60e01b6000523360045260246000fd5b3461032157600036600319011261032157604080516001815260026020820152f35b61014090600319011261032157600490565b61014090602319011261032157602490565b61014036600319011261032157610795610636366105f9565b61063e613210565b610646613230565b604081019061068161067c61065a84612230565b6001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1490565b61223a565b6106a361069c61069083612297565b6001600160801b031690565b34146122a1565b6106c96106c26106b66101008401612230565b6001600160a01b031690565b33146122e7565b6107836106d582612c60565b926107066106f76106f0866000526007602052604060002090565b5460ff1690565b61070081610b15565b15612342565b6107366107316106f061071b60e08701612226565b63ffffffff166000526006602052604060002090565b612385565b61077561074560c08501612226565b63ffffffff807f0000000000000000000000000000000000000000000000000000000000007595169116146123d1565b61077e8361344d565b612230565b61078f61069083612297565b90613551565b6100196001600255565b34610321576020366003190112610321576004356107bc81610310565b6107c46136a2565b6001600160a01b03166000908152600960205260409020805460ff19169055005b6060366003190112610321576004356107fd816103a4565b60243561080981610310565b604435906001600160401b0382116103215763ffffffff7fd054cd999785d4c556d1f55b27cc59caba458cd5663063989d47725b970092329161095c6108566109279536906004016104a7565b610861969196613210565b610869613230565b33600052600960205261088360ff6040600020541661240e565b6109006108bb856108a48b63ffffffff16600052600a602052604060002090565b9060018060a01b0316600052602052604060002090565b8561ffff82546108cc81151561244b565b7f000000000000000000000000000000000000000000000000000000000000006482168082101561096957505b16916136e2565b9661092061090c6124fe565b913483526000602084015233933691612547565b888a613888565b805190604061094060208301516001600160401b031690565b910151519160405195869560018060a01b03169916978561257e565b0390a36100196001600255565b90506108f9565b3461032157600036600319011261032157602060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000007595168152f35b8015150361032157565b346103215760a0366003190112610321576004356109d881610310565b6024359060008051602061595b833981519152610aae604435926109fb84610310565b610a948560643595610a0c876109b1565b8360843591610a1a83610310565b610a226136a2565b610a2d8415156125af565b6001600160a01b03811698610a438a15156125fa565b610a576001600160a01b038516151561263d565b15610ab357610a6f610a84926108a4610a7f936103bd565b6001600160801b03851690613979565b61271c565b610a8e8285613a73565b83613b0e565b6040519485526001600160a01b0316939081906020820190565b0390a3005b610af5826108a4610aef61069088610ade610690610ad7610afa9a6108a48b6103bd565b5460801c90565b610aea82821015612685565b6126e7565b936103bd565b6126f9565b610a84565b634e487b7160e01b600052602160045260246000fd5b60051115610b1f57565b610aff565b3461032157602036600319011261032157600435600052600760205260ff604060002054166040516005821015610b1f576020918152f35b34610321576040366003190112610321577f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b6040600435610b9c816103a4565b63ffffffff60243591610bad6136a2565b169081600052600160205280836000205582519182526020820152a1005b3461032157602036600319011261032157600435610be881610310565b60018060a01b03166000526008602052602060ff604060002054166040519015158152f35b3461032157600036600319011261032157610c266136a2565b60035460ff811615610c655760ff19166003557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b638dfc202b60e01b60005260046000fd5b3461032157600036600319011261032157602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000064168152f35b346103215760203660031901126103215763ffffffff600435610cd7816103a4565b610cdf6136a2565b168060005260066020526040600020600160ff198254161790557fa7dbeb6ef5cb64125bfb03ac211f1aea3f639de95ceb37b16706d4f0735d1863600080a2005b908160809103126103215790565b346103215761018036600319011261032157610d49366105f9565b610144356001600160401b03811161032157610d699036906004016104a7565b90610164356001600160401b03811161032157610e2a91610d91610e23923690600401610d20565b93610d9a613210565b610da2613230565b336000526009602052610dbc60ff6040600020541661240e565b610ddc610dd7610dd3604089013561065a81610310565b1590565b612772565b610ded610de886613bd5565b6127ca565b610df686613bed565b91309230927f00000000000000000000000000000000000000000000000000000000000075959289613d8f565b9183613f4f565b604051828152909391906001600160a01b0385169084907f86d7c80bc9d060acd32be0a39bbd97538a0e7b1f748c30d4e87b186b1d3589bb90602090a3610e7082614138565b15610ee85750819250610e90610e95926000526005602052604060002090565b612805565b610eb9610eac826000526007602052604060002090565b805460ff19166004179055565b7fe82916be8cebf4000a0d08979cca286e4bfe07a019f19c0c930305aceacdcaf6600080a26100196001600255565b610ef193613551565b610795565b3461032157602036600319011261032157600435610f1381610310565b610f1b6136a2565b6001600160a01b03166000908152600960205260409020805460ff19166001179055005b346103215760203660031901126103215763ffffffff600435610f61816103a4565b166000526006602052602060ff604060002054166040519015158152f35b3461032157600036600319011261032157602060ff600354166040519015158152f35b34610321576000366003190112610321576040517f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b03168152602090f35b346103215760203660031901126103215760043561100481610310565b61100c6136a2565b6001600160a01b03166000908152600860205260409020805460ff19169055005b34610321576000366003190112610321576110466136a2565b600080546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b6101403660031901126103215761109c366105f9565b6110a4613210565b6110ac613230565b3360005260096020526110c660ff6040600020541661240e565b6110f1307f0000000000000000000000000000000000000000000000000000000000007595836141a0565b90606081019161110361065a84612230565b156111c25761112161111a61069060208501612297565b3414612a28565b8161112b81614138565b156111b457506111479033906111413685612a7f565b906143c0565b61115361065a83612230565b156111875761116461079592612230565b90611181610690602061117a6101208501612230565b9301612297565b91613b0e565b6111966106b6610ef193612230565b906111ac610690602061117a6101208501612230565b913390614613565b6111bd916142c8565b611147565b6111cc34156129c4565b611121565b34610321576040366003190112610321576111ed6004356103a4565b602060405160008152f35b346103215760203660031901126103215760043561121581610310565b60018060a01b03166000526009602052602060ff604060002054166040519015158152f35b346103215760a03660031901126103215761125436610496565b506064356001600160401b038111610321576112749036906004016104a7565b5050602060843561128481610310565b6040516001600160a01b0390911630148152f35b34610321576000366003190112610321576112b16136a2565b6112b9613230565b600160ff1960035416176003557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b919082519283825260005b84811061131e575050826000602080949584010152601f8019910116010190565b806020809284010151828286010152016112fd565b3461032157600036600319011261032157611373611381611352614657565b604092919251938493600f60f81b855260e0602086015260e08501906112f2565b9083820360408501526112f2565b466060830152306080830152600060a083015281810360c0830152602060605191828152019060809060005b8181106113bb575050500390f35b82518452859450602093840193909201916001016113ad565b34610321576000366003190112610321576000546040516001600160a01b039091168152602090f35b346103215760403660031901126103215760043561141a81610310565b6024356114256136a2565b478061144b575b508061143457005b60005461001992906001600160a01b031690613b0e565b60008080809360018060a01b038254165af1611465612b3e565b5015611471573861142c565b60405162461bcd60e51b8152602060048201526017602482015276115d1a195c881dda5d1a191c985dd85b0819985a5b1959604a1b6044820152606490fd5b610180366003190112610321576004356114c93661060b565b610164356001600160401b038111610321576114e99036906004016104a7565b6114f4929192613210565b6114fc613230565b8361150683612c60565b036115ef577f8168c9ac1d18802efe1afee0a6bf2de2b35d9f041a5b42a072b06252ba84fe509261159d9261155f3033307f00000000000000000000000000000000000000000000000000000000000075958a86614763565b611583611576876000526007602052604060002090565b805460ff19166003179055565b61159860c0611591886148ce565b9201612226565b6148f0565b80516115e260406115b860208501516001600160401b031690565b93015151604051938493846001600160401b03604092959493606083019683521660208201520152565b0390a26100196001600255565b60405162461bcd60e51b815260206004820152602a60248201527f5375626d6974746564206f72646572206461746120646f65736e2774206d617460448201526918da081bdc99195c925960b21b6064820152608490fd5b346103215761016036600319011261032157611662366105f9565b610144356001600160401b03811161032157610795916116896107839236906004016104a7565b611694939193613210565b61169c613230565b3360005260096020526116b660ff6040600020541661240e565b61077e60408401916117376117318435976116d089610310565b6001600160a01b038916936116fb73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee861415612772565b61170489613bed565b91309230927f0000000000000000000000000000000000000000000000000000000000007595928c613d8f565b96610310565b6101008501359061174782610310565b611755863561069081612286565b913091614613565b346103215760203660031901126103215760043560005260056020526040600020805461049260018060a01b036001840154166002840154936117a08560e01c90565b6003820154906117d460046117c563ffffffff85169460201c6001600160a01b031690565b9401546001600160a01b031690565b604080516001600160801b0389168152608098891c60208201526001600160a01b0396871691810191909152858916606082015260a089811c63ffffffff9081169983019990995260c0998a1c89169082015291871697820197909752941660e08501528116610100840152909216610120820152908190610140820190565b6101603660031901126103215761186a366105f9565b610144356001600160401b0381116103215761188a903690600401610d20565b90611893613210565b61189b613230565b3360005260096020526118b560ff6040600020541661240e565b61199f6118e3307f0000000000000000000000000000000000000000000000000000000000007595846141a0565b916118ee8482614928565b936001600160a01b039061190490602001612230565b16837fd6fb3db9629fef5e875e0d0138b2fb4ae60575aba13837c23c1c9a6aa1e35bac6040518061193a89829190602083019252565b0390a3611957602082019461195161069087612297565b906126e7565b928161196281614138565b156119c857506119789033906111413685612a7f565b606081019361118161069061199961012061199289612230565b9501612230565b92612297565b806119ae576100196001600255565b6119c1916119bc3391612230565b613b0e565b3880610795565b6119d1916142c8565b611978565b34610321576101403660031901126103215760206119fb6119f6366105f9565b612c60565b604051908152f35b602060408183019282815284518094520192019060005b818110611a275750505090565b82511515845260209384019390920191600101611a1a565b34610321576020366003190112610321576004356001600160401b0381116103215736602382011215610321578060040135906001600160401b038211610321573660248360051b8301011161032157610492916024611a9f9201612c89565b60405191829182611a03565b346103215760203660031901126103215763ffffffff600435611acd816103a4565b1660005260016020526020604060002054604051908152f35b346103215760203660031901126103215763ffffffff600435611b08816103a4565b611b106136a2565b16806000526006602052604060002060ff1981541690557f79df5d328757ca456e42d3dc087c02eedd4cf61d984a6aa526cfac31f1542dcd600080a2005b3461032157602036600319011261032157610795600435611b6d613210565b611b75613230565b806000526005602052611cce6040600020611ca0611c8f6004611b9661250d565b84546001600160801b0381168252909490611bc690611bb6905b60801c90565b6001600160801b03166020870152565b6001810154611be9906001600160a01b03165b6001600160a01b03166040870152565b60028101546001600160a01b0381166060870152611c3990611c2c9063ffffffff60a082901c16608089015263ffffffff60c082901c1660a08901525b60e01c90565b63ffffffff1660c0870152565b611c81611c706003830154611c61611c548263ffffffff1690565b63ffffffff1660e08a0152565b60201c6001600160a01b031690565b6001600160a01b0316610100870152565b01546001600160a01b031690565b6001600160a01b0316610120830152565b309033903090857f000000000000000000000000000000000000000000000000000000000000759591614d00565b614e41565b346103215760006020366003190112611d7d5780600435611cf381610310565b611cfb6136a2565b7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b0316803b15611d795760405163ca5eb5e160e01b81526001600160a01b0390921660048301529091908290602490829084905af18015611d74578290611d665780f35b611d6f916124dd565b388180f35b612e85565b5050fd5b80fd5b346103215760c036600319011261032157600435611d9d816103a4565b6024359060ff8216820361032157604435906001600160401b0382116103215761049292611dd2611dfe9336906004016104a7565b60643591611ddf836109b1565b60843593611dec856103a4565b60a43595611df987610310565b612ec3565b6040519081529081906020820190565b34610321576020611e4a611e2136610333565b6001600160a01b0391821660009081526004855260408082209290931681526020919091522090565b5460801c604051908152f35b3461032157604036600319011261032157600435602435611e7681610310565b611e7e6136a2565b611e92826000526007602052604060002090565b5460ff16611e9f81610b15565b600114611eab90613006565b6001600160a01b03811690611ec182151561263d565b611ed5836000526005602052604060002090565b611ede90612d9b565b9260c0840151611ef19063ffffffff1690565b7f000000000000000000000000000000000000000000000000000000000000759563ffffffff169063ffffffff1614611f2990613052565b604084015184516001600160801b0316946001600160a01b039091169290859081908590611f578383613a73565b611f6b866000526007602052604060002090565b805460ff1916600317905561010001516001600160a01b0316611f8d906103bd565b6001600160a01b0390911660009081526020919091526040902090611fb191613979565b611fba9061271c565b611fc49184613b0e565b6040519182917fe8d9861dbc9c663ed3accd261bbe2fe01e0d3d9e5f51fa38523b265c7757a93a600080a26001600160801b039490941690526001600160a01b039092169160008051602061595b83398151915290602090a3005b346103215760203660031901126103215760043561203c81610310565b6120446136a2565b6001600160a01b03166000908152600860205260409020805460ff19166001179055005b346103215760203660031901126103215760043561208581610310565b61208d6136a2565b6001600160a01b031680156120df57600080546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b631e4fbdf760e01b600052600060045260246000fd5b346103215760403660031901126103215760043561211281610310565b60243561211d613210565b612125613230565b80336000526004602052612152610ad78460406000209060018060a01b0316600052602052604060002090565b9161215e8315156130b4565b806121c257505061218961217c6106908380945b610aea8288613a73565b610af5846108a4336103bd565b612194813384613b0e565b6040519081526001600160a01b0390911690339060008051602061595b83398151915290806020810161095c565b61069082846121da61217c9461218996971015612685565b612172565b346103215760603660031901126103215760206121fb36610496565b63ffffffff813561220b816103a4565b16600052600182528160406000205491013560405191148152f35b35610358816103a4565b3561035881610310565b1561224157565b60405162461bcd60e51b815260206004820152601f60248201527f4f72646572206d7573742073706563696679206e617469766520746f6b656e006044820152606490fd5b6001600160801b0381160361032157565b3561035881612286565b156122a857565b60405162461bcd60e51b8152602060048201526017602482015276125b98dbdc9c9958dd081b985d1a5d9948185b5bdd5b9d604a1b6044820152606490fd5b156122ee57565b60405162461bcd60e51b815260206004820152602660248201527f4f6e6c79206f6666657265722063616e206465706f736974206e617469766520604482015265746f6b656e7360d01b6064820152608490fd5b1561234957565b60405162461bcd60e51b81526020600482015260146024820152734f7264657220616c72656164792065786973747360601b6044820152606490fd5b1561238c57565b60405162461bcd60e51b815260206004820152601f60248201527f44657374696e6174696f6e20636861696e206e6f7420737570706f72746564006044820152606490fd5b156123d857565b60405162461bcd60e51b815260206004820152600e60248201526d086d0c2d2dc40dad2e6dac2e8c6d60931b6044820152606490fd5b1561241557565b60405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b7b63b32b960911b6044820152606490fd5b1561245257565b60405162461bcd60e51b8152602060048201526012602482015271139bc81bdc99195c9cc81c1c9bdd9a59195960721b6044820152606490fd5b634e487b7160e01b600052604160045260246000fd5b604081019081106001600160401b038211176124bd57604052565b61248c565b606081019081106001600160401b038211176124bd57604052565b90601f801991011681019081106001600160401b038211176124bd57604052565b604051906103316040836124dd565b60405190610331610140836124dd565b6040519061033160a0836124dd565b6001600160401b0381116124bd57601f01601f191660200190565b9291926125538261252c565b9161256160405193846124dd565b829481845281830111610321578281602093846000960137010152565b9060609295949361259f6001600160401b03926080855260808501906112f2565b9660208401521660408201520152565b156125b657565b606460405162461bcd60e51b815260206004820152602060248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152fd5b1561260157565b60405162461bcd60e51b8152602060048201526014602482015273496e76616c69642075736572206164647265737360601b6044820152606490fd5b1561264457565b60405162461bcd60e51b8152602060048201526019602482015278496e76616c696420726563697069656e74206164647265737360381b6044820152606490fd5b1561268c57565b60405162461bcd60e51b815260206004820152601d60248201527f496e73756666696369656e7420756e6c6f636b65642062616c616e63650000006044820152606490fd5b634e487b7160e01b600052601160045260246000fd5b919082039182116126f457565b6126d1565b80546001600160801b031660809290921b6001600160801b031916919091179055565b1561272357565b60405162461bcd60e51b815260206004820152602160248201527f4661696c656420746f206465637265617365206c6f636b65642062616c616e636044820152606560f81b6064820152608490fd5b1561277957565b60405162461bcd60e51b815260206004820152602360248201527f557365206465706f7369744e617469766520666f72206e617469766520746f6b604482015262656e7360e81b6064820152608490fd5b156127d157565b60405162461bcd60e51b815260206004820152600c60248201526b4d697373696e6720686f6f6b60a01b6044820152606490fd5b60046129a36101206103319461283961281d82612297565b86546001600160801b0319166001600160801b03909116178655565b61284e61284860208301612297565b866126f9565b61288061285d60408301612230565b6001870180546001600160a01b0319166001600160a01b03909216919091179055565b61293c600286016128b261289660608501612230565b82546001600160a01b0319166001600160a01b03909116178255565b6128e16128c160808501612226565b825463ffffffff60a01b191660a09190911b63ffffffff60a01b16178255565b6129106128f060a08501612226565b825463ffffffff60c01b191660c09190911b63ffffffff60c01b16178255565b61291c60c08401612226565b81546001600160e01b031660e09190911b6001600160e01b031916179055565b61299d6003860161296861295260e08501612226565b825463ffffffff191663ffffffff909116178255565b6129756101008401612230565b8154640100000000600160c01b03191660209190911b640100000000600160c01b0316179055565b01612230565b910180546001600160a01b0319166001600160a01b03909216919091179055565b156129cb57565b60405162461bcd60e51b815260206004820152602f60248201527f4e6f206e617469766520746f6b656e732073686f756c642062652073656e742060448201526e666f722045524332302066696c6c7360881b6064820152608490fd5b15612a2f57565b60405162461bcd60e51b815260206004820152601c60248201527f496e636f7272656374206e617469766520616d6f756e742073656e74000000006044820152606490fd5b359061033182612286565b91908261014091031261032157612b36610120612a9a61250d565b93612aa481612a74565b8552612ab260208201612a74565b6020860152612ac360408201610326565b6040860152612ad460608201610326565b6060860152612ae5608082016103b2565b6080860152612af660a082016103b2565b60a0860152612b0760c082016103b2565b60c0860152612b1860e082016103b2565b60e0860152612b2a6101008201610326565b61010086015201610326565b610120830152565b3d15612b69573d90612b4f8261252c565b91612b5d60405193846124dd565b82523d6000602084013e565b606090565b61033190929192610120612c5281610140840196612b9c85612b8f83612a74565b6001600160801b03169052565b612bab611bb660208301612a74565b612bba611bd960408301610326565b612bd9612bc960608301610326565b6001600160a01b03166060870152565b612bf5612be8608083016103b2565b63ffffffff166080870152565b612c11612c0460a083016103b2565b63ffffffff1660a0870152565b612c20611c2c60c083016103b2565b612c3c612c2f60e083016103b2565b63ffffffff1660e0870152565b612c4c611c706101008301610326565b01610326565b6001600160a01b0316910152565b604051612c8381612c75602082019485612b6e565b03601f1981018352826124dd565b51902090565b612c916136a2565b612c9a82612d60565b91612ca860405193846124dd565b808352601f19612cb782612d60565b0136602085013760005b818110612cce5750505090565b8063ffffffff612ce16001938587612d77565b35612ceb816103a4565b16600052600660205260406000208260ff19825416179055612d22612d19612d14838688612d77565b612226565b63ffffffff1690565b7fa7dbeb6ef5cb64125bfb03ac211f1aea3f639de95ceb37b16706d4f0735d1863600080a2612d5a612d548287612d87565b60019052565b01612cc1565b6001600160401b0381116124bd5760051b60200190565b91908110156104055760051b0190565b80518210156104055760209160051b010190565b90610331612e746004612dac61250d565b85546001600160801b0381168252909590612dda90612dca90611bb0565b6001600160801b03166020880152565b60018101546001600160a01b0316604087015260028101546001600160a01b0381166060880152612e3b90612e2e9063ffffffff60a082901c1660808a015263ffffffff60c082901c1660a08a0152611c26565b63ffffffff1660c0880152565b611c81612e636003830154611c61612e568263ffffffff1690565b63ffffffff1660e08b0152565b6001600160a01b0316610100880152565b6001600160a01b0316610120840152565b6040513d6000823e3d90fd5b90612e9b8261252c565b612ea860405191826124dd565b8281528092612eb9601f199161252c565b0190602036910137565b9391612f3c90612f34612f2f612f7d9694612f07612f989b63ffffffff60409c16600052600a6020528b6000209060018060a01b0316600052602052604060002090565b547f000000000000000000000000000000000000000000000000000000000000006491614f0e565b612e91565b923691612547565b90612f45613768565b50612f4f856130fc565b612f66612f5a61251d565b63ffffffff9097168752565b602086015285850152606084015215156080830152565b815180938192631bb8518b60e31b835230906004840161381a565b03817f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b03165afa908115611d7457600091612fd957505190565b612ffb915060403d604011612fff575b612ff381836124dd565b810190614f85565b5190565b503d612fe9565b1561300d57565b60405162461bcd60e51b815260206004820152601d60248201527f43616e206f6e6c792063616e63656c20616374697665206f72646572730000006044820152606490fd5b1561305957565b60405162461bcd60e51b815260206004820152602d60248201527f456d657267656e63792063616e63656c206f6e6c7920616c6c6f776564206f6e60448201526c1039b7bab931b29031b430b4b760991b6064820152608490fd5b156130bb57565b60405162461bcd60e51b8152602060048201526019602482015278139bdb8b5e995c9bc818985b185b98d9481c995c5d5a5c9959603a1b6044820152606490fd5b63ffffffff1680600052600160205260406000205490811561311c575090565b63f6ff4fb760e01b60005260045260246000fd5b9350509350915061313f613230565b81156131db573561314f816103a4565b61315982846153fa565b3560f81c6002811015610b1f5761316f816148c4565b6001810361318257505061033191615550565b61318e819392936148c4565b61319b5761033192615403565b60405162461bcd60e51b8152602060048201526018602482015277556e737570706f72746564207061796c6f6164207479706560401b6044820152606490fd5b60405162461bcd60e51b815260206004820152600d60248201526c115b5c1d1e481c185e5b1bd859609a1b6044820152606490fd5b600280541461321f5760028055565b633ee5aeb560e01b60005260046000fd5b60ff6003541661323c57565b63d93c066560e01b60005260046000fd5b1561325457565b60405162461bcd60e51b815260206004820152600f60248201526e24b73b30b634b21037b33332b932b960891b6044820152606490fd5b1561329257565b60405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b6044820152606490fd5b156132d257565b60405162461bcd60e51b815260206004820152601060248201526f496e76616c696420656e642074696d6560801b6044820152606490fd5b1561331157565b60405162461bcd60e51b815260206004820152601160248201527013dc99195c881b9bdd081cdd185c9d1959607a1b6044820152606490fd5b1561335157565b60405162461bcd60e51b815260206004820152601160248201527013dc99195c881a185cc8195e1c1a5c9959607a1b6044820152606490fd5b1561339157565b60405162461bcd60e51b8152602060048201526014602482015273125b9d985b1a59081a5b9c1d5d08185b5bdd5b9d60621b6044820152606490fd5b156133d457565b60405162461bcd60e51b8152602060048201526015602482015274125b9d985b1a59081bdd5d1c1d5d08185b5bdd5b9d605a1b6044820152606490fd5b1561341857565b60405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b2103a37b5b2b760991b6044820152606490fd5b610331906134716001600160a01b036134696101008401612230565b16151561324d565b61348b6134846106b66101208401612230565b151561328b565b6134e5608082016134d26134c36134a183612226565b92612d1460a087019463ffffffff6134bb612d1988612226565b9116106132cb565b63ffffffff429116111561330a565b6134df612d194292612226565b1161334a565b6135016001600160801b036134f983612297565b16151561338a565b61351a61351361069060208401612297565b15156133cd565b6135296106b660408301612230565b15159081613538575b50613411565b613549915060606106b69101612230565b151538613532565b9161369161365e61369d936136597f8e45fa612720ed3142e896a3a29c981f4ca01c25bca19c3a5c203398ee1bc3d79661010086013561359081610310565b6001600160a01b0390811660009081526004602090815260408083209385168352929052206135f2906135d56135c586614f99565b82546001600160801b0316614fcc565b81546001600160801b0319166001600160801b0391909116179055565b8860005260076020526040600020600160ff1982541617905561362386610e908b6000526005602052604060002090565b60016136398a6000526005602052604060002090565b0180546001600160a01b0319166001600160a01b03909216919091179055565b614f99565b613672866000526005602052604060002090565b80546001600160801b0319166001600160801b03909216919091179055565b60405191829182612b6e565b0390a2565b6000546001600160a01b031633036136b657565b63118cdaa760e01b6000523360045260246000fd5b63ffffffff166017019063ffffffff82116126f457565b908260051b621fffe061ffe08216911681036126f457612f2f612d1961370f6137149396949661ffff1690565b6136cb565b928160481b9060581b17602084015281600052602060002093825491820393603781015b838681111561375c57906000602092811901958119908a0101805483525501613738565b50509392915093505590565b60405190613775826124a2565b60006020838281520152565b6040519061378e826124c2565b81600081526000602082015260406137a4613768565b910152565b9190826040910312610321576040516137c1816124a2565b6020808294805184520151910152565b60808183031261032157604051916137e8836124c2565b8151835260208201516001600160401b0381168103610321576020840152613812916040016137a9565b604082015290565b906020909392936040835263ffffffff8151166040840152818101516060840152608061386e613858604084015160a08488015260e08701906112f2565b6060840151868203603f190160a08801526112f2565b910151151560c08401526001600160a01b03909416910152565b6138e560809492613901969461389c613781565b5060206138a98651614fe5565b95019182518061396a575b506138be856130fc565b92511515926138ce612f5a61251d565b602086015260408501526060840152151585830152565b6040518095819482936302637a4560e41b84526004840161381a565b03917f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b03165af1908115611d7457600091613941575090565b610358915060803d608011613963575b61395b81836124dd565b8101906137d1565b503d613951565b61397390615004565b386138b4565b805490916001600160801b039182169081039091169081116139b95781546001600160801b0319166001600160801b03909116179055600190565b600190565b5050600090565b90816020910312610321575190565b156139d657565b60405162461bcd60e51b815260206004820152601d60248201527f496e73756666696369656e7420636f6e74726163742062616c616e63650000006044820152606490fd5b15613a2257565b60405162461bcd60e51b8152602060048201526024808201527f496e73756666696369656e7420636f6e7472616374206e61746976652062616c604482015263616e636560e01b6064820152608490fd5b6001600160a01b03169073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8203613aa5576103319150471015613a1b565b6040516370a0823160e01b815230600482015291602090839060249082905afa8015611d745761033192600091613adf575b5010156139cf565b613b01915060203d602011613b07575b613af981836124dd565b8101906139c0565b38613ad7565b503d613aef565b6001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8103613b9557506000918291829182916001600160a01b03165af1613b4f612b3e565b5015613b5757565b60405162461bcd60e51b815260206004820152601660248201527513985d1a5d99481d1c985b9cd9995c8819985a5b195960521b6044820152606490fd5b60405163a9059cbb60e01b60208201526001600160a01b03909216602483015260448083019390935291815261033191613bd06064836124dd565b61537e565b35613bdf81610310565b6001600160a01b0316151590565b61035890803590613bfd82612286565b613d1b6020820135613c0e81612286565b612c75604084013593613c2085610310565b606081013590613c2f82610310565b613c3b60808201612226565b613c4760a08301612226565b613c5360c08401612226565b90613c6060e08501612226565b92613c7b610120613c746101008801612230565b9601612230565b956040519a8b9960208b019d8e7f16210483e9c961c9c307e53963eafad0795395f2fce68f0c9c294cca1ac5a06a81526001600160801b039182166020820152911660408201526001600160a01b039182166060820152918116608083015263ffffffff92831660a083015292821660c082015292811660e084015292909216610100820152918116610120830152919091166101408201526101600190565b5190206150bd565b90816020910312610321575160058110156103215790565b908160209103126103215751610358816109b1565b15613d5757565b60405162461bcd60e51b815260206004820152601060248201526f496e76616c69645369676e617475726560801b6044820152606490fd5b90613dd49392959796602060405181810190613daf81612c758885612b6e565b519020809a6040518080998194632dff692d60e01b8352600483019190602083019252565b03915afa908115611d7457613dfb602092613e3097600091613edf575b5061070081610b15565b613e0760e08501612226565b60405163167d0a6960e21b815263ffffffff909116600482015295869190829081906024820190565b03915afa918215611d7457613e97613e7663ffffffff9695613e7060c0956103319b613e69613ea6998c9b600091613eb0575b50612385565b3691612547565b9061512a565b613e866106b66101008501612230565b6001600160a01b0390911614613d50565b613ea08161344d565b01612226565b92169116146123d1565b613ed2915060203d602011613ed8575b613eca81836124dd565b810190613d3b565b38613e63565b503d613ec0565b613eff9150843d8611613f05575b613ef781836124dd565b810190613d23565b38613df1565b503d613eed565b15613f1357565b60405162461bcd60e51b8152602060048201526014602482015273496e76616c696420686f6f6b206164647265737360601b6044820152606490fd5b91908035613f5c81610310565b6001600160a01b0316600090815260086020526040902054613f809060ff16613f0c565b613fbb613f926106b660408601612230565b613f9f6101008601612230565b613fa884612230565b90613fb561069088612297565b92614613565b613fc483614138565b1561407d57613ff8613fe3613fd883612230565b9260608101906140ba565b606086019391613ff285612230565b926151b6565b906140576140516106906020870161401d61401561069083612297565b8710156140ec565b61404c61402986612230565b9861404061012061403989612230565b9201612230565b61118161069085612297565b612297565b836126e7565b80614063575b50509190565b61406f61407692612230565b3390613b0e565b388061405d565b915061035861408b83612230565b61077e60406140af6140a060608801886140ba565b602089019591613ff287612230565b9501358510156140ec565b903590601e198136030182121561032157018035906001600160401b0382116103215760200191813603831361032157565b156140f357565b60405162461bcd60e51b815260206004820152601d60248201527f496e73756666696369656e74206f75747075742066726f6d20686f6f6b0000006044820152606490fd5b63ffffffff8060e060c08401359361414f856103a4565b013561415a816103a4565b1691161490565b1561416857565b60405162461bcd60e51b815260206004820152601060248201526f4f72646572206e6f742061637469766560801b6044820152606490fd5b9291906141ac8461344d565b6141c360e085019163ffffffff80613ea685612226565b63ffffffff6141f9612d196141f360c060405160208101906141e981612c758d85612b6e565b5190209801612226565b93612226565b91160361426657604051632dff692d60e01b81526004810184905290602090829060249082905afa908115611d745761033191600191600091614247575b5061424181610b15565b14614161565b614260915060203d602011613f0557613ef781836124dd565b38614237565b604051632dff692d60e01b81526004810184905290602090829060249082905afa8015611d7457610331916000916142a9575b506142a381610b15565b15614161565b6142c2915060203d602011613f0557613ef781836124dd565b38614299565b908160005260076020526142e76040600020600260ff19825416179055565b63ffffffff60c08201356142fa816103a4565b166000908152600a60209081526040808320338452909152902080549091600160401b8210156124bd57614358827f7f80314442bfb82d1f9dfa4f96cbc84ae8fef158c7a93315024778ca3fc1671694600161369d950181556103ed565b81549060031b9086821b91600019901b191617905560405191829182612b6e565b1561438057565b60405162461bcd60e51b815260206004820152601860248201527710985b185b98d9481bdc195c985d1a5bdb8819985a5b195960421b6044820152606490fd5b610100820180519193916001600160a01b03166143dc906103bd565b604084810180516001600160a01b031660009081526020939093529120909390546001600160801b03169282614411826103bd565b86516001600160a01b03166000908152602091909152604090205460801c81519093908190889085906001600160a01b031661444c906103bd565b82516001600160a01b0316600090815260209190915260409020546001600160801b031683516001600160801b03166001600160801b031690600160801b600190031610156144d561451f610ad761450f61450961454f9f6144da6144d56145499d61453b9c6144e69b6144fc9561452d9c61458d575b505090516001600160a01b0316919050565b6103bd565b89516001600160a01b03165b60018060a01b0316600052602052604060002090565b546001600160801b031690565b9a6103bd565b86516001600160a01b03166144e6565b99516001600160a01b031690565b91516001600160a01b031690565b50516001600160801b031690565b936152a4565b614566610eac826000526007602052604060002090565b7fe82916be8cebf4000a0d08979cca286e4bfe07a019f19c0c930305aceacdcaf6600080a2565b614602926145f06145e26145f6936144e661452d6145dc6145ca6145ba6144d58d5160018060a01b031690565b85516001600160a01b03166144e6565b87516001600160801b03165b90613979565b976103bd565b91516001600160801b031690565b9061527e565b8161460b575b50614379565b8f8e908d6144c3565b9050386145fc565b6040516323b872dd60e01b60208201526001600160a01b03928316602482015292909116604483015260648083019390935291815261033191613bd06084836124dd565b604090815161466683826124dd565b6004815263416f726960e01b602082015291614684815191826124dd565b6005815264302e332e3160d81b602082015290565b156146a057565b60405162461bcd60e51b81526020600482015260186024820152772737ba1037b7103232b9ba34b730ba34b7b71031b430b4b760411b6044820152606490fd5b156146e757565b60405162461bcd60e51b815260206004820152604860248201527f4f6e6c792077686974656c697374656420736f6c7665722c206f66666572657260448201527f2c206f7220726563697069656e742028616674657220657870697279292063616064820152671b8818d85b98d95b60c21b608482015260a490fd5b929060209161478b6147ab9463ffffffff8061478160e08a01612226565b9216911614614699565b6040518080958194632dff692d60e01b8352600483019190602083019252565b03915afa8015611d74576147ca916000916142a957506142a381610b15565b604051631f798dcd60e21b81526001600160a01b038316600482015292602090849060249082905afa918215611d7457610331936000936148a3575b508215614863575b821561481c575b50506146e0565b90915061482f6106b66101208401612230565b6001600160a01b0390911614908161484a575b503880614815565b61485b915060a0612d199101612226565b421138614842565b91506148756106b66101008301612230565b6001600160a01b038316148061488c575b9161480e565b5061489c612d1960a08301612226565b4211614886565b6148bd91935060203d602011613ed857613eca81836124dd565b9138614806565b60021115610b1f57565b60405190600160f81b60208301526021820152602181526103586041826124dd565b6103589392916148fe613781565b506149226040519361490f856124a2565b3485526000602086015233953691612547565b91613888565b906149e461069060206149dd61035894803561494381610310565b6001600160a01b031660009081526008845260409020546149669060ff16613f0c565b60608101358015614a175783820161498061065a82612230565b156149ec575060008080808461499a6149b9963414614ad1565b6149a96106b66106b689612230565b5af16149b3612b3e565b50614b31565b6149d06149c582612230565b9160408101906140ba565b90613ff260608a01612230565b9401612297565b821015614b7d565b90614a016106b6614a129361077e3415614a63565b614a0a84612230565b903390614613565b6149b9565b50614a1234614a2257565b60405162461bcd60e51b8152602060048201526019602482015278139bc81b985d1a5d99481d1bdad95b9cc8195e1c1958dd1959603a1b6044820152606490fd5b15614a6a57565b60405162461bcd60e51b815260206004820152603960248201527f4e6f206e617469766520746f6b656e732073686f756c642062652073656e74206044820152783337b91022a921991810383932b332b93932b2103a37b5b2b760391b6064820152608490fd5b15614ad857565b60405162461bcd60e51b815260206004820152602b60248201527f496e636f7272656374206e617469766520616d6f756e7420666f72207072656660448201526a32b93932b2103a37b5b2b760a91b6064820152608490fd5b15614b3857565b60405162461bcd60e51b815260206004820152601e60248201527f4e6174697665207472616e7366657220746f20686f6f6b206661696c656400006044820152606490fd5b15614b8457565b60405162461bcd60e51b815260206004820152603560248201527f486f6f6b206d7573742070726f76696465206174206c656173742074686520656044820152741e1c1958dd1959081bdd5d1c1d5d08185b5bdd5b9d605a1b6064820152608490fd5b15614bee57565b60405162461bcd60e51b81526020600482015260136024820152722737ba1037b71039b7bab931b29031b430b4b760691b6044820152606490fd5b15614c3057565b60405162461bcd60e51b815260206004820152603b60248201527f43726f73732d636861696e206f7264657273206d7573742062652063616e636560448201527f6c6c65642066726f6d2064657374696e6174696f6e20636861696e00000000006064820152608490fd5b15614ca257565b60405162461bcd60e51b815260206004820152603060248201527f4f6e6c7920736f6c766572206f72206f6666657265722028616674657220657860448201526f1c1a5c9e4a4818d85b8818d85b98d95b60821b6064820152608490fd5b92614d2e9160209161478b60c087019563ffffffff80614d24895163ffffffff1690565b9216911614614be7565b03915afa918215611d7457614d576001614d8294614d6194600091614247575061424181610b15565b5163ffffffff1690565b63ffffffff614d7a612d1960e086015163ffffffff1690565b911614614c29565b604051631f798dcd60e21b81526001600160a01b038316600482015292602090849060249082905afa918215611d745761033193600093614e20575b508215614dcd575b5050614c9b565b61010082015191925090614de9906001600160a01b03166106b6565b6001600160a01b03909116149081614e04575b503880614dc6565b60a00151614e18915063ffffffff16612d19565b421138614dfc565b614e3a91935060203d602011613ed857613eca81836124dd565b9138614dbe565b806000526007602052614e67600160ff60406000205416614e6181610b15565b14613006565b614ee7614e86614e81836000526005602052604060002090565b612d9b565b80516040820151610100909201516001600160801b03909116916001600160a01b039182169116614eb78382613a73565b614ece611576866000526007602052604060002090565b6119bc610a7f84614ee2846108a4876103bd565b613979565b7fe8d9861dbc9c663ed3accd261bbe2fe01e0d3d9e5f51fa38523b265c7757a93a600080a2565b90919060ff1660018103614f2457505050602190565b614f49576103589161ffff91821680821015614f4257505b166153d9565b9050614f3c565b60405162461bcd60e51b8152602060048201526014602482015273496e76616c6964206d657373616765207479706560601b6044820152606490fd5b9060408282031261032157610358916137a9565b6001600160801b038111614fb3576001600160801b031690565b6306dfcc6560e41b600052608060045260245260446000fd5b6001600160801b0391821690821601919082116126f457565b803403614fef5790565b6304fb820960e51b6000523460045260246000fd5b60405163393f876560e21b81527f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b03169190602081600481865afa908115611d7457600091615082575b506001600160a01b031691821561507157610331923390614613565b6329b99a9560e11b60005260046000fd5b90506020813d6020116150b5575b8161509d602093836124dd565b8101031261032157516150af81610310565b38615055565b3d9150615090565b906150c6614657565b604093919351937f91ab3d17e3a50a9d89e63fd30b92be7f5336b03b287bb946787a83a9d62a276660005260208151910120602052602081519101206040523060605260806000206020526119016000526040526042601e20916040526000606052565b919091604051928051806040146151945760411461515557505050505b638baa579f6000526004601cfd5b602091606082015160001a835260408201516060525b60005201516040526020600160806000825afa519160006060526040523d610331575050615147565b506020916040820151601b8160ff1c01845260018060ff1b031660605261516b565b6000919392908291826151c930876155b6565b96826040519384928337810182815203925af16151e4612b3e565b501561524b576151f59030906155b6565b9080821061520657610358916126e7565b60405162461bcd60e51b815260206004820152601f60248201527f486f6f6b2064656372656173656420636f6e74726163742062616c616e6365006044820152606490fd5b60405162461bcd60e51b815260206004820152600b60248201526a10d85b1b0819985a5b195960aa1b6044820152606490fd5b8054909160809190911c9081016001600160801b03169081106139b9576139b4916126f9565b92939192906001600160801b03906152bd908490614fcc565b166001600160801b0390911603615339576001600160801b03916152e19190614fcc565b166001600160801b03909116036152f457565b60405162461bcd60e51b815260206004820152601b60248201527f496e636f6e73697374656e7420736f6c7665722062616c616e636500000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601c60248201527f496e636f6e73697374656e74206f6666657265722062616c616e6365000000006044820152606490fd5b906000602091828151910182855af115612e85576000513d6153d057506001600160a01b0381163b155b6153af5750565b635274afe760e01b60009081526001600160a01b0391909116600452602490fd5b600114156153a8565b8060051b90808204602014901517156126f457601701806017116126f45790565b90156104055790565b9190916017831061550c576154188382615678565b9390916154268583836156bc565b60005b61ffff8616811061543c57505050505050565b60018161544d61ffff938686615741565b868861547660e061546b614e81866000526005602052604060002090565b015163ffffffff1690565b63ffffffff821663ffffffff82160361549c57505061549491615805565b019050615429565b7fbb563f7e333f32ed0571f8dc4913648b41737753db5df83c58657c6bfcc2ef569250615504604051928392839060a09263ffffffff809216835216602082015260606040820152600c60608201526b08ad2c840dad2e6dac2e8c6d60a31b60808201520190565b0390a2615494565b606460405162461bcd60e51b815260206004820152602060248201527f5061796c6f616420746f6f2073686f727420666f7220736574746c656d656e746044820152fd5b90602103615565576001610331910135614e41565b60405162461bcd60e51b815260206004820152602360248201527f496e76616c69642063616e63656c6c6174696f6e207061796c6f6164206c656e6044820152620cee8d60eb1b6064820152608490fd5b6001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81036155df57503190565b6040516370a0823160e01b81526001600160a01b039092166004830152602090829060249082905afa908115611d745760009161561a575090565b610358915060203d602011613b0757613af981836124dd565b1561563a57565b60405162461bcd60e51b8152602060048201526016602482015275092dcecc2d8d2c840e0c2f2d8dec2c840d8cadccee8d60531b6044820152606490fd5b9190916156886017841015615633565b600181013560601c928060151015610405576016101561040557601581013560f01c61ff00166016919091013560f81c1790565b5090621fffe061ffff82169160051b1690808204602014901517156126f45760170190816017116126f457036156ee57565b60405162461bcd60e51b815260206004820152602560248201527f496e76616c6964207061796c6f6164206c656e67746820666f7220736574746c604482015264195b595b9d60da1b6064820152608490fd5b9061574f6017821015615633565b60161981019081116126f45760051c8210156157715760179160051b01013590565b60405162461bcd60e51b8152602060048201526013602482015272496e646578206f7574206f6620626f756e647360681b6044820152606490fd5b906040516157b9816124a2565b91546001600160801b038116835260801c6020830152565b815181546001600160801b0319166001600160801b039190911617815561033191602001516001600160801b0316906126f9565b90600161581f6106f0846000526007602052604060002090565b61582881610b15565b0361595657615844614e81836000526005602052604060002090565b6101008101805191929091615861906001600160a01b03166103bd565b6040840180519093916158869161588191906001600160a01b03166144e6565b6157ac565b9061589661588161450f856103bd565b946158e36158d36158c36158b36144d5865160018060a01b031690565b88516001600160a01b03166144e6565b83516001600160801b03166145d6565b916145f06145e26144da886103bd565b901590811561594d575b5061590e575050505050614566610eac826000526007602052604060002090565b51610331955061594893926144e69261452d926144d591908790615938906001600160a01b031684565b87516001600160a01b03166144e6565b6157d1565b905015386158ed565b505056fe9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eba26469706673582212202463fc3c173b6a5cc2bef337128c18ef1cd9704d7eb70d9979f92d42aa4971ad64736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001a44076050125825900e736c501f859c50fe728c000000000000000000000000941327e206b8d8cfe1014a8a95b05e1536dfd00d00000000000000000000000000000000000000000000000000000000000075950000000000000000000000000000000000000000000000000000000000000064
-----Decoded View---------------
Arg [0] : _endpoint (address): 0x1a44076050125825900e736c501f859c50fE728c
Arg [1] : _owner (address): 0x941327E206b8d8cfe1014A8A95B05E1536dFD00d
Arg [2] : _eid (uint32): 30101
Arg [3] : _maxFillsPerSettle (uint16): 100
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000001a44076050125825900e736c501f859c50fe728c
Arg [1] : 000000000000000000000000941327e206b8d8cfe1014a8a95b05e1536dfd00d
Arg [2] : 0000000000000000000000000000000000000000000000000000000000007595
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000064
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.