Overview
APE Balance
APE Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
EverclearSpoke
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; /* Coded for Everclear with ♥ by ░██╗░░░░░░░██╗░█████╗░███╗░░██╗██████╗░███████╗██████╗░██╗░░░░░░█████╗░███╗░░██╗██████╗░ ░██║░░██╗░░██║██╔══██╗████╗░██║██╔══██╗██╔════╝██╔══██╗██║░░░░░██╔══██╗████╗░██║██╔══██╗ ░╚██╗████╗██╔╝██║░░██║██╔██╗██║██║░░██║█████╗░░██████╔╝██║░░░░░███████║██╔██╗██║██║░░██║ ░░████╔═████║░██║░░██║██║╚████║██║░░██║██╔══╝░░██╔══██╗██║░░░░░██╔══██║██║╚████║██║░░██║ ░░╚██╔╝░╚██╔╝░╚█████╔╝██║░╚███║██████╔╝███████╗██║░░██║███████╗██║░░██║██║░╚███║██████╔╝ ░░░╚═╝░░░╚═╝░░░╚════╝░╚═╝░░╚══╝╚═════╝░╚══════╝╚═╝░░╚═╝╚══════╝╚═╝░░╚═╝╚═╝░░╚══╝╚═════╝░ https://defi.sucks */ import {OwnableUpgradeable} from '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol'; import {UUPSUpgradeable} from '@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol'; import {NoncesUpgradeable} from '@openzeppelin/contracts-upgradeable/utils/NoncesUpgradeable.sol'; import {ERC20} from '@openzeppelin/contracts/token/ERC20/ERC20.sol'; import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; import {ECDSA} from '@openzeppelin/contracts/utils/cryptography/ECDSA.sol'; import {MessageHashUtils} from '@openzeppelin/contracts/utils/cryptography/MessageHashUtils.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 {QueueLib} from 'contracts/common/QueueLib.sol'; import {TypeCasts} from 'contracts/common/TypeCasts.sol'; import {Constants} from 'contracts/intent/lib/Constants.sol'; import {IEverclear} from 'interfaces/common/IEverclear.sol'; import {IMessageReceiver} from 'interfaces/common/IMessageReceiver.sol'; import {IPermit2} from 'interfaces/common/IPermit2.sol'; import {ISettlementModule} from 'interfaces/common/ISettlementModule.sol'; import {IEverclearSpoke} from 'interfaces/intent/IEverclearSpoke.sol'; import {ISpokeGateway} from 'interfaces/intent/ISpokeGateway.sol'; import {SpokeStorage} from 'contracts/intent/SpokeStorage.sol'; /** * @title EverclearSpoke * @notice Spoke contract for Everclear */ contract EverclearSpoke is SpokeStorage, UUPSUpgradeable, OwnableUpgradeable, NoncesUpgradeable, IEverclearSpoke, IMessageReceiver { using QueueLib for QueueLib.IntentQueue; using QueueLib for QueueLib.FillQueue; using SafeERC20 for IERC20; using TypeCasts for address; using TypeCasts for bytes32; constructor() { _disableInitializers(); } /*/////////////////////////////////////////////////////////////// EXTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ /// @inheritdoc IEverclearSpoke function pause() external hasPauseAccess { paused = true; emit Paused(); } /// @inheritdoc IEverclearSpoke function unpause() external hasPauseAccess { paused = false; emit Unpaused(); } /// @inheritdoc IEverclearSpoke function setStrategyForAsset(address _asset, IEverclear.Strategy _strategy) external onlyOwner { strategies[_asset] = _strategy; emit StrategySetForAsset(_asset, _strategy); } /// @inheritdoc IEverclearSpoke function setModuleForStrategy(IEverclear.Strategy _strategy, ISettlementModule _module) external onlyOwner { modules[_strategy] = _module; emit ModuleSetForStrategy(_strategy, _module); } /// @inheritdoc IEverclearSpoke function updateSecurityModule( address _newSecurityModule ) external onlyOwner { gateway.updateSecurityModule(_newSecurityModule); } /// @inheritdoc IMessageReceiver function receiveMessage( bytes calldata ) external { _delegate(messageReceiver); } /// @inheritdoc IEverclearSpoke function newIntent( uint32[] memory _destinations, address _receiver, address _inputAsset, address _outputAsset, uint256 _amount, uint24 _maxFee, uint48 _ttl, bytes calldata _data ) external whenNotPaused returns (bytes32 _intentId, Intent memory _intent) { if (_destinations.length > 10) revert EverclearSpoke_NewIntent_InvalidIntent(); (_intentId, _intent) = _newIntent({ _destinations: _destinations, _receiver: _receiver, _inputAsset: _inputAsset, _outputAsset: _outputAsset, _amount: _amount, _maxFee: _maxFee, _ttl: _ttl, _data: _data, _usesPermit2: false }); } /// @inheritdoc IEverclearSpoke function newIntent( uint32[] memory _destinations, address _receiver, address _inputAsset, address _outputAsset, uint256 _amount, uint24 _maxFee, uint48 _ttl, bytes calldata _data, Permit2Params calldata _permit2Params ) external whenNotPaused returns (bytes32 _intentId, Intent memory _intent) { if (_destinations.length > 10) revert EverclearSpoke_NewIntent_InvalidIntent(); PERMIT2.permitTransferFrom( IPermit2.PermitTransferFrom({ permitted: IPermit2.TokenPermissions({token: IERC20(_inputAsset), amount: _amount}), nonce: _permit2Params.nonce, deadline: _permit2Params.deadline }), IPermit2.SignatureTransferDetails({to: address(this), requestedAmount: _amount}), msg.sender, _permit2Params.signature ); (_intentId, _intent) = _newIntent({ _destinations: _destinations, _receiver: _receiver, _inputAsset: _inputAsset, _outputAsset: _outputAsset, _amount: _amount, _maxFee: _maxFee, _ttl: _ttl, _data: _data, _usesPermit2: true }); } /// @inheritdoc IEverclearSpoke function fillIntent( Intent calldata _intent, uint24 _fee ) external whenNotPaused returns (FillMessage memory _fillMessage) { _fillMessage = _fillIntent(_intent, msg.sender, _fee); } /// @inheritdoc IEverclearSpoke function fillIntentForSolver( address _solver, Intent calldata _intent, uint256 _nonce, uint24 _fee, bytes calldata _signature ) external whenNotPaused returns (FillMessage memory _fillMessage) { bytes memory _data = abi.encode(FILL_INTENT_FOR_SOLVER_TYPEHASH, _intent, _nonce, _fee); _verifySignature(_solver, _data, _nonce, _signature); _fillMessage = _fillIntent(_intent, _solver, _fee); } /// @inheritdoc IEverclearSpoke function processIntentQueue( Intent[] calldata _intents ) external payable whenNotPaused { (bytes memory _batchIntentmessage, uint256 _firstIdx) = _processIntentQueue(_intents); (bytes32 _messageId, uint256 _feeSpent) = gateway.sendMessage{value: msg.value}(EVERCLEAR, _batchIntentmessage, messageGasLimit); emit IntentQueueProcessed(_messageId, _firstIdx, _firstIdx + _intents.length, _feeSpent); } /// @inheritdoc IEverclearSpoke function processFillQueue( uint32 _amount ) external payable whenNotPaused { (bytes memory _batchFillMessage, uint256 _firstIdx) = _processFillQueue(_amount); (bytes32 _messageId, uint256 _feeSpent) = gateway.sendMessage{value: msg.value}(EVERCLEAR, _batchFillMessage, messageGasLimit); emit FillQueueProcessed(_messageId, _firstIdx, _firstIdx + _amount, _feeSpent); } /// @inheritdoc IEverclearSpoke function processIntentQueueViaRelayer( uint32 _domain, Intent[] calldata _intents, address _relayer, uint256 _ttl, uint256 _nonce, uint256 _bufferDBPS, bytes calldata _signature ) external whenNotPaused { uint32 _amount = uint32(_intents.length); bytes memory _data = abi.encode(PROCESS_INTENT_QUEUE_VIA_RELAYER_TYPEHASH, _domain, _amount, _relayer, _ttl, _nonce, _bufferDBPS); _verifySignature(lighthouse, _data, _nonce, _signature); _processQueueChecks(_domain, _relayer, _ttl); (bytes memory _batchIntentmessage, uint256 _firstIdx) = _processIntentQueue(_intents); uint256 _fee = gateway.quoteMessage(EVERCLEAR, _batchIntentmessage, messageGasLimit); (bytes32 _messageId, uint256 _feeSpent) = gateway.sendMessage( EVERCLEAR, _batchIntentmessage, _fee + ((_fee * _bufferDBPS) / Common.DBPS_DENOMINATOR), messageGasLimit ); emit IntentQueueProcessed(_messageId, _firstIdx, _firstIdx + _amount, _feeSpent); } /// @inheritdoc IEverclearSpoke function processFillQueueViaRelayer( uint32 _domain, uint32 _amount, address _relayer, uint256 _ttl, uint256 _nonce, uint256 _bufferDBPS, bytes calldata _signature ) external whenNotPaused { bytes memory _data = abi.encode(PROCESS_FILL_QUEUE_VIA_RELAYER_TYPEHASH, _domain, _amount, _relayer, _ttl, _nonce, _bufferDBPS); _verifySignature(lighthouse, _data, _nonce, _signature); _processQueueChecks(_domain, _relayer, _ttl); (bytes memory _batchFillMessage, uint256 _firstIdx) = _processFillQueue(_amount); uint256 _fee = gateway.quoteMessage(EVERCLEAR, _batchFillMessage, messageGasLimit); (bytes32 _messageId, uint256 _feeSpent) = gateway.sendMessage( EVERCLEAR, _batchFillMessage, _fee + ((_fee * _bufferDBPS) / Common.DBPS_DENOMINATOR), messageGasLimit ); emit FillQueueProcessed(_messageId, _firstIdx, _firstIdx + _amount, _feeSpent); } /// @inheritdoc IEverclearSpoke function deposit(address _asset, uint256 _amount) external whenNotPaused { _pullTokens(msg.sender, _asset, _amount); balances[_asset.toBytes32()][msg.sender.toBytes32()] += _amount; emit Deposited(msg.sender, _asset, _amount); } /// @inheritdoc IEverclearSpoke function withdraw(address _asset, uint256 _amount) external whenNotPaused { balances[_asset.toBytes32()][msg.sender.toBytes32()] -= _amount; _pushTokens(msg.sender, _asset, _amount); emit Withdrawn(msg.sender, _asset, _amount); } /// @inheritdoc IEverclearSpoke function updateGateway( address _newGateway ) external onlyOwner { address _oldGateway = address(gateway); gateway = ISpokeGateway(_newGateway); emit GatewayUpdated(_oldGateway, _newGateway); } /// @inheritdoc IEverclearSpoke function updateMessageReceiver( address _newMessageReceiver ) external onlyOwner { address _oldMessageReceiver = messageReceiver; messageReceiver = _newMessageReceiver; emit MessageReceiverUpdated(_oldMessageReceiver, _newMessageReceiver); } /// @inheritdoc IEverclearSpoke function updateMessageGasLimit( uint256 _newGasLimit ) external onlyOwner { uint256 _oldGasLimit = messageGasLimit; messageGasLimit = _newGasLimit; emit MessageGasLimitUpdated(_oldGasLimit, _newGasLimit); } /// @inheritdoc IEverclearSpoke function executeIntentCalldata( Intent calldata _intent ) external whenNotPaused validDestination(_intent) { bytes32 _intentId = keccak256(abi.encode(_intent)); if (status[_intentId] != IntentStatus.SETTLED) { revert EverclearSpoke_ExecuteIntentCalldata_InvalidStatus(_intentId); } // internal method will revert if it fails _executeCalldata(_intentId, _intent.data); status[_intentId] = IntentStatus.SETTLED_AND_MANUALLY_EXECUTED; } /*/////////////////////////////////////////////////////////////// INITIALIZER //////////////////////////////////////////////////////////////*/ /// @inheritdoc IEverclearSpoke function initialize( SpokeInitializationParams calldata _init ) public initializer { DOMAIN = uint32(block.chainid); gateway = _init.gateway; messageReceiver = _init.messageReceiver; lighthouse = _init.lighthouse; watchtower = _init.watchtower; callExecutor = _init.callExecutor; EVERCLEAR = _init.hubDomain; messageGasLimit = 20_000_000; __Ownable_init(_init.owner); // Intialize the queues intentQueue.first = 1; fillQueue.first = 1; } /*/////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Creates a new intent * @param _destinations The destination chains of the intent * @param _receiver The destinantion address of the intent * @param _inputAsset The asset address on origin * @param _outputAsset The asset address on destination * @param _amount The amount of the asset * @param _maxFee The maximum fee that can be taken by solvers * @param _ttl The time to live of the intent * @param _data The data of the intent * @param _usesPermit2 If the intent uses permit2 * @return _intentId The ID of the intent * @return _intent The intent structure */ function _newIntent( uint32[] memory _destinations, address _receiver, address _inputAsset, address _outputAsset, uint256 _amount, uint24 _maxFee, uint48 _ttl, bytes calldata _data, bool _usesPermit2 ) internal returns (bytes32 _intentId, Intent memory _intent) { if (_destinations.length == 1) { // output asset should not be null if the intent has a single destination and ttl != 0 if (_ttl != 0 && _outputAsset == address(0)) revert EverclearSpoke_NewIntent_InvalidIntent(); } else { // output asset should be null if the intent has multiple destinations // ttl should be 0 if the intent has multiple destinations if (_ttl != 0 || _outputAsset != address(0)) revert EverclearSpoke_NewIntent_InvalidIntent(); } if (_maxFee > Common.DBPS_DENOMINATOR) { revert EverclearSpoke_NewIntent_MaxFeeExceeded(_maxFee, Common.DBPS_DENOMINATOR); } if (_data.length > Common.MAX_CALLDATA_SIZE) { revert EverclearSpoke_NewIntent_CalldataExceedsLimit(); } uint256 _normalizedAmount = AssetUtils.normalizeDecimals(ERC20(_inputAsset).decimals(), Common.DEFAULT_NORMALIZED_DECIMALS, _amount); // check normalized amount before pulling tokens if (_normalizedAmount == 0) { revert EverclearSpoke_NewIntent_ZeroAmount(); } if (!_usesPermit2) { Strategy _strategy = strategies[_inputAsset]; if (_strategy == Strategy.DEFAULT) { _pullTokens(msg.sender, _inputAsset, _amount); } else { ISettlementModule _module = modules[_strategy]; _module.handleBurnStrategy(_inputAsset, msg.sender, _amount, ''); } } _intent = Intent({ initiator: msg.sender.toBytes32(), receiver: _receiver.toBytes32(), inputAsset: _inputAsset.toBytes32(), outputAsset: _outputAsset.toBytes32(), maxFee: _maxFee, origin: DOMAIN, nonce: ++nonce, timestamp: uint48(block.timestamp), ttl: _ttl, amount: _normalizedAmount, destinations: _destinations, data: _data }); _intentId = keccak256(abi.encode(_intent)); intentQueue.enqueueIntent(_intentId); status[_intentId] = IntentStatus.ADDED; emit IntentAdded(_intentId, intentQueue.last, _intent); } /** * @notice Fills an intent * @param _intent The intent structure * @param _solver The solver address * @param _fee The total fee, expressed in dbps, represents the solver fee plus the sum of protocol fees for the token * @return _fillMessage The fill message */ function _fillIntent( Intent calldata _intent, address _solver, uint24 _fee ) internal validDestination(_intent) returns (FillMessage memory _fillMessage) { bytes32 _intentId = keccak256(abi.encode(_intent)); if (block.timestamp >= _intent.timestamp + _intent.ttl) { revert EverclearSpoke_FillIntent_IntentExpired(_intentId); } if (_fee > _intent.maxFee) { revert EverclearSpoke_FillIntent_MaxFeeExceeded(_fee, _intent.maxFee); } if (status[_intentId] != IntentStatus.NONE) { revert EverclearSpoke_FillIntent_InvalidStatus(_intentId); } uint256 _amount = AssetUtils.normalizeDecimals( Common.DEFAULT_NORMALIZED_DECIMALS, ERC20(_intent.outputAsset.toAddress()).decimals(), _intent.amount ); uint256 _feeDeduction = _amount * _fee / Common.DBPS_DENOMINATOR; uint256 _finalAmount = _amount - _feeDeduction; if (balances[_intent.outputAsset][_solver.toBytes32()] < _finalAmount) { revert EverclearSpoke_FillIntent_InsufficientFunds( _finalAmount, balances[_intent.outputAsset][_solver.toBytes32()] ); } balances[_intent.outputAsset][_solver.toBytes32()] -= _finalAmount; status[_intentId] = IntentStatus.FILLED; if (_intent.receiver != 0 && _intent.outputAsset != 0 && _amount != 0) { _pushTokens(_intent.receiver.toAddress(), _intent.outputAsset.toAddress(), _finalAmount); } if (keccak256(_intent.data) != Constants.EMPTY_HASH) { _executeCalldata(_intentId, _intent.data); } _fillMessage = FillMessage({ intentId: _intentId, initiator: _intent.initiator, solver: _solver.toBytes32(), executionTimestamp: uint48(block.timestamp), fee: _fee }); fillQueue.enqueueFill(_fillMessage); emit IntentFilled(_intentId, _solver, _fee, fillQueue.last, _intent); } /** * @notice Verifies a signature * @param _signer The signer of the message * @param _data The data of the message * @param _nonce The nonce of the message * @param _signature The signature of the message */ function _verifySignature(address _signer, bytes memory _data, uint256 _nonce, bytes calldata _signature) internal { bytes32 _hash = keccak256(_data); address _recoveredSigner = ECDSA.recover(MessageHashUtils.toEthSignedMessageHash(_hash), _signature); if (_recoveredSigner != _signer) { revert EverclearSpoke_InvalidSignature(); } _useCheckedNonce(_recoveredSigner, _nonce); } /** * @notice Process the intent queue messages to send a batching message to the transport layer * @param _intents The intents to process, the order of the intents must match the order in the queue * @return _batchIntentmessage The batched intent message * @return _firstIdx The first index of the intents processed */ function _processIntentQueue( Intent[] calldata _intents ) internal validQueueAmount(intentQueue.first, intentQueue.last, _intents.length) returns (bytes memory _batchIntentmessage, uint256 _firstIdx) { _firstIdx = intentQueue.first; for (uint32 _i; _i < _intents.length; _i++) { bytes32 _queueIntentId = intentQueue.dequeueIntent(); bytes32 _intentHash = keccak256(abi.encode(_intents[_i])); // verify the intent and its position in the queue if (_queueIntentId != _intentHash) { revert EverclearSpoke_ProcessIntentQueue_NotFound(_intentHash, _i); } } _batchIntentmessage = MessageLib.formatIntentMessageBatch(_intents); } /** * @notice Process the fill queue messages to send a batching message to the transport layer * @param _amount The amount of messages to process * @return _batchFillMessage The batched fill message * @return _firstIdx The first index of the fills processed */ function _processFillQueue( uint32 _amount ) internal validQueueAmount(fillQueue.first, fillQueue.last, _amount) returns (bytes memory _batchFillMessage, uint256 _firstIdx) { _firstIdx = fillQueue.first; FillMessage[] memory _fillMessages = new FillMessage[](_amount); for (uint32 _i; _i < _amount; _i++) { _fillMessages[_i] = fillQueue.dequeueFill(); } _batchFillMessage = MessageLib.formatFillMessageBatch(_fillMessages); } /** * @notice Executes the calldata of an intent * @param _intentId The intent ID * @param _data The calldata of the intent */ function _executeCalldata(bytes32 _intentId, bytes memory _data) internal { (address _target, bytes memory _calldata) = abi.decode(_data, (address, bytes)); (bool _success, bytes memory _returnData) = callExecutor.excessivelySafeCall( _target, gasleft() - Constants.EXECUTE_CALLDATA_RESERVE_GAS, 0, Constants.DEFAULT_COPY_BYTES, _calldata ); if (_success) { emit ExternalCalldataExecuted(_intentId, _returnData); } else { revert EverclearSpoke_ExecuteIntentCalldata_ExternalCallFailed(); } } /** * @notice Pull tokens from the sender to the spoke contract * @param _sender The address of the sender * @param _asset The address of the asset * @param _amount The amount of the asset */ function _pullTokens(address _sender, address _asset, uint256 _amount) internal { IERC20(_asset).safeTransferFrom(_sender, address(this), _amount); } /** * @notice Push tokens from the spoke contract to the recipient * @param _recipient The address of the recipient * @param _asset The address of the asset * @param _amount The amount of the asset */ function _pushTokens(address _recipient, address _asset, uint256 _amount) internal { IERC20(_asset).safeTransfer(_recipient, _amount); } /** * @notice Perform a `delegatcall` * @param _delegatee The address of the delegatee */ function _delegate( address _delegatee ) internal { assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas(), _delegatee, 0, calldatasize(), 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /** * @notice Checks that the upgrade function is called by the owner */ function _authorizeUpgrade( address ) internal override onlyOwner {} /** * @notice Process queue checks (applied when a relayer tries to process a queue) * @param _domain The domain of the queue * @param _relayer The relayer address * @param _ttl The time to live of the message */ function _processQueueChecks(uint32 _domain, address _relayer, uint256 _ttl) internal view { if (_domain != DOMAIN) { revert EverclearSpoke_ProcessFillViaRelayer_WrongDomain(); } if (_relayer != msg.sender) { revert EverclearSpoke_ProcessFillViaRelayer_NotRelayer(); } if (block.timestamp > _ttl) { revert EverclearSpoke_ProcessFillViaRelayer_TTLExpired(); } } }
// 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) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.20; import {IERC1822Proxiable} from "@openzeppelin/contracts/interfaces/draft-IERC1822.sol"; import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol"; import {Initializable} from "./Initializable.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. */ abstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address private immutable __self = address(this); /** * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)` * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called, * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string. * If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function * during an upgrade. */ string public constant UPGRADE_INTERFACE_VERSION = "5.0.0"; /** * @dev The call is from an unauthorized context. */ error UUPSUnauthorizedCallContext(); /** * @dev The storage `slot` is unsupported as a UUID. */ error UUPSUnsupportedProxiableUUID(bytes32 slot); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { _checkProxy(); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { _checkNotDelegated(); _; } function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual notDelegated returns (bytes32) { return ERC1967Utils.IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data); } /** * @dev Reverts if the execution is not performed via delegatecall or the execution * context is not of a proxy with an ERC1967-compliant implementation pointing to self. * See {_onlyProxy}. */ function _checkProxy() internal view virtual { if ( address(this) == __self || // Must be called through delegatecall ERC1967Utils.getImplementation() != __self // Must be called through an active proxy ) { revert UUPSUnauthorizedCallContext(); } } /** * @dev Reverts if the execution is performed via delegatecall. * See {notDelegated}. */ function _checkNotDelegated() internal view virtual { if (address(this) != __self) { // Must not be called through delegatecall revert UUPSUnauthorizedCallContext(); } } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call. * * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value * is expected to be the implementation slot in ERC1967. * * Emits an {IERC1967-Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) { revert UUPSUnsupportedProxiableUUID(slot); } ERC1967Utils.upgradeToAndCall(newImplementation, data); } catch { // The implementation is not UUPS revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Nonces.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides tracking nonces for addresses. Nonces will only increment. */ abstract contract NoncesUpgradeable is Initializable { /** * @dev The nonce used for an `account` is not the expected current nonce. */ error InvalidAccountNonce(address account, uint256 currentNonce); /// @custom:storage-location erc7201:openzeppelin.storage.Nonces struct NoncesStorage { mapping(address account => uint256) _nonces; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Nonces")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant NoncesStorageLocation = 0x5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb00; function _getNoncesStorage() private pure returns (NoncesStorage storage $) { assembly { $.slot := NoncesStorageLocation } } function __Nonces_init() internal onlyInitializing { } function __Nonces_init_unchained() internal onlyInitializing { } /** * @dev Returns the next unused nonce for an address. */ function nonces(address owner) public view virtual returns (uint256) { NoncesStorage storage $ = _getNoncesStorage(); return $._nonces[owner]; } /** * @dev Consumes a nonce. * * Returns the current value and increments nonce. */ function _useNonce(address owner) internal virtual returns (uint256) { NoncesStorage storage $ = _getNoncesStorage(); // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be // decremented or reset. This guarantees that the nonce never overflows. unchecked { // It is important to do x++ and not ++x here. return $._nonces[owner]++; } } /** * @dev Same as {_useNonce} but checking that `nonce` is the next valid for `owner`. */ function _useCheckedNonce(address owner, uint256 nonce) internal virtual { uint256 current = _useNonce(owner); if (nonce != current) { revert InvalidAccountNonce(owner, current); } } }
// 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 // 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/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError, bytes32) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS, s); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol) pragma solidity ^0.8.20; import {Strings} from "../Strings.sol"; /** * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. * * The library provides methods for generating a hash of a message that conforms to the * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] * specifications. */ library MessageHashUtils { /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing a bytes32 `messageHash` with * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with * keccak256, although any bytes32 value can be safely used because the final digest will * be re-hashed. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20) } } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing an arbitrary `message` with * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) { return keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message)); } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x00` (data with intended validator). * * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended * `validator` address. Then hashing the result. * * See {ECDSA-recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked(hex"19_00", validator, data)); } /** * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`). * * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with * `\x19\x01` and hashing the result. It corresponds to the hash signed by the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. * * See {ECDSA-recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, hex"19_01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) digest := keccak256(ptr, 0x42) } } }
// 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 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 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; library Constants { // Reserved gas required after the calldata execution uint256 public constant EXECUTE_CALLDATA_RESERVE_GAS = 10_000; // Bytes to copy from the calldata uint16 public constant DEFAULT_COPY_BYTES = 256; // The empty hash bytes32 public constant EMPTY_HASH = keccak256(''); }
// 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.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; 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 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 {IEverclear} from 'interfaces/common/IEverclear.sol'; import {ISettlementModule} from 'interfaces/common/ISettlementModule.sol'; import {ISpokeStorage} from './ISpokeStorage.sol'; /** * @title IEverclearSpoke * @notice Interface for the EverclearSpoke contract */ interface IEverclearSpoke is ISpokeStorage { /*/////////////////////////////////////////////////////////////// STRUCTS //////////////////////////////////////////////////////////////*/ /** * @notice Parameters needed to execute a permit2 * @param nonce The nonce of the permit * @param deadline The deadline of the permit * @param signature The signature of the permit */ struct Permit2Params { uint256 nonce; uint256 deadline; bytes signature; } /*/////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ /** * @notice emitted when a new intent is added on origin * @param _intentId The ID of the intent * @param _queueIdx The index of the intent in the IntentQueue * @param _intent The intent object */ event IntentAdded(bytes32 indexed _intentId, uint256 _queueIdx, Intent _intent); /** * @notice emitted when an intent is filled on destination * @param _intentId The ID of the intent * @param _solver The address of the intent solver * @param _totalFeeDBPS The total amount of fee deducted from the transferred amount * @param _queueIdx The index of the FillMessage in the FillQueue * @param _intent The full intent object */ event IntentFilled( bytes32 indexed _intentId, address indexed _solver, uint256 _totalFeeDBPS, uint256 _queueIdx, Intent _intent ); /** * @notice emitted when solver (or anyone) deposits an asset in the EverclearSpoke * @param _depositant The address of the depositant * @param _asset The address of the deposited asset * @param _amount The amount of the deposited asset */ event Deposited(address indexed _depositant, address indexed _asset, uint256 _amount); /** * @notice emitted when solver (or anyone) withdraws an asset from the EverclearSpoke * @param _withdrawer The address of the withdrawer * @param _asset The address of the withdrawn asset * @param _amount The amount of the withdrawn asset */ event Withdrawn(address indexed _withdrawer, address indexed _asset, uint256 _amount); /** * @notice Emitted when the intent queue is processed * @param _messageId The ID of the message * @param _firstIdx The first index of the queue to be processed * @param _lastIdx The last index of the queue to be processed * @param _quote The quote amount */ event IntentQueueProcessed(bytes32 indexed _messageId, uint256 _firstIdx, uint256 _lastIdx, uint256 _quote); /** * @notice Emitted when the fill queue is processed * @param _messageId The ID of the message * @param _firstIdx The first index of the queue to be processed * @param _lastIdx The last index of the queue to be processed * @param _quote The quote amount */ event FillQueueProcessed(bytes32 indexed _messageId, uint256 _firstIdx, uint256 _lastIdx, uint256 _quote); /** * @notice Emitted when an external call is executed * @param _intentId The ID of the intent * @param _returnData The return data of the call */ event ExternalCalldataExecuted(bytes32 indexed _intentId, bytes _returnData); /*/////////////////////////////////////////////////////////////// ERRORS //////////////////////////////////////////////////////////////*/ /** * @notice Thrown when the intent is already filled * @param _intentId The id of the intent which is being tried to fill */ error EverclearSpoke_FillIntent_InvalidStatus(bytes32 _intentId); /** * @notice Thrown when trying to fill an expired intent * @param _intentId The id of the intent which is being tried to fill */ error EverclearSpoke_FillIntent_IntentExpired(bytes32 _intentId); /** * @notice Thrown when calling newIntent with invalid intent parameters */ error EverclearSpoke_NewIntent_InvalidIntent(); /** * @notice Thrown when the maxFee is exceeded * @param _fee The fee chosen by the user * @param _maxFee The maximum possible fee */ error EverclearSpoke_NewIntent_MaxFeeExceeded(uint256 _fee, uint24 _maxFee); /** * @notice Thrown when the intent amount is zero */ error EverclearSpoke_NewIntent_ZeroAmount(); /** * @notice Thrown when the solver doesnt have sufficient funds to fill an intent * @param _requested The amount of tokens needed to fill the intent * @param _available The amount of tokens the solver has deposited in the `EverclearSpoke` */ error EverclearSpoke_FillIntent_InsufficientFunds(uint256 _requested, uint256 _available); /** * @notice Thrown when the fee exceeds the maximum fee * @param _fee The fee chosen by the solver * @param _maxFee The actual fee the intent solver set for his intent */ error EverclearSpoke_FillIntent_MaxFeeExceeded(uint256 _fee, uint24 _maxFee); /** * @notice Thrown when the intent calldata exceeds the limit */ error EverclearSpoke_NewIntent_CalldataExceedsLimit(); /** * @notice Thrown when a signature signer does not match the expected address */ error EverclearSpoke_InvalidSignature(); /** * @notice Thrown when the domain does not match the expected domain */ error EverclearSpoke_ProcessFillViaRelayer_WrongDomain(); /** * @notice Thrown when the relayer address does not match the msg.sender */ error EverclearSpoke_ProcessFillViaRelayer_NotRelayer(); /** * @notice Thrown when the TTL of the message has expired */ error EverclearSpoke_ProcessFillViaRelayer_TTLExpired(); /** * @notice Thrown when processing the intent queue and the intent is not found in the position specified in the parameter * @param _intentId The id of the intent being processed * @param _position The position specified by the queue processor */ error EverclearSpoke_ProcessIntentQueue_NotFound(bytes32 _intentId, uint256 _position); /** * @notice Thrown when trying to execute the calldata of an intent with invalid status * @param _intentId The id of the intent whose calldata is trying to be executed */ error EverclearSpoke_ExecuteIntentCalldata_InvalidStatus(bytes32 _intentId); /** * @notice Thrown when the external call failed on executeIntentCalldata */ error EverclearSpoke_ExecuteIntentCalldata_ExternalCallFailed(); /*/////////////////////////////////////////////////////////////// LOGIC //////////////////////////////////////////////////////////////*/ /** * @notice Pauses the contract * @dev only the lighthouse and watchtower can pause the contract */ function pause() external; /** * @notice Unpauses the contract * @dev only the lighthouse and watchtower can unpause the contract */ function unpause() external; /** * @notice Sets a minting / burning strategy for an asset * @param _asset The asset address * @param _strategy The strategy id (see `enum Strategy`) */ function setStrategyForAsset(address _asset, IEverclear.Strategy _strategy) external; /** * @notice Sets a module for a strategy * @param _strategy The strategy id (see `enum Strategy`) * @param _module The module contract */ function setModuleForStrategy(IEverclear.Strategy _strategy, ISettlementModule _module) external; /** * @notice Updates the security module * @param _newSecurityModule The address of the new security module */ function updateSecurityModule( address _newSecurityModule ) external; /** * @notice Initialize the EverclearSpoke contract * @param _init The spoke initialization parameters */ function initialize( SpokeInitializationParams calldata _init ) external; /** * @notice Creates a new intent * @param _destinations The possible destination chains of the intent * @param _receiver The destinantion address of the intent * @param _inputAsset The asset address on origin * @param _outputAsset The asset address on destination * @param _amount The amount of the asset * @param _maxFee The maximum fee that can be taken by solvers * @param _ttl The time to live of the intent * @param _data The data of the intent * @return _intentId The ID of the intent * @return _intent The intent object */ function newIntent( uint32[] memory _destinations, address _receiver, address _inputAsset, address _outputAsset, uint256 _amount, uint24 _maxFee, uint48 _ttl, bytes calldata _data ) external returns (bytes32 _intentId, Intent calldata _intent); /** * @notice Creates a new intent with permit2 * @param _destinations The possible destination chains of the intent * @param _receiver The destinantion address of the intent * @param _inputAsset The asset address on origin * @param _outputAsset The asset address on destination * @param _amount The amount of the asset * @param _maxFee The maximum fee that can be taken by solvers * @param _ttl The time to live of the intent * @param _data The data of the intent * @param _permit2Params The parameters needed to execute a permit2 * @return _intentId The ID of the intent * @return _intent The intent object */ function newIntent( uint32[] memory _destinations, address _receiver, address _inputAsset, address _outputAsset, uint256 _amount, uint24 _maxFee, uint48 _ttl, bytes calldata _data, Permit2Params calldata _permit2Params ) external returns (bytes32 _intentId, Intent calldata _intent); /** * @notice fills an intent * @param _intent The intent structure * @param _fee The total fee, expressed in dbps, represents the solver fee plus the sum of protocol fees for the token * @return _fillMessage The enqueued fill message */ function fillIntent(Intent calldata _intent, uint24 _fee) external returns (FillMessage calldata _fillMessage); /** * @notice Allows a relayer to fill an intent for a solver * @param _solver The address of the solver * @param _intent The intent structure * @param _nonce The nonce of the signature * @param _fee The total fee, expressed in dbps, represents the solver fee plus the sum of protocol fees for the token * @param _signature The solver signature * @return _fillMessage The enqueued fill message */ function fillIntentForSolver( address _solver, Intent calldata _intent, uint256 _nonce, uint24 _fee, bytes calldata _signature ) external returns (FillMessage memory _fillMessage); /** * @notice Process the intent queue messages to send a batched message to the transport layer * @param _intents The intents to process, must respect the intent queue order */ function processIntentQueue( Intent[] calldata _intents ) external payable; /** * @notice Process the fill queue messages to send a batched message to the transport layer * @param _amount The amount of messages to process and batch */ function processFillQueue( uint32 _amount ) external payable; /** * @notice Process the intent queue messages to send a batched message to the transport layer (via relayer) * @param _domain The domain of the message * @param _intents The intents to process, must respect the intent queue order * @param _relayer The address of the relayer * @param _ttl The time to live of the message * @param _nonce The nonce of the signature * @param _bufferDBPS The buffer in DBPS to add to the fee * @param _signature The signature of the data */ function processIntentQueueViaRelayer( uint32 _domain, Intent[] calldata _intents, address _relayer, uint256 _ttl, uint256 _nonce, uint256 _bufferDBPS, bytes calldata _signature ) external; /** * @notice Process the fill queue messages to send a batched message to the transport layer (via relayer) * @param _domain The domain of the message * @param _amount The amount of messages to process and batch * @param _relayer The address of the relayer * @param _ttl The time to live of the message * @param _nonce The nonce of the signature * @param _bufferDBPS The buffer in DBPS to add to the fee * @param _signature The signature of the data */ function processFillQueueViaRelayer( uint32 _domain, uint32 _amount, address _relayer, uint256 _ttl, uint256 _nonce, uint256 _bufferDBPS, bytes calldata _signature ) external; /** * @notice deposits an asset into the EverclearSpoke * @dev should be only called by solvers but it is permissionless, the funds will be used by the solvers to execute intents * @param _asset The address of the asset * @param _amount The amount of the asset */ function deposit(address _asset, uint256 _amount) external; /** * @notice withdraws an asset from the EverclearSpoke * @dev can be called by solvers or users * @param _asset The address of the asset * @param _amount The amount of the asset */ function withdraw(address _asset, uint256 _amount) external; /** * @notice Updates the gateway * @param _newGateway The address of the new gateway */ function updateGateway( address _newGateway ) external; /** * @notice Updates the message receiver * @param _newMessageReceiver The address of the new message receiver */ function updateMessageReceiver( address _newMessageReceiver ) external; /** * @notice Updates the max gas limit used for outgoing messages * @param _newGasLimit The new gas limit */ function updateMessageGasLimit( uint256 _newGasLimit ) external; /** * @notice Executes the calldata of an intent * @param _intent The intent object */ function executeIntentCalldata( Intent calldata _intent ) 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) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.20; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Utils.sol) pragma solidity ^0.8.20; import {IBeacon} from "../beacon/IBeacon.sol"; import {Address} from "../../utils/Address.sol"; import {StorageSlot} from "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. */ library ERC1967Utils { // We re-declare ERC-1967 events here because they can't be used directly from IERC1967. // This will be fixed in Solidity 0.8.21. At that point we should remove these events. /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev The `implementation` of the proxy is invalid. */ error ERC1967InvalidImplementation(address implementation); /** * @dev The `admin` of the proxy is invalid. */ error ERC1967InvalidAdmin(address admin); /** * @dev The `beacon` of the proxy is invalid. */ error ERC1967InvalidBeacon(address beacon); /** * @dev An upgrade function sees `msg.value > 0` that may be lost. */ error ERC1967NonPayable(); /** * @dev Returns the current implementation address. */ function getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { if (newImplementation.code.length == 0) { revert ERC1967InvalidImplementation(newImplementation); } StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Performs implementation upgrade with additional setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); if (data.length > 0) { Address.functionDelegateCall(newImplementation, data); } else { _checkNonPayable(); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { if (newAdmin == address(0)) { revert ERC1967InvalidAdmin(address(0)); } StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {IERC1967-AdminChanged} event. */ function changeAdmin(address newAdmin) internal { emit AdminChanged(getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { if (newBeacon.code.length == 0) { revert ERC1967InvalidBeacon(newBeacon); } StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon; address beaconImplementation = IBeacon(newBeacon).implementation(); if (beaconImplementation.code.length == 0) { revert ERC1967InvalidImplementation(beaconImplementation); } } /** * @dev Change the beacon and trigger a setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-BeaconUpgraded} event. * * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for * efficiency. */ function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } else { _checkNonPayable(); } } /** * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract * if an upgrade doesn't perform an initialization call. */ function _checkNonPayable() private { if (msg.value > 0) { revert ERC1967NonPayable(); } } }
// 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 // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } }
// 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 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; /** * @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 // OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.20; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {UpgradeableBeacon} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.20; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(newImplementation.code.length > 0); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// 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":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[],"name":"EverclearSpoke_ExecuteIntentCalldata_ExternalCallFailed","type":"error"},{"inputs":[{"internalType":"bytes32","name":"_intentId","type":"bytes32"}],"name":"EverclearSpoke_ExecuteIntentCalldata_InvalidStatus","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requested","type":"uint256"},{"internalType":"uint256","name":"_available","type":"uint256"}],"name":"EverclearSpoke_FillIntent_InsufficientFunds","type":"error"},{"inputs":[{"internalType":"bytes32","name":"_intentId","type":"bytes32"}],"name":"EverclearSpoke_FillIntent_IntentExpired","type":"error"},{"inputs":[{"internalType":"bytes32","name":"_intentId","type":"bytes32"}],"name":"EverclearSpoke_FillIntent_InvalidStatus","type":"error"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"uint24","name":"_maxFee","type":"uint24"}],"name":"EverclearSpoke_FillIntent_MaxFeeExceeded","type":"error"},{"inputs":[],"name":"EverclearSpoke_InvalidMessageType","type":"error"},{"inputs":[],"name":"EverclearSpoke_InvalidSignature","type":"error"},{"inputs":[],"name":"EverclearSpoke_InvalidVarUpdate","type":"error"},{"inputs":[],"name":"EverclearSpoke_NewIntent_CalldataExceedsLimit","type":"error"},{"inputs":[],"name":"EverclearSpoke_NewIntent_InvalidIntent","type":"error"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"uint24","name":"_maxFee","type":"uint24"}],"name":"EverclearSpoke_NewIntent_MaxFeeExceeded","type":"error"},{"inputs":[],"name":"EverclearSpoke_NewIntent_ZeroAmount","type":"error"},{"inputs":[],"name":"EverclearSpoke_Pause_NotAuthorized","type":"error"},{"inputs":[],"name":"EverclearSpoke_Paused","type":"error"},{"inputs":[],"name":"EverclearSpoke_ProcessFillViaRelayer_NotRelayer","type":"error"},{"inputs":[],"name":"EverclearSpoke_ProcessFillViaRelayer_TTLExpired","type":"error"},{"inputs":[],"name":"EverclearSpoke_ProcessFillViaRelayer_WrongDomain","type":"error"},{"inputs":[{"internalType":"bytes32","name":"_intentId","type":"bytes32"},{"internalType":"uint256","name":"_position","type":"uint256"}],"name":"EverclearSpoke_ProcessIntentQueue_NotFound","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":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidAccountNonce","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"},{"inputs":[],"name":"Queue_EmptyQueue","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"UUPSUnsupportedProxiableUUID","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":true,"internalType":"address","name":"_depositant","type":"address"},{"indexed":true,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"_intentId","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"_returnData","type":"bytes"}],"name":"ExternalCalldataExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"_messageId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_firstIdx","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_lastIdx","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_quote","type":"uint256"}],"name":"FillQueueProcessed","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":true,"internalType":"bytes32","name":"_intentId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_queueIdx","type":"uint256"},{"components":[{"internalType":"bytes32","name":"initiator","type":"bytes32"},{"internalType":"bytes32","name":"receiver","type":"bytes32"},{"internalType":"bytes32","name":"inputAsset","type":"bytes32"},{"internalType":"bytes32","name":"outputAsset","type":"bytes32"},{"internalType":"uint24","name":"maxFee","type":"uint24"},{"internalType":"uint32","name":"origin","type":"uint32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"uint48","name":"timestamp","type":"uint48"},{"internalType":"uint48","name":"ttl","type":"uint48"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint32[]","name":"destinations","type":"uint32[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false,"internalType":"struct IEverclear.Intent","name":"_intent","type":"tuple"}],"name":"IntentAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"_intentId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"_solver","type":"address"},{"indexed":false,"internalType":"uint256","name":"_totalFeeDBPS","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_queueIdx","type":"uint256"},{"components":[{"internalType":"bytes32","name":"initiator","type":"bytes32"},{"internalType":"bytes32","name":"receiver","type":"bytes32"},{"internalType":"bytes32","name":"inputAsset","type":"bytes32"},{"internalType":"bytes32","name":"outputAsset","type":"bytes32"},{"internalType":"uint24","name":"maxFee","type":"uint24"},{"internalType":"uint32","name":"origin","type":"uint32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"uint48","name":"timestamp","type":"uint48"},{"internalType":"uint48","name":"ttl","type":"uint48"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint32[]","name":"destinations","type":"uint32[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false,"internalType":"struct IEverclear.Intent","name":"_intent","type":"tuple"}],"name":"IntentFilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"_messageId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_firstIdx","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_lastIdx","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_quote","type":"uint256"}],"name":"IntentQueueProcessed","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":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_withdrawer","type":"address"},{"indexed":true,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"Withdrawn","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":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"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":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"initiator","type":"bytes32"},{"internalType":"bytes32","name":"receiver","type":"bytes32"},{"internalType":"bytes32","name":"inputAsset","type":"bytes32"},{"internalType":"bytes32","name":"outputAsset","type":"bytes32"},{"internalType":"uint24","name":"maxFee","type":"uint24"},{"internalType":"uint32","name":"origin","type":"uint32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"uint48","name":"timestamp","type":"uint48"},{"internalType":"uint48","name":"ttl","type":"uint48"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint32[]","name":"destinations","type":"uint32[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IEverclear.Intent","name":"_intent","type":"tuple"}],"name":"executeIntentCalldata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"initiator","type":"bytes32"},{"internalType":"bytes32","name":"receiver","type":"bytes32"},{"internalType":"bytes32","name":"inputAsset","type":"bytes32"},{"internalType":"bytes32","name":"outputAsset","type":"bytes32"},{"internalType":"uint24","name":"maxFee","type":"uint24"},{"internalType":"uint32","name":"origin","type":"uint32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"uint48","name":"timestamp","type":"uint48"},{"internalType":"uint48","name":"ttl","type":"uint48"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint32[]","name":"destinations","type":"uint32[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IEverclear.Intent","name":"_intent","type":"tuple"},{"internalType":"uint24","name":"_fee","type":"uint24"}],"name":"fillIntent","outputs":[{"components":[{"internalType":"bytes32","name":"intentId","type":"bytes32"},{"internalType":"bytes32","name":"solver","type":"bytes32"},{"internalType":"bytes32","name":"initiator","type":"bytes32"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"uint48","name":"executionTimestamp","type":"uint48"}],"internalType":"struct IEverclear.FillMessage","name":"_fillMessage","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_solver","type":"address"},{"components":[{"internalType":"bytes32","name":"initiator","type":"bytes32"},{"internalType":"bytes32","name":"receiver","type":"bytes32"},{"internalType":"bytes32","name":"inputAsset","type":"bytes32"},{"internalType":"bytes32","name":"outputAsset","type":"bytes32"},{"internalType":"uint24","name":"maxFee","type":"uint24"},{"internalType":"uint32","name":"origin","type":"uint32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"uint48","name":"timestamp","type":"uint48"},{"internalType":"uint48","name":"ttl","type":"uint48"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint32[]","name":"destinations","type":"uint32[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IEverclear.Intent","name":"_intent","type":"tuple"},{"internalType":"uint256","name":"_nonce","type":"uint256"},{"internalType":"uint24","name":"_fee","type":"uint24"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"fillIntentForSolver","outputs":[{"components":[{"internalType":"bytes32","name":"intentId","type":"bytes32"},{"internalType":"bytes32","name":"solver","type":"bytes32"},{"internalType":"bytes32","name":"initiator","type":"bytes32"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"uint48","name":"executionTimestamp","type":"uint48"}],"internalType":"struct IEverclear.FillMessage","name":"_fillMessage","type":"tuple"}],"stateMutability":"nonpayable","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":[{"components":[{"internalType":"contract ISpokeGateway","name":"gateway","type":"address"},{"internalType":"contract ICallExecutor","name":"callExecutor","type":"address"},{"internalType":"address","name":"messageReceiver","type":"address"},{"internalType":"address","name":"lighthouse","type":"address"},{"internalType":"address","name":"watchtower","type":"address"},{"internalType":"uint32","name":"hubDomain","type":"uint32"},{"internalType":"address","name":"owner","type":"address"}],"internalType":"struct ISpokeStorage.SpokeInitializationParams","name":"_init","type":"tuple"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"uint32[]","name":"_destinations","type":"uint32[]"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"address","name":"_inputAsset","type":"address"},{"internalType":"address","name":"_outputAsset","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint24","name":"_maxFee","type":"uint24"},{"internalType":"uint48","name":"_ttl","type":"uint48"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"newIntent","outputs":[{"internalType":"bytes32","name":"_intentId","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"initiator","type":"bytes32"},{"internalType":"bytes32","name":"receiver","type":"bytes32"},{"internalType":"bytes32","name":"inputAsset","type":"bytes32"},{"internalType":"bytes32","name":"outputAsset","type":"bytes32"},{"internalType":"uint24","name":"maxFee","type":"uint24"},{"internalType":"uint32","name":"origin","type":"uint32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"uint48","name":"timestamp","type":"uint48"},{"internalType":"uint48","name":"ttl","type":"uint48"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint32[]","name":"destinations","type":"uint32[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IEverclear.Intent","name":"_intent","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32[]","name":"_destinations","type":"uint32[]"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"address","name":"_inputAsset","type":"address"},{"internalType":"address","name":"_outputAsset","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint24","name":"_maxFee","type":"uint24"},{"internalType":"uint48","name":"_ttl","type":"uint48"},{"internalType":"bytes","name":"_data","type":"bytes"},{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct IEverclearSpoke.Permit2Params","name":"_permit2Params","type":"tuple"}],"name":"newIntent","outputs":[{"internalType":"bytes32","name":"_intentId","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"initiator","type":"bytes32"},{"internalType":"bytes32","name":"receiver","type":"bytes32"},{"internalType":"bytes32","name":"inputAsset","type":"bytes32"},{"internalType":"bytes32","name":"outputAsset","type":"bytes32"},{"internalType":"uint24","name":"maxFee","type":"uint24"},{"internalType":"uint32","name":"origin","type":"uint32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"uint48","name":"timestamp","type":"uint48"},{"internalType":"uint48","name":"ttl","type":"uint48"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint32[]","name":"destinations","type":"uint32[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IEverclear.Intent","name":"_intent","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nonce","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_amount","type":"uint32"}],"name":"processFillQueue","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_domain","type":"uint32"},{"internalType":"uint32","name":"_amount","type":"uint32"},{"internalType":"address","name":"_relayer","type":"address"},{"internalType":"uint256","name":"_ttl","type":"uint256"},{"internalType":"uint256","name":"_nonce","type":"uint256"},{"internalType":"uint256","name":"_bufferDBPS","type":"uint256"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"processFillQueueViaRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"initiator","type":"bytes32"},{"internalType":"bytes32","name":"receiver","type":"bytes32"},{"internalType":"bytes32","name":"inputAsset","type":"bytes32"},{"internalType":"bytes32","name":"outputAsset","type":"bytes32"},{"internalType":"uint24","name":"maxFee","type":"uint24"},{"internalType":"uint32","name":"origin","type":"uint32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"uint48","name":"timestamp","type":"uint48"},{"internalType":"uint48","name":"ttl","type":"uint48"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint32[]","name":"destinations","type":"uint32[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IEverclear.Intent[]","name":"_intents","type":"tuple[]"}],"name":"processIntentQueue","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_domain","type":"uint32"},{"components":[{"internalType":"bytes32","name":"initiator","type":"bytes32"},{"internalType":"bytes32","name":"receiver","type":"bytes32"},{"internalType":"bytes32","name":"inputAsset","type":"bytes32"},{"internalType":"bytes32","name":"outputAsset","type":"bytes32"},{"internalType":"uint24","name":"maxFee","type":"uint24"},{"internalType":"uint32","name":"origin","type":"uint32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"uint48","name":"timestamp","type":"uint48"},{"internalType":"uint48","name":"ttl","type":"uint48"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint32[]","name":"destinations","type":"uint32[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IEverclear.Intent[]","name":"_intents","type":"tuple[]"},{"internalType":"address","name":"_relayer","type":"address"},{"internalType":"uint256","name":"_ttl","type":"uint256"},{"internalType":"uint256","name":"_nonce","type":"uint256"},{"internalType":"uint256","name":"_bufferDBPS","type":"uint256"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"processIntentQueueViaRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"receiveMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum IEverclear.Strategy","name":"_strategy","type":"uint8"},{"internalType":"contract ISettlementModule","name":"_module","type":"address"}],"name":"setModuleForStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"enum IEverclear.Strategy","name":"_strategy","type":"uint8"}],"name":"setStrategyForAsset","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":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newGateway","type":"address"}],"name":"updateGateway","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newGasLimit","type":"uint256"}],"name":"updateMessageGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newMessageReceiver","type":"address"}],"name":"updateMessageReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newSecurityModule","type":"address"}],"name":"updateSecurityModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"watchtower","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a06040523060805234801562000014575f80fd5b506200001f62000025565b620000d9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff1615620000765760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b0390811614620000d65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b608051615825620001005f395f8181612dc301528181612dec0152612f9c01526158255ff3fe608060405260043610610303575f3560e01c80638456cb5911610191578063c0346b20116100dc578063e2cae9f511610087578063f3fef3a311610062578063f3fef3a314610a12578063f953cec714610a31578063fa12957c14610a50575f80fd5b8063e2cae9f5146109b9578063f2fde38b146109d8578063f37c0a2e146109f7575f80fd5b8063cab0071e116100b7578063cab0071e14610957578063d6979ef61461096c578063df7a760114610986575f80fd5b8063c0346b20146108e5578063c13eedbe14610904578063c2aeb7bd14610923575f80fd5b8063990969f61161013c578063affed0e011610117578063affed0e014610855578063b4c20477146108a7578063beff4ce2146108c6575f80fd5b8063990969f6146107c25780639eb93f1f146107e1578063ad3cb1cc14610800575f80fd5b80638da5cb5b1161016c5780638da5cb5b146107385780638fd689401461077457806391a3ef8e146107a3575f80fd5b80638456cb59146106f25780638467b5b5146107065780638af5f77914610725575f80fd5b806352d1902d116102515780636afdd850116101fc57806373e554f6116101d757806373e554f61461064d5780637ecebe00146106805780637f7673f9146106d3575f80fd5b80636afdd850146105f8578063715018a61461061a578063715fc7361461062e575f80fd5b80635d394d3b1161022c5780635d394d3b1461059c578063601ae9b8146105bb5780636301fd63146105ce575f80fd5b806352d1902d146105285780635c8ff7611461053c5780635c975abb1461055b575f80fd5b80634a943d21116102b1578063522dbaa51161028c578063522dbaa51461048257806352a9674b146104b557806352ad0d5e146104ed575f80fd5b80634a943d21146104235780634c739c32146104505780634f1ef2861461046f575f80fd5b806339ebf823116102e157806339ebf823146103b35780633f4ba83a146103ee57806347e7ef2414610404575f80fd5b8063043dca0414610307578063116191b61461035057806311a4cbbf14610387575b5f80fd5b348015610312575f80fd5b5061033d6103213660046141eb565b600660209081525f928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b34801561035b575f80fd5b5060035461036f906001600160a01b031681565b6040516001600160a01b039091168152602001610347565b348015610392575f80fd5b506103a66103a1366004614239565b610a6f565b6040516103479190614284565b3480156103be575f80fd5b506103e16103cd3660046142e9565b60086020525f908152604090205460ff1681565b6040516103479190614345565b3480156103f9575f80fd5b50610402610b00565b005b34801561040f575f80fd5b5061040261041e366004614353565b610bba565b34801561042e575f80fd5b5061044261043d366004614508565b610c96565b604051610347929190614742565b34801561045b575f80fd5b5061040261046a36600461475a565b610da9565b61040261047d3660046147de565b611133565b34801561048d575f80fd5b5061033d7f0afae807991f914b71165fd92589f1dc28648cb9fb1f8558f3a6c7507d56deff81565b3480156104c0575f80fd5b505f546104d890640100000000900463ffffffff1681565b60405163ffffffff9091168152602001610347565b3480156104f8575f80fd5b5061051b61050736600461482b565b60076020525f908152604090205460ff1681565b6040516103479190614842565b348015610533575f80fd5b5061033d611152565b348015610547575f80fd5b506104026105563660046142e9565b611180565b348015610566575f80fd5b5060045461058c9074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610347565b3480156105a7575f80fd5b506104026105b636600461482b565b611202565b6104026105c936600461485c565b611248565b3480156105d9575f80fd5b505f5461036f906801000000000000000090046001600160a01b031681565b348015610603575f80fd5b5061036f6e22d473030f116ddee9f6b43ac78ba381565b348015610625575f80fd5b506104026113aa565b348015610639575f80fd5b50610402610648366004614875565b6113bd565b348015610658575f80fd5b5061033d7f8104c8a42e1531612796e696e327ea52a475d9583ee6d64ffdefcafad22c0b2481565b34801561068b575f80fd5b5061033d61069a3660046142e9565b6001600160a01b03165f9081527f5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb00602052604090205490565b3480156106de575f80fd5b5060015461036f906001600160a01b031681565b3480156106fd575f80fd5b506104026115ab565b348015610711575f80fd5b506104026107203660046148a7565b61167c565b610402610733366004614976565b611926565b348015610743575f80fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031661036f565b34801561077f575f80fd5b50600a54600b5461078e919082565b60408051928352602083019190915201610347565b3480156107ae575f80fd5b506104026107bd3660046142e9565b611a84565b3480156107cd575f80fd5b5060045461036f906001600160a01b031681565b3480156107ec575f80fd5b506104026107fb3660046149b5565b611b02565b34801561080b575f80fd5b506108486040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516103479190614a3d565b348015610860575f80fd5b5060045461088e907501000000000000000000000000000000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff9091168152602001610347565b3480156108b2575f80fd5b506104426108c1366004614a5f565b611dae565b3480156108d1575f80fd5b506104026108e0366004614b50565b611f7e565b3480156108f0575f80fd5b506104026108ff3660046142e9565b61200e565b34801561090f575f80fd5b5061040261091e366004614b85565b612088565b34801561092e575f80fd5b5061036f61093d366004614baf565b60096020525f90815260409020546001600160a01b031681565b348015610962575f80fd5b5061033d60055481565b348015610977575f80fd5b50600d54600e5461078e919082565b348015610991575f80fd5b5061033d7fce47b2c080dbcd8e420dc92bcf58f25f73f2e008a3b34ac41b9d468d1fb45d5a81565b3480156109c4575f80fd5b5060025461036f906001600160a01b031681565b3480156109e3575f80fd5b506104026109f23660046142e9565b612117565b348015610a02575f80fd5b505f546104d89063ffffffff1681565b348015610a1d575f80fd5b50610402610a2c366004614353565b61216d565b348015610a3c575f80fd5b50610402610a4b366004614bc8565b612242565b348015610a5b575f80fd5b506103a6610a6a366004614bfb565b612257565b6040805160a0810182525f8082526020820181905291810182905260608101829052608081019190915260045474010000000000000000000000000000000000000000900460ff1615610aee576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610af9833384612343565b9392505050565b5f546801000000000000000090046001600160a01b03163314801590610b3157506001546001600160a01b03163314155b15610b68576040517f9e54918800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d16933905f90a1565b60045474010000000000000000000000000000000000000000900460ff1615610c0f576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c1a33838361283c565b6001600160a01b0382165f90815260066020908152604080832033845290915281208054839290610c4c908490614cb9565b90915550506040518181526001600160a01b0383169033907f8752a472e571a816aea92eec8dae9baf628e840f4929fbcc2d155e6233ff68a7906020015b60405180910390a35050565b60408051610180810182525f8082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082018390526101208201839052610140820181905261016082015260045474010000000000000000000000000000000000000000900460ff1615610d49576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a8b511115610d85576040517f1b51089c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d978b8b8b8b8b8b8b8b8b5f612856565b909c909b509950505050505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610df35750825b90505f8267ffffffffffffffff166001148015610e0f5750303b155b905081158015610e1d575080155b15610e54576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610eb55784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b5f80547fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff166401000000004663ffffffff1602179055610ef860208701876142e9565b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055610f4060608701604088016142e9565b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055610f8860808701606088016142e9565b5f80546001600160a01b039290921668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff909216919091179055610fdc60a08701608088016142e9565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b039290921691909117905561102460408701602088016142e9565b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b039290921691909117905561106c60c0870160a0880161485c565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff929092169190911790556301312d006005556110c06110bb60e0880160c089016142e9565b612da7565b6001600a819055600d55831561112b5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b61113b612db8565b61114482612e88565b61114e8282612e90565b5050565b5f61115b612f91565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b611188612ff3565b600280546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f7a193273ad96e9aef3cc696a63e316b572c173af157d568ea56dcbc6425a7e7891015b60405180910390a15050565b61120a612ff3565b600580549082905560408051828152602081018490527f93e4453d7ab6f59ea20f42db2f427c07a21a4447b279a2dc2ce878997b5a488091016111f6565b60045474010000000000000000000000000000000000000000900460ff161561129d576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f806112a883613067565b6003545f80546005546040517f3e8c4294000000000000000000000000000000000000000000000000000000008152959750939550909384936001600160a01b0390931692633e8c429492349261130c9263ffffffff909216918a91600401614ccc565b604080518083038185885af1158015611327573d5f803e3d5ffd5b50505050506040513d601f19601f8201168201806040525081019061134c9190614cfa565b9092509050817f5e3a5b80dcf8e0fb984fe128ed0db507a86cc0674c4f5980f83b129b2cfdc69e8461138463ffffffff891682614cb9565b604080519283526020830191909152810184905260600160405180910390a25050505050565b6113b2612ff3565b6113bb5f613210565b565b60045474010000000000000000000000000000000000000000900460ff1615611412576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f548190640100000000900463ffffffff16611432610140830183614d1c565b5f81811061144257611442614d80565b9050602002016020810190611457919061485c565b63ffffffff1614611494576040517f43d7dc7b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f826040516020016114a69190614fe5565b60408051601f198184030181529190528051602090910120905060065f8281526007602052604090205460ff1660098111156114e4576114e4614304565b14611523576040517f4bfd0ae5000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b61156e81611535610160860186614ff7565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061329892505050565b5f90815260076020819052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690911790555050565b5f546801000000000000000090046001600160a01b031633148015906115dc57506001546001600160a01b03163314155b15611613576040517f9e54918800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e752905f90a1565b60045474010000000000000000000000000000000000000000900460ff16156116d1576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080517f0afae807991f914b71165fd92589f1dc28648cb9fb1f8558f3a6c7507d56deff602082015263ffffffff8a811682840152891660608201526001600160a01b03888116608083015260a0820188905260c0820187905260e0808301879052835180840390910181526101009092019092525f5490916117659168010000000000000000900416828786866133b7565b61177089888861348b565b5f8061177b8a613067565b6003545f80546005546040517f0278681b00000000000000000000000000000000000000000000000000000000815295975093955090936001600160a01b0390921692630278681b926117d99263ffffffff16918891600401614ccc565b602060405180830381865afa1580156117f4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118189190615058565b6003545f80549293509182916001600160a01b0316906304e77a669063ffffffff1687620186a06118498e8961506f565b6118539190615086565b61185d9088614cb9565b6005546040518563ffffffff1660e01b815260040161187f94939291906150be565b60408051808303815f875af115801561189a573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118be9190614cfa565b91509150817f5e3a5b80dcf8e0fb984fe128ed0db507a86cc0674c4f5980f83b129b2cfdc69e858f63ffffffff16876118f79190614cb9565b604080519283526020830191909152810184905260600160405180910390a25050505050505050505050505050565b60045474010000000000000000000000000000000000000000900460ff161561197b576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f806119878484613552565b6003545f80546005546040517f3e8c4294000000000000000000000000000000000000000000000000000000008152959750939550909384936001600160a01b0390931692633e8c42949234926119eb9263ffffffff909216918a91600401614ccc565b604080518083038185885af1158015611a06573d5f803e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190611a2b9190614cfa565b9092509050817f43a52e9a77f317a192970b363b14ece56df243fe0dd94f459f63029d657efec384611a5d8882614cb9565b604080519283526020830191909152810184905260600160405180910390a2505050505050565b611a8c612ff3565b6003546040517f91a3ef8e0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152909116906391a3ef8e906024015f604051808303815f87803b158015611ae9575f80fd5b505af1158015611afb573d5f803e3d5ffd5b5050505050565b60045474010000000000000000000000000000000000000000900460ff1615611b57576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080517f8104c8a42e1531612796e696e327ea52a475d9583ee6d64ffdefcafad22c0b24602082015263ffffffff8b811682840152891660608201526001600160a01b03888116608083015260a0820188905260c0820187905260e0808301879052835180840390910181526101009092019092525f548992611beb9168010000000000000000900416828887876133b7565b611bf68b898961348b565b5f80611c028c8c613552565b6003545f80546005546040517f0278681b00000000000000000000000000000000000000000000000000000000815295975093955090936001600160a01b0390921692630278681b92611c609263ffffffff16918891600401614ccc565b602060405180830381865afa158015611c7b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c9f9190615058565b6003545f80549293509182916001600160a01b0316906304e77a669063ffffffff1687620186a0611cd08f8961506f565b611cda9190615086565b611ce49088614cb9565b6005546040518563ffffffff1660e01b8152600401611d0694939291906150be565b60408051808303815f875af1158015611d21573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d459190614cfa565b9092509050817f43a52e9a77f317a192970b363b14ece56df243fe0dd94f459f63029d657efec385611d7d63ffffffff8b1682614cb9565b604080519283526020830191909152810184905260600160405180910390a250505050505050505050505050505050565b60408051610180810182525f8082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082018390526101208201839052610140820181905261016082015260045474010000000000000000000000000000000000000000900460ff1615611e61576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a8c511115611e9d576040517f1b51089c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160a0810182526001600160a01b038c1660608201908152608082018b9052815284356020808301919091528581013582840152825180840184523081529081018b90526e22d473030f116ddee9f6b43ac78ba3926330f28b7a9291903390611f0b90890189614ff7565b6040518663ffffffff1660e01b8152600401611f2b9594939291906150ef565b5f604051808303815f87803b158015611f42575f80fd5b505af1158015611f54573d5f803e3d5ffd5b50505050611f6b8c8c8c8c8c8c8c8c8c6001612856565b909d909c509a5050505050505050505050565b611f86612ff3565b8060095f846001811115611f9c57611f9c614304565b6001811115611fad57611fad614304565b81526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b031602179055507f37c2b523addce9bbdac7ccde6d3a471e90d82c1b538b6779ce00beb4b7ae1edb82826040516111f6929190615151565b612016612ff3565b600380546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f68e84423772dadc3e4047f8b5bd221ddb02dc67796e7852533fd976947d86c5191016111f6565b612090612ff3565b6001600160a01b0382165f90815260086020526040902080548291907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600183818111156120e1576120e1614304565b02179055507f01373f2d31dc702eb723a3420b82d31bde7c67ce32b2711eae415fd6137810c982826040516111f6929190615175565b61211f612ff3565b6001600160a01b038116612161576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f600482015260240161151a565b61216a81613210565b50565b60045474010000000000000000000000000000000000000000900460ff16156121c2576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0382165f908152600660209081526040808320338452909152812080548392906121f4908490615192565b9091555061220590503383836136e8565b6040518181526001600160a01b0383169033907fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb90602001610c8a565b60025461114e906001600160a01b03166136fc565b6040805160a0810182525f8082526020820181905291810182905260608101829052608081019190915260045474010000000000000000000000000000000000000000900460ff16156122d6576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7fce47b2c080dbcd8e420dc92bcf58f25f73f2e008a3b34ac41b9d468d1fb45d5a87878760405160200161230e94939291906151a5565b604051602081830303815290604052905061232c88828887876133b7565b612337878987612343565b98975050505050505050565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091525f548490640100000000900463ffffffff1661238d610140830183614d1c565b5f81811061239d5761239d614d80565b90506020020160208101906123b2919061485c565b63ffffffff16146123ef576040517f43d7dc7b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f856040516020016124019190614fe5565b60408051601f198184030181529190528051602090910120905061242d610120870161010088016151d9565b61243e610100880160e089016151d9565b61244891906151f2565b65ffffffffffff16421061248b576040517fc55b0e480000000000000000000000000000000000000000000000000000000081526004810182905260240161151a565b61249b60a0870160808801615218565b62ffffff168462ffffff1611156124fe57836124bd60a0880160808901615218565b6040517fa0cec32600000000000000000000000000000000000000000000000000000000815262ffffff92831660048201529116602482015260440161151a565b5f8181526007602052604081205460ff16600981111561252057612520614304565b1461255a576040517f9cc863db0000000000000000000000000000000000000000000000000000000081526004810182905260240161151a565b5f6125cf601260608901356001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125a0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125c49190615231565b89610120013561371a565b90505f620186a06125e562ffffff88168461506f565b6125ef9190615086565b90505f6125fc8284615192565b60608a01355f9081526006602090815260408083206001600160a01b038d1684529091529020549091508111156126925760608901355f9081526006602090815260408083206001600160a01b038c168452909152908190205490517ff0cb85ec00000000000000000000000000000000000000000000000000000000815260048101839052602481019190915260440161151a565b60608901355f9081526006602090815260408083206001600160a01b038c168452909152812080548392906126c8908490615192565b90915550505f84815260076020908152604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660031790558901351580159061271a5750606089013515155b801561272557508215155b1561273d5761273d60208a013560608b0135836136e8565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47061276c6101608b018b614ff7565b60405161277a929190615251565b60405180910390201461279957612799846115356101608c018c614ff7565b6040805160a08101909152848152602081016001600160a01b038a1681528a35602082015262ffffff8916604082015265ffffffffffff421660609091015295506127e5600d8761378a565b876001600160a01b0316847f11cd513bfc9cb4365a2f38d87c35bea962f9cea1c1fe9c8a9a9488df7d50727589600d600101548d60405161282893929190615260565b60405180910390a350505050509392505050565b6128516001600160a01b03831684308461382a565b505050565b60408051610180810182525f8082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e082018390526101008201839052610120820183905261014082018190526101608201528b516001036129175765ffffffffffff8616158015906128db57506001600160a01b038916155b15612912576040517f1b51089c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61296c565b65ffffffffffff861615158061293557506001600160a01b03891615155b1561296c576040517f1b51089c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620186a062ffffff881611156129be576040517f77f649f300000000000000000000000000000000000000000000000000000000815262ffffff88166004820152620186a0602482015260440161151a565b61c3508411156129fa576040517f6415b96a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f612a668b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a3a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a5e9190615231565b60128b61371a565b9050805f03612aa1576040517fee6def7500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83612bc0576001600160a01b038b165f9081526008602052604081205460ff1690816001811115612ad457612ad4614304565b03612ae957612ae4338d8c61283c565b612bbe565b5f60095f836001811115612aff57612aff614304565b6001811115612b1057612b10614304565b81526020019081526020015f205f9054906101000a90046001600160a01b03169050806001600160a01b031663f3a9a59e8e338e6040518463ffffffff1660e01b8152600401612b8f939291906001600160a01b03938416815291909216602082015260408101919091526080606082018190525f9082015260a00190565b5f604051808303815f87803b158015612ba6575f80fd5b505af1158015612bb8573d5f803e3d5ffd5b50505050505b505b604080516101808101909152803381526020016001600160a01b038e1681526020016001600160a01b038d1681526020016001600160a01b038c16815262ffffff8a1660208201525f54640100000000900463ffffffff16604082015260048054606090920191601590612c56907501000000000000000000000000000000000000000000900467ffffffffffffffff16615283565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff1681526020014265ffffffffffff1681526020018865ffffffffffff1681526020018281526020018e815260200187878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050915250604051909250612cfd9083906020016152a9565b60408051601f1981840301815291905280516020909101209250612d22600a846138ac565b5f838152600760205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600b54905184917fefe68281645929e2db845c5b42e12f7c73485fb5f18737b7b29379da006fa5f791612d8f91908690614742565b60405180910390a2509a509a98505050505050505050565b612daf6138de565b61216a81613945565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480612e5157507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612e457f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156113bb576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61216a612ff3565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612eea575060408051601f3d908101601f19168201909252612ee791810190615058565b60015b612f2b576040517f4c9c8ce30000000000000000000000000000000000000000000000000000000081526001600160a01b038316600482015260240161151a565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612f87576040517faa1d49a40000000000000000000000000000000000000000000000000000000081526004810182905260240161151a565b612851838361394d565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146113bb576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336130257f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146113bb576040517f118cdaa700000000000000000000000000000000000000000000000000000000815233600482015260240161151a565b600d54600e546060915f9163ffffffff85168084036130b2576040517f7c0ffbda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160016130bf8386614cb9565b6130c99190615192565b1115613112576040517fa617ee6800000000000000000000000000000000000000000000000000000000815260048101849052602481018390526044810182905260640161151a565b600d5493505f63ffffffff871667ffffffffffffffff8111156131375761313761437d565b6040519080825280602002602001820160405280156131ad57816020015b6040805160a0810182525f808252602080830182905292820181905260608201819052608082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816131555790505b5090505f5b8763ffffffff168163ffffffff1610156131fb576131d0600d6139a2565b828263ffffffff16815181106131e8576131e8614d80565b60209081029190910101526001016131b2565b5061320581613abe565b955050505050915091565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080547fffffffffffffffffffffffff000000000000000000000000000000000000000081166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f80828060200190518101906132ae91906152fd565b60045491935091505f9081906001600160a01b0316636dc63837856127105a6132d79190615192565b5f610100886040518663ffffffff1660e01b81526004016132fc959493929190615341565b5f604051808303815f875af1158015613317573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261333e9190810190615387565b91509150811561338557857f72c7d97e6fac52d20092b101af2183fd0bd04b357a936e82537e8974ea2c0eb7826040516133789190614a3d565b60405180910390a261112b565b6040517f2f5746e500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835160208501207f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f908152601c829052603c812061342b9085858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250613af092505050565b9050866001600160a01b0316816001600160a01b031614613478576040517f24c55ca400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6134828186613b18565b50505050505050565b5f5463ffffffff84811664010000000090920416146134d6576040517f66b0477d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0382163314613518576040517f4744936400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80421115612851576040517f26f774b000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a54600b546060915f9184808403613597576040517f7c0ffbda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160016135a48386614cb9565b6135ae9190615192565b11156135f7576040517fa617ee6800000000000000000000000000000000000000000000000000000000815260048101849052602481018390526044810182905260640161151a565b600a5493505f5b63ffffffff81168711156136c9575f613617600a613ba2565b90505f89898463ffffffff1681811061363257613632614d80565b905060200281019061364491906153bc565b6040516020016136549190614fe5565b6040516020818303038152906040528051906020012090508082146136b4576040517f908c3ec70000000000000000000000000000000000000000000000000000000081526004810182905263ffffffff8416602482015260440161151a565b505080806136c1906153f8565b9150506135fe565b506136dc6136d78789615410565b613c11565b94505050509250929050565b6128516001600160a01b0383168483613c28565b365f80375f80365f845af43d5f803e808015613716573d5ff35b3d5ffd5b5f8260ff168460ff160361372f575080610af9565b8260ff168460ff161015613763576137478484615560565b61375290600a615697565b61375c908361506f565b9050610af9565b61376d8385615560565b61377890600a615697565b6137829083615086565b949350505050565b6001826001015f82825461379e9190614cb9565b90915550506001808301545f908152600293840160209081526040918290208451815590840151928101929092558201519281019290925560608101516003909201805460809092015165ffffffffffff166301000000027fffffffffffffffffffffffffffffffffffffffffffffff00000000000000000090921662ffffff90931692909217179055565b6040516001600160a01b0384811660248301528381166044830152606482018390526138a69186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613c59565b50505050565b6001826001015f8282546138c09190614cb9565b909155505060018201545f9081526002909201602052604090912055565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff166113bb576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211f6138de565b61395682613cd3565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561399a576128518282613d7a565b61114e613dec565b6040805160a0810182525f80825260208201819052918101829052606081018290526080810191909152815460018301541015613a0b576040517f950f1c1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5080545f818152600280840160208181526040808520815160a08101835281548152600180830180548387015296830180549483019490945260038301805462ffffff8116606085015265ffffffffffff630100000082041660808501529989529590945290869055938590558490557fffffffffffffffffffffffffffffffffffffffffffffff000000000000000000909416905583549092918491613ab3908490614cb9565b909155509092915050565b6060613aea600183604051602001613ad691906156a5565b604051602081830303815290604052613e24565b92915050565b5f805f80613afe8686613e61565b925092509250613b0e8282613eaa565b5090949350505050565b6001600160a01b0382165f9081527f5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb0060205260409020805460018101909155818114612851576040517f752d88c00000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024810182905260440161151a565b5f815f015482600101541015613be4576040517f950f1c1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5080545f908152600282016020526040812080549082905582549091600191849190613ab3908490614cb9565b6060613aea5f83604051602001613ad6919061572a565b6040516001600160a01b0383811660248301526044820183905261285191859182169063a9059cbb9060640161385f565b5f613c6d6001600160a01b03841683613fad565b905080515f14158015613c91575080806020019051810190613c8f91906157aa565b155b15612851576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b038416600482015260240161151a565b806001600160a01b03163b5f03613d21576040517f4c9c8ce30000000000000000000000000000000000000000000000000000000081526001600160a01b038216600482015260240161151a565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60605f80846001600160a01b031684604051613d9691906157c3565b5f60405180830381855af49150503d805f8114613dce576040519150601f19603f3d011682016040523d82523d5f602084013e613dd3565b606091505b5091509150613de3858383613fba565b95945050505050565b34156113bb576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060826003811115613e3857613e38614304565b82604051602001613e4a9291906157d4565b604051602081830303815290604052905092915050565b5f805f8351604103613e98576020840151604085015160608601515f1a613e8a8882858561402f565b955095509550505050613ea3565b505081515f91506002905b9250925092565b5f826003811115613ebd57613ebd614304565b03613ec6575050565b6001826003811115613eda57613eda614304565b03613f11576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002826003811115613f2557613f25614304565b03613f5f576040517ffce698f70000000000000000000000000000000000000000000000000000000081526004810182905260240161151a565b6003826003811115613f7357613f73614304565b0361114e576040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004810182905260240161151a565b6060610af983835f6140f7565b606082613fcf57613fca826141a9565b610af9565b8151158015613fe657506001600160a01b0384163b155b15614028576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015260240161151a565b5080610af9565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561406857505f915060039050826140ed565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa1580156140b9573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b0381166140e457505f9250600191508290506140ed565b92505f91508190505b9450945094915050565b606081471015614135576040517fcd78605900000000000000000000000000000000000000000000000000000000815230600482015260240161151a565b5f80856001600160a01b0316848660405161415091906157c3565b5f6040518083038185875af1925050503d805f811461418a576040519150601f19603f3d011682016040523d82523d5f602084013e61418f565b606091505b509150915061419f868383613fba565b9695505050505050565b8051156141b95780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80604083850312156141fc575f80fd5b50508035926020909101359150565b5f610180828403121561421c575f80fd5b50919050565b803562ffffff81168114614234575f80fd5b919050565b5f806040838503121561424a575f80fd5b823567ffffffffffffffff811115614260575f80fd5b61426c8582860161420b565b92505061427b60208401614222565b90509250929050565b60a08101613aea828480518252602081015160208301526040810151604083015262ffffff606082015116606083015265ffffffffffff60808201511660808301525050565b6001600160a01b038116811461216a575f80fd5b8035614234816142ca565b5f602082840312156142f9575f80fd5b8135610af9816142ca565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b6002811061434157614341614304565b9052565b60208101613aea8284614331565b5f8060408385031215614364575f80fd5b823561436f816142ca565b946020939093013593505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051610180810167ffffffffffffffff811182821017156143ce576143ce61437d565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156143fd576143fd61437d565b604052919050565b5f67ffffffffffffffff82111561441e5761441e61437d565b5060051b60200190565b803563ffffffff81168114614234575f80fd5b5f82601f83011261444a575f80fd5b8135602061445f61445a83614405565b6143d4565b8083825260208201915060208460051b870101935086841115614480575f80fd5b602086015b848110156144a35761449681614428565b8352918301918301614485565b509695505050505050565b803565ffffffffffff81168114614234575f80fd5b5f8083601f8401126144d3575f80fd5b50813567ffffffffffffffff8111156144ea575f80fd5b602083019150836020828501011115614501575f80fd5b9250929050565b5f805f805f805f805f6101008a8c031215614521575f80fd5b893567ffffffffffffffff80821115614538575f80fd5b6145448d838e0161443b565b9a5060208c01359150614556826142ca565b90985060408b013590614568826142ca565b90975060608b01359061457a826142ca565b81975060808c0135965061459060a08d01614222565b955061459e60c08d016144ae565b945060e08c01359150808211156145b3575f80fd5b506145c08c828d016144c3565b915080935050809150509295985092959850929598565b5f815180845260208085019450602084015f5b8381101561460c57815163ffffffff16875295820195908201906001016145ea565b509495945050505050565b5f5b83811015614631578181015183820152602001614619565b50505f910152565b5f8151808452614650816020860160208601614617565b601f01601f19169290920160200192915050565b5f6101808251845260208301516020850152604083015160408501526060830151606085015260808301516146a0608086018262ffffff169052565b5060a08301516146b860a086018263ffffffff169052565b5060c08301516146d460c086018267ffffffffffffffff169052565b5060e08301516146ee60e086018265ffffffffffff169052565b506101008381015165ffffffffffff1690850152610120808401519085015261014080840151818601839052614726838701826145d7565b92505050610160808401518583038287015261419f8382614639565b828152604060208201525f6137826040830184614664565b5f60e0828403121561421c575f80fd5b5f67ffffffffffffffff8211156147835761478361437d565b50601f01601f191660200190565b5f82601f8301126147a0575f80fd5b81356147ae61445a8261476a565b8181528460208386010111156147c2575f80fd5b816020850160208301375f918101602001919091529392505050565b5f80604083850312156147ef575f80fd5b82356147fa816142ca565b9150602083013567ffffffffffffffff811115614815575f80fd5b61482185828601614791565b9150509250929050565b5f6020828403121561483b575f80fd5b5035919050565b60208101600a831061485657614856614304565b91905290565b5f6020828403121561486c575f80fd5b610af982614428565b5f60208284031215614885575f80fd5b813567ffffffffffffffff81111561489b575f80fd5b6137828482850161420b565b5f805f805f805f8060e0898b0312156148be575f80fd5b6148c789614428565b97506148d560208a01614428565b965060408901356148e5816142ca565b9550606089013594506080890135935060a0890135925060c089013567ffffffffffffffff811115614915575f80fd5b6149218b828c016144c3565b999c989b5096995094979396929594505050565b5f8083601f840112614945575f80fd5b50813567ffffffffffffffff81111561495c575f80fd5b6020830191508360208260051b8501011115614501575f80fd5b5f8060208385031215614987575f80fd5b823567ffffffffffffffff81111561499d575f80fd5b6149a985828601614935565b90969095509350505050565b5f805f805f805f805f60e08a8c0312156149cd575f80fd5b6149d68a614428565b985060208a013567ffffffffffffffff808211156149f2575f80fd5b6149fe8d838e01614935565b909a50985060408c01359150614a13826142ca565b90965060608b0135955060808b0135945060a08b0135935060c08b013590808211156145b3575f80fd5b602081525f610af96020830184614639565b5f6060828403121561421c575f80fd5b5f805f805f805f805f806101208b8d031215614a79575f80fd5b8a3567ffffffffffffffff80821115614a90575f80fd5b614a9c8e838f0161443b565b9b50614aaa60208e016142de565b9a50614ab860408e016142de565b9950614ac660608e016142de565b985060808d01359750614adb60a08e01614222565b9650614ae960c08e016144ae565b955060e08d0135915080821115614afe575f80fd5b614b0a8e838f016144c3565b90955093506101008d0135915080821115614b23575f80fd5b50614b308d828e01614a4f565b9150509295989b9194979a5092959850565b803560028110614234575f80fd5b5f8060408385031215614b61575f80fd5b614b6a83614b42565b91506020830135614b7a816142ca565b809150509250929050565b5f8060408385031215614b96575f80fd5b8235614ba1816142ca565b915061427b60208401614b42565b5f60208284031215614bbf575f80fd5b610af982614b42565b5f8060208385031215614bd9575f80fd5b823567ffffffffffffffff811115614bef575f80fd5b6149a9858286016144c3565b5f805f805f8060a08789031215614c10575f80fd5b8635614c1b816142ca565b9550602087013567ffffffffffffffff80821115614c37575f80fd5b614c438a838b0161420b565b965060408901359550614c5860608a01614222565b94506080890135915080821115614c6d575f80fd5b50614c7a89828a016144c3565b979a9699509497509295939492505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115613aea57613aea614c8c565b63ffffffff84168152606060208201525f614cea6060830185614639565b9050826040830152949350505050565b5f8060408385031215614d0b575f80fd5b505080516020909101519092909150565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614d4f575f80fd5b83018035915067ffffffffffffffff821115614d69575f80fd5b6020019150600581901b3603821315614501575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b803567ffffffffffffffff81168114614234575f80fd5b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614df7575f80fd5b830160208101925035905067ffffffffffffffff811115614e16575f80fd5b8060051b3603821315614501575f80fd5b8183525f60208085019450825f5b8581101561460c5763ffffffff614e4b83614428565b1687529582019590820190600101614e35565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614e91575f80fd5b830160208101925035905067ffffffffffffffff811115614eb0575f80fd5b803603821315614501575f80fd5b81835281816020850137505f602082840101525f6020601f19601f840116840101905092915050565b5f61018082358452602083013560208501526040830135604085015260608301356060850152614f1960808401614222565b62ffffff166080850152614f2f60a08401614428565b63ffffffff1660a0850152614f4660c08401614dad565b67ffffffffffffffff1660c0850152614f6160e084016144ae565b65ffffffffffff1660e0850152610100614f7c8482016144ae565b65ffffffffffff16908501526101208381013590850152610140614fa281850185614dc4565b8383880152614fb48488018284614e27565b9350505050610160614fc881850185614e5e565b86840383880152614fda848284614ebe565b979650505050505050565b602081525f610af96020830184614ee7565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261502a575f80fd5b83018035915067ffffffffffffffff821115615044575f80fd5b602001915036819003821315614501575f80fd5b5f60208284031215615068575f80fd5b5051919050565b8082028115828204841417613aea57613aea614c8c565b5f826150b9577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b63ffffffff85168152608060208201525f6150dc6080830186614639565b6040830194909452506060015292915050565b5f61010087516001600160a01b038082511685526020820151602086015260208a0151604086015260408a01516060860152808951166080860152602089015160a086015280881660c086015250508060e08401526123378184018587614ebe565b6040810161515f8285614331565b6001600160a01b03831660208301529392505050565b6001600160a01b038316815260408101610af96020830184614331565b81810381811115613aea57613aea614c8c565b848152608060208201525f6151bd6080830186614ee7565b905083604083015262ffffff8316606083015295945050505050565b5f602082840312156151e9575f80fd5b610af9826144ae565b65ffffffffffff81811683821601908082111561521157615211614c8c565b5092915050565b5f60208284031215615228575f80fd5b610af982614222565b5f60208284031215615241575f80fd5b815160ff81168114610af9575f80fd5b818382375f9101908152919050565b62ffffff84168152826020820152606060408201525f613de36060830184614ee7565b5f67ffffffffffffffff80831681810361529f5761529f614c8c565b6001019392505050565b602081525f610af96020830184614664565b5f82601f8301126152ca575f80fd5b81516152d861445a8261476a565b8181528460208386010111156152ec575f80fd5b613782826020830160208701614617565b5f806040838503121561530e575f80fd5b8251615319816142ca565b602084015190925067ffffffffffffffff811115615335575f80fd5b614821858286016152bb565b6001600160a01b038616815284602082015283604082015261ffff8316606082015260a060808201525f614fda60a0830184614639565b80518015158114614234575f80fd5b5f8060408385031215615398575f80fd5b6153a183615378565b9150602083015167ffffffffffffffff811115615335575f80fd5b5f82357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe818336030181126153ee575f80fd5b9190910192915050565b5f63ffffffff80831681810361529f5761529f614c8c565b5f61541d61445a84614405565b80848252602080830192508560051b85013681111561543a575f80fd5b855b8181101561555457803567ffffffffffffffff8082111561545b575f80fd5b81890191506101808236031215615470575f80fd5b6154786143aa565b823581528583013586820152604080840135908201526060808401359082015260806154a5818501614222565b9082015260a06154b6848201614428565b9082015260c06154c7848201614dad565b9082015260e06154d88482016144ae565b908201526101006154ea8482016144ae565b908201526101208381013590820152610140808401358381111561550c575f80fd5b6155183682870161443b565b8284015250506101608084013583811115615531575f80fd5b61553d36828701614791565b91830191909152508752505093820193820161543c565b50919695505050505050565b60ff8281168282160390811115613aea57613aea614c8c565b600181815b808511156155d257817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156155b8576155b8614c8c565b808516156155c557918102915b93841c939080029061557e565b509250929050565b5f826155e857506001613aea565b816155f457505f613aea565b816001811461560a576002811461561457615630565b6001915050613aea565b60ff84111561562557615625614c8c565b50506001821b613aea565b5060208310610133831016604e8410600b8410161715615653575081810a613aea565b61565d8383615579565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561568f5761568f614c8c565b029392505050565b5f610af960ff8416836155da565b602080825282518282018190525f9190848201906040850190845b8181101561571e5761570b83855180518252602081015160208301526040810151604083015262ffffff606082015116606083015265ffffffffffff60808201511660808301525050565b9284019260a092909201916001016156c0565b50909695505050505050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b8281101561579d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261578b858351614664565b94509285019290850190600101615751565b5092979650505050505050565b5f602082840312156157ba575f80fd5b610af982615378565b5f82516153ee818460208701614617565b60ff83168152604060208201525f613782604083018461463956fea2646970667358221220d4fb78ed786bdaff9137bb2da7ec006f5af6ce166472f2b4c3faa6fe6b93204364736f6c63430008170033
Deployed Bytecode
0x608060405260043610610303575f3560e01c80638456cb5911610191578063c0346b20116100dc578063e2cae9f511610087578063f3fef3a311610062578063f3fef3a314610a12578063f953cec714610a31578063fa12957c14610a50575f80fd5b8063e2cae9f5146109b9578063f2fde38b146109d8578063f37c0a2e146109f7575f80fd5b8063cab0071e116100b7578063cab0071e14610957578063d6979ef61461096c578063df7a760114610986575f80fd5b8063c0346b20146108e5578063c13eedbe14610904578063c2aeb7bd14610923575f80fd5b8063990969f61161013c578063affed0e011610117578063affed0e014610855578063b4c20477146108a7578063beff4ce2146108c6575f80fd5b8063990969f6146107c25780639eb93f1f146107e1578063ad3cb1cc14610800575f80fd5b80638da5cb5b1161016c5780638da5cb5b146107385780638fd689401461077457806391a3ef8e146107a3575f80fd5b80638456cb59146106f25780638467b5b5146107065780638af5f77914610725575f80fd5b806352d1902d116102515780636afdd850116101fc57806373e554f6116101d757806373e554f61461064d5780637ecebe00146106805780637f7673f9146106d3575f80fd5b80636afdd850146105f8578063715018a61461061a578063715fc7361461062e575f80fd5b80635d394d3b1161022c5780635d394d3b1461059c578063601ae9b8146105bb5780636301fd63146105ce575f80fd5b806352d1902d146105285780635c8ff7611461053c5780635c975abb1461055b575f80fd5b80634a943d21116102b1578063522dbaa51161028c578063522dbaa51461048257806352a9674b146104b557806352ad0d5e146104ed575f80fd5b80634a943d21146104235780634c739c32146104505780634f1ef2861461046f575f80fd5b806339ebf823116102e157806339ebf823146103b35780633f4ba83a146103ee57806347e7ef2414610404575f80fd5b8063043dca0414610307578063116191b61461035057806311a4cbbf14610387575b5f80fd5b348015610312575f80fd5b5061033d6103213660046141eb565b600660209081525f928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b34801561035b575f80fd5b5060035461036f906001600160a01b031681565b6040516001600160a01b039091168152602001610347565b348015610392575f80fd5b506103a66103a1366004614239565b610a6f565b6040516103479190614284565b3480156103be575f80fd5b506103e16103cd3660046142e9565b60086020525f908152604090205460ff1681565b6040516103479190614345565b3480156103f9575f80fd5b50610402610b00565b005b34801561040f575f80fd5b5061040261041e366004614353565b610bba565b34801561042e575f80fd5b5061044261043d366004614508565b610c96565b604051610347929190614742565b34801561045b575f80fd5b5061040261046a36600461475a565b610da9565b61040261047d3660046147de565b611133565b34801561048d575f80fd5b5061033d7f0afae807991f914b71165fd92589f1dc28648cb9fb1f8558f3a6c7507d56deff81565b3480156104c0575f80fd5b505f546104d890640100000000900463ffffffff1681565b60405163ffffffff9091168152602001610347565b3480156104f8575f80fd5b5061051b61050736600461482b565b60076020525f908152604090205460ff1681565b6040516103479190614842565b348015610533575f80fd5b5061033d611152565b348015610547575f80fd5b506104026105563660046142e9565b611180565b348015610566575f80fd5b5060045461058c9074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610347565b3480156105a7575f80fd5b506104026105b636600461482b565b611202565b6104026105c936600461485c565b611248565b3480156105d9575f80fd5b505f5461036f906801000000000000000090046001600160a01b031681565b348015610603575f80fd5b5061036f6e22d473030f116ddee9f6b43ac78ba381565b348015610625575f80fd5b506104026113aa565b348015610639575f80fd5b50610402610648366004614875565b6113bd565b348015610658575f80fd5b5061033d7f8104c8a42e1531612796e696e327ea52a475d9583ee6d64ffdefcafad22c0b2481565b34801561068b575f80fd5b5061033d61069a3660046142e9565b6001600160a01b03165f9081527f5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb00602052604090205490565b3480156106de575f80fd5b5060015461036f906001600160a01b031681565b3480156106fd575f80fd5b506104026115ab565b348015610711575f80fd5b506104026107203660046148a7565b61167c565b610402610733366004614976565b611926565b348015610743575f80fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031661036f565b34801561077f575f80fd5b50600a54600b5461078e919082565b60408051928352602083019190915201610347565b3480156107ae575f80fd5b506104026107bd3660046142e9565b611a84565b3480156107cd575f80fd5b5060045461036f906001600160a01b031681565b3480156107ec575f80fd5b506104026107fb3660046149b5565b611b02565b34801561080b575f80fd5b506108486040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516103479190614a3d565b348015610860575f80fd5b5060045461088e907501000000000000000000000000000000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff9091168152602001610347565b3480156108b2575f80fd5b506104426108c1366004614a5f565b611dae565b3480156108d1575f80fd5b506104026108e0366004614b50565b611f7e565b3480156108f0575f80fd5b506104026108ff3660046142e9565b61200e565b34801561090f575f80fd5b5061040261091e366004614b85565b612088565b34801561092e575f80fd5b5061036f61093d366004614baf565b60096020525f90815260409020546001600160a01b031681565b348015610962575f80fd5b5061033d60055481565b348015610977575f80fd5b50600d54600e5461078e919082565b348015610991575f80fd5b5061033d7fce47b2c080dbcd8e420dc92bcf58f25f73f2e008a3b34ac41b9d468d1fb45d5a81565b3480156109c4575f80fd5b5060025461036f906001600160a01b031681565b3480156109e3575f80fd5b506104026109f23660046142e9565b612117565b348015610a02575f80fd5b505f546104d89063ffffffff1681565b348015610a1d575f80fd5b50610402610a2c366004614353565b61216d565b348015610a3c575f80fd5b50610402610a4b366004614bc8565b612242565b348015610a5b575f80fd5b506103a6610a6a366004614bfb565b612257565b6040805160a0810182525f8082526020820181905291810182905260608101829052608081019190915260045474010000000000000000000000000000000000000000900460ff1615610aee576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610af9833384612343565b9392505050565b5f546801000000000000000090046001600160a01b03163314801590610b3157506001546001600160a01b03163314155b15610b68576040517f9e54918800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d16933905f90a1565b60045474010000000000000000000000000000000000000000900460ff1615610c0f576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c1a33838361283c565b6001600160a01b0382165f90815260066020908152604080832033845290915281208054839290610c4c908490614cb9565b90915550506040518181526001600160a01b0383169033907f8752a472e571a816aea92eec8dae9baf628e840f4929fbcc2d155e6233ff68a7906020015b60405180910390a35050565b60408051610180810182525f8082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082018390526101208201839052610140820181905261016082015260045474010000000000000000000000000000000000000000900460ff1615610d49576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a8b511115610d85576040517f1b51089c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d978b8b8b8b8b8b8b8b8b5f612856565b909c909b509950505050505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610df35750825b90505f8267ffffffffffffffff166001148015610e0f5750303b155b905081158015610e1d575080155b15610e54576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610eb55784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b5f80547fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff166401000000004663ffffffff1602179055610ef860208701876142e9565b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055610f4060608701604088016142e9565b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055610f8860808701606088016142e9565b5f80546001600160a01b039290921668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff909216919091179055610fdc60a08701608088016142e9565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b039290921691909117905561102460408701602088016142e9565b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b039290921691909117905561106c60c0870160a0880161485c565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff929092169190911790556301312d006005556110c06110bb60e0880160c089016142e9565b612da7565b6001600a819055600d55831561112b5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b61113b612db8565b61114482612e88565b61114e8282612e90565b5050565b5f61115b612f91565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b611188612ff3565b600280546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f7a193273ad96e9aef3cc696a63e316b572c173af157d568ea56dcbc6425a7e7891015b60405180910390a15050565b61120a612ff3565b600580549082905560408051828152602081018490527f93e4453d7ab6f59ea20f42db2f427c07a21a4447b279a2dc2ce878997b5a488091016111f6565b60045474010000000000000000000000000000000000000000900460ff161561129d576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f806112a883613067565b6003545f80546005546040517f3e8c4294000000000000000000000000000000000000000000000000000000008152959750939550909384936001600160a01b0390931692633e8c429492349261130c9263ffffffff909216918a91600401614ccc565b604080518083038185885af1158015611327573d5f803e3d5ffd5b50505050506040513d601f19601f8201168201806040525081019061134c9190614cfa565b9092509050817f5e3a5b80dcf8e0fb984fe128ed0db507a86cc0674c4f5980f83b129b2cfdc69e8461138463ffffffff891682614cb9565b604080519283526020830191909152810184905260600160405180910390a25050505050565b6113b2612ff3565b6113bb5f613210565b565b60045474010000000000000000000000000000000000000000900460ff1615611412576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f548190640100000000900463ffffffff16611432610140830183614d1c565b5f81811061144257611442614d80565b9050602002016020810190611457919061485c565b63ffffffff1614611494576040517f43d7dc7b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f826040516020016114a69190614fe5565b60408051601f198184030181529190528051602090910120905060065f8281526007602052604090205460ff1660098111156114e4576114e4614304565b14611523576040517f4bfd0ae5000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b61156e81611535610160860186614ff7565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061329892505050565b5f90815260076020819052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690911790555050565b5f546801000000000000000090046001600160a01b031633148015906115dc57506001546001600160a01b03163314155b15611613576040517f9e54918800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e752905f90a1565b60045474010000000000000000000000000000000000000000900460ff16156116d1576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080517f0afae807991f914b71165fd92589f1dc28648cb9fb1f8558f3a6c7507d56deff602082015263ffffffff8a811682840152891660608201526001600160a01b03888116608083015260a0820188905260c0820187905260e0808301879052835180840390910181526101009092019092525f5490916117659168010000000000000000900416828786866133b7565b61177089888861348b565b5f8061177b8a613067565b6003545f80546005546040517f0278681b00000000000000000000000000000000000000000000000000000000815295975093955090936001600160a01b0390921692630278681b926117d99263ffffffff16918891600401614ccc565b602060405180830381865afa1580156117f4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118189190615058565b6003545f80549293509182916001600160a01b0316906304e77a669063ffffffff1687620186a06118498e8961506f565b6118539190615086565b61185d9088614cb9565b6005546040518563ffffffff1660e01b815260040161187f94939291906150be565b60408051808303815f875af115801561189a573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118be9190614cfa565b91509150817f5e3a5b80dcf8e0fb984fe128ed0db507a86cc0674c4f5980f83b129b2cfdc69e858f63ffffffff16876118f79190614cb9565b604080519283526020830191909152810184905260600160405180910390a25050505050505050505050505050565b60045474010000000000000000000000000000000000000000900460ff161561197b576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f806119878484613552565b6003545f80546005546040517f3e8c4294000000000000000000000000000000000000000000000000000000008152959750939550909384936001600160a01b0390931692633e8c42949234926119eb9263ffffffff909216918a91600401614ccc565b604080518083038185885af1158015611a06573d5f803e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190611a2b9190614cfa565b9092509050817f43a52e9a77f317a192970b363b14ece56df243fe0dd94f459f63029d657efec384611a5d8882614cb9565b604080519283526020830191909152810184905260600160405180910390a2505050505050565b611a8c612ff3565b6003546040517f91a3ef8e0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152909116906391a3ef8e906024015f604051808303815f87803b158015611ae9575f80fd5b505af1158015611afb573d5f803e3d5ffd5b5050505050565b60045474010000000000000000000000000000000000000000900460ff1615611b57576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080517f8104c8a42e1531612796e696e327ea52a475d9583ee6d64ffdefcafad22c0b24602082015263ffffffff8b811682840152891660608201526001600160a01b03888116608083015260a0820188905260c0820187905260e0808301879052835180840390910181526101009092019092525f548992611beb9168010000000000000000900416828887876133b7565b611bf68b898961348b565b5f80611c028c8c613552565b6003545f80546005546040517f0278681b00000000000000000000000000000000000000000000000000000000815295975093955090936001600160a01b0390921692630278681b92611c609263ffffffff16918891600401614ccc565b602060405180830381865afa158015611c7b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c9f9190615058565b6003545f80549293509182916001600160a01b0316906304e77a669063ffffffff1687620186a0611cd08f8961506f565b611cda9190615086565b611ce49088614cb9565b6005546040518563ffffffff1660e01b8152600401611d0694939291906150be565b60408051808303815f875af1158015611d21573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d459190614cfa565b9092509050817f43a52e9a77f317a192970b363b14ece56df243fe0dd94f459f63029d657efec385611d7d63ffffffff8b1682614cb9565b604080519283526020830191909152810184905260600160405180910390a250505050505050505050505050505050565b60408051610180810182525f8082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082018390526101208201839052610140820181905261016082015260045474010000000000000000000000000000000000000000900460ff1615611e61576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a8c511115611e9d576040517f1b51089c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160a0810182526001600160a01b038c1660608201908152608082018b9052815284356020808301919091528581013582840152825180840184523081529081018b90526e22d473030f116ddee9f6b43ac78ba3926330f28b7a9291903390611f0b90890189614ff7565b6040518663ffffffff1660e01b8152600401611f2b9594939291906150ef565b5f604051808303815f87803b158015611f42575f80fd5b505af1158015611f54573d5f803e3d5ffd5b50505050611f6b8c8c8c8c8c8c8c8c8c6001612856565b909d909c509a5050505050505050505050565b611f86612ff3565b8060095f846001811115611f9c57611f9c614304565b6001811115611fad57611fad614304565b81526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b031602179055507f37c2b523addce9bbdac7ccde6d3a471e90d82c1b538b6779ce00beb4b7ae1edb82826040516111f6929190615151565b612016612ff3565b600380546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f68e84423772dadc3e4047f8b5bd221ddb02dc67796e7852533fd976947d86c5191016111f6565b612090612ff3565b6001600160a01b0382165f90815260086020526040902080548291907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600183818111156120e1576120e1614304565b02179055507f01373f2d31dc702eb723a3420b82d31bde7c67ce32b2711eae415fd6137810c982826040516111f6929190615175565b61211f612ff3565b6001600160a01b038116612161576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f600482015260240161151a565b61216a81613210565b50565b60045474010000000000000000000000000000000000000000900460ff16156121c2576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0382165f908152600660209081526040808320338452909152812080548392906121f4908490615192565b9091555061220590503383836136e8565b6040518181526001600160a01b0383169033907fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb90602001610c8a565b60025461114e906001600160a01b03166136fc565b6040805160a0810182525f8082526020820181905291810182905260608101829052608081019190915260045474010000000000000000000000000000000000000000900460ff16156122d6576040517f02bb18c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7fce47b2c080dbcd8e420dc92bcf58f25f73f2e008a3b34ac41b9d468d1fb45d5a87878760405160200161230e94939291906151a5565b604051602081830303815290604052905061232c88828887876133b7565b612337878987612343565b98975050505050505050565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091525f548490640100000000900463ffffffff1661238d610140830183614d1c565b5f81811061239d5761239d614d80565b90506020020160208101906123b2919061485c565b63ffffffff16146123ef576040517f43d7dc7b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f856040516020016124019190614fe5565b60408051601f198184030181529190528051602090910120905061242d610120870161010088016151d9565b61243e610100880160e089016151d9565b61244891906151f2565b65ffffffffffff16421061248b576040517fc55b0e480000000000000000000000000000000000000000000000000000000081526004810182905260240161151a565b61249b60a0870160808801615218565b62ffffff168462ffffff1611156124fe57836124bd60a0880160808901615218565b6040517fa0cec32600000000000000000000000000000000000000000000000000000000815262ffffff92831660048201529116602482015260440161151a565b5f8181526007602052604081205460ff16600981111561252057612520614304565b1461255a576040517f9cc863db0000000000000000000000000000000000000000000000000000000081526004810182905260240161151a565b5f6125cf601260608901356001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125a0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125c49190615231565b89610120013561371a565b90505f620186a06125e562ffffff88168461506f565b6125ef9190615086565b90505f6125fc8284615192565b60608a01355f9081526006602090815260408083206001600160a01b038d1684529091529020549091508111156126925760608901355f9081526006602090815260408083206001600160a01b038c168452909152908190205490517ff0cb85ec00000000000000000000000000000000000000000000000000000000815260048101839052602481019190915260440161151a565b60608901355f9081526006602090815260408083206001600160a01b038c168452909152812080548392906126c8908490615192565b90915550505f84815260076020908152604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660031790558901351580159061271a5750606089013515155b801561272557508215155b1561273d5761273d60208a013560608b0135836136e8565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47061276c6101608b018b614ff7565b60405161277a929190615251565b60405180910390201461279957612799846115356101608c018c614ff7565b6040805160a08101909152848152602081016001600160a01b038a1681528a35602082015262ffffff8916604082015265ffffffffffff421660609091015295506127e5600d8761378a565b876001600160a01b0316847f11cd513bfc9cb4365a2f38d87c35bea962f9cea1c1fe9c8a9a9488df7d50727589600d600101548d60405161282893929190615260565b60405180910390a350505050509392505050565b6128516001600160a01b03831684308461382a565b505050565b60408051610180810182525f8082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e082018390526101008201839052610120820183905261014082018190526101608201528b516001036129175765ffffffffffff8616158015906128db57506001600160a01b038916155b15612912576040517f1b51089c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61296c565b65ffffffffffff861615158061293557506001600160a01b03891615155b1561296c576040517f1b51089c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620186a062ffffff881611156129be576040517f77f649f300000000000000000000000000000000000000000000000000000000815262ffffff88166004820152620186a0602482015260440161151a565b61c3508411156129fa576040517f6415b96a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f612a668b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a3a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a5e9190615231565b60128b61371a565b9050805f03612aa1576040517fee6def7500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83612bc0576001600160a01b038b165f9081526008602052604081205460ff1690816001811115612ad457612ad4614304565b03612ae957612ae4338d8c61283c565b612bbe565b5f60095f836001811115612aff57612aff614304565b6001811115612b1057612b10614304565b81526020019081526020015f205f9054906101000a90046001600160a01b03169050806001600160a01b031663f3a9a59e8e338e6040518463ffffffff1660e01b8152600401612b8f939291906001600160a01b03938416815291909216602082015260408101919091526080606082018190525f9082015260a00190565b5f604051808303815f87803b158015612ba6575f80fd5b505af1158015612bb8573d5f803e3d5ffd5b50505050505b505b604080516101808101909152803381526020016001600160a01b038e1681526020016001600160a01b038d1681526020016001600160a01b038c16815262ffffff8a1660208201525f54640100000000900463ffffffff16604082015260048054606090920191601590612c56907501000000000000000000000000000000000000000000900467ffffffffffffffff16615283565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff1681526020014265ffffffffffff1681526020018865ffffffffffff1681526020018281526020018e815260200187878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050915250604051909250612cfd9083906020016152a9565b60408051601f1981840301815291905280516020909101209250612d22600a846138ac565b5f838152600760205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600b54905184917fefe68281645929e2db845c5b42e12f7c73485fb5f18737b7b29379da006fa5f791612d8f91908690614742565b60405180910390a2509a509a98505050505050505050565b612daf6138de565b61216a81613945565b306001600160a01b037f000000000000000000000000255aba6e7f08d40b19872d11313688c2ed65d1c9161480612e5157507f000000000000000000000000255aba6e7f08d40b19872d11313688c2ed65d1c96001600160a01b0316612e457f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156113bb576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61216a612ff3565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612eea575060408051601f3d908101601f19168201909252612ee791810190615058565b60015b612f2b576040517f4c9c8ce30000000000000000000000000000000000000000000000000000000081526001600160a01b038316600482015260240161151a565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612f87576040517faa1d49a40000000000000000000000000000000000000000000000000000000081526004810182905260240161151a565b612851838361394d565b306001600160a01b037f000000000000000000000000255aba6e7f08d40b19872d11313688c2ed65d1c916146113bb576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336130257f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146113bb576040517f118cdaa700000000000000000000000000000000000000000000000000000000815233600482015260240161151a565b600d54600e546060915f9163ffffffff85168084036130b2576040517f7c0ffbda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160016130bf8386614cb9565b6130c99190615192565b1115613112576040517fa617ee6800000000000000000000000000000000000000000000000000000000815260048101849052602481018390526044810182905260640161151a565b600d5493505f63ffffffff871667ffffffffffffffff8111156131375761313761437d565b6040519080825280602002602001820160405280156131ad57816020015b6040805160a0810182525f808252602080830182905292820181905260608201819052608082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816131555790505b5090505f5b8763ffffffff168163ffffffff1610156131fb576131d0600d6139a2565b828263ffffffff16815181106131e8576131e8614d80565b60209081029190910101526001016131b2565b5061320581613abe565b955050505050915091565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080547fffffffffffffffffffffffff000000000000000000000000000000000000000081166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f80828060200190518101906132ae91906152fd565b60045491935091505f9081906001600160a01b0316636dc63837856127105a6132d79190615192565b5f610100886040518663ffffffff1660e01b81526004016132fc959493929190615341565b5f604051808303815f875af1158015613317573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261333e9190810190615387565b91509150811561338557857f72c7d97e6fac52d20092b101af2183fd0bd04b357a936e82537e8974ea2c0eb7826040516133789190614a3d565b60405180910390a261112b565b6040517f2f5746e500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835160208501207f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f908152601c829052603c812061342b9085858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250613af092505050565b9050866001600160a01b0316816001600160a01b031614613478576040517f24c55ca400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6134828186613b18565b50505050505050565b5f5463ffffffff84811664010000000090920416146134d6576040517f66b0477d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0382163314613518576040517f4744936400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80421115612851576040517f26f774b000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a54600b546060915f9184808403613597576040517f7c0ffbda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160016135a48386614cb9565b6135ae9190615192565b11156135f7576040517fa617ee6800000000000000000000000000000000000000000000000000000000815260048101849052602481018390526044810182905260640161151a565b600a5493505f5b63ffffffff81168711156136c9575f613617600a613ba2565b90505f89898463ffffffff1681811061363257613632614d80565b905060200281019061364491906153bc565b6040516020016136549190614fe5565b6040516020818303038152906040528051906020012090508082146136b4576040517f908c3ec70000000000000000000000000000000000000000000000000000000081526004810182905263ffffffff8416602482015260440161151a565b505080806136c1906153f8565b9150506135fe565b506136dc6136d78789615410565b613c11565b94505050509250929050565b6128516001600160a01b0383168483613c28565b365f80375f80365f845af43d5f803e808015613716573d5ff35b3d5ffd5b5f8260ff168460ff160361372f575080610af9565b8260ff168460ff161015613763576137478484615560565b61375290600a615697565b61375c908361506f565b9050610af9565b61376d8385615560565b61377890600a615697565b6137829083615086565b949350505050565b6001826001015f82825461379e9190614cb9565b90915550506001808301545f908152600293840160209081526040918290208451815590840151928101929092558201519281019290925560608101516003909201805460809092015165ffffffffffff166301000000027fffffffffffffffffffffffffffffffffffffffffffffff00000000000000000090921662ffffff90931692909217179055565b6040516001600160a01b0384811660248301528381166044830152606482018390526138a69186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613c59565b50505050565b6001826001015f8282546138c09190614cb9565b909155505060018201545f9081526002909201602052604090912055565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff166113bb576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211f6138de565b61395682613cd3565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561399a576128518282613d7a565b61114e613dec565b6040805160a0810182525f80825260208201819052918101829052606081018290526080810191909152815460018301541015613a0b576040517f950f1c1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5080545f818152600280840160208181526040808520815160a08101835281548152600180830180548387015296830180549483019490945260038301805462ffffff8116606085015265ffffffffffff630100000082041660808501529989529590945290869055938590558490557fffffffffffffffffffffffffffffffffffffffffffffff000000000000000000909416905583549092918491613ab3908490614cb9565b909155509092915050565b6060613aea600183604051602001613ad691906156a5565b604051602081830303815290604052613e24565b92915050565b5f805f80613afe8686613e61565b925092509250613b0e8282613eaa565b5090949350505050565b6001600160a01b0382165f9081527f5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb0060205260409020805460018101909155818114612851576040517f752d88c00000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024810182905260440161151a565b5f815f015482600101541015613be4576040517f950f1c1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5080545f908152600282016020526040812080549082905582549091600191849190613ab3908490614cb9565b6060613aea5f83604051602001613ad6919061572a565b6040516001600160a01b0383811660248301526044820183905261285191859182169063a9059cbb9060640161385f565b5f613c6d6001600160a01b03841683613fad565b905080515f14158015613c91575080806020019051810190613c8f91906157aa565b155b15612851576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b038416600482015260240161151a565b806001600160a01b03163b5f03613d21576040517f4c9c8ce30000000000000000000000000000000000000000000000000000000081526001600160a01b038216600482015260240161151a565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60605f80846001600160a01b031684604051613d9691906157c3565b5f60405180830381855af49150503d805f8114613dce576040519150601f19603f3d011682016040523d82523d5f602084013e613dd3565b606091505b5091509150613de3858383613fba565b95945050505050565b34156113bb576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060826003811115613e3857613e38614304565b82604051602001613e4a9291906157d4565b604051602081830303815290604052905092915050565b5f805f8351604103613e98576020840151604085015160608601515f1a613e8a8882858561402f565b955095509550505050613ea3565b505081515f91506002905b9250925092565b5f826003811115613ebd57613ebd614304565b03613ec6575050565b6001826003811115613eda57613eda614304565b03613f11576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002826003811115613f2557613f25614304565b03613f5f576040517ffce698f70000000000000000000000000000000000000000000000000000000081526004810182905260240161151a565b6003826003811115613f7357613f73614304565b0361114e576040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004810182905260240161151a565b6060610af983835f6140f7565b606082613fcf57613fca826141a9565b610af9565b8151158015613fe657506001600160a01b0384163b155b15614028576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015260240161151a565b5080610af9565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561406857505f915060039050826140ed565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa1580156140b9573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b0381166140e457505f9250600191508290506140ed565b92505f91508190505b9450945094915050565b606081471015614135576040517fcd78605900000000000000000000000000000000000000000000000000000000815230600482015260240161151a565b5f80856001600160a01b0316848660405161415091906157c3565b5f6040518083038185875af1925050503d805f811461418a576040519150601f19603f3d011682016040523d82523d5f602084013e61418f565b606091505b509150915061419f868383613fba565b9695505050505050565b8051156141b95780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80604083850312156141fc575f80fd5b50508035926020909101359150565b5f610180828403121561421c575f80fd5b50919050565b803562ffffff81168114614234575f80fd5b919050565b5f806040838503121561424a575f80fd5b823567ffffffffffffffff811115614260575f80fd5b61426c8582860161420b565b92505061427b60208401614222565b90509250929050565b60a08101613aea828480518252602081015160208301526040810151604083015262ffffff606082015116606083015265ffffffffffff60808201511660808301525050565b6001600160a01b038116811461216a575f80fd5b8035614234816142ca565b5f602082840312156142f9575f80fd5b8135610af9816142ca565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b6002811061434157614341614304565b9052565b60208101613aea8284614331565b5f8060408385031215614364575f80fd5b823561436f816142ca565b946020939093013593505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051610180810167ffffffffffffffff811182821017156143ce576143ce61437d565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156143fd576143fd61437d565b604052919050565b5f67ffffffffffffffff82111561441e5761441e61437d565b5060051b60200190565b803563ffffffff81168114614234575f80fd5b5f82601f83011261444a575f80fd5b8135602061445f61445a83614405565b6143d4565b8083825260208201915060208460051b870101935086841115614480575f80fd5b602086015b848110156144a35761449681614428565b8352918301918301614485565b509695505050505050565b803565ffffffffffff81168114614234575f80fd5b5f8083601f8401126144d3575f80fd5b50813567ffffffffffffffff8111156144ea575f80fd5b602083019150836020828501011115614501575f80fd5b9250929050565b5f805f805f805f805f6101008a8c031215614521575f80fd5b893567ffffffffffffffff80821115614538575f80fd5b6145448d838e0161443b565b9a5060208c01359150614556826142ca565b90985060408b013590614568826142ca565b90975060608b01359061457a826142ca565b81975060808c0135965061459060a08d01614222565b955061459e60c08d016144ae565b945060e08c01359150808211156145b3575f80fd5b506145c08c828d016144c3565b915080935050809150509295985092959850929598565b5f815180845260208085019450602084015f5b8381101561460c57815163ffffffff16875295820195908201906001016145ea565b509495945050505050565b5f5b83811015614631578181015183820152602001614619565b50505f910152565b5f8151808452614650816020860160208601614617565b601f01601f19169290920160200192915050565b5f6101808251845260208301516020850152604083015160408501526060830151606085015260808301516146a0608086018262ffffff169052565b5060a08301516146b860a086018263ffffffff169052565b5060c08301516146d460c086018267ffffffffffffffff169052565b5060e08301516146ee60e086018265ffffffffffff169052565b506101008381015165ffffffffffff1690850152610120808401519085015261014080840151818601839052614726838701826145d7565b92505050610160808401518583038287015261419f8382614639565b828152604060208201525f6137826040830184614664565b5f60e0828403121561421c575f80fd5b5f67ffffffffffffffff8211156147835761478361437d565b50601f01601f191660200190565b5f82601f8301126147a0575f80fd5b81356147ae61445a8261476a565b8181528460208386010111156147c2575f80fd5b816020850160208301375f918101602001919091529392505050565b5f80604083850312156147ef575f80fd5b82356147fa816142ca565b9150602083013567ffffffffffffffff811115614815575f80fd5b61482185828601614791565b9150509250929050565b5f6020828403121561483b575f80fd5b5035919050565b60208101600a831061485657614856614304565b91905290565b5f6020828403121561486c575f80fd5b610af982614428565b5f60208284031215614885575f80fd5b813567ffffffffffffffff81111561489b575f80fd5b6137828482850161420b565b5f805f805f805f8060e0898b0312156148be575f80fd5b6148c789614428565b97506148d560208a01614428565b965060408901356148e5816142ca565b9550606089013594506080890135935060a0890135925060c089013567ffffffffffffffff811115614915575f80fd5b6149218b828c016144c3565b999c989b5096995094979396929594505050565b5f8083601f840112614945575f80fd5b50813567ffffffffffffffff81111561495c575f80fd5b6020830191508360208260051b8501011115614501575f80fd5b5f8060208385031215614987575f80fd5b823567ffffffffffffffff81111561499d575f80fd5b6149a985828601614935565b90969095509350505050565b5f805f805f805f805f60e08a8c0312156149cd575f80fd5b6149d68a614428565b985060208a013567ffffffffffffffff808211156149f2575f80fd5b6149fe8d838e01614935565b909a50985060408c01359150614a13826142ca565b90965060608b0135955060808b0135945060a08b0135935060c08b013590808211156145b3575f80fd5b602081525f610af96020830184614639565b5f6060828403121561421c575f80fd5b5f805f805f805f805f806101208b8d031215614a79575f80fd5b8a3567ffffffffffffffff80821115614a90575f80fd5b614a9c8e838f0161443b565b9b50614aaa60208e016142de565b9a50614ab860408e016142de565b9950614ac660608e016142de565b985060808d01359750614adb60a08e01614222565b9650614ae960c08e016144ae565b955060e08d0135915080821115614afe575f80fd5b614b0a8e838f016144c3565b90955093506101008d0135915080821115614b23575f80fd5b50614b308d828e01614a4f565b9150509295989b9194979a5092959850565b803560028110614234575f80fd5b5f8060408385031215614b61575f80fd5b614b6a83614b42565b91506020830135614b7a816142ca565b809150509250929050565b5f8060408385031215614b96575f80fd5b8235614ba1816142ca565b915061427b60208401614b42565b5f60208284031215614bbf575f80fd5b610af982614b42565b5f8060208385031215614bd9575f80fd5b823567ffffffffffffffff811115614bef575f80fd5b6149a9858286016144c3565b5f805f805f8060a08789031215614c10575f80fd5b8635614c1b816142ca565b9550602087013567ffffffffffffffff80821115614c37575f80fd5b614c438a838b0161420b565b965060408901359550614c5860608a01614222565b94506080890135915080821115614c6d575f80fd5b50614c7a89828a016144c3565b979a9699509497509295939492505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115613aea57613aea614c8c565b63ffffffff84168152606060208201525f614cea6060830185614639565b9050826040830152949350505050565b5f8060408385031215614d0b575f80fd5b505080516020909101519092909150565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614d4f575f80fd5b83018035915067ffffffffffffffff821115614d69575f80fd5b6020019150600581901b3603821315614501575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b803567ffffffffffffffff81168114614234575f80fd5b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614df7575f80fd5b830160208101925035905067ffffffffffffffff811115614e16575f80fd5b8060051b3603821315614501575f80fd5b8183525f60208085019450825f5b8581101561460c5763ffffffff614e4b83614428565b1687529582019590820190600101614e35565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614e91575f80fd5b830160208101925035905067ffffffffffffffff811115614eb0575f80fd5b803603821315614501575f80fd5b81835281816020850137505f602082840101525f6020601f19601f840116840101905092915050565b5f61018082358452602083013560208501526040830135604085015260608301356060850152614f1960808401614222565b62ffffff166080850152614f2f60a08401614428565b63ffffffff1660a0850152614f4660c08401614dad565b67ffffffffffffffff1660c0850152614f6160e084016144ae565b65ffffffffffff1660e0850152610100614f7c8482016144ae565b65ffffffffffff16908501526101208381013590850152610140614fa281850185614dc4565b8383880152614fb48488018284614e27565b9350505050610160614fc881850185614e5e565b86840383880152614fda848284614ebe565b979650505050505050565b602081525f610af96020830184614ee7565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261502a575f80fd5b83018035915067ffffffffffffffff821115615044575f80fd5b602001915036819003821315614501575f80fd5b5f60208284031215615068575f80fd5b5051919050565b8082028115828204841417613aea57613aea614c8c565b5f826150b9577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b63ffffffff85168152608060208201525f6150dc6080830186614639565b6040830194909452506060015292915050565b5f61010087516001600160a01b038082511685526020820151602086015260208a0151604086015260408a01516060860152808951166080860152602089015160a086015280881660c086015250508060e08401526123378184018587614ebe565b6040810161515f8285614331565b6001600160a01b03831660208301529392505050565b6001600160a01b038316815260408101610af96020830184614331565b81810381811115613aea57613aea614c8c565b848152608060208201525f6151bd6080830186614ee7565b905083604083015262ffffff8316606083015295945050505050565b5f602082840312156151e9575f80fd5b610af9826144ae565b65ffffffffffff81811683821601908082111561521157615211614c8c565b5092915050565b5f60208284031215615228575f80fd5b610af982614222565b5f60208284031215615241575f80fd5b815160ff81168114610af9575f80fd5b818382375f9101908152919050565b62ffffff84168152826020820152606060408201525f613de36060830184614ee7565b5f67ffffffffffffffff80831681810361529f5761529f614c8c565b6001019392505050565b602081525f610af96020830184614664565b5f82601f8301126152ca575f80fd5b81516152d861445a8261476a565b8181528460208386010111156152ec575f80fd5b613782826020830160208701614617565b5f806040838503121561530e575f80fd5b8251615319816142ca565b602084015190925067ffffffffffffffff811115615335575f80fd5b614821858286016152bb565b6001600160a01b038616815284602082015283604082015261ffff8316606082015260a060808201525f614fda60a0830184614639565b80518015158114614234575f80fd5b5f8060408385031215615398575f80fd5b6153a183615378565b9150602083015167ffffffffffffffff811115615335575f80fd5b5f82357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe818336030181126153ee575f80fd5b9190910192915050565b5f63ffffffff80831681810361529f5761529f614c8c565b5f61541d61445a84614405565b80848252602080830192508560051b85013681111561543a575f80fd5b855b8181101561555457803567ffffffffffffffff8082111561545b575f80fd5b81890191506101808236031215615470575f80fd5b6154786143aa565b823581528583013586820152604080840135908201526060808401359082015260806154a5818501614222565b9082015260a06154b6848201614428565b9082015260c06154c7848201614dad565b9082015260e06154d88482016144ae565b908201526101006154ea8482016144ae565b908201526101208381013590820152610140808401358381111561550c575f80fd5b6155183682870161443b565b8284015250506101608084013583811115615531575f80fd5b61553d36828701614791565b91830191909152508752505093820193820161543c565b50919695505050505050565b60ff8281168282160390811115613aea57613aea614c8c565b600181815b808511156155d257817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156155b8576155b8614c8c565b808516156155c557918102915b93841c939080029061557e565b509250929050565b5f826155e857506001613aea565b816155f457505f613aea565b816001811461560a576002811461561457615630565b6001915050613aea565b60ff84111561562557615625614c8c565b50506001821b613aea565b5060208310610133831016604e8410600b8410161715615653575081810a613aea565b61565d8383615579565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561568f5761568f614c8c565b029392505050565b5f610af960ff8416836155da565b602080825282518282018190525f9190848201906040850190845b8181101561571e5761570b83855180518252602081015160208301526040810151604083015262ffffff606082015116606083015265ffffffffffff60808201511660808301525050565b9284019260a092909201916001016156c0565b50909695505050505050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b8281101561579d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261578b858351614664565b94509285019290850190600101615751565b5092979650505050505050565b5f602082840312156157ba575f80fd5b610af982615378565b5f82516153ee818460208701614617565b60ff83168152604060208201525f613782604083018461463956fea2646970667358221220d4fb78ed786bdaff9137bb2da7ec006f5af6ce166472f2b4c3faa6fe6b93204364736f6c63430008170033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.