Overview
APE Balance
APE Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
SpokeMessageReceiver
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 10000 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; import {OwnableUpgradeable} from '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol'; import {ERC20} from '@openzeppelin/contracts/token/ERC20/ERC20.sol'; import {AssetUtils} from 'contracts/common/AssetUtils.sol'; import {Constants as Common} from 'contracts/common/Constants.sol'; import {MessageLib} from 'contracts/common/MessageLib.sol'; import {TypeCasts} from 'contracts/common/TypeCasts.sol'; import {IMessageReceiver} from 'interfaces/common/IMessageReceiver.sol'; import {ISettlementModule} from 'interfaces/common/ISettlementModule.sol'; import {ISpokeGateway} from 'interfaces/intent/ISpokeGateway.sol'; import {SpokeStorage} from 'contracts/intent/SpokeStorage.sol'; contract SpokeMessageReceiver is SpokeStorage, OwnableUpgradeable, IMessageReceiver { using TypeCasts for bytes32; /** * @notice Checks that the function is called by the gateway */ modifier onlyAuthorized() { if (msg.sender != owner() && (msg.sender != address(gateway) || paused)) { revert EverclearSpoke_Unauthorized(); } _; } /// @inheritdoc IMessageReceiver function receiveMessage( bytes memory _message ) external onlyAuthorized { (MessageLib.MessageType _messageType, bytes memory _data) = MessageLib.parseMessage(_message); if (_messageType == MessageLib.MessageType.SETTLEMENT) { _handleBatchSettlement(_data); } else if (_messageType == MessageLib.MessageType.VAR_UPDATE) { (bytes32 _updateVariable, bytes memory _updateData) = MessageLib.parseVarUpdateMessage(_data); _handleVarUpdate(_updateVariable, _updateData); } else { revert EverclearSpoke_InvalidMessageType(); } } /** * @notice handle a variable update message * @param _updateVariable The hash of the variable being updated * @param _updateData The data of the update */ function _handleVarUpdate(bytes32 _updateVariable, bytes memory _updateData) internal { if (_updateVariable == Common.GATEWAY_HASH) { address _newGateway = MessageLib.parseAddressUpdateMessage(_updateData).toAddress(); _updateGateway(_newGateway); } else if (_updateVariable == Common.MAILBOX_HASH) { address _newMailbox = MessageLib.parseAddressUpdateMessage(_updateData).toAddress(); _updateMailbox(_newMailbox); } else if (_updateVariable == Common.LIGHTHOUSE_HASH) { address _newLighthouse = MessageLib.parseAddressUpdateMessage(_updateData).toAddress(); _updateLighthouse(_newLighthouse); } else if (_updateVariable == Common.WATCHTOWER_HASH) { address _newWatchtower = MessageLib.parseAddressUpdateMessage(_updateData).toAddress(); _updateWatchtower(_newWatchtower); } else { revert EverclearSpoke_InvalidVarUpdate(); } } /** * @notice Handles a batch of settlement messages * @param _data The batch of settlement messages */ function _handleBatchSettlement( bytes memory _data ) internal { Settlement[] memory _settlementMessage = MessageLib.parseSettlementBatch(_data); for (uint256 _i; _i < _settlementMessage.length; _i++) { Settlement memory _message = _settlementMessage[_i]; _handleSettlement(_message); } } /** * @notice Handles a settlement message * @param _message The settlement message */ function _handleSettlement( Settlement memory _message ) internal { address _asset = _message.asset.toAddress(); address _recipient = _message.recipient.toAddress(); IntentStatus _intentStatus = status[_message.intentId]; // if already settled, ignore (shouldn't happen) if (_intentStatus == IntentStatus.SETTLED || _intentStatus == IntentStatus.SETTLED_AND_MANUALLY_EXECUTED) { return; } status[_message.intentId] = IntentStatus.SETTLED; uint256 _amount = AssetUtils.normalizeDecimals(Common.DEFAULT_NORMALIZED_DECIMALS, ERC20(_asset).decimals(), _message.amount); // after decimals normalization, the _amount can be 0 as result of loss of precision, check if it's > 0 if (_amount > 0) { // if amount is > 0 proceed with the settlement according to the strategy // fetch strategy for asset Strategy _strategy = strategies[_asset]; if (_strategy == Strategy.DEFAULT) { // default strategy if (_message.updateVirtualBalance) { balances[_message.asset][_message.recipient] += _amount; } else { // if transfer fails (eg. blacklisted recipient), increase virtual balance instead bytes memory _transferData = abi.encodeWithSignature('transfer(address,uint256)', _recipient, _amount); (bool _success, bytes memory _res) = _asset.call(_transferData); // doing the transfer as a low-level call to avoid reverting the whole batch if the transfer calls revert // applying the same checks as `SafeERC20` for the `transfer` as it can't be wrapped in a `try/catch` block if (!_success || (_res.length != 0 && !abi.decode(_res, (bool)))) { balances[_message.asset][_message.recipient] += _amount; emit AssetTransferFailed(_asset, _recipient, _amount); } } } else { // dedicated strategy ISettlementModule _module = modules[_strategy]; address _mintRecipient = _message.updateVirtualBalance ? address(this) : _recipient; bool _success = _module.handleMintStrategy(_asset, _mintRecipient, _recipient, _amount, ''); if (_success && _message.updateVirtualBalance) { balances[_message.asset][_message.recipient] += _amount; } else if (!_success) { emit AssetMintFailed(_asset, _recipient, _amount, _strategy); } } } emit Settled(_message.intentId, _recipient, _asset, _amount); } /** * @notice Update the gateway * @param _newGateway The new gateway address */ function _updateGateway( address _newGateway ) internal validAddress(_newGateway) { address _oldGateway = address(gateway); gateway = ISpokeGateway(_newGateway); emit GatewayUpdated(_oldGateway, _newGateway); } /** * @notice Update the local mailbox address * @param _newMailbox The new mailbox address */ function _updateMailbox( address _newMailbox ) internal { gateway.updateMailbox(_newMailbox); } /** * @notice Update the interchain security module address * @param _newSecurityModule The new security module address */ function _updateSecurityModule( address _newSecurityModule ) internal { gateway.updateSecurityModule(_newSecurityModule); } /** * @notice Update the lighthouse address * @param _newLighthouse The new lighthouse address */ function _updateLighthouse( address _newLighthouse ) internal validAddress(_newLighthouse) { address _oldLighthouse = lighthouse; lighthouse = _newLighthouse; emit LighthouseUpdated(_oldLighthouse, _newLighthouse); } /** * @notice Update the watchtower address * @param _newWatchtower The new watchtower address */ function _updateWatchtower( address _newWatchtower ) internal validAddress(_newWatchtower) { address _oldWatchtower = watchtower; watchtower = _newWatchtower; emit WatchtowerUpdated(_oldWatchtower, _newWatchtower); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @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. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { 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) { OwnableStorage storage $ = _getOwnableStorage(); 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 { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC20Metadata} from "./extensions/IERC20Metadata.sol"; import {Context} from "../../utils/Context.sol"; import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. */ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { mapping(address account => uint256) private _balances; mapping(address account => mapping(address spender => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows _totalSupply += value; } else { uint256 fromBalance = _balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. _balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. _totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. _balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * ``` * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } _allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner` s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; /** * @title AssetUtils * @notice Library for asset utility functions */ library AssetUtils { /** * @notice This function translates the _amount in _in decimals * to _out decimals * * @param _in The decimals of the asset in / amount in * @param _out The decimals of the target asset * @param _amount The value to normalize to the `_out` decimals * @return _normalized Normalized decimals. */ function normalizeDecimals(uint8 _in, uint8 _out, uint256 _amount) internal pure returns (uint256 _normalized) { if (_in == _out) { return _amount; } // Convert this value to the same decimals as _out if (_in < _out) { _normalized = _amount * (10 ** (_out - _in)); } else { _normalized = _amount / (10 ** (_in - _out)); } } /** * @notice Get the hash of an asset * @param _asset The address of the asset * @param _domain The domain of the asset * @return _assetHash The hash of the asset */ function getAssetHash(bytes32 _asset, uint32 _domain) internal pure returns (bytes32 _assetHash) { return keccak256(abi.encode(_asset, _domain)); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; library Constants { // Default normalized decimals for tokens uint8 public constant DEFAULT_NORMALIZED_DECIMALS = 18; // 1/10 of a basis point denominator uint24 public constant DBPS_DENOMINATOR = 100_000; // Precomputed hashes (reduce gas costs) bytes32 public constant GATEWAY_HASH = keccak256(abi.encode('GATEWAY')); bytes32 public constant MAILBOX_HASH = keccak256(abi.encode('MAILBOX')); bytes32 public constant LIGHTHOUSE_HASH = keccak256(abi.encode('LIGHTHOUSE')); bytes32 public constant WATCHTOWER_HASH = keccak256(abi.encode('WATCHTOWER')); bytes32 public constant MAX_FEE_HASH = keccak256(abi.encode('MAX_FEE')); bytes32 public constant INTENT_TTL_HASH = keccak256(abi.encode('INTENT_TTL')); // Default gas limit for external calls uint256 public constant DEFAULT_GAS_LIMIT = 50_000; // Maximum calldata size for external calls uint256 public constant MAX_CALLDATA_SIZE = 50_000; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; import {IEverclear} from 'interfaces/common/IEverclear.sol'; library MessageLib { /*////////////////////////////////////////////////////////////// ENUMS //////////////////////////////////////////////////////////////*/ /** * @dev Enum for message types * INTENT: Intent message type * FILL: Fill message type * SETTLEMENT: Settlement message type * VAR_UPDATE: Variable update message type */ enum MessageType { INTENT, FILL, SETTLEMENT, VAR_UPDATE } /*////////////////////////////////////////////////////////////// GENERAL PURPOSE FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @dev Formats a message with a message type and data * @param _messageType The message type * @param _data The data to send in the message * @return _message The formatted message */ function formatMessage(MessageType _messageType, bytes memory _data) internal pure returns (bytes memory _message) { _message = abi.encode(uint8(_messageType), _data); } /** * @dev Parses a message into its message type and data * @param _message The message to parse * @return _messageType The message type * @return _data The data in the message */ function parseMessage( bytes memory _message ) internal pure returns (MessageType _messageType, bytes memory _data) { uint8 _msgTypeNumber; (_msgTypeNumber, _data) = abi.decode(_message, (uint8, bytes)); _messageType = MessageType(_msgTypeNumber); } /*////////////////////////////////////////////////////////////// MESSAGE FORMATTING //////////////////////////////////////////////////////////////*/ /** * @dev Formats an intent message * @param _intents Array of intents * @return _message The formatted intent message */ function formatIntentMessageBatch( IEverclear.Intent[] memory _intents ) internal pure returns (bytes memory _message) { _message = formatMessage(MessageType.INTENT, abi.encode(_intents)); } /** * @dev Formats a fill message * @param _fillMessages Array of fill messages * @return _message The formatted fill message */ function formatFillMessageBatch( IEverclear.FillMessage[] memory _fillMessages ) internal pure returns (bytes memory _message) { _message = formatMessage(MessageType.FILL, abi.encode(_fillMessages)); } /** * @dev Formats a settlement message * @param _settlementMessages Array of settlement messages * @return _message The formatted settlement message */ function formatSettlementBatch( IEverclear.Settlement[] memory _settlementMessages ) internal pure returns (bytes memory _message) { _message = formatMessage(MessageType.SETTLEMENT, abi.encode(_settlementMessages)); } /** * @dev Formats a var update message * @param _data The data (encoded variable) * @return _message The formatted var update message */ function formatVarUpdateMessage( bytes memory _data ) internal pure returns (bytes memory _message) { _message = formatMessage(MessageType.VAR_UPDATE, _data); } /** * @dev Formats an address updating message (Mailbox, SecurityModule, Gateway) * @param _updateVariable the name of the variable being updated * @param _address The new address * @return _message The formatted address update message */ function formatAddressUpdateMessage( bytes32 _updateVariable, bytes32 _address ) internal pure returns (bytes memory _message) { _message = formatVarUpdateMessage(abi.encode(_updateVariable, abi.encode(_address))); } /** * @dev Formats a uint updating message (MaxRoutersFee) * @param _updateVariable the hashed name of the variable being updated * @param _value The new value * @return _message The formatted uint update message */ function formatUintUpdateMessage( bytes32 _updateVariable, uint256 _value ) internal pure returns (bytes memory _message) { _message = formatVarUpdateMessage(abi.encode(_updateVariable, abi.encode(_value))); } /*////////////////////////////////////////////////////////////// MESSAGE PARSING //////////////////////////////////////////////////////////////*/ /** * @dev Parses an intent message * @param _data The intent message data * @return _intents Array of decoded intents */ function parseIntentMessageBatch( bytes memory _data ) internal pure returns (IEverclear.Intent[] memory _intents) { (_intents) = abi.decode(_data, (IEverclear.Intent[])); } /** * @dev Parses a fill message * @param _data The packed fill message data * @return _fillMessages Array of fill messages */ function parseFillMessageBatch( bytes memory _data ) internal pure returns (IEverclear.FillMessage[] memory _fillMessages) { (_fillMessages) = abi.decode(_data, (IEverclear.FillMessage[])); } /** * @dev Parses a settlement message * @param _data The packed settlement message data * @return _settlementMessages Array of settlement messages */ function parseSettlementBatch( bytes memory _data ) internal pure returns (IEverclear.Settlement[] memory _settlementMessages) { (_settlementMessages) = abi.decode(_data, (IEverclear.Settlement[])); } /** * @dev Parses a var update message * @param _data The abi encoded variable * @return _updateVariable The hashed name of the variable being updated * @return _varData The encoded variable data */ function parseVarUpdateMessage( bytes memory _data ) internal pure returns (bytes32 _updateVariable, bytes memory _varData) { (_updateVariable, _varData) = abi.decode(_data, (bytes32, bytes)); } /** * @dev Parses an address update message * @param _data The abi encoded address * @return _address The decoded address */ function parseAddressUpdateMessage( bytes memory _data ) internal pure returns (bytes32 _address) { _address = abi.decode(_data, (bytes32)); } /** * @dev Parses a uint update message * @param _data The abi encoded uint * @return _value The decoded uint */ function parseUintUpdateMessage( bytes memory _data ) internal pure returns (uint256 _value) { _value = abi.decode(_data, (uint256)); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity 0.8.23; /** * @title TypeCasts * @notice Library for type casts */ library TypeCasts { // alignment preserving cast /** * @notice Cast an address to a bytes32 * @param _addr The address to cast */ function toBytes32( address _addr ) internal pure returns (bytes32) { return bytes32(uint256(uint160(_addr))); } // alignment preserving cast /** * @notice Cast a bytes32 to an address * @param _buf The bytes32 to cast */ function toAddress( bytes32 _buf ) internal pure returns (address) { return address(uint160(uint256(_buf))); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; /** * @title IMessageReceiver * @notice Interface for the transport layer communication with the message receiver */ interface IMessageReceiver { /*/////////////////////////////////////////////////////////////// LOGIC //////////////////////////////////////////////////////////////*/ /** * @notice Receive a message from the transport layer * @param _message The message to receive encoded as bytes * @dev This function should be called by the the gateway contract */ function receiveMessage( bytes calldata _message ) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; /** * @title ISettlementModule * @notice Interface for the base settlement module */ interface ISettlementModule { /*/////////////////////////////////////////////////////////////// LOGIC //////////////////////////////////////////////////////////////*/ /** * @notice Handle a mint action for a specific strategy * @param _asset The address of the asset to mint * @param _recipient The recipient of the minted assets * @param _fallbackRecipient The fallback recipient of the minted assets (in case of failure) * @param _amount The amount to mint * @param _data Extra data needed by some modules * @return _success The outcome of the minting strategy * @dev In case of failure, the parent module will handle the operation accordingly */ function handleMintStrategy( address _asset, address _recipient, address _fallbackRecipient, uint256 _amount, bytes calldata _data ) external returns (bool _success); /** * @notice Handle a burn action for a specific strategy * @param _asset The address of the asset to burn * @param _user The user whose assets are being burned * @param _amount The amount to burn * @param _data Extra data needed by some modules * @dev In case of failure, the `newIntent` flow will revert */ function handleBurnStrategy(address _asset, address _user, uint256 _amount, bytes calldata _data) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; import {IGateway} from 'interfaces/common/IGateway.sol'; /** * @title ISpokeGateway * @notice Interface for the SpokeGateway contract, sends and receives messages to and from the transport layer */ interface ISpokeGateway is IGateway { /*/////////////////////////////////////////////////////////////// LOGIC //////////////////////////////////////////////////////////////*/ /** * @notice Initialize Gateway variables * @param _owner The address of the owner * @param _mailbox The address of the local mailbox * @param _receiver The address of the local message receiver (EverclearSpoke) * @param _interchainSecurityModule The address of the chosen interchain security module * @param _everclearId The id of the Everclear domain * @param _hubGateway The bytes32 representation of the Hub gateway * @dev Only called once on initialization */ function initialize( address _owner, address _mailbox, address _receiver, address _interchainSecurityModule, uint32 _everclearId, bytes32 _hubGateway ) external; /*/////////////////////////////////////////////////////////////// VIEWS //////////////////////////////////////////////////////////////*/ /** * @notice Returns the Everclear hub chain id * @return _hubChainId The Everclear chain id */ function EVERCLEAR_ID() external view returns (uint32 _hubChainId); /** * @notice Returns the `HubGateway` gateway address * @return _hubGateway The `HubGateway` address */ function EVERCLEAR_GATEWAY() external view returns (bytes32 _hubGateway); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; import {QueueLib} from 'contracts/common/QueueLib.sol'; import {IPermit2} from 'interfaces/common/IPermit2.sol'; import {ISettlementModule} from 'interfaces/common/ISettlementModule.sol'; import {ICallExecutor} from 'interfaces/intent/ICallExecutor.sol'; import {ISpokeGateway} from 'interfaces/intent/ISpokeGateway.sol'; import {ISpokeStorage} from 'interfaces/intent/ISpokeStorage.sol'; /** * @title SpokeStorage * @notice Storage layout and modifiers for the `EverclearSpoke` */ abstract contract SpokeStorage is ISpokeStorage { /// @inheritdoc ISpokeStorage bytes32 public constant FILL_INTENT_FOR_SOLVER_TYPEHASH = keccak256( 'function fillIntentForSolver(address _solver, Intent calldata _intent, uint256 _nonce, uint24 _fee, bytes memory _signature)' ); /// @inheritdoc ISpokeStorage bytes32 public constant PROCESS_INTENT_QUEUE_VIA_RELAYER_TYPEHASH = keccak256( 'function processIntentQueueViaRelayer(uint32 _domain, Intent[] memory _intents, address _relayer, uint256 _ttl, uint256 _nonce, uint256 _bufferDBPS, bytes memory _signature)' ); /// @inheritdoc ISpokeStorage bytes32 public constant PROCESS_FILL_QUEUE_VIA_RELAYER_TYPEHASH = keccak256( 'function processFillQueueViaRelayer(uint32 _domain, uint32 _amount, address _relayer, uint256 _ttl, uint256 _nonce, uint256 _bufferDBPS, bytes memory _signature)' ); /// @inheritdoc ISpokeStorage IPermit2 public constant PERMIT2 = IPermit2(0x000000000022D473030F116dDEE9F6B43aC78BA3); /// @inheritdoc ISpokeStorage uint32 public EVERCLEAR; /// @inheritdoc ISpokeStorage uint32 public DOMAIN; /// @inheritdoc ISpokeStorage address public lighthouse; /// @inheritdoc ISpokeStorage address public watchtower; /// @inheritdoc ISpokeStorage address public messageReceiver; /// @inheritdoc ISpokeStorage ISpokeGateway public gateway; /// @inheritdoc ISpokeStorage ICallExecutor public callExecutor; /// @inheritdoc ISpokeStorage bool public paused; /// @inheritdoc ISpokeStorage uint64 public nonce; /// @inheritdoc ISpokeStorage uint256 public messageGasLimit; /// @inheritdoc ISpokeStorage mapping(bytes32 _asset => mapping(bytes32 _user => uint256 _amount)) public balances; /// @inheritdoc ISpokeStorage mapping(bytes32 _intentId => IntentStatus status) public status; /// @inheritdoc ISpokeStorage mapping(address _asset => Strategy _strategy) public strategies; /// @inheritdoc ISpokeStorage mapping(Strategy _strategy => ISettlementModule _module) public modules; /** * @notice The intent queue */ QueueLib.IntentQueue public intentQueue; /** * @notice The fill queue */ QueueLib.FillQueue public fillQueue; /** * @notice Checks that the address is valid */ modifier validAddress( address _address ) { if (_address == address(0)) { revert EverclearSpoke_ZeroAddress(); } _; } /** * @notice Checks that the local domain is included in the destinations * @param _intent The intent to check */ modifier validDestination( Intent calldata _intent ) { // when it's an xcall executable, destinations.length is always 1 if (_intent.destinations[0] != DOMAIN) { revert EverclearSpoke_WrongDestination(); } _; } /** * @notice Checks when processing a queue that the amount is valid for the queue being processed * @param _first The first index of the queue * @param _last The last index of the queue * @param _amount The amount to process */ modifier validQueueAmount(uint256 _first, uint256 _last, uint256 _amount) { if (_amount == 0) { revert EverclearSpoke_ProcessQueue_ZeroAmount(); } if (_first + _amount - 1 > _last) { revert EverclearSpoke_ProcessQueue_InvalidAmount(_first, _last, _amount); } _; } /** * @notice Checks that the contract is not paused */ modifier whenNotPaused() { if (paused) { revert EverclearSpoke_Paused(); } _; } /** * @notice Checks that the caller has access to pause the contract */ modifier hasPauseAccess() { if (msg.sender != lighthouse && msg.sender != watchtower) { revert EverclearSpoke_Pause_NotAuthorized(); } _; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } 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.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ 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.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// 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.0.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; /** * @title IEverclear * @notice Common interface for EverclearHub and EverclearSpoke */ interface IEverclear { /*////////////////////////////////////////////////////////////// ENUMS //////////////////////////////////////////////////////////////*/ /** * @notice Enum representing statuses of an intent */ enum IntentStatus { NONE, // 0 ADDED, // 1 DEPOSIT_PROCESSED, // 2 FILLED, // 3 ADDED_AND_FILLED, // 4 INVOICED, // 5 SETTLED, // 6 SETTLED_AND_MANUALLY_EXECUTED, // 7 UNSUPPORTED, // 8 UNSUPPORTED_RETURNED // 9 } /** * @notice Enum representing asset strategies */ enum Strategy { DEFAULT, XERC20 } /*/////////////////////////////////////////////////////////////// STRUCTS //////////////////////////////////////////////////////////////*/ /** * @notice The structure of an intent * @param initiator The address of the intent initiator * @param receiver The address of the intent receiver * @param inputAsset The address of the intent asset on origin * @param outputAsset The address of the intent asset on destination * @param maxFee The maximum fee that can be taken by solvers * @param origin The origin chain of the intent * @param destinations The possible destination chains of the intent * @param nonce The nonce of the intent * @param timestamp The timestamp of the intent * @param ttl The time to live of the intent * @param amount The amount of the intent asset normalized to 18 decimals * @param data The data of the intent */ struct Intent { bytes32 initiator; bytes32 receiver; bytes32 inputAsset; bytes32 outputAsset; uint24 maxFee; uint32 origin; uint64 nonce; uint48 timestamp; uint48 ttl; uint256 amount; uint32[] destinations; bytes data; } /** * @notice The structure of a fill message * @param intentId The ID of the intent * @param solver The address of the intent solver in bytes32 format * @param initiator The address of the intent initiator * @param fee The total fee of the expressed in dbps, represents the solver fee plus the sum of protocol fees for the token * @param executionTimestamp The execution timestamp of the intent */ struct FillMessage { bytes32 intentId; bytes32 solver; bytes32 initiator; uint24 fee; uint48 executionTimestamp; } /** * @notice The structure of a settlement * @param intentId The ID of the intent * @param amount The amount of the asset * @param asset The address of the asset * @param recipient The address of the recipient * @param updateVirtualBalance If set to true, the settlement will not be transferred to the recipient in spoke domain and the virtual balance will be increased */ struct Settlement { bytes32 intentId; uint256 amount; bytes32 asset; bytes32 recipient; bool updateVirtualBalance; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import {IMailbox} from '@hyperlane/interfaces/IMailbox.sol'; import {IMessageReceiver} from 'interfaces/common/IMessageReceiver.sol'; interface IGateway { /*/////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ /** * @notice Emitted when the mailbox is updated * @param _oldMailbox The old mailbox address * @param _newMailbox The new mailbox address */ event MailboxUpdated(address _oldMailbox, address _newMailbox); /** * @notice Emitted when the security module is updated * @param _oldSecurityModule The old security module address * @param _newSecurityModule The new security module address */ event SecurityModuleUpdated(address _oldSecurityModule, address _newSecurityModule); /*/////////////////////////////////////////////////////////////// ERRORS //////////////////////////////////////////////////////////////*/ /** * @notice Thrown when the message origin is invalid */ error Gateway_Handle_InvalidOriginDomain(); /** * @notice Thrown when the sender is not the appropriate remote Gateway */ error Gateway_Handle_InvalidSender(); /** * @notice Thrown when the caller is not the local mailbox */ error Gateway_Handle_NotCalledByMailbox(); /** * @notice Thrown when the GasTank does not have enough native asset to cover the fee */ error Gateway_SendMessage_InsufficientBalance(); /** * @notice Thrown when the message dispatcher is not the local receiver */ error Gateway_SendMessage_UnauthorizedCaller(); /** * @notice Thrown when the call returning the unused fee fails */ error Gateway_SendMessage_UnsuccessfulRebate(); /** * @notice Thrown when an address equals the address zero */ error Gateway_ZeroAddress(); /*/////////////////////////////////////////////////////////////// LOGIC //////////////////////////////////////////////////////////////*/ /** * @notice Send a message to the transport layer using the gas tank * @param _chainId The id of the destination chain * @param _message The message to send * @param _fee The fee to send the message * @param _gasLimit The gas limit to use on destination * @return _messageId The id message of the transport layer * @return _feeSpent The fee spent to send the message * @dev only called by the spoke contract */ function sendMessage( uint32 _chainId, bytes memory _message, uint256 _fee, uint256 _gasLimit ) external returns (bytes32 _messageId, uint256 _feeSpent); /** * @notice Send a message to the transport layer * @param _chainId The id of the destination chain * @param _message The message to send * @param _gasLimit The gas limit to use on destination * @return _messageId The id message of the transport layer * @return _feeSpent The fee spent to send the message * @dev only called by the spoke contract */ function sendMessage( uint32 _chainId, bytes memory _message, uint256 _gasLimit ) external payable returns (bytes32 _messageId, uint256 _feeSpent); /** * @notice Updates the mailbox * @param _mailbox The new mailbox address * @dev only called by the `receiver` */ function updateMailbox( address _mailbox ) external; /** * @notice Updates the gateway security module * @param _securityModule The address of the new security module * @dev only called by the `receiver` */ function updateSecurityModule( address _securityModule ) external; /*/////////////////////////////////////////////////////////////// VIEWS //////////////////////////////////////////////////////////////*/ /** * @notice Returns the transport layer message routing smart contract * @dev this is independent of the transport layer used, adopting mailbox name because its descriptive enough * using address instead of specific interface to be independent from HL or any other TL * @return _mailbox The mailbox contract */ function mailbox() external view returns (IMailbox _mailbox); /** * @notice Returns the message receiver for this Gateway (EverclearHub / EverclearSpoke) * @return _receiver The message receiver */ function receiver() external view returns (IMessageReceiver _receiver); /** * @notice Quotes cost of sending a message to the transport layer * @param _chainId The id of the destination chain * @param _message The message to send * @param _gasLimit The gas limit for delivering the message * @return _fee The fee to send the message */ function quoteMessage(uint32 _chainId, bytes memory _message, uint256 _gasLimit) external view returns (uint256 _fee); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; import {IEverclear} from 'interfaces/common/IEverclear.sol'; /** * @title QueueLib * @notice Library for managing queues */ library QueueLib { /** * @notice Structure for the IntentQueue * @dev first should always be initialized to 1 * @param first The first position in the queue * @param last The last position in the queue * @param queue The queue of intent ids */ struct IntentQueue { uint256 first; uint256 last; mapping(uint256 _position => bytes32 _intentId) queue; } /** * @notice Structure for the FillQueue * @dev Member first should always be initialized to 1 * @param first The first position in the queue * @param last The last position in the queue * @param queue The queue of fill messages */ struct FillQueue { uint256 first; uint256 last; mapping(uint256 _position => IEverclear.FillMessage _fillMessage) queue; } /** * @notice Thrown when the queue is empty */ error Queue_EmptyQueue(); /** * @notice Enqueue an intent id to the IntentQueue * @param _queue The IntentQueue * @param _intentId The intent id to enqueue */ function enqueueIntent(IntentQueue storage _queue, bytes32 _intentId) internal { _queue.last += 1; _queue.queue[_queue.last] = _intentId; } /** * @notice Enqueue a fill message to the FillQueue * @param _queue The FillQueue * @param _fillMessage The fill message to enqueue */ function enqueueFill(FillQueue storage _queue, IEverclear.FillMessage memory _fillMessage) internal { _queue.last += 1; _queue.queue[_queue.last] = _fillMessage; } /** * @notice Dequeue an intent id from the IntentQueue * @param _queue The IntentQueue * @return _intentId The dequeued intent id */ function dequeueIntent( IntentQueue storage _queue ) internal returns (bytes32 _intentId) { // non-empty queue check if (_queue.last < _queue.first) revert Queue_EmptyQueue(); _intentId = _queue.queue[_queue.first]; delete _queue.queue[_queue.first]; _queue.first += 1; } /** * @notice Dequeue a fill message from the FillQueue * @param _queue The FillQueue * @return _fillMessage The dequeued fill message */ function dequeueFill( FillQueue storage _queue ) internal returns (IEverclear.FillMessage memory _fillMessage) { // non-empty queue if (_queue.last < _queue.first) revert Queue_EmptyQueue(); _fillMessage = _queue.queue[_queue.first]; delete _queue.queue[_queue.first]; _queue.first += 1; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; /** * @title IPermit2 * @notice Interface for permit2 */ interface IPermit2 { /*/////////////////////////////////////////////////////////////// STRUCTS //////////////////////////////////////////////////////////////*/ /** * @notice Struct for token and amount in a permit message * @param token The token to transfer * @param amount The amount to transfer */ struct TokenPermissions { IERC20 token; uint256 amount; } /** * @notice Struct for the permit2 message * @param permitted The permitted token and amount * @param nonce The unique identifier for this permit * @param deadline The expiration for this permit */ struct PermitTransferFrom { TokenPermissions permitted; uint256 nonce; uint256 deadline; } /** * @notice Struct for the transfer details for permitTransferFrom() * @param to The recipient of the tokens * @param requestedAmount The amount to transfer */ struct SignatureTransferDetails { address to; uint256 requestedAmount; } /*/////////////////////////////////////////////////////////////// LOGIC //////////////////////////////////////////////////////////////*/ /** * @notice Consume a permit2 message and transfer tokens * @param permit The permit message * @param transferDetails The transfer details * @param owner The owner of the tokens * @param signature The signature of the permit */ function permitTransferFrom( PermitTransferFrom calldata permit, SignatureTransferDetails calldata transferDetails, address owner, bytes calldata signature ) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; /** * @title ICallExecutor * @notice Interface for the CallExecutor contract, executes calls to external contracts */ interface ICallExecutor { /** * @notice Safely call a target contract, use when you _really_ really _really_ don't trust the called * contract. This prevents the called contract from causing reversion of the caller in as many ways as we can. * @param _target The address to call * @param _gas The amount of gas to forward to the remote contract * @param _value The value in wei to send to the remote contract * @param _maxCopy The maximum number of bytes of returndata to copy to memory * @param _calldata The data to send to the remote contract * @return _success Whether the call was successful * @return _returnData Returndata as `.call()`. Returndata is capped to `_maxCopy` bytes. */ function excessivelySafeCall( address _target, uint256 _gas, uint256 _value, uint16 _maxCopy, bytes memory _calldata ) external returns (bool _success, bytes memory _returnData); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; import {IEverclear} from 'interfaces/common/IEverclear.sol'; import {IPermit2} from 'interfaces/common/IPermit2.sol'; import {ISettlementModule} from 'interfaces/common/ISettlementModule.sol'; import {ICallExecutor} from 'interfaces/intent/ICallExecutor.sol'; import {ISpokeGateway} from 'interfaces/intent/ISpokeGateway.sol'; /** * @title ISpokeStorage * @notice Interface for the SpokeStorage contract */ interface ISpokeStorage is IEverclear { /*/////////////////////////////////////////////////////////////// STRUCTS //////////////////////////////////////////////////////////////*/ /** * @notice Parameters needed to initiliaze `EverclearSpoke` * @param gateway The local `SpokeGateway` * @param callExecutor The local `CallExecutor` * @param messageReceiver The address for the `SpokeMessageReceiver` module * @param lighthouse The address for the Lighthouse agent * @param watchtower The address for the Watchtower agent * @param hubDomain The chain id for the Everclear domain * @param owner The initial owner of the contract */ struct SpokeInitializationParams { ISpokeGateway gateway; ICallExecutor callExecutor; address messageReceiver; address lighthouse; address watchtower; uint32 hubDomain; address owner; } /*/////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ /** * @notice emitted when the Gateway address is updated * @param _oldGateway The address of the old gateway * @param _newGateway The address of the new gateway */ event GatewayUpdated(address _oldGateway, address _newGateway); /** * @notice emitted when the Lighthouse address is updated * @param _oldLightHouse The address of the old lighthouse * @param _newLightHouse The address of the new lighthouse */ event LighthouseUpdated(address _oldLightHouse, address _newLightHouse); /** * @notice emitted when the Watchtower address is updated * @param _oldWatchtower The address of the old watchtower * @param _newWatchtower The address of the new watchtower */ event WatchtowerUpdated(address _oldWatchtower, address _newWatchtower); /** * @notice emitted when the MessageReceiver address is updated * @param _oldMessageReceiver The address of the old message receiver * @param _newMessageReceiver The address of the new message receiver */ event MessageReceiverUpdated(address _oldMessageReceiver, address _newMessageReceiver); /** * @notice emitted when messageGasLimit is updated * @param _oldGasLimit The old gas limit * @param _newGasLimit The new gas limit */ event MessageGasLimitUpdated(uint256 _oldGasLimit, uint256 _newGasLimit); /** * @notice emitted when the protocol is paused (domain-level) */ event Paused(); /** * @notice emitted when the protocol is paused (domain-level) */ event Unpaused(); /** * @notice emitted when a strategy is set for an asset * @param _asset The address of the asset being configured * @param _strategy The id for the strategy (see `enum Strategy`) */ event StrategySetForAsset(address _asset, IEverclear.Strategy _strategy); /** * @notice emitted when the module is set for a strategy * @param _strategy The id for the strategy (see `enum Strategy`) * @param _module The settlement module */ event ModuleSetForStrategy(IEverclear.Strategy _strategy, ISettlementModule _module); /** * @notice emitted when the EverclearSpoke processes a settlement * @param _intentId The ID of the intent * @param _account The address of the account * @param _asset The address of the asset * @param _amount The amount of the asset */ event Settled(bytes32 indexed _intentId, address _account, address _asset, uint256 _amount); /** * @notice emitted when `_handleSettlement` fails to transfer tokens to a user (eg. blacklisted recipient) * @param _asset The address of the asset * @param _recipient The address of the recipient * @param _amount The amount of the asset */ event AssetTransferFailed(address indexed _asset, address indexed _recipient, uint256 _amount); /** * @notice emitted when `_handleSettlement` fails to mint the non-default stategy asset * @param _asset The address of the asset * @param _recipient The address of the recipient * @param _amount The amount of the asset * @param _strategy The strategy used for the asset */ event AssetMintFailed(address indexed _asset, address indexed _recipient, uint256 _amount, Strategy _strategy); /*/////////////////////////////////////////////////////////////// ERRORS //////////////////////////////////////////////////////////////*/ /** * @notice Thrown when the spoke is receiving a message from an address that is not the authorized gateway, admin or owner */ error EverclearSpoke_Unauthorized(); /** * @notice Thrown when a message is not a valid message type */ error EverclearSpoke_InvalidMessageType(); /** * @notice Thrown when the destination is wrong */ error EverclearSpoke_WrongDestination(); /** * @notice Thrown when a variable update is invalid */ error EverclearSpoke_InvalidVarUpdate(); /** * @notice Thrown when calling to a processQueue method with a zero amount */ error EverclearSpoke_ProcessQueue_ZeroAmount(); /** * @notice Thrown when calling to a processQueue method with an invalid amount * @param _first The index of the first element of the queue * @param _last The index of the last element of the queue * @param _amount The amount of items being tried to process */ error EverclearSpoke_ProcessQueue_InvalidAmount(uint256 _first, uint256 _last, uint256 _amount); /** * @notice Thrown when calling a function with the zero address */ error EverclearSpoke_ZeroAddress(); /** * @notice Thrown when a function is called when the spoke is paused */ error EverclearSpoke_Paused(); /** * @notice Thrown when the caller is not authorized to pause the spoke */ error EverclearSpoke_Pause_NotAuthorized(); /*/////////////////////////////////////////////////////////////// VIEWS //////////////////////////////////////////////////////////////*/ /** * @notice returns the typehash for `fillIntentForSolver` * @return _typeHash The `fillIntentForSolver` type hash */ function FILL_INTENT_FOR_SOLVER_TYPEHASH() external view returns (bytes32 _typeHash); /** * @notice returns the typehash for `processIntentQueueViaRelayer` * @return _typeHash The `processIntentQueueViaRelayer` type hash */ function PROCESS_INTENT_QUEUE_VIA_RELAYER_TYPEHASH() external view returns (bytes32 _typeHash); /** * @notice returns the typehash for `processFillQueueViaRelayer` * @return _typeHash The `processFillQueueViaRelayer` type hash */ function PROCESS_FILL_QUEUE_VIA_RELAYER_TYPEHASH() external view returns (bytes32 _typeHash); /** * @notice returns the permit2 contract * @return _permit2 The Permit2 singleton address */ function PERMIT2() external view returns (IPermit2 _permit2); /** * @notice returns the domain id for the Everclear rollup * @return _domain The id of the Everclear domain */ function EVERCLEAR() external view returns (uint32 _domain); /** * @notice returns the current domain * @return _domain The id of the current domain */ function DOMAIN() external view returns (uint32 _domain); /** * @notice returns the lighthouse address * @return _lighthouse The address of the Lighthouse agent */ function lighthouse() external view returns (address _lighthouse); /** * @notice returns the watchtower address * @return _watchtower The address of the Watchtower agent */ function watchtower() external view returns (address _watchtower); /** * @notice returns the message receiver address * @return _messageReceiver The address of the `SpokeMessageReceiver` */ function messageReceiver() external view returns (address _messageReceiver); /** * @notice returns the gateway * @return _gateway The local `SpokeGateway` */ function gateway() external view returns (ISpokeGateway _gateway); /** * @notice returns the call executor * @return _callExecutor The local `CallExecutor` */ function callExecutor() external view returns (ICallExecutor _callExecutor); /** * @notice returns the paused status of the spoke * @return _paused The boolean indicating if the contract is paused */ function paused() external view returns (bool _paused); /** * @notice returns the current intent nonce * @return _nonce The current nonce */ function nonce() external view returns (uint64 _nonce); /** * @notice returns the gas limit used for outgoing messages * @return _messageGasLimit the max gas limit */ function messageGasLimit() external view returns (uint256 _messageGasLimit); /** * @notice returns the balance of an asset for a user * @param _asset The address of the asset * @param _user The address of the user * @return _amount The amount of assets locked in the contract */ function balances(bytes32 _asset, bytes32 _user) external view returns (uint256 _amount); /** * @notice returns the status of an intent * @param _intentId The ID of the intent * @return _status The status of the intent */ function status( bytes32 _intentId ) external view returns (IntentStatus _status); /** * @notice returns the configured strategy id for an asset * @param _asset The address of the asset * @return _strategy The strategy for the asset */ function strategies( address _asset ) external view returns (IEverclear.Strategy _strategy); /** * @notice returns the module address for a strategy * @param _strategy The strategy id * @return _module The strategy module */ function modules( IEverclear.Strategy _strategy ) external view returns (ISettlementModule _module); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; import {IInterchainSecurityModule} from "./IInterchainSecurityModule.sol"; import {IPostDispatchHook} from "./hooks/IPostDispatchHook.sol"; interface IMailbox { // ============ Events ============ /** * @notice Emitted when a new message is dispatched via Hyperlane * @param sender The address that dispatched the message * @param destination The destination domain of the message * @param recipient The message recipient address on `destination` * @param message Raw bytes of message */ event Dispatch( address indexed sender, uint32 indexed destination, bytes32 indexed recipient, bytes message ); /** * @notice Emitted when a new message is dispatched via Hyperlane * @param messageId The unique message identifier */ event DispatchId(bytes32 indexed messageId); /** * @notice Emitted when a Hyperlane message is processed * @param messageId The unique message identifier */ event ProcessId(bytes32 indexed messageId); /** * @notice Emitted when a Hyperlane message is delivered * @param origin The origin domain of the message * @param sender The message sender address on `origin` * @param recipient The address that handled the message */ event Process( uint32 indexed origin, bytes32 indexed sender, address indexed recipient ); function localDomain() external view returns (uint32); function delivered(bytes32 messageId) external view returns (bool); function defaultIsm() external view returns (IInterchainSecurityModule); function defaultHook() external view returns (IPostDispatchHook); function requiredHook() external view returns (IPostDispatchHook); function latestDispatchedId() external view returns (bytes32); function dispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody ) external payable returns (bytes32 messageId); function quoteDispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody ) external view returns (uint256 fee); function dispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata body, bytes calldata defaultHookMetadata ) external payable returns (bytes32 messageId); function quoteDispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody, bytes calldata defaultHookMetadata ) external view returns (uint256 fee); function dispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata body, bytes calldata customHookMetadata, IPostDispatchHook customHook ) external payable returns (bytes32 messageId); function quoteDispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody, bytes calldata customHookMetadata, IPostDispatchHook customHook ) external view returns (uint256 fee); function process( bytes calldata metadata, bytes calldata message ) external payable; function recipientIsm( address recipient ) external view returns (IInterchainSecurityModule module); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; interface IInterchainSecurityModule { enum Types { UNUSED, ROUTING, AGGREGATION, LEGACY_MULTISIG, MERKLE_ROOT_MULTISIG, MESSAGE_ID_MULTISIG, NULL, // used with relayer carrying no metadata CCIP_READ } /** * @notice Returns an enum that represents the type of security model * encoded by this ISM. * @dev Relayers infer how to fetch and format metadata. */ function moduleType() external view returns (uint8); /** * @notice Defines a security model responsible for verifying interchain * messages based on the provided metadata. * @param _metadata Off-chain metadata provided by a relayer, specific to * the security model encoded by the module (e.g. validator signatures) * @param _message Hyperlane encoded interchain message * @return True if the message was verified */ function verify( bytes calldata _metadata, bytes calldata _message ) external returns (bool); } interface ISpecifiesInterchainSecurityModule { function interchainSecurityModule() external view returns (IInterchainSecurityModule); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; /*@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@ HYPERLANE @@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@*/ interface IPostDispatchHook { enum Types { UNUSED, ROUTING, AGGREGATION, MERKLE_TREE, INTERCHAIN_GAS_PAYMASTER, FALLBACK_ROUTING, ID_AUTH_ISM, PAUSABLE, PROTOCOL_FEE, LAYER_ZERO_V1 } /** * @notice Returns an enum that represents the type of hook */ function hookType() external view returns (uint8); /** * @notice Returns whether the hook supports metadata * @param metadata metadata * @return Whether the hook supports metadata */ function supportsMetadata( bytes calldata metadata ) external view returns (bool); /** * @notice Post action after a message is dispatched via the Mailbox * @param metadata The metadata required for the hook * @param message The message passed from the Mailbox.dispatch() call */ function postDispatch( bytes calldata metadata, bytes calldata message ) external payable; /** * @notice Compute the payment required by the postDispatch call * @param metadata The metadata required for the hook * @param message The message passed from the Mailbox.dispatch() call * @return Quoted payment for the postDispatch call */ function quoteDispatch( bytes calldata metadata, bytes calldata message ) external view returns (uint256); }
{ "remappings": [ "ds-test/=../../node_modules/ds-test/src/", "forge-std/=../../node_modules/forge-std/src/", "isolmate/=../../node_modules/isolmate/src/", "@hyperlane/=../../node_modules/@hyperlane-xyz/core/contracts/", "@openzeppelin/=../../node_modules/@openzeppelin/", "@upgrades/=lib/openzeppelin-foundry-upgrades/src/", "xerc20/=lib/xerc20/solidity/contracts/", "contracts/=src/contracts/", "interfaces/=src/interfaces/", "utils/=script/utils/", "@eth-optimism/=../../node_modules/@eth-optimism/", "@hyperlane-xyz/=../../node_modules/@hyperlane-xyz/", "@layerzerolabs/=../../node_modules/@layerzerolabs/", "erc4626-tests/=lib/xerc20/lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-gas-snapshot/=lib/xerc20/lib/permit2/lib/forge-gas-snapshot/src/", "fx-portal/=../../node_modules/fx-portal/", "openzeppelin-contracts/=lib/xerc20/lib/openzeppelin-contracts/", "openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src/", "openzeppelin/=lib/xerc20/lib/openzeppelin-contracts/contracts/", "permit2/=lib/xerc20/lib/permit2/", "prb-test/=lib/xerc20/lib/prb-test/src/", "prb/test/=lib/xerc20/lib/prb-test/src/", "solidity-stringutils/=lib/openzeppelin-foundry-upgrades/lib/solidity-stringutils/", "solmate/=lib/xerc20/lib/permit2/lib/solmate/" ], "optimizer": { "enabled": true, "runs": 10000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "shanghai", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"EverclearSpoke_InvalidMessageType","type":"error"},{"inputs":[],"name":"EverclearSpoke_InvalidVarUpdate","type":"error"},{"inputs":[],"name":"EverclearSpoke_Pause_NotAuthorized","type":"error"},{"inputs":[],"name":"EverclearSpoke_Paused","type":"error"},{"inputs":[{"internalType":"uint256","name":"_first","type":"uint256"},{"internalType":"uint256","name":"_last","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"EverclearSpoke_ProcessQueue_InvalidAmount","type":"error"},{"inputs":[],"name":"EverclearSpoke_ProcessQueue_ZeroAmount","type":"error"},{"inputs":[],"name":"EverclearSpoke_Unauthorized","type":"error"},{"inputs":[],"name":"EverclearSpoke_WrongDestination","type":"error"},{"inputs":[],"name":"EverclearSpoke_ZeroAddress","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_asset","type":"address"},{"indexed":true,"internalType":"address","name":"_recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"enum IEverclear.Strategy","name":"_strategy","type":"uint8"}],"name":"AssetMintFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_asset","type":"address"},{"indexed":true,"internalType":"address","name":"_recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"AssetTransferFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_oldGateway","type":"address"},{"indexed":false,"internalType":"address","name":"_newGateway","type":"address"}],"name":"GatewayUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_oldLightHouse","type":"address"},{"indexed":false,"internalType":"address","name":"_newLightHouse","type":"address"}],"name":"LighthouseUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_oldGasLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newGasLimit","type":"uint256"}],"name":"MessageGasLimitUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_oldMessageReceiver","type":"address"},{"indexed":false,"internalType":"address","name":"_newMessageReceiver","type":"address"}],"name":"MessageReceiverUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum IEverclear.Strategy","name":"_strategy","type":"uint8"},{"indexed":false,"internalType":"contract ISettlementModule","name":"_module","type":"address"}],"name":"ModuleSetForStrategy","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":[],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"_intentId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"_account","type":"address"},{"indexed":false,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"Settled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"enum IEverclear.Strategy","name":"_strategy","type":"uint8"}],"name":"StrategySetForAsset","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_oldWatchtower","type":"address"},{"indexed":false,"internalType":"address","name":"_newWatchtower","type":"address"}],"name":"WatchtowerUpdated","type":"event"},{"inputs":[],"name":"DOMAIN","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EVERCLEAR","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FILL_INTENT_FOR_SOLVER_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT2","outputs":[{"internalType":"contract IPermit2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROCESS_FILL_QUEUE_VIA_RELAYER_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROCESS_INTENT_QUEUE_VIA_RELAYER_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_asset","type":"bytes32"},{"internalType":"bytes32","name":"_user","type":"bytes32"}],"name":"balances","outputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"callExecutor","outputs":[{"internalType":"contract ICallExecutor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fillQueue","outputs":[{"internalType":"uint256","name":"first","type":"uint256"},{"internalType":"uint256","name":"last","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gateway","outputs":[{"internalType":"contract ISpokeGateway","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"intentQueue","outputs":[{"internalType":"uint256","name":"first","type":"uint256"},{"internalType":"uint256","name":"last","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lighthouse","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"messageGasLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"messageReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IEverclear.Strategy","name":"_strategy","type":"uint8"}],"name":"modules","outputs":[{"internalType":"contract ISettlementModule","name":"_module","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nonce","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_message","type":"bytes"}],"name":"receiveMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_intentId","type":"bytes32"}],"name":"status","outputs":[{"internalType":"enum IEverclear.IntentStatus","name":"status","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"}],"name":"strategies","outputs":[{"internalType":"enum IEverclear.Strategy","name":"_strategy","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"watchtower","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561000f575f80fd5b50611b2a8061001d5f395ff3fe608060405234801561000f575f80fd5b506004361061018f575f3560e01c80638da5cb5b116100dd578063d6979ef611610088578063f2fde38b11610063578063f2fde38b146104e6578063f37c0a2e146104f9578063f953cec714610508575f80fd5b8063d6979ef614610491578063df7a76011461049f578063e2cae9f5146104c6575f80fd5b8063affed0e0116100b8578063affed0e01461040d578063c2aeb7bd14610453578063cab0071e14610488575f80fd5b80638da5cb5b1461038d5780638fd68940146103ca578063990969f6146103ed575f80fd5b80635c975abb1161013d578063715018a611610118578063715018a61461033c57806373e554f6146103465780637f7673f91461036d575f80fd5b80635c975abb146102c65780636301fd63146102fb5780636afdd85014610326575f80fd5b8063522dbaa51161016d578063522dbaa51461024457806352a9674b1461026b57806352ad0d5e14610297575f80fd5b8063043dca0414610193578063116191b6146101d057806339ebf82314610215575b5f80fd5b6101bd6101a1366004611435565b600660209081525f928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6003546101f09073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101c7565b610237610223366004611455565b60086020525f908152604090205460ff1681565b6040516101c791906114c9565b6101bd7f0afae807991f914b71165fd92589f1dc28648cb9fb1f8558f3a6c7507d56deff81565b5f5461028290640100000000900463ffffffff1681565b60405163ffffffff90911681526020016101c7565b6102b96102a53660046114d7565b60076020525f908152604090205460ff1681565b6040516101c791906114ee565b6004546102eb9074010000000000000000000000000000000000000000900460ff1681565b60405190151581526020016101c7565b5f546101f09068010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6101f06e22d473030f116ddee9f6b43ac78ba381565b61034461051b565b005b6101bd7f8104c8a42e1531612796e696e327ea52a475d9583ee6d64ffdefcafad22c0b2481565b6001546101f09073ffffffffffffffffffffffffffffffffffffffff1681565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff166101f0565b600a54600b546103d8919082565b604080519283526020830191909152016101c7565b6004546101f09073ffffffffffffffffffffffffffffffffffffffff1681565b60045461043a907501000000000000000000000000000000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016101c7565b6101f0610461366004611508565b60096020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6101bd60055481565b600d54600e546103d8919082565b6101bd7fce47b2c080dbcd8e420dc92bcf58f25f73f2e008a3b34ac41b9d468d1fb45d5a81565b6002546101f09073ffffffffffffffffffffffffffffffffffffffff1681565b6103446104f4366004611455565b61052e565b5f546102829063ffffffff1681565b610344610516366004611610565b610596565b6105236106f2565b61052c5f610780565b565b6105366106f2565b73ffffffffffffffffffffffffffffffffffffffff811661058a576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b61059381610780565b50565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff163314801590610619575060035473ffffffffffffffffffffffffffffffffffffffff1633141580610619575060045474010000000000000000000000000000000000000000900460ff165b15610650576040517fa756e44800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8061065b83610815565b9092509050600282600381111561067457610674611488565b03610687576106828161084e565b505050565b600382600381111561069b5761069b611488565b036106c0575f806106ab83610894565b915091506106b982826108b5565b5050505050565b6040517f0a88c33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336107317f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff161461052c576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610581565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080547fffffffffffffffffffffffff0000000000000000000000000000000000000000811673ffffffffffffffffffffffffffffffffffffffff848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f60605f8380602001905181019061082d919061170b565b9250905060ff8116600381111561084657610846611488565b925050915091565b5f61085882610abe565b90505f5b8151811015610682575f82828151811061087857610878611756565b6020026020010151905061088b81610ada565b5060010161085c565b5f6060828060200190518101906108ab9190611783565b9094909350915050565b6040516020016108f69060208082526007908201527f4741544557415900000000000000000000000000000000000000000000000000604082015260600190565b60405160208183030381529060405280519060200120820361092d575f61092261091f836110b3565b90565b9050610682816110c8565b60405160200161096e9060208082526007908201527f4d41494c424f5800000000000000000000000000000000000000000000000000604082015260600190565b6040516020818303038152906040528051906020012082036109a2575f61099761091f836110b3565b90506106828161119e565b6040516020016109e3906020808252600a908201527f4c49474854484f55534500000000000000000000000000000000000000000000604082015260600190565b604051602081830303815290604052805190602001208203610a17575f610a0c61091f836110b3565b90506106828161121a565b604051602001610a58906020808252600a908201527f5741544348544f57455200000000000000000000000000000000000000000000604082015260600190565b604051602081830303815290604052805190602001208203610a8c575f610a8161091f836110b3565b9050610682816112f6565b6040517f12109f2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606081806020019051810190610ad491906117c0565b92915050565b5f610ae6826040015190565b90505f610af4836060015190565b83515f9081526007602052604090205490915060ff166006816009811115610b1e57610b1e611488565b1480610b3b57506007816009811115610b3957610b39611488565b145b15610b465750505050565b83515f9081526007602052604090208054600691907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018302179055505f610c0260128573ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bd4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bf891906118a8565b87602001516113c3565b905080156110525773ffffffffffffffffffffffffffffffffffffffff84165f9081526008602052604081205460ff1690816001811115610c4557610c45611488565b03610e7357856080015115610c8f576040808701515f9081526006602090815282822060608a0151835290529081208054849290610c849084906118ee565b909155506110509050565b60405173ffffffffffffffffffffffffffffffffffffffff85166024820152604481018390525f90606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052519091505f90819073ffffffffffffffffffffffffffffffffffffffff891690610d5b908590611901565b5f604051808303815f865af19150503d805f8114610d94576040519150601f19603f3d011682016040523d82523d5f602084013e610d99565b606091505b5091509150811580610dc75750805115801590610dc7575080806020019051810190610dc5919061191c565b155b15610e6b576040808a01515f9081526006602090815282822060608d0151835290529081208054879290610dfc9084906118ee565b925050819055508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f4bb241f3b40fc832b91e1567c9d919078fe98ec3808ffaf1970b75b68248794287604051610e6291815260200190565b60405180910390a35b505050611050565b5f60095f836001811115610e8957610e89611488565b6001811115610e9a57610e9a611488565b815260208101919091526040015f90812054608089015173ffffffffffffffffffffffffffffffffffffffff9091169250610ed55785610ed7565b305b6040517f55389fb000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8981166004830152808316602483015288811660448301526064820187905260a060848301525f60a483018190529293508416906355389fb09060c4016020604051808303815f875af1158015610f6b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f8f919061191c565b9050808015610f9f575088608001515b15610fdf576040808a01515f9081526006602090815282822060608d0151835290529081208054879290610fd49084906118ee565b9091555061104c9050565b8061104c578673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f8557f7d07a398ea2e78b2bc72cc07a853cf05a78160fa3626be99b5613e171498787604051611043929190611935565b60405180910390a35b5050505b505b84516040805173ffffffffffffffffffffffffffffffffffffffff8087168252871660208201529081018390527f4190759d37d5cfe7a1a70e06ec7508a05d12fd9cb76f353da1c9e028e5a48dcf9060600160405180910390a25050505050565b5f81806020019051810190610ad49190611949565b8073ffffffffffffffffffffffffffffffffffffffff8116611116576040517fe713a76300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003805473ffffffffffffffffffffffffffffffffffffffff8481167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f68e84423772dadc3e4047f8b5bd221ddb02dc67796e7852533fd976947d86c5191015b60405180910390a1505050565b6003546040517f8a901b9f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff838116600483015290911690638a901b9f906024015f604051808303815f87803b158015611208575f80fd5b505af11580156106b9573d5f803e3d5ffd5b8073ffffffffffffffffffffffffffffffffffffffff8116611268576040517fe713a76300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805473ffffffffffffffffffffffffffffffffffffffff848116680100000000000000008181027fffffffff0000000000000000000000000000000000000000ffffffffffffffff85161790945560408051949093049091168084526020840191909152917f0be32d823eb66f9bc102ffe567930c4a8f19e2d4d5aedb1cb8b97c2c640aa3159101611191565b8073ffffffffffffffffffffffffffffffffffffffff8116611344576040517fe713a76300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001805473ffffffffffffffffffffffffffffffffffffffff8481167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f68bcfd6b375bdfac05ba92dc0447413c6f7d61309f75f08e297e245571cf1f339101611191565b5f8260ff168460ff16036113d857508061142e565b8260ff168460ff16101561140c576113f08484611960565b6113fb90600a611a97565b6114059083611aa5565b905061142e565b6114168385611960565b61142190600a611a97565b61142b9083611abc565b90505b9392505050565b5f8060408385031215611446575f80fd5b50508035926020909101359150565b5f60208284031215611465575f80fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461142e575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b600281106114c5576114c5611488565b9052565b60208101610ad482846114b5565b5f602082840312156114e7575f80fd5b5035919050565b60208101600a831061150257611502611488565b91905290565b5f60208284031215611518575f80fd5b81356002811061142e575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60405160a0810167ffffffffffffffff8111828210171561157657611576611526565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156115c3576115c3611526565b604052919050565b5f67ffffffffffffffff8211156115e4576115e4611526565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f60208284031215611620575f80fd5b813567ffffffffffffffff811115611636575f80fd5b8201601f81018413611646575f80fd5b8035611659611654826115cb565b61157c565b81815285602083850101111561166d575f80fd5b816020840160208301375f91810160200191909152949350505050565b805160ff8116811461169a575f80fd5b919050565b5f5b838110156116b95781810151838201526020016116a1565b50505f910152565b5f82601f8301126116d0575f80fd5b81516116de611654826115cb565b8181528460208386010111156116f2575f80fd5b61170382602083016020870161169f565b949350505050565b5f806040838503121561171c575f80fd5b6117258361168a565b9150602083015167ffffffffffffffff811115611740575f80fd5b61174c858286016116c1565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f8060408385031215611794575f80fd5b82519150602083015167ffffffffffffffff811115611740575f80fd5b8051801515811461169a575f80fd5b5f60208083850312156117d1575f80fd5b825167ffffffffffffffff808211156117e8575f80fd5b818501915085601f8301126117fb575f80fd5b81518181111561180d5761180d611526565b61181b848260051b0161157c565b818152848101925060a0918202840185019188831115611839575f80fd5b938501935b8285101561189c5780858a031215611854575f80fd5b61185c611553565b855181528686015187820152604080870151908201526060808701519082015260806118898188016117b1565b908201528452938401939285019261183e565b50979650505050505050565b5f602082840312156118b8575f80fd5b61142e8261168a565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115610ad457610ad46118c1565b5f825161191281846020870161169f565b9190910192915050565b5f6020828403121561192c575f80fd5b61142e826117b1565b8281526040810161142e60208301846114b5565b5f60208284031215611959575f80fd5b5051919050565b60ff8281168282160390811115610ad457610ad46118c1565b600181815b808511156119d257817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156119b8576119b86118c1565b808516156119c557918102915b93841c939080029061197e565b509250929050565b5f826119e857506001610ad4565b816119f457505f610ad4565b8160018114611a0a5760028114611a1457611a30565b6001915050610ad4565b60ff841115611a2557611a256118c1565b50506001821b610ad4565b5060208310610133831016604e8410600b8410161715611a53575081810a610ad4565b611a5d8383611979565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115611a8f57611a8f6118c1565b029392505050565b5f61142e60ff8416836119da565b8082028115828204841417610ad457610ad46118c1565b5f82611aef577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b50049056fea2646970667358221220732fc6355dd2e082c969ea5cfd3bd625b35a7bb6b93b1116300f98ea9fa727bf64736f6c63430008170033
Deployed Bytecode
0x608060405234801561000f575f80fd5b506004361061018f575f3560e01c80638da5cb5b116100dd578063d6979ef611610088578063f2fde38b11610063578063f2fde38b146104e6578063f37c0a2e146104f9578063f953cec714610508575f80fd5b8063d6979ef614610491578063df7a76011461049f578063e2cae9f5146104c6575f80fd5b8063affed0e0116100b8578063affed0e01461040d578063c2aeb7bd14610453578063cab0071e14610488575f80fd5b80638da5cb5b1461038d5780638fd68940146103ca578063990969f6146103ed575f80fd5b80635c975abb1161013d578063715018a611610118578063715018a61461033c57806373e554f6146103465780637f7673f91461036d575f80fd5b80635c975abb146102c65780636301fd63146102fb5780636afdd85014610326575f80fd5b8063522dbaa51161016d578063522dbaa51461024457806352a9674b1461026b57806352ad0d5e14610297575f80fd5b8063043dca0414610193578063116191b6146101d057806339ebf82314610215575b5f80fd5b6101bd6101a1366004611435565b600660209081525f928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6003546101f09073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101c7565b610237610223366004611455565b60086020525f908152604090205460ff1681565b6040516101c791906114c9565b6101bd7f0afae807991f914b71165fd92589f1dc28648cb9fb1f8558f3a6c7507d56deff81565b5f5461028290640100000000900463ffffffff1681565b60405163ffffffff90911681526020016101c7565b6102b96102a53660046114d7565b60076020525f908152604090205460ff1681565b6040516101c791906114ee565b6004546102eb9074010000000000000000000000000000000000000000900460ff1681565b60405190151581526020016101c7565b5f546101f09068010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6101f06e22d473030f116ddee9f6b43ac78ba381565b61034461051b565b005b6101bd7f8104c8a42e1531612796e696e327ea52a475d9583ee6d64ffdefcafad22c0b2481565b6001546101f09073ffffffffffffffffffffffffffffffffffffffff1681565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff166101f0565b600a54600b546103d8919082565b604080519283526020830191909152016101c7565b6004546101f09073ffffffffffffffffffffffffffffffffffffffff1681565b60045461043a907501000000000000000000000000000000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016101c7565b6101f0610461366004611508565b60096020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6101bd60055481565b600d54600e546103d8919082565b6101bd7fce47b2c080dbcd8e420dc92bcf58f25f73f2e008a3b34ac41b9d468d1fb45d5a81565b6002546101f09073ffffffffffffffffffffffffffffffffffffffff1681565b6103446104f4366004611455565b61052e565b5f546102829063ffffffff1681565b610344610516366004611610565b610596565b6105236106f2565b61052c5f610780565b565b6105366106f2565b73ffffffffffffffffffffffffffffffffffffffff811661058a576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b61059381610780565b50565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff163314801590610619575060035473ffffffffffffffffffffffffffffffffffffffff1633141580610619575060045474010000000000000000000000000000000000000000900460ff165b15610650576040517fa756e44800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8061065b83610815565b9092509050600282600381111561067457610674611488565b03610687576106828161084e565b505050565b600382600381111561069b5761069b611488565b036106c0575f806106ab83610894565b915091506106b982826108b5565b5050505050565b6040517f0a88c33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336107317f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff161461052c576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610581565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080547fffffffffffffffffffffffff0000000000000000000000000000000000000000811673ffffffffffffffffffffffffffffffffffffffff848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f60605f8380602001905181019061082d919061170b565b9250905060ff8116600381111561084657610846611488565b925050915091565b5f61085882610abe565b90505f5b8151811015610682575f82828151811061087857610878611756565b6020026020010151905061088b81610ada565b5060010161085c565b5f6060828060200190518101906108ab9190611783565b9094909350915050565b6040516020016108f69060208082526007908201527f4741544557415900000000000000000000000000000000000000000000000000604082015260600190565b60405160208183030381529060405280519060200120820361092d575f61092261091f836110b3565b90565b9050610682816110c8565b60405160200161096e9060208082526007908201527f4d41494c424f5800000000000000000000000000000000000000000000000000604082015260600190565b6040516020818303038152906040528051906020012082036109a2575f61099761091f836110b3565b90506106828161119e565b6040516020016109e3906020808252600a908201527f4c49474854484f55534500000000000000000000000000000000000000000000604082015260600190565b604051602081830303815290604052805190602001208203610a17575f610a0c61091f836110b3565b90506106828161121a565b604051602001610a58906020808252600a908201527f5741544348544f57455200000000000000000000000000000000000000000000604082015260600190565b604051602081830303815290604052805190602001208203610a8c575f610a8161091f836110b3565b9050610682816112f6565b6040517f12109f2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606081806020019051810190610ad491906117c0565b92915050565b5f610ae6826040015190565b90505f610af4836060015190565b83515f9081526007602052604090205490915060ff166006816009811115610b1e57610b1e611488565b1480610b3b57506007816009811115610b3957610b39611488565b145b15610b465750505050565b83515f9081526007602052604090208054600691907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018302179055505f610c0260128573ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bd4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bf891906118a8565b87602001516113c3565b905080156110525773ffffffffffffffffffffffffffffffffffffffff84165f9081526008602052604081205460ff1690816001811115610c4557610c45611488565b03610e7357856080015115610c8f576040808701515f9081526006602090815282822060608a0151835290529081208054849290610c849084906118ee565b909155506110509050565b60405173ffffffffffffffffffffffffffffffffffffffff85166024820152604481018390525f90606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052519091505f90819073ffffffffffffffffffffffffffffffffffffffff891690610d5b908590611901565b5f604051808303815f865af19150503d805f8114610d94576040519150601f19603f3d011682016040523d82523d5f602084013e610d99565b606091505b5091509150811580610dc75750805115801590610dc7575080806020019051810190610dc5919061191c565b155b15610e6b576040808a01515f9081526006602090815282822060608d0151835290529081208054879290610dfc9084906118ee565b925050819055508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f4bb241f3b40fc832b91e1567c9d919078fe98ec3808ffaf1970b75b68248794287604051610e6291815260200190565b60405180910390a35b505050611050565b5f60095f836001811115610e8957610e89611488565b6001811115610e9a57610e9a611488565b815260208101919091526040015f90812054608089015173ffffffffffffffffffffffffffffffffffffffff9091169250610ed55785610ed7565b305b6040517f55389fb000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8981166004830152808316602483015288811660448301526064820187905260a060848301525f60a483018190529293508416906355389fb09060c4016020604051808303815f875af1158015610f6b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f8f919061191c565b9050808015610f9f575088608001515b15610fdf576040808a01515f9081526006602090815282822060608d0151835290529081208054879290610fd49084906118ee565b9091555061104c9050565b8061104c578673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f8557f7d07a398ea2e78b2bc72cc07a853cf05a78160fa3626be99b5613e171498787604051611043929190611935565b60405180910390a35b5050505b505b84516040805173ffffffffffffffffffffffffffffffffffffffff8087168252871660208201529081018390527f4190759d37d5cfe7a1a70e06ec7508a05d12fd9cb76f353da1c9e028e5a48dcf9060600160405180910390a25050505050565b5f81806020019051810190610ad49190611949565b8073ffffffffffffffffffffffffffffffffffffffff8116611116576040517fe713a76300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003805473ffffffffffffffffffffffffffffffffffffffff8481167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f68e84423772dadc3e4047f8b5bd221ddb02dc67796e7852533fd976947d86c5191015b60405180910390a1505050565b6003546040517f8a901b9f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff838116600483015290911690638a901b9f906024015f604051808303815f87803b158015611208575f80fd5b505af11580156106b9573d5f803e3d5ffd5b8073ffffffffffffffffffffffffffffffffffffffff8116611268576040517fe713a76300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805473ffffffffffffffffffffffffffffffffffffffff848116680100000000000000008181027fffffffff0000000000000000000000000000000000000000ffffffffffffffff85161790945560408051949093049091168084526020840191909152917f0be32d823eb66f9bc102ffe567930c4a8f19e2d4d5aedb1cb8b97c2c640aa3159101611191565b8073ffffffffffffffffffffffffffffffffffffffff8116611344576040517fe713a76300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001805473ffffffffffffffffffffffffffffffffffffffff8481167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f68bcfd6b375bdfac05ba92dc0447413c6f7d61309f75f08e297e245571cf1f339101611191565b5f8260ff168460ff16036113d857508061142e565b8260ff168460ff16101561140c576113f08484611960565b6113fb90600a611a97565b6114059083611aa5565b905061142e565b6114168385611960565b61142190600a611a97565b61142b9083611abc565b90505b9392505050565b5f8060408385031215611446575f80fd5b50508035926020909101359150565b5f60208284031215611465575f80fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461142e575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b600281106114c5576114c5611488565b9052565b60208101610ad482846114b5565b5f602082840312156114e7575f80fd5b5035919050565b60208101600a831061150257611502611488565b91905290565b5f60208284031215611518575f80fd5b81356002811061142e575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60405160a0810167ffffffffffffffff8111828210171561157657611576611526565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156115c3576115c3611526565b604052919050565b5f67ffffffffffffffff8211156115e4576115e4611526565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f60208284031215611620575f80fd5b813567ffffffffffffffff811115611636575f80fd5b8201601f81018413611646575f80fd5b8035611659611654826115cb565b61157c565b81815285602083850101111561166d575f80fd5b816020840160208301375f91810160200191909152949350505050565b805160ff8116811461169a575f80fd5b919050565b5f5b838110156116b95781810151838201526020016116a1565b50505f910152565b5f82601f8301126116d0575f80fd5b81516116de611654826115cb565b8181528460208386010111156116f2575f80fd5b61170382602083016020870161169f565b949350505050565b5f806040838503121561171c575f80fd5b6117258361168a565b9150602083015167ffffffffffffffff811115611740575f80fd5b61174c858286016116c1565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f8060408385031215611794575f80fd5b82519150602083015167ffffffffffffffff811115611740575f80fd5b8051801515811461169a575f80fd5b5f60208083850312156117d1575f80fd5b825167ffffffffffffffff808211156117e8575f80fd5b818501915085601f8301126117fb575f80fd5b81518181111561180d5761180d611526565b61181b848260051b0161157c565b818152848101925060a0918202840185019188831115611839575f80fd5b938501935b8285101561189c5780858a031215611854575f80fd5b61185c611553565b855181528686015187820152604080870151908201526060808701519082015260806118898188016117b1565b908201528452938401939285019261183e565b50979650505050505050565b5f602082840312156118b8575f80fd5b61142e8261168a565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115610ad457610ad46118c1565b5f825161191281846020870161169f565b9190910192915050565b5f6020828403121561192c575f80fd5b61142e826117b1565b8281526040810161142e60208301846114b5565b5f60208284031215611959575f80fd5b5051919050565b60ff8281168282160390811115610ad457610ad46118c1565b600181815b808511156119d257817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156119b8576119b86118c1565b808516156119c557918102915b93841c939080029061197e565b509250929050565b5f826119e857506001610ad4565b816119f457505f610ad4565b8160018114611a0a5760028114611a1457611a30565b6001915050610ad4565b60ff841115611a2557611a256118c1565b50506001821b610ad4565b5060208310610133831016604e8410600b8410161715611a53575081810a610ad4565b611a5d8383611979565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115611a8f57611a8f6118c1565b029392505050565b5f61142e60ff8416836119da565b8082028115828204841417610ad457610ad46118c1565b5f82611aef577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b50049056fea2646970667358221220732fc6355dd2e082c969ea5cfd3bd625b35a7bb6b93b1116300f98ea9fa727bf64736f6c63430008170033
Loading...
Loading
Loading...
Loading
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.