Overview
ETH Balance
0.00062482721860672 ETH
Eth Value
$2.12 (@ $3,395.38/ETH)More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 578 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Wormhole Receive | 20532349 | 162 days ago | IN | 0 ETH | 0.00079408 | ||||
Wormhole Receive | 20302317 | 194 days ago | IN | 0 ETH | 0.00071388 | ||||
Wormhole Receive | 20302299 | 194 days ago | IN | 0 ETH | 0.00069121 | ||||
Wormhole Receive | 20302292 | 194 days ago | IN | 0 ETH | 0.00068027 | ||||
Wormhole Receive | 20302211 | 194 days ago | IN | 0 ETH | 0.00097488 | ||||
Wormhole Receive | 20181867 | 210 days ago | IN | 0 ETH | 0.00132555 | ||||
Wormhole Receive | 20171754 | 212 days ago | IN | 0 ETH | 0.00101835 | ||||
Wormhole Receive | 20171747 | 212 days ago | IN | 0 ETH | 0.00108684 | ||||
Update Permissio... | 20170782 | 212 days ago | IN | 0 ETH | 0.00036778 | ||||
Update Wormhole ... | 20170758 | 212 days ago | IN | 0 ETH | 0.00071573 | ||||
Update X Chain R... | 20170751 | 212 days ago | IN | 0 ETH | 0.00065835 | ||||
Wormhole Receive | 20046987 | 229 days ago | IN | 0 ETH | 0.00262728 | ||||
Wormhole Receive | 19986016 | 238 days ago | IN | 0 ETH | 0.00202721 | ||||
Wormhole Receive | 19978044 | 239 days ago | IN | 0 ETH | 0.00288663 | ||||
Wormhole Receive | 19897856 | 250 days ago | IN | 0 ETH | 0.00126375 | ||||
Wormhole Receive | 19875257 | 253 days ago | IN | 0 ETH | 0.00184296 | ||||
Wormhole Receive | 19829965 | 260 days ago | IN | 0 ETH | 0.00150353 | ||||
Wormhole Receive | 19829839 | 260 days ago | IN | 0 ETH | 0.0014012 | ||||
Wormhole Receive | 19829682 | 260 days ago | IN | 0 ETH | 0.00125886 | ||||
Wormhole Receive | 19821103 | 261 days ago | IN | 0 ETH | 0.0012639 | ||||
Wormhole Receive | 19818404 | 261 days ago | IN | 0 ETH | 0.00204577 | ||||
Wormhole Receive | 19814339 | 262 days ago | IN | 0 ETH | 0.00121025 | ||||
Wormhole Receive | 19813353 | 262 days ago | IN | 0 ETH | 0.00213054 | ||||
Wormhole Receive | 19813257 | 262 days ago | IN | 0 ETH | 0.00171891 | ||||
Wormhole Receive | 19813193 | 262 days ago | IN | 0 ETH | 0.00167984 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
20752826 | 131 days ago | 0.00000201 ETH | ||||
20296423 | 194 days ago | 0.00000201 ETH | ||||
19985828 | 238 days ago | 0.00000201 ETH | ||||
19977746 | 239 days ago | 0.00000201 ETH | ||||
19917673 | 247 days ago | 0.00000028 ETH | ||||
19888517 | 251 days ago | 0.00000201 ETH | ||||
19813794 | 262 days ago | 0.00000201 ETH | ||||
19813341 | 262 days ago | 0.00000201 ETH | ||||
19813310 | 262 days ago | 0.00000201 ETH | ||||
19813260 | 262 days ago | 0.00000201 ETH | ||||
19813242 | 262 days ago | 0.00000201 ETH | ||||
19813206 | 262 days ago | 0.00000201 ETH | ||||
19813113 | 262 days ago | 0.00000201 ETH | ||||
19813050 | 262 days ago | 0.00000201 ETH | ||||
19812458 | 262 days ago | 0.00000201 ETH | ||||
19812386 | 262 days ago | 0.00000201 ETH | ||||
19811805 | 262 days ago | 0.00000296 ETH | ||||
19810553 | 262 days ago | 0.0000037 ETH | ||||
19809445 | 263 days ago | 0.00000201 ETH | ||||
19809329 | 263 days ago | 0.00000201 ETH | ||||
19807006 | 263 days ago | 0.00000201 ETH | ||||
19806845 | 263 days ago | 0.00000201 ETH | ||||
19805152 | 263 days ago | 0.00000201 ETH | ||||
19803938 | 263 days ago | 0.00000201 ETH | ||||
19803923 | 263 days ago | 0.00000201 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
HashflowWormholeMessenger
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
/** * SPDX-License-Identifier: UNLICENSED */ pragma solidity 0.8.18; import '@openzeppelin/contracts/security/ReentrancyGuard.sol'; import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; import '../interfaces/external/IWormhole.sol'; import '../interfaces/xchain/IHashflowWormholeMessenger.sol'; import '../interfaces/IHashflowPool.sol'; import '../interfaces/IHashflowRouter.sol'; import './HashflowXChainMessengerBase.sol'; contract HashflowWormholeMessenger is HashflowXChainMessengerBase, IHashflowWormholeMessenger, ReentrancyGuard { using SafeERC20 for IERC20; using Address for address; address public wormholeEndpoint; uint8 public wormholeConsistencyLevel; uint8 public wormholeConsistencyLevelFast; // These mappings manage H-Chain ID <-> Wormhole Chain ID links. mapping(uint16 => uint16) public hChainIdToWormholeChainId; mapping(uint16 => uint16) public wormholeChainIdToHChainId; mapping(uint16 => bytes32) public permissionedRelayers; receive() external payable {} constructor(uint16 _hChainId, address _router) HashflowXChainMessengerBase(_hChainId, _router) {} /// @inheritdoc IHashflowWormholeMessenger function updateWormhole(address wormhole) external override onlyOwner { require( wormhole.isContract(), 'HashflowWormholeMessenger::updateWormhole Wormhole endpoint must be a contract.' ); emit UpdateWormholeEndpoint(wormhole, wormholeEndpoint); wormholeEndpoint = wormhole; } /// @inheritdoc IHashflowWormholeMessenger function updateWormholeConsistencyLevel(uint8 consistencyLevel) external override onlyOwner { require( consistencyLevel != 0, 'HashflowWormholeMessenger::updateWormholeConsistencyLevel Consistency level cannot be 0.' ); wormholeConsistencyLevel = consistencyLevel; emit UpdateWormholeConsistencyLevel(wormholeConsistencyLevel); } /// @inheritdoc IHashflowWormholeMessenger function updateWormholeConsistencyLevelFast(uint8 consistencyLevel) external override onlyOwner { require( consistencyLevel != 0, 'HashflowWormholeMessenger::updateWormholeConsistencyLevelFast Consistency level cannot be 0.' ); wormholeConsistencyLevelFast = consistencyLevel; emit UpdateWormholeConsistencyLevelFast(wormholeConsistencyLevelFast); } /// @inheritdoc IHashflowWormholeMessenger function updatePermissionedRelayer(uint16 _hChainId, bytes32 relayer) external override onlyOwner { require( _hChainId != hChainId, 'HashflowWormholeMessenger::updatePermissionedRelayer Cannot update relayer for same chain.' ); require( relayer != bytes32(0), 'HashflowWormholeMessenger::updatePermissionedRelayer Relayer address cannot be 0.' ); permissionedRelayers[_hChainId] = relayer; emit UpdatePermissionedRelayer(_hChainId, relayer); } /// @inheritdoc IHashflowXChainMessenger function tradeXChain( XChainQuote memory quote, address caller, bytes32 dstContract, bytes memory dstCalldata ) external payable { require( _msgSender() == router, 'HashflowWormholeMessenger::tradeXChain Sender must be router.' ); require( quote.srcChainId == hChainId, 'HashflowWormholeMessenger::tradeXChain Incorrect srcChainId.' ); _wormholeSend(quote, caller, dstContract, dstCalldata); } /// @dev Send message via Wormhole. function _wormholeSend( XChainQuote memory quote, address caller, bytes32 dstContract, bytes memory dstCalldata ) private { uint256 wormholeMessageFee = IWormhole(wormholeEndpoint).messageFee(); uint256 totalWormholeMessageFee = wormholeMessageFee; // We double the fee for fast relays. if ( wormholeConsistencyLevelFast != 0 && permissionedRelayers[quote.dstChainId] != bytes32(0) ) { totalWormholeMessageFee = totalWormholeMessageFee * 2; } require( msg.value >= totalWormholeMessageFee, 'HashflowWormholeMessenger::_wormholeSend Insufficient Wormhole fees.' ); uint16 wormholeDstChainId = hChainIdToWormholeChainId[quote.dstChainId]; require( wormholeDstChainId != 0 && xChainRemotes[quote.dstChainId].length > 0, 'HashflowWormholeMessenger::_wormholeSend Wormhole destination chain ID not configured' ); require( wormholeConsistencyLevel != 0, 'HashflowWormholeMessenger::_wormholeSend Consistency level not set.' ); { bytes memory payload = _generateTradePayload( quote, caller, bytes32(0), dstContract, dstCalldata ); uint256 sequence = IWormhole(wormholeEndpoint).publishMessage{ value: wormholeMessageFee }( 0, // Nonce. payload, wormholeConsistencyLevel ); emit WormholeSend( quote.txid, msg.value - totalWormholeMessageFee, sequence ); } if ( wormholeConsistencyLevelFast != 0 && permissionedRelayers[quote.dstChainId] != bytes32(0) ) { bytes memory payload = _generateTradePayload( quote, caller, permissionedRelayers[quote.dstChainId], dstContract, dstCalldata ); uint256 sequence = IWormhole(wormholeEndpoint).publishMessage{ value: wormholeMessageFee }( 0, // Nonce. payload, wormholeConsistencyLevelFast ); emit WormholeSendFast( quote.txid, msg.value - totalWormholeMessageFee, sequence ); } } /// @inheritdoc IHashflowWormholeMessenger function wormholeReceive(bytes memory encodedVM) external override nonReentrant { ( WormholeStructs.VM memory vm, bool valid, string memory reason ) = IWormhole(wormholeEndpoint).parseAndVerifyVM(encodedVM); // We make sure the message is valid and has been signed by // Guardians. require(valid, reason); // We check that the emitter chain has been properly configured. // It is OK to revert if not -- the message can be retried later on. // Wormhole VAAs are non-blocking. uint16 srcHChainId = wormholeChainIdToHChainId[vm.emitterChainId]; require( srcHChainId != 0, 'HashflowWormholeMessenger::wormholeReceive Invalid source chain.' ); // We ensure that the sender of the message is a valid Hashflow contract. bytes32 authorizedRemote = bytes32( uint256(bytes32(xChainRemotes[srcHChainId])) >> ((32 - xChainRemotes[srcHChainId].length) * 8) ); require( authorizedRemote == vm.emitterAddress, 'HashflowWormholeMessenger::wormholeReceive Unauthorized remote.' ); XChainTradePayload memory tradePayload = abi.decode( vm.payload, (XChainTradePayload) ); IHashflowRouter.XChainFillMessage memory fillMessage; // We need to check that this is the intended receiving chain. require( tradePayload.dstChainId == hChainId, 'HashflowWormholeMessenger::wormholeReceive Incorrect destination chain.' ); if (tradePayload.permissionedRelayer != bytes32(0)) { require( bytes32( uint256(uint160(uint256(tradePayload.permissionedRelayer))) ) == tradePayload.permissionedRelayer, 'HashflowWormholeMessenger::wormholeReceive permissionedRelayer is not EVM address.' ); require( address(uint160(uint256(tradePayload.permissionedRelayer))) == _msgSender(), 'HashflowWormholeMessenger::wormholeReceive Relayer not authorized.' ); } require( bytes32(uint256(uint160(uint256(tradePayload.dstPool)))) == tradePayload.dstPool, 'HashflowWormholeMessenger::wormholeReceive dstPool is not EVM address.' ); require( bytes32( uint256(uint160(uint256(tradePayload.dstExternalAccount))) ) == tradePayload.dstExternalAccount, 'HashflowWormholeMessenger::wormholeReceive dstExternalAccount is not EVM address.' ); require( bytes32(uint256(uint160(uint256(tradePayload.dstTrader)))) == tradePayload.dstTrader, 'HashflowWormholeMessenger::wormholeReceive dstTrader is not EVM address.' ); require( bytes32(uint256(uint160(uint256(tradePayload.quoteToken)))) == tradePayload.quoteToken, 'HashflowWormholeMessenger::wormholeReceive quoteToken is not EVM address.' ); fillMessage.srcHashflowChainId = srcHChainId; fillMessage.srcPool = tradePayload.srcPool; fillMessage.dstPool = address(uint160(uint256(tradePayload.dstPool))); fillMessage.dstExternalAccount = address( uint160(uint256(tradePayload.dstExternalAccount)) ); fillMessage.dstTrader = address( uint160(uint256(tradePayload.dstTrader)) ); fillMessage.quoteToken = address( uint160(uint256(tradePayload.quoteToken)) ); fillMessage.quoteTokenAmount = tradePayload.quoteTokenAmount; fillMessage.txid = tradePayload.txid; fillMessage.srcCaller = tradePayload.srcCaller; if (tradePayload.dstContract != bytes32(0)) { require( bytes32(uint256(uint160(uint256(tradePayload.dstContract)))) == tradePayload.dstContract, 'HashflowWormholeMessenger::wormholeReceive dstContract is not EVM address.' ); fillMessage.dstContract = address( uint160(uint256(tradePayload.dstContract)) ); fillMessage.dstContractCalldata = tradePayload.dstContractCalldata; } IHashflowRouter(router).fillXChain(fillMessage); emit WormholeReceive(fillMessage.txid); } /// @inheritdoc IHashflowWormholeMessenger function updateWormholeChainIdForHashflowChainId( uint16 hashflowChainId, uint16 wormholeChainId ) external override onlyOwner { require( hashflowChainId != 0 && wormholeChainId != 0, 'HashflowWormholeMessenger::updateWormholeChainIdForHashflowChainId chainId cannot be 0.' ); // If this wormhole Chain ID is already assigned, we need to unassign it first. require( wormholeChainIdToHChainId[wormholeChainId] == 0, 'HashflowWormholeMessenger::updateWormholeChainIdForHashflowChainId Wormhole Chain ID already assigned.' ); uint16 previouslyAssignedWormholeChainId = hChainIdToWormholeChainId[ hashflowChainId ]; // We free up the previously assigned ID. if (previouslyAssignedWormholeChainId != 0) { wormholeChainIdToHChainId[previouslyAssignedWormholeChainId] = 0; } hChainIdToWormholeChainId[hashflowChainId] = wormholeChainId; wormholeChainIdToHChainId[wormholeChainId] = hashflowChainId; emit UpdateWormholeChainId(hashflowChainId, wormholeChainId); } /// @dev We do not allow the owner to renounce ownership. function renounceOwnership() public view override onlyOwner { revert( 'HashflowWormholeMessenger::renounceOwnership Renouncing ownership not allowed.' ); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @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 { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol) pragma solidity ^0.8.0; import "./Ownable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); _transferOwnership(sender); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC1271 standard signature validation method for * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. * * _Available since v4.1._ */ interface IERC1271 { /** * @dev Should return whether the signature provided is valid for the provided data * @param hash Hash of the data to be signed * @param signature Signature byte array associated with _data */ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @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. */ 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]. */ 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 v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @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 amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` 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 amount) 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 `amount` 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 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` 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 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../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 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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 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); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to * 0 before setting it to a non-zero value. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @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, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @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.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @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, it is bubbled up by this * function (like regular Solidity function calls). * * 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. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @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`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @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; } }
// contracts/Messages.sol // SPDX-License-Identifier: Apache 2 pragma solidity ^0.8.0; import './WormholeStructs.sol'; interface IWormhole is WormholeStructs { event LogMessagePublished( address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel ); function publishMessage( uint32 nonce, bytes memory payload, uint8 consistencyLevel ) external payable returns (uint64 sequence); function parseAndVerifyVM(bytes calldata encodedVM) external view returns ( WormholeStructs.VM memory vm, bool valid, string memory reason ); function verifyVM(WormholeStructs.VM memory vm) external view returns (bool valid, string memory reason); function verifySignatures( bytes32 hash, WormholeStructs.Signature[] memory signatures, WormholeStructs.GuardianSet memory guardianSet ) external pure returns (bool valid, string memory reason); function parseVM(bytes memory encodedVM) external pure returns (WormholeStructs.VM memory vm); function getGuardianSet(uint32 index) external view returns (WormholeStructs.GuardianSet memory); function getCurrentGuardianSetIndex() external view returns (uint32); function getGuardianSetExpiry() external view returns (uint32); function governanceActionIsConsumed(bytes32 hash) external view returns (bool); function isInitialized(address impl) external view returns (bool); function chainId() external view returns (uint16); function governanceChainId() external view returns (uint16); function governanceContract() external view returns (bytes32); function messageFee() external view returns (uint256); }
// contracts/Structs.sol // SPDX-License-Identifier: Apache 2 pragma solidity ^0.8.0; interface WormholeStructs { struct Provider { uint16 chainId; uint16 governanceChainId; bytes32 governanceContract; } struct GuardianSet { address[] keys; uint32 expirationTime; } struct Signature { bytes32 r; bytes32 s; uint8 v; uint8 guardianIndex; } struct VM { uint8 version; uint32 timestamp; uint32 nonce; uint16 emitterChainId; bytes32 emitterAddress; uint64 sequence; uint8 consistencyLevel; bytes payload; uint32 guardianSetIndex; Signature[] signatures; bytes32 hash; } }
/** * SPDX-License-Identifier: UNLICENSED */ pragma solidity >=0.8.0; import '@openzeppelin/contracts/interfaces/IERC1271.sol'; import './IQuote.sol'; /// @title IHashflowPool /// @author Victor Ionescu /** * Pool contract used for trading. The Pool can either hold funds or * rely on external accounts. External accounts are used in order to preserve * Capital Efficiency on the Market Maker side. This way, a Market Maker can * make markets using funds that are also used on other venues. */ interface IHashflowPool is IQuote, IERC1271 { /// @notice Specifies a HashflowPool on a foreign chain. struct AuthorizedXChainPool { uint16 chainId; bytes32 pool; } /// @notice Contains a signer verification address, and whether trading is enabled. struct SignerConfiguration { address signer; bool enabled; } /// @notice Emitted when the authorization status of a withdrawal account changes. /// @param account The account for which the status changes. /// @param authorized The new authorization status. event UpdateWithdrawalAccount(address account, bool authorized); /// @notice Emitted when the signer key used for the pool has changed. /// @param signer The new signer key. /// @param prevSigner The old signer key. event UpdateSigner(address signer, address prevSigner); /// @notice Emitted when liquidity is withdrawn from the pool. /// @param token Token being withdrawn. /// @param recipient Address receiving the token. /// @param withdrawAmount Amount being withdrawn. event RemoveLiquidity( address token, address recipient, uint256 withdrawAmount ); /// @notice Emitted when an intra-chain trade happens. /// @param trader The trader. /// @param effectiveTrader The effective Trader. /// @param txid The txid of the quote. /// @param baseToken The token the trader sold. /// @param quoteToken The token the trader bought. /// @param baseTokenAmount The amount of baseToken sold. /// @param quoteTokenAmount The amount of quoteToken bought. event Trade( address trader, address effectiveTrader, bytes32 txid, address baseToken, address quoteToken, uint256 baseTokenAmount, uint256 quoteTokenAmount ); /// @notice Emitted when a cross-chain trade happens. /// @param dstChainId The Hashflow Chain ID for the destination chain. /// @param dstPool The pool address on the destination chain. /// @param trader The trader address. /// @param txid The txid of the quote. /// @param baseToken The token the trader sold. /// @param quoteToken The token the trader bought. /// @param baseTokenAmount The amount of baseToken sold. /// @param quoteTokenAmount The amount of quoteToken bought. event XChainTrade( uint16 dstChainId, bytes32 dstPool, address trader, bytes32 dstTrader, bytes32 txid, address baseToken, bytes32 quoteToken, uint256 baseTokenAmount, uint256 quoteTokenAmount ); /// @notice Emitted when a cross-chain trade is filled. /// @param txid The txid identified the quote that was filled. event XChainTradeFill(bytes32 txid); /// @notice Main initializer. /// @param name Name of the pool. /// @param signer Signer key used for quote / deposit verification. /// @param operations Operations key that governs the pool. /// @param router Address of the HashflowRouter contract. function initialize( string calldata name, address signer, address operations, address router ) external; /// @notice Returns the pool name. function name() external view returns (string memory); /// @notice Returns the signer address and whether the pool is enabled. function signerConfiguration() external view returns (address, bool); /// @notice Returns the Operations address of this pool. function operations() external view returns (address); /// @notice Returns the Router contract address. function router() external view returns (address); /// @notice Returns the current nonce for a trader. function nonces(address trader) external view returns (uint256); /// @notice Removes liquidity from the pool. /// @param token Token to withdraw. /// @param recipient Address to send token to. /// @param amount Amount to withdraw. function removeLiquidity( address token, address recipient, uint256 amount ) external; /// @notice Execute an RFQ-T trade. /// @param quote The quote to be executed. function tradeRFQT(RFQTQuote memory quote) external payable; /// @notice Execute an RFQ-M trade. /// @param quote The quote to be executed. function tradeRFQM(RFQMQuote memory quote) external; /// @notice Execute a cross-chain RFQ-T trade. /// @param quote The quote to be executed. /// @param trader The account that sends baseToken on this chain. function tradeXChainRFQT(XChainRFQTQuote memory quote, address trader) external payable; /// @notice Execute a cross-chain RFQ-M trade. /// @param quote The quote to be executed. function tradeXChainRFQM(XChainRFQMQuote memory quote) external; /// @notice Changes authorization for a set of pools to send X-Chain messages. /// @param pools The pools to change authorization status for. /// @param authorized The new authorization status. function updateXChainPoolAuthorization( AuthorizedXChainPool[] calldata pools, bool authorized ) external; /// @notice Changes authorization for an X-Chain Messenger app. /// @param xChainMessenger The address of the Messenger app. /// @param authorized The new authorization status. function updateXChainMessengerAuthorization( address xChainMessenger, bool authorized ) external; /// @notice Fills an x-chain order that completed on the source chain. /// @param externalAccount The external account to fill from, if any. /// @param txid The txid of the quote. /// @param trader The trader to receive the funds. /// @param quoteToken The token to be sent. /// @param quoteTokenAmount The amount of quoteToken to be sent. function fillXChain( address externalAccount, bytes32 txid, address trader, address quoteToken, uint256 quoteTokenAmount ) external; /// @notice Updates withdrawal account authorization. /// @param withdrawalAccounts the accounts for which to update authorization status. /// @param authorized The new authorization status. function updateWithdrawalAccount( address[] memory withdrawalAccounts, bool authorized ) external; /// @notice Updates the signer key. /// @param signer The new signer key. function updateSigner(address signer) external; /// @notice Used by the router to disable pool actions (Trade, Withdraw, Deposit) function killswitchOperations(bool enabled) external; /// @notice Returns the token reserves for this pool. /// @param token The token to check reserves for. function getReserves(address token) external view returns (uint256); /// @notice Approves a token for spend. Used for 1inch RFQ protocol. /// @param token The address of the ERC-20 token. /// @param spender The spender address (typically the 1inch RFQ order router) /// @param amount The approval amount. function approveToken( address token, address spender, uint256 amount ) external; /// @notice Increases allowance for a token. Used for 1inch RFQ protocol. /// @param token The address of the ERC-20 token. /// @param spender The spender address (typically the 1inch RFQ order router). /// @param amount The approval amount. function increaseTokenAllowance( address token, address spender, uint256 amount ) external; /// @notice Decreases allowance for a token. Used for 1inch RFQ protocol. /// @param token The address of the ERC-20 token. /// @param spender The spender address (typically the 1inch RFQ order router) /// @param amount The approval amount. function decreaseTokenAllowance( address token, address spender, uint256 amount ) external; }
/** * SPDX-License-Identifier: UNLICENSED */ pragma solidity >=0.8.0; import './IQuote.sol'; /// @title IHashflowRouter /// @author Victor Ionescu /** * @notice In terms of user-facing functionality, the Router is responsible for: * - orchestrating trades * - managing cross-chain permissions * * Every trade requires consent from two parties: the Trader and the Market Maker. * However, there are two models to establish consent: * - RFQ-T: in this model, the Market Maker provides an EIP-191 signature for the quote, * while the Trader signs the transaction and submits it on-chain * - RFQ-M: in this model, the Trader provides an EIP-712 signature for the quote, * the Market Maker provides an EIP-191 signature, and a 3rd party relays the trade. * The 3rd party can be the Market Maker itself. * * In terms of Hashflow internals, the Router maintains a set of authorized pool * contracts that are allowed to be used for trading. This allowlist creates * guarantees against malicious behavior, as documented in specific places. * * The Router contract is not upgradeable. In order to change functionality, a new * Router has to be deployed, and new HashflowPool contracts have to be deployed * by the Market Makers. */ /// @dev Trade / liquidity events are emitted at the HashflowPool level, rather than the router. interface IHashflowRouter is IQuote { /** * @notice X-Chain message received from an X-Chain Messenger. This is used by the * Router to communicate a fill to a HashflowPool. */ struct XChainFillMessage { /// @notice The Hashflow Chain ID of the source chain. uint16 srcHashflowChainId; /// @notice The address of the HashflowPool on the source chain. bytes32 srcPool; /// @notice The HashflowPool to disburse funds on the destination chain. address dstPool; /** * @notice The external account linked to the HashflowPool on the destination chain. * If the HashflowPool holds funds, this should be bytes32(0). */ address dstExternalAccount; /// @notice The recipient of the quoteToken on the destination chain. address dstTrader; /// @notice The token that the trader buys on the destination chain. address quoteToken; /// @notice The amount of quoteToken bought. uint256 quoteTokenAmount; /// @notice Unique identifier for the quote. /// @dev Generated off-chain via a distributed UUID generator. bytes32 txid; /// @notice The caller of the trade function on the source chain. bytes32 srcCaller; /// @notice The contract to call, if any. address dstContract; /// @notice The calldata for the contract. bytes dstContractCalldata; } /// @notice Emitted when the authorization status of a pool changes. /// @param pool The pool whose status changed. /// @param authorized The new auth status. event UpdatePoolAuthorizaton(address pool, bool authorized); /// @notice Emitted when a sender pool authorization changes. /// @param pool Pool address on this chain. /// @param otherHashflowChainId Hashflow Chain ID of the other chain. /// @param otherChainPool Pool address on the other chain. /// @param authorized Whether the pool is authorized. event UpdateXChainPoolAuthorization( address indexed pool, uint16 otherHashflowChainId, bytes32 otherChainPool, bool authorized ); /// @notice Emitted when the authorization of an x-caller changes. /// @param pool Pool address on this chain. /// @param otherHashflowChainId Hashflow Chain ID of the other chain. /// @param caller Caller address on the other chain. /// @param authorized Whether the caller is authorized. event UpdateXChainCallerAuthorization( address indexed pool, uint16 otherHashflowChainId, bytes32 caller, bool authorized ); /// @notice Emitted when the authorization status of an X-Chain Messenger changes for a pool. /// @param pool Pool address for which the Messenger authorization changes. /// @param xChainMessenger Address of the Messenger. /// @param authorized Whether the X-Chain Messenger is authorized. event UpdateXChainMessengerAuthorization( address indexed pool, address xChainMessenger, bool authorized ); /// @notice Emitted when the authorized status of an X-Chain Messenger changes for a callee. /// @param callee Address of the callee. /// @param xChainMessenger Address of the Messenger. /// @param authorized Whether the X-Chain Messenger is authorized. event UpdateXChainMessengerCallerAuthorization( address indexed callee, address xChainMessenger, bool authorized ); /// @notice Emitted when the Limit Order Guardian address is updated. /// @param guardian The new Guardian address. event UpdateLimitOrderGuardian(address guardian); /// @notice Initializes the Router. Called one time. /// @param factory The address of the HashflowFactory contract. function initialize(address factory) external; /// @notice Returns the address of the associated HashflowFactor contract. function factory() external view returns (address); function authorizedXChainPools( bytes32 dstPool, uint16 srcHChainId, bytes32 srcPool ) external view returns (bool); function authorizedXChainCallers( address dstContract, uint16 srcHashflowChainId, bytes32 caller ) external view returns (bool); function authorizedXChainMessengersByPool(address pool, address messenger) external view returns (bool); function authorizedXChainMessengersByCallee( address callee, address messenger ) external view returns (bool); /// @notice Executes an intra-chain RFQ-T trade. /// @param quote The quote data to be executed. function tradeRFQT(RFQTQuote memory quote) external payable; /// @notice Executes an intra-chain RFQ-T trade, leveraging an ERC-20 permit. /// @param quote The quote data to be executed. /// @dev Does not support native tokens for the baseToken. function tradeRFQTWithPermit( RFQTQuote memory quote, uint256 deadline, uint8 v, bytes32 r, bytes32 s, uint256 amountToApprove ) external; /// @notice Executes an intra-chain RFQ-T trade. /// @param quote The quote to be executed. function tradeRFQM(RFQMQuote memory quote) external; /// @notice Executes an intra-chain RFQ-T trade, leveraging an ERC-20 permit. /// @param quote The quote to be executed. /// @param deadline The deadline of the ERC-20 permit. /// @param v v-part of the signature. /// @param r r-part of the signature. /// @param s s-part of the signature. /// @param amountToApprove The amount being approved. function tradeRFQMWithPermit( RFQMQuote memory quote, uint256 deadline, uint8 v, bytes32 r, bytes32 s, uint256 amountToApprove ) external; /// @notice Executes an intra-chain RFQ-T trade. /// @param quote The quote to be executed. /// @param guardianSignature A signature issued by the Limit Order Guardian. function tradeRFQMLimitOrder( RFQMQuote memory quote, bytes memory guardianSignature ) external; /// @notice Executes an intra-chain RFQ-T trade, leveraging an ERC-20 permit. /// @param quote The quote to be executed. /// @param guardianSignature A signature issued by the Limit Order Guardian. /// @param deadline The deadline of the ERC-20 permit. /// @param v v-part of the signature. /// @param r r-part of the signature. /// @param s s-part of the signature. /// @param amountToApprove The amount being approved. function tradeRFQMLimitOrderWithPermit( RFQMQuote memory quote, bytes memory guardianSignature, uint256 deadline, uint8 v, bytes32 r, bytes32 s, uint256 amountToApprove ) external; /// @notice Executes an RFQ-T cross-chain trade. /// @param quote The quote to be executed. /// @param dstContract The address of the contract to be called on the destination chain. /// @param dstCalldata The calldata for the smart contract call. function tradeXChainRFQT( XChainRFQTQuote memory quote, bytes32 dstContract, bytes memory dstCalldata ) external payable; /// @notice Executes an RFQ-T cross-chain trade, leveraging an ERC-20 permit. /// @param quote The quote to be executed. /// @param dstContract The address of the contract to be called on the destination chain. /// @param dstCalldata The calldata for the smart contract call. /// @param deadline The deadline of the ERC-20 permit. /// @param v v-part of the signature. /// @param r r-part of the signature. /// @param s s-part of the signature. /// @param amountToApprove The amount being approved. function tradeXChainRFQTWithPermit( XChainRFQTQuote memory quote, bytes32 dstContract, bytes memory dstCalldata, uint256 deadline, uint8 v, bytes32 r, bytes32 s, uint256 amountToApprove ) external payable; /// @notice Executes an RFQ-M cross-chain trade. /// @param quote The quote to be executed. /// @param dstContract The address of the contract to be called on the destination chain. /// @param dstCalldata The calldata for the smart contract call. function tradeXChainRFQM( XChainRFQMQuote memory quote, bytes32 dstContract, bytes memory dstCalldata ) external payable; /// @notice Similar to tradeXChainRFQm, but includes a spend permit for the baseToken. /// @param quote The quote to be executed. /// @param dstContract The address of the contract to be called on the destination chain. /// @param dstCalldata The calldata for the smart contract call. /// @param deadline The deadline of the ERC-20 permit. /// @param v v-part of the signature. /// @param r r-part of the signature. /// @param s s-part of the signature. /// @param amountToApprove The amount to approve. function tradeXChainRFQMWithPermit( XChainRFQMQuote memory quote, bytes32 dstContract, bytes memory dstCalldata, uint256 deadline, uint8 v, bytes32 r, bytes32 s, uint256 amountToApprove ) external payable; /// @notice Completes the second leg of a cross-chain trade. /// @param fillMessage Payload containing information necessary to complete the trade. function fillXChain(XChainFillMessage memory fillMessage) external; /// @notice Returns whether the pool is authorized for trading. /// @param pool The address of the HashflowPool. function authorizedPools(address pool) external view returns (bool); /// @notice Allows the owner to unauthorize a potentially compromised pool. Cannot be reverted. /// @param pool The address of the HashflowPool. function forceUnauthorizePool(address pool) external; /// @notice Authorizes a HashflowPool for trading. /// @dev Can only be called by the HashflowFactory or the admin. function updatePoolAuthorization(address pool, bool authorized) external; /// @notice Updates the authorization status of an X-Chain pool pair. /// @param otherHashflowChainId The Hashflow Chain ID of the peer chain. /// @param otherPool The 32-byte representation of the Pool address on the peer chain. /// @param authorized Whether the pool is authorized to communicate with the sender pool. function updateXChainPoolAuthorization( uint16 otherHashflowChainId, bytes32 otherPool, bool authorized ) external; /// @notice Updates the authorization status of an X-Chain caller. /// @param otherHashflowChainId The Hashflow Chain ID of the peer chain. /// @param caller The caller address. /// @param authorized Whether the caller is authorized to send an x-call to the sender pool. function updateXChainCallerAuthorization( uint16 otherHashflowChainId, bytes32 caller, bool authorized ) external; /// @notice Updates the authorization status of an X-Chain Messenger app. /// @param xChainMessenger The address of the Messenger App. /// @param authorized The new authorization status. function updateXChainMessengerAuthorization( address xChainMessenger, bool authorized ) external; /// @notice Updates the authorization status of an X-Chain Messenger app. /// @param xChainMessenger The address of the Messenger App. /// @param authorized The new authorization status. function updateXChainMessengerCallerAuthorization( address xChainMessenger, bool authorized ) external; /// @notice Used to stop all operations on a pool, in case of an emergency. /// @param pool The address of the HashflowPool. /// @param enabled Whether the pool is enabled. function killswitchPool(address pool, bool enabled) external; /// @notice Used to update the Limit Order Guardian. /// @param guardian The address of the new Guardian. function updateLimitOrderGuardian(address guardian) external; /// @notice Allows the owner to withdraw excess funds from the Router. /// @dev Under normal operations, the Router should not have excess funds. function withdrawFunds(address token) external; }
/** * SPDX-License-Identifier: UNLICENSED */ pragma solidity >=0.8.0; /// @title IQuote /// @author Victor Ionescu /** * @notice Interface for quote structs used for trading. There are two major types of trades: * - intra-chain: atomic transactions within one chain * - cross-chain: multi-leg transactions between two chains, which utilize interoperability protocols * such as Wormhole. * * Separately, there are two trading modes: * - RFQ-T: the trader signs the transaction, the market maker signs the quote * - RFQ-M: both the trader and Market Maker sign the quote, any relayer can sign the transaction */ interface IQuote { /// @notice Used for intra-chain RFQ-T trades. struct RFQTQuote { /// @notice The address of the HashflowPool to trade against. address pool; /** * @notice The external account linked to the HashflowPool. * If the HashflowPool holds funds, this should be address(0). */ address externalAccount; /// @notice The recipient of the quoteToken at the end of the trade. address trader; /** * @notice The account "effectively" making the trade (ultimately receiving the funds). * This is commonly used by aggregators, where a proxy contract (the 'trader') * receives the quoteToken, and the effective trader is the user initiating the call. * * This field DOES NOT influence movement of funds. However, it is used to check against * quote replay. */ address effectiveTrader; /// @notice The token that the trader sells. address baseToken; /// @notice The token that the trader buys. address quoteToken; /** * @notice The amount of baseToken sold in this trade. The exchange rate * is going to be preserved as the quoteTokenAmount / baseTokenAmount ratio. * * Most commonly, effectiveBaseTokenAmount will == baseTokenAmount. */ uint256 effectiveBaseTokenAmount; /// @notice The max amount of baseToken sold. uint256 baseTokenAmount; /// @notice The amount of quoteToken bought when baseTokenAmount is sold. uint256 quoteTokenAmount; /// @notice The Unix timestamp (in seconds) when the quote expires. /// @dev This gets checked against block.timestamp. uint256 quoteExpiry; /// @notice The nonce used by this effectiveTrader. Nonces are used to protect against replay. uint256 nonce; /// @notice Unique identifier for the quote. /// @dev Generated off-chain via a distributed UUID generator. bytes32 txid; /// @notice Signature provided by the market maker (EIP-191). bytes signature; } /// @notice Used for intra-chain RFQ-M trades. struct RFQMQuote { /// @notice The address of the HashflowPool to trade against. address pool; /** * @notice The external account linked to the HashflowPool. * If the HashflowPool holds funds, this should be address(0). */ address externalAccount; /// @notice The account that will be debited baseToken / credited quoteToken. address trader; /// @notice The token that the trader sells. address baseToken; /// @notice The token that the trader buys. address quoteToken; /// @notice The amount of baseToken sold. uint256 baseTokenAmount; /// @notice The amount of quoteToken bought. uint256 quoteTokenAmount; /// @notice The Unix timestamp (in seconds) when the quote expires. /// @dev This gets checked against block.timestamp. uint256 quoteExpiry; /// @notice Unique identifier for the quote. /// @dev Generated off-chain via a distributed UUID generator. bytes32 txid; /// @notice Signature provided by the trader (EIP-712). bytes takerSignature; /// @notice Signature provided by the market maker (EIP-191). bytes makerSignature; } /// @notice Used for cross-chain RFQ-T trades. struct XChainRFQTQuote { /// @notice The Hashflow Chain ID of the source chain. uint16 srcChainId; /// @notice The Hashflow Chain ID of the destination chain. uint16 dstChainId; /// @notice The address of the HashflowPool to trade against on the source chain. address srcPool; /// @notice The HashflowPool to disburse funds on the destination chain. /// @dev This is bytes32 in order to anticipate non-EVM chains. bytes32 dstPool; /** * @notice The external account linked to the HashflowPool on the source chain. * If the HashflowPool holds funds, this should be address(0). */ address srcExternalAccount; /** * @notice The external account linked to the HashflowPool on the destination chain. * If the HashflowPool holds funds, this should be bytes32(0). */ bytes32 dstExternalAccount; /// @notice The recipient of the quoteToken on the destination chain. bytes32 dstTrader; /// @notice The token that the trader sells on the source chain. address baseToken; /// @notice The token that the trader buys on the destination chain. bytes32 quoteToken; /** * @notice The amount of baseToken sold in this trade. The exchange rate * is going to be preserved as the quoteTokenAmount / baseTokenAmount ratio. * * Most commonly, effectiveBaseTokenAmount will == baseTokenAmount. */ uint256 effectiveBaseTokenAmount; /// @notice The amount of baseToken sold. uint256 baseTokenAmount; /// @notice The amount of quoteToken bought. uint256 quoteTokenAmount; /** * @notice The Unix timestamp (in seconds) when the quote expire. Only enforced * on the source chain. */ /// @dev This gets checked against block.timestamp. uint256 quoteExpiry; /// @notice The nonce used by this trader. uint256 nonce; /// @notice Unique identifier for the quote. /// @dev Generated off-chain via a distributed UUID generator. bytes32 txid; /** * @notice The address of the IHashflowXChainMessenger contract used for * cross-chain communication. */ address xChainMessenger; /// @notice Signature provided by the market maker (EIP-191). bytes signature; } /// @notice Used for Cross-Chain RFQ-M trades. struct XChainRFQMQuote { /// @notice The Hashflow Chain ID of the source chain. uint16 srcChainId; /// @notice The Hashflow Chain ID of the destination chain. uint16 dstChainId; /// @notice The address of the HashflowPool to trade against on the source chain. address srcPool; /// @notice The HashflowPool to disburse funds on the destination chain. /// @dev This is bytes32 in order to anticipate non-EVM chains. bytes32 dstPool; /** * @notice The external account linked to the HashflowPool on the source chain. * If the HashflowPool holds funds, this should be address(0). */ address srcExternalAccount; /** * @notice The external account linked to the HashflowPool on the destination chain. * If the HashflowPool holds funds, this should be bytes32(0). */ bytes32 dstExternalAccount; /// @notice The account that will be debited baseToken on the source chain. address trader; /// @notice The recipient of the quoteToken on the destination chain. bytes32 dstTrader; /// @notice The token that the trader sells on the source chain. address baseToken; /// @notice The token that the trader buys on the destination chain. bytes32 quoteToken; /// @notice The amount of baseToken sold. uint256 baseTokenAmount; /// @notice The amount of quoteToken bought. uint256 quoteTokenAmount; /** * @notice The Unix timestamp (in seconds) when the quote expire. Only enforced * on the source chain. */ /// @dev This gets checked against block.timestamp. uint256 quoteExpiry; /// @notice Unique identifier for the quote. /// @dev Generated off-chain via a distributed UUID generator. bytes32 txid; /** * @notice The address of the IHashflowXChainMessenger contract used for * cross-chain communication. */ address xChainMessenger; /// @notice Signature provided by the trader (EIP-712). bytes takerSignature; /// @notice Signature provided by the market maker (EIP-191). bytes makerSignature; } }
/** * SPDX-License-Identifier: UNLICENSED */ pragma solidity >=0.8.0; import './IHashflowXChainMessenger.sol'; interface IHashflowWormholeMessenger is IHashflowXChainMessenger { /// @notice Emitted when the Wormhole endpoint is updated. /// @param wormholeEndpoint The new Wormhole endpoint. /// @param prevWormholeEndpoint The old Wormhole endpoint. event UpdateWormholeEndpoint( address wormholeEndpoint, address prevWormholeEndpoint ); /// @notice Emitted when the Wormhole consistency level is updated. /// @param consistencyLevel The new consistencyLevel. event UpdateWormholeConsistencyLevel(uint256 consistencyLevel); /// @notice Emitted when the Wormhole fast consistency level is updated. /// @param consistencyLevel The new consistencyLevel. event UpdateWormholeConsistencyLevelFast(uint256 consistencyLevel); /// @notice Emitted when a Wormhole Chain ID is updated. /// @param hChainId The Hashflow Chain ID. /// @param wormholeChainId The Wormhole Chain ID. event UpdateWormholeChainId(uint256 hChainId, uint256 wormholeChainId); event UpdatePermissionedRelayer(uint16 hChainId, bytes32 relayer); /// @notice Emitted when a message is sent via Wormhole. /// @dev The sequence is used offline by the Relayer to fetch the VAA. event WormholeSend(bytes32 txid, uint256 value, uint256 sequence); /// @notice Emitted when a message is sent with fast consistency level. event WormholeSendFast(bytes32 txid, uint256 value, uint256 sequence); /// @notice Emitted when a Wormhole message is successfully received. event WormholeReceive(bytes32 txid); /// @notice Returns the currently set Wormhole endpoint. function wormholeEndpoint() external view returns (address); /// @notice Returns the currently set consistency level for Wormhole. function wormholeConsistencyLevel() external view returns (uint8); /// @notice Returns the currently set consistency level for Wormhole fast messages. function wormholeConsistencyLevelFast() external view returns (uint8); /// @notice Returns the associated Hashflow Chain ID to a Wormhole Chain ID. /// @param wormholeChainId The Wormhole Chain ID. function wormholeChainIdToHChainId(uint16 wormholeChainId) external view returns (uint16); /// @notice Returns the associated Wormhole Chain ID to a Hashflow Chain ID. /// @param hChainId The Hashflow Chain Id. function hChainIdToWormholeChainId(uint16 hChainId) external view returns (uint16); /// @notice Returns the currently set permissioned Relayer for a Hashflow Chain. /// @param hChainId The Hashflow Chain ID. function permissionedRelayers(uint16 hChainId) external view returns (bytes32); /// @notice Updates the Wormhole bridge endpoint. /// @param wormhole The new Wormhole bridge endpoint. function updateWormhole(address wormhole) external; /// @notice Updates the Wormhole consistency level. /// @param consistencyLevel The new consistency level. function updateWormholeConsistencyLevel(uint8 consistencyLevel) external; /// @notice Updates the Wormhole fast consistency level. /// @param consistencyLevel The new fast consistency level. function updateWormholeConsistencyLevelFast(uint8 consistencyLevel) external; /// @notice Updates the permissioned Relayer for a hashflow chain ID. /// @param hChainId The Hashflow Chain ID. /// @param relayer The permissioned Relayer. function updatePermissionedRelayer(uint16 hChainId, bytes32 relayer) external; /// @notice Receives a message sent via Wormhole. /// @param encodedVM the encoded Wormhole VAA. function wormholeReceive(bytes memory encodedVM) external; /// @notice Sets the Wormhole Chain ID for a Hashflow Chain ID. /// @param hChainId The Hashflow Chain ID. /// @param wormholeChainId The Wormhole Chain ID. function updateWormholeChainIdForHashflowChainId( uint16 hChainId, uint16 wormholeChainId ) external; }
/** * SPDX-License-Identifier: UNLICENSED */ pragma solidity >=0.8.0; /// @title IHashflowMessenger /// @author Victor Ionescu /** * @notice This interface should be implemented by any contract * that is to be used for X-Chain Message passing. */ interface IHashflowXChainMessenger { struct XChainQuote { uint16 srcChainId; uint16 dstChainId; address srcPool; bytes32 dstPool; address srcExternalAccount; bytes32 dstExternalAccount; address trader; bytes32 dstTrader; address baseToken; bytes32 quoteToken; uint256 baseTokenAmount; uint256 quoteTokenAmount; bytes32 txid; } struct XChainTradePayload { uint16 dstChainId; bytes32 txid; bytes32 srcPool; bytes32 dstPool; bytes32 dstExternalAccount; bytes32 quoteToken; bytes32 dstTrader; uint256 quoteTokenAmount; bytes32 permissionedRelayer; bytes32 srcCaller; bytes32 dstContract; bytes dstContractCalldata; } /// @notice Emitted when an associated IHashflowMessenger on a source chain changes. /// @param chainId The Hashflow Chain ID. /// @param remoteAddress The address of the remote, pre-padded to 32 bytes. event UpdateXChainRemoteAddress(uint16 chainId, bytes remoteAddress); /// @notice The Hashflow Chain ID for this chain. function hChainId() external view returns (uint16); /// @notice Returns the Hashflow Router. function router() external view returns (address); /// @notice Returns the registered remote for a Hashflow Chain ID. /// @param hChainId The foreign Hashflow Chain ID. function xChainRemotes(uint16 hChainId) external view returns (bytes memory); /// @notice Send X-Chain trade fill message. /// @param xChainQuote Quote object. /// @param caller The caller of the X-Chain trade. /// @param dstContract The contract to call on the destination chain. /// @param dstCalldata The calldata to pass to the contract. function tradeXChain( XChainQuote memory xChainQuote, address caller, bytes32 dstContract, bytes memory dstCalldata ) external payable; /// @notice Updates the associated IHashflowMessenger address on a different chain. /// @param hChainId The Hashflow Chain ID of the peer chain. /// @param remoteAddress The address of the IHashflowMessenger on the peer chain. function updateXChainRemoteAddress( uint16 hChainId, bytes calldata remoteAddress ) external; /// @notice Withdraws excess fees to the owner. function withdrawFunds() external; }
/** * SPDX-License-Identifier: UNLICENSED */ pragma solidity 0.8.18; import '@openzeppelin/contracts/access/Ownable2Step.sol'; import '@openzeppelin/contracts/utils/Address.sol'; import '../interfaces/xchain/IHashflowXChainMessenger.sol'; abstract contract HashflowXChainMessengerBase is IHashflowXChainMessenger, Ownable2Step { using Address for address payable; uint16 public immutable hChainId; address public immutable router; mapping(uint16 => bytes) public xChainRemotes; constructor(uint16 _hChainId, address _router) { require( _hChainId != 0, 'HashflowXChainMessengerBase::constructor Hashflow Chain ID cannot be 0.' ); require( _router != address(0), 'HashflowXChainMessengerBase::constructor Router cannot be 0 address.' ); hChainId = _hChainId; router = _router; } /// @inheritdoc IHashflowXChainMessenger function updateXChainRemoteAddress( uint16 _hChainId, bytes calldata remoteAddress ) external override onlyOwner { xChainRemotes[_hChainId] = remoteAddress; emit UpdateXChainRemoteAddress(_hChainId, remoteAddress); } /// @inheritdoc IHashflowXChainMessenger function withdrawFunds() external onlyOwner { payable(_msgSender()).sendValue(address(this).balance); } function _generateTradePayload( XChainQuote memory quote, address caller, bytes32 permissionedRelayer, bytes32 dstContract, bytes memory dstContractCalldata ) internal pure returns (bytes memory) { XChainTradePayload memory pld; pld.dstChainId = quote.dstChainId; pld.txid = quote.txid; pld.srcPool = bytes32(uint256(uint160(quote.srcPool))); pld.dstPool = quote.dstPool; pld.dstExternalAccount = quote.dstExternalAccount; pld.quoteToken = quote.quoteToken; pld.dstTrader = quote.dstTrader; pld.quoteTokenAmount = quote.quoteTokenAmount; pld.permissionedRelayer = permissionedRelayer; pld.srcCaller = bytes32(uint256(uint160(caller))); pld.dstContract = dstContract; pld.dstContractCalldata = dstContractCalldata; return abi.encode(pld); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint16","name":"_hChainId","type":"uint16"},{"internalType":"address","name":"_router","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"hChainId","type":"uint16"},{"indexed":false,"internalType":"bytes32","name":"relayer","type":"bytes32"}],"name":"UpdatePermissionedRelayer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"hChainId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"wormholeChainId","type":"uint256"}],"name":"UpdateWormholeChainId","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"consistencyLevel","type":"uint256"}],"name":"UpdateWormholeConsistencyLevel","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"consistencyLevel","type":"uint256"}],"name":"UpdateWormholeConsistencyLevelFast","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"wormholeEndpoint","type":"address"},{"indexed":false,"internalType":"address","name":"prevWormholeEndpoint","type":"address"}],"name":"UpdateWormholeEndpoint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"chainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"remoteAddress","type":"bytes"}],"name":"UpdateXChainRemoteAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"txid","type":"bytes32"}],"name":"WormholeReceive","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"txid","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sequence","type":"uint256"}],"name":"WormholeSend","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"txid","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sequence","type":"uint256"}],"name":"WormholeSendFast","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hChainId","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"hChainIdToWormholeChainId","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"permissionedRelayers","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"srcChainId","type":"uint16"},{"internalType":"uint16","name":"dstChainId","type":"uint16"},{"internalType":"address","name":"srcPool","type":"address"},{"internalType":"bytes32","name":"dstPool","type":"bytes32"},{"internalType":"address","name":"srcExternalAccount","type":"address"},{"internalType":"bytes32","name":"dstExternalAccount","type":"bytes32"},{"internalType":"address","name":"trader","type":"address"},{"internalType":"bytes32","name":"dstTrader","type":"bytes32"},{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"bytes32","name":"quoteToken","type":"bytes32"},{"internalType":"uint256","name":"baseTokenAmount","type":"uint256"},{"internalType":"uint256","name":"quoteTokenAmount","type":"uint256"},{"internalType":"bytes32","name":"txid","type":"bytes32"}],"internalType":"struct IHashflowXChainMessenger.XChainQuote","name":"quote","type":"tuple"},{"internalType":"address","name":"caller","type":"address"},{"internalType":"bytes32","name":"dstContract","type":"bytes32"},{"internalType":"bytes","name":"dstCalldata","type":"bytes"}],"name":"tradeXChain","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_hChainId","type":"uint16"},{"internalType":"bytes32","name":"relayer","type":"bytes32"}],"name":"updatePermissionedRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wormhole","type":"address"}],"name":"updateWormhole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"hashflowChainId","type":"uint16"},{"internalType":"uint16","name":"wormholeChainId","type":"uint16"}],"name":"updateWormholeChainIdForHashflowChainId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"consistencyLevel","type":"uint8"}],"name":"updateWormholeConsistencyLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"consistencyLevel","type":"uint8"}],"name":"updateWormholeConsistencyLevelFast","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_hChainId","type":"uint16"},{"internalType":"bytes","name":"remoteAddress","type":"bytes"}],"name":"updateXChainRemoteAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"wormholeChainIdToHChainId","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wormholeConsistencyLevel","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wormholeConsistencyLevelFast","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wormholeEndpoint","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedVM","type":"bytes"}],"name":"wormholeReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"xChainRemotes","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60c06040523480156200001157600080fd5b5060405162002e7038038062002e708339810160408190526200003491620001d7565b818162000041336200015d565b8161ffff16600003620000c05760405162461bcd60e51b8152602060048201526047602482015260008051602062002e5083398151915260448201527f7374727563746f722048617368666c6f7720436861696e2049442063616e6e6f6064820152663a10313290181760c91b608482015260a4015b60405180910390fd5b6001600160a01b0381166200013b5760405162461bcd60e51b81526020600482015260446024820181905260008051602062002e50833981519152908201527f7374727563746f7220526f757465722063616e6e6f742062652030206164647260648201526332b9b99760e11b608482015260a401620000b7565b61ffff9091166080526001600160a01b031660a0525050600160035562000227565b600180546001600160a01b0319169055620001848162000187602090811b620016f017901c565b50565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060408385031215620001eb57600080fd5b825161ffff81168114620001fe57600080fd5b60208401519092506001600160a01b03811681146200021c57600080fd5b809150509250929050565b60805160a051612be06200027060003960008181610490015281816112eb015261149701526000818161036d015281816107bf01528181610dec01526115340152612be06000f3fe6080604052600436106101445760003560e01c8063ae4dd35d116100b6578063da118ff81161006f578063da118ff8146103cf578063e30c397814610400578063eed9214c1461041e578063f2fde38b14610431578063f310dfa814610451578063f887ea401461047e57600080fd5b8063ae4dd35d146102df578063af8dd410146102ff578063bd6f3d5714610320578063c07cddfc1461035b578063c60280271461038f578063cdf0ae76146103af57600080fd5b8063758cf42c11610108578063758cf42c146101f457806379ba50971461021457806381eae0a414610229578063885580e5146102495780638da5cb5b1461028d578063ad47f57d146102bf57600080fd5b8063230118481461015057806324600fc3146101725780632b447401146101875780636c4d3b96146101a7578063715018a6146101df57600080fd5b3661014b57005b600080fd5b34801561015c57600080fd5b5061017061016b366004611f4e565b6104b2565b005b34801561017e57600080fd5b50610170610519565b34801561019357600080fd5b506101706101a2366004611fd2565b61052d565b3480156101b357600080fd5b506004546101c890600160a01b900460ff1681565b60405160ff90911681526020015b60405180910390f35b3480156101eb57600080fd5b50610170610728565b34801561020057600080fd5b5061017061020f36600461200b565b6107b5565b34801561022057600080fd5b5061017061093c565b34801561023557600080fd5b50610170610244366004612046565b6109b6565b34801561025557600080fd5b5061027a61026436600461206a565b60066020526000908152604090205461ffff1681565b60405161ffff90911681526020016101d6565b34801561029957600080fd5b506000546001600160a01b03165b6040516001600160a01b0390911681526020016101d6565b3480156102cb57600080fd5b506101706102da366004612046565b610aa3565b3480156102eb57600080fd5b506004546102a7906001600160a01b031681565b34801561030b57600080fd5b506004546101c890600160a81b900460ff1681565b34801561032c57600080fd5b5061034d61033b36600461206a565b60076020526000908152604090205481565b6040519081526020016101d6565b34801561036757600080fd5b5061027a7f000000000000000000000000000000000000000000000000000000000000000081565b34801561039b57600080fd5b506101706103aa3660046121db565b610b89565b3480156103bb57600080fd5b506101706103ca36600461222e565b6113a0565b3480156103db57600080fd5b5061027a6103ea36600461206a565b60056020526000908152604090205461ffff1681565b34801561040c57600080fd5b506001546001600160a01b03166102a7565b61017061042c366004612249565b611494565b34801561043d57600080fd5b5061017061044c36600461222e565b6115e5565b34801561045d57600080fd5b5061047161046c36600461206a565b611656565b6040516101d691906123c4565b34801561048a57600080fd5b506102a77f000000000000000000000000000000000000000000000000000000000000000081565b6104ba611740565b61ffff831660009081526002602052604090206104d882848361245f565b507fadbf43a98b12e14ff175a053f107b2637a94e9a262ea9222a4417141c7b069b783838360405161050c9392919061251f565b60405180910390a1505050565b610521611740565b61052b334761179a565b565b610535611740565b61ffff82161580159061054b575061ffff811615155b6105d65760405162461bcd60e51b81526020600482015260576024820152600080516020612b6b83398151915260448201527f65576f726d686f6c65436861696e4964466f7248617368666c6f77436861696e60648201527f496420636861696e49642063616e6e6f7420626520302e000000000000000000608482015260a4015b60405180910390fd5b61ffff80821660009081526006602052604090205416156106825760405162461bcd60e51b81526020600482015260666024820152600080516020612b6b83398151915260448201527f65576f726d686f6c65436861696e4964466f7248617368666c6f77436861696e60648201527f496420576f726d686f6c6520436861696e20494420616c72656164792061737360848201526534b3b732b21760d11b60a482015260c4016105cd565b61ffff8083166000908152600560205260409020541680156106bb5761ffff81166000908152600660205260409020805461ffff191690555b61ffff8381166000818152600560209081526040808320805495881661ffff19968716811790915580845260068352928190208054909516841790945583519283528201527f62b70d50d9a46e5f93d9a7c011107721ad2165202e8dc3dcdb29437331a7f6c2910161050c565b610730611740565b60405162461bcd60e51b815260206004820152604e60248201527f48617368666c6f77576f726d686f6c654d657373656e6765723a3a72656e6f7560448201527f6e63654f776e6572736869702052656e6f756e63696e67206f776e657273686960648201526d38103737ba1030b63637bbb2b21760911b608482015260a4016105cd565b6107bd611740565b7f000000000000000000000000000000000000000000000000000000000000000061ffff168261ffff160361086e5760405162461bcd60e51b815260206004820152605a6024820152600080516020612b6b83398151915260448201527f655065726d697373696f6e656452656c617965722043616e6e6f74207570646160648201527f74652072656c6179657220666f722073616d6520636861696e2e000000000000608482015260a4016105cd565b806108e95760405162461bcd60e51b81526020600482015260516024820152600080516020612b6b83398151915260448201527f655065726d697373696f6e656452656c617965722052656c61796572206164646064820152703932b9b99031b0b73737ba10313290181760791b608482015260a4016105cd565b61ffff8216600081815260076020908152604091829020849055815192835282018390527f4c30136e54c9530459b002e4388bc9574f7ad6129ce7eae27c5b284b6eff301a910160405180910390a15050565b60015433906001600160a01b031681146109aa5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016105cd565b6109b3816118b8565b50565b6109be611740565b8060ff16600003610a4b5760405162461bcd60e51b815260206004820152605c6024820152600080516020612b6b83398151915260448201527f65576f726d686f6c65436f6e73697374656e63794c6576656c4661737420436f60648201527f6e73697374656e6379206c6576656c2063616e6e6f7420626520302e00000000608482015260a4016105cd565b6004805460ff60a81b1916600160a81b60ff8481168202929092179283905560405192041681527f38710bc268b11f2d90804ed3e31fc26a9dfc388a69fcc101e14c2c0cf6856868906020015b60405180910390a150565b610aab611740565b8060ff16600003610b385760405162461bcd60e51b81526020600482015260586024820152600080516020612b6b83398151915260448201527f65576f726d686f6c65436f6e73697374656e63794c6576656c20436f6e73697360648201527f74656e6379206c6576656c2063616e6e6f7420626520302e0000000000000000608482015260a4016105cd565b6004805460ff60a01b1916600160a01b60ff8481168202929092179283905560405192041681527f08d353f374af01b976f218707acddbc799efd3730d4ae1a84e1b3288bb80000990602001610a98565b610b916118d1565b6004805460405163607ec5ef60e11b8152600092839283926001600160a01b039091169163c0fd8bde91610bc7918891016123c4565b600060405180830381865afa158015610be4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c0c91908101906126b8565b925092509250818190610c325760405162461bcd60e51b81526004016105cd91906123c4565b50606083015161ffff90811660009081526006602052604081205490911690819003610cb6576040805162461bcd60e51b8152602060048201526024810191909152600080516020612b8b83398151915260448201527f6f6c655265636569766520496e76616c696420736f7572636520636861696e2e60648201526084016105cd565b61ffff811660009081526002602052604081208054610cd4906123d7565b610ce091506020612825565b610ceb90600861283e565b61ffff83166000908152600260205260409020610d0790612855565b6080870151911c91508114610d725760405162461bcd60e51b815260206004820152603f6024820152600080516020612b8b83398151915260448201527f6f6c655265636569766520556e617574686f72697a65642072656d6f74652e0060648201526084016105cd565b60008560e00151806020019051810190610d8c9190612896565b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082018390526101208201929092526101408101919091529091507f000000000000000000000000000000000000000000000000000000000000000061ffff16826000015161ffff1614610e895760405162461bcd60e51b81526020600482015260476024820152600080516020612b8b83398151915260448201527f6f6c655265636569766520496e636f72726563742064657374696e6174696f6e6064820152661031b430b4b71760c91b608482015260a4016105cd565b61010082015115610f9c576101008201516001600160a01b03811614610f205760405162461bcd60e51b81526020600482015260526024820152600080516020612b8b83398151915260448201527f6f6c6552656365697665207065726d697373696f6e656452656c61796572206960648201527139903737ba1022ab269030b2323932b9b99760711b608482015260a4016105cd565b6101008201516001600160a01b03163314610f9c5760405162461bcd60e51b81526020600482015260426024820152600080516020612b8b83398151915260448201527f6f6c65526563656976652052656c61796572206e6f7420617574686f72697a65606482015261321760f11b608482015260a4016105cd565b60608201516001600160a01b0381161461101b5760405162461bcd60e51b81526020600482015260466024820152600080516020612b8b83398151915260448201527f6f6c655265636569766520647374506f6f6c206973206e6f742045564d206164606482015265323932b9b99760d11b608482015260a4016105cd565b60808201516001600160a01b038116146110a55760405162461bcd60e51b81526020600482015260516024820152600080516020612b8b83398151915260448201527f6f6c65526563656976652064737445787465726e616c4163636f756e74206973606482015270103737ba1022ab269030b2323932b9b99760791b608482015260a4016105cd565b60c08201516001600160a01b038116146111265760405162461bcd60e51b81526020600482015260486024820152600080516020612b8b83398151915260448201527f6f6c655265636569766520647374547261646572206973206e6f742045564d2060648201526730b2323932b9b99760c11b608482015260a4016105cd565b60a08201516001600160a01b038116146111a85760405162461bcd60e51b81526020600482015260496024820152600080516020612b8b83398151915260448201527f6f6c65526563656976652071756f7465546f6b656e206973206e6f742045564d6064820152681030b2323932b9b99760b91b608482015260a4016105cd565b61ffff841681526040808301516020808401919091526060808501516001600160a01b039081169385019390935260808086015184169185019190915260c08086015184169185019190915260a0808601519093169284019290925260e0808501519284019290925283015190820152610120820151610100820152610140820151156112d4576101408201516001600160a01b038116146112b35760405162461bcd60e51b815260206004820152604a6024820152600080516020612b8b83398151915260448201527f6f6c655265636569766520647374436f6e7472616374206973206e6f74204556606482015269269030b2323932b9b99760b11b608482015260a4016105cd565b610140808301516001600160a01b0316610120830152610160830151908201525b604051630c02799960e41b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c027999090611320908490600401612982565b600060405180830381600087803b15801561133a57600080fd5b505af115801561134e573d6000803e3d6000fd5b505050507fdaa359c534878df499fed928ebd547efd9ab9cad42c0200a4deb8bec55dea0128160e0015160405161138791815260200190565b60405180910390a1505050505050506109b36001600355565b6113a8611740565b6001600160a01b0381163b61142b5760405162461bcd60e51b815260206004820152604f6024820152600080516020612b6b83398151915260448201527f65576f726d686f6c6520576f726d686f6c6520656e64706f696e74206d75737460648201526e10313290309031b7b73a3930b1ba1760891b608482015260a4016105cd565b600454604080516001600160a01b03808516825290921660208301527f41bc02113522bf9d1c5b2fa77fd65106307a6a90648c65230404710ce6d74c99910160405180910390a1600480546001600160a01b0319166001600160a01b0392909216919091179055565b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146115325760405162461bcd60e51b815260206004820152603d60248201527f48617368666c6f77576f726d686f6c654d657373656e6765723a3a747261646560448201527f58436861696e2053656e646572206d75737420626520726f757465722e00000060648201526084016105cd565b7f000000000000000000000000000000000000000000000000000000000000000061ffff16846000015161ffff16146115d35760405162461bcd60e51b815260206004820152603c60248201527f48617368666c6f77576f726d686f6c654d657373656e6765723a3a747261646560448201527f58436861696e20496e636f727265637420737263436861696e49642e0000000060648201526084016105cd565b6115df8484848461192a565b50505050565b6115ed611740565b600180546001600160a01b0383166001600160a01b0319909116811790915561161e6000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6002602052600090815260409020805461166f906123d7565b80601f016020809104026020016040519081016040528092919081815260200182805461169b906123d7565b80156116e85780601f106116bd576101008083540402835291602001916116e8565b820191906000526020600020905b8154815290600101906020018083116116cb57829003601f168201915b505050505081565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000546001600160a01b0316331461052b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105cd565b804710156117ea5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016105cd565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611837576040519150601f19603f3d011682016040523d82523d6000602084013e61183c565b606091505b50509050806118b35760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016105cd565b505050565b600180546001600160a01b03191690556109b3816116f0565b6002600354036119235760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016105cd565b6002600355565b6000600460009054906101000a90046001600160a01b03166001600160a01b0316631a90a2196040518163ffffffff1660e01b8152600401602060405180830381865afa15801561197f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a39190612a59565b6004549091508190600160a81b900460ff16158015906119da575060208087015161ffff1660009081526007909152604090205415155b156119ed576119ea81600261283e565b90505b80341015611a715760405162461bcd60e51b8152602060048201526044602482018190527f48617368666c6f77576f726d686f6c654d657373656e6765723a3a5f776f726d908201527f686f6c6553656e6420496e73756666696369656e7420576f726d686f6c65206660648201526332b2b99760e11b608482015260a4016105cd565b60208087015161ffff90811660009081526005909252604090912054168015801590611abf575060208088015161ffff1660009081526002909152604081208054611abb906123d7565b9050115b611b4f5760405162461bcd60e51b815260206004820152605560248201527f48617368666c6f77576f726d686f6c654d657373656e6765723a3a5f776f726d60448201527f686f6c6553656e6420576f726d686f6c652064657374696e6174696f6e206368606482015274185a5b881251081b9bdd0818dbdb999a59dd5c9959605a1b608482015260a4016105cd565b600454600160a01b900460ff16600003611bdd5760405162461bcd60e51b815260206004820152604360248201527f48617368666c6f77576f726d686f6c654d657373656e6765723a3a5f776f726d60448201527f686f6c6553656e6420436f6e73697374656e6379206c6576656c206e6f74207360648201526232ba1760e91b608482015260a4016105cd565b6000611bec8888838989611e21565b600480546040516358cd21bf60e11b81529293506000926001600160a01b0382169263b19a437e928992611c309287928992600160a01b90910460ff169101612a72565b60206040518083038185885af1158015611c4e573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611c739190612aa4565b6001600160401b031690507f5226e00d4650d3a00a0cc6446dfafdd1a8f825a3a6c7396eb5ccfcf737190d1a8961018001518534611cb19190612825565b604080519283526020830191909152810183905260600160405180910390a15050600454600160a81b900460ff1615801590611d04575060208088015161ffff1660009081526007909152604090205415155b15611e185760208088015161ffff16600090815260079091526040812054611d3190899089908989611e21565b600480546040516358cd21bf60e11b81529293506000926001600160a01b0382169263b19a437e928992611d759287928992600160a81b90910460ff169101612a72565b60206040518083038185885af1158015611d93573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611db89190612aa4565b6001600160401b031690507f4264a0964b8918276a33db4ae2c82c7a9a0a85f60afed61592141470235b88278961018001518534611df69190612825565b604080519283526020830191909152810183905260600160405180910390a150505b50505050505050565b604080516101808101825260008082526020820181905291810182905260608181018390526080820183905260a0820183905260c0820183905260e0820183905261010082018390526101208201839052610140820192909252610160810182905260208088015161ffff168252610180880151828201526040808901516001600160a01b03908116828501526060808b01519085015260a0808b01516080860152610120808c01519186019190915260e0808c015160c0870152610160808d01519187019190915261010086018a9052918a16908501526101408401879052830185905251611f1391839101612abf565b60405160208183030381529060405291505095945050505050565b61ffff811681146109b357600080fd5b8035611f4981611f2e565b919050565b600080600060408486031215611f6357600080fd5b8335611f6e81611f2e565b925060208401356001600160401b0380821115611f8a57600080fd5b818601915086601f830112611f9e57600080fd5b813581811115611fad57600080fd5b876020828501011115611fbf57600080fd5b6020830194508093505050509250925092565b60008060408385031215611fe557600080fd5b8235611ff081611f2e565b9150602083013561200081611f2e565b809150509250929050565b6000806040838503121561201e57600080fd5b823561202981611f2e565b946020939093013593505050565b60ff811681146109b357600080fd5b60006020828403121561205857600080fd5b813561206381612037565b9392505050565b60006020828403121561207c57600080fd5b813561206381611f2e565b634e487b7160e01b600052604160045260246000fd5b6040516101a081016001600160401b03811182821017156120c0576120c0612087565b60405290565b604051608081016001600160401b03811182821017156120c0576120c0612087565b60405161016081016001600160401b03811182821017156120c0576120c0612087565b60405161018081016001600160401b03811182821017156120c0576120c0612087565b604051601f8201601f191681016001600160401b038111828210171561215657612156612087565b604052919050565b60006001600160401b0382111561217757612177612087565b50601f01601f191660200190565b600082601f83011261219657600080fd5b81356121a96121a48261215e565b61212e565b8181528460208386010111156121be57600080fd5b816020850160208301376000918101602001919091529392505050565b6000602082840312156121ed57600080fd5b81356001600160401b0381111561220357600080fd5b61220f84828501612185565b949350505050565b80356001600160a01b0381168114611f4957600080fd5b60006020828403121561224057600080fd5b61206382612217565b60008060008084860361020081121561226157600080fd5b6101a08082121561227157600080fd5b61227961209d565b915061228487611f3e565b825261229260208801611f3e565b60208301526122a360408801612217565b6040830152606087013560608301526122be60808801612217565b608083015260a087013560a08301526122d960c08801612217565b60c083015260e087013560e08301526101006122f6818901612217565b9083015261012087810135908301526101408088013590830152610160808801359083015261018080880135908301529094508490612336818801612217565b945050506101c085013591506101e08501356001600160401b0381111561235c57600080fd5b61236887828801612185565b91505092959194509250565b60005b8381101561238f578181015183820152602001612377565b50506000910152565b600081518084526123b0816020860160208601612374565b601f01601f19169290920160200192915050565b6020815260006120636020830184612398565b600181811c908216806123eb57607f821691505b60208210810361240b57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156118b357600081815260208120601f850160051c810160208610156124385750805b601f850160051c820191505b8181101561245757828155600101612444565b505050505050565b6001600160401b0383111561247657612476612087565b61248a8361248483546123d7565b83612411565b6000601f8411600181146124be57600085156124a65750838201355b600019600387901b1c1916600186901b178355612518565b600083815260209020601f19861690835b828110156124ef57868501358255602094850194600190920191016124cf565b508682101561250c5760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b61ffff8416815260406020820152816040820152818360608301376000818301606090810191909152601f909201601f1916010192915050565b8051611f4981612037565b805163ffffffff81168114611f4957600080fd5b8051611f4981611f2e565b80516001600160401b0381168114611f4957600080fd5b600082601f8301126125ab57600080fd5b81516125b96121a48261215e565b8181528460208386010111156125ce57600080fd5b61220f826020830160208701612374565b600082601f8301126125f057600080fd5b815160206001600160401b0382111561260b5761260b612087565b612619818360051b0161212e565b82815260079290921b8401810191818101908684111561263857600080fd5b8286015b8481101561269d57608081890312156126555760008081fd5b61265d6120c6565b81518152848201518582015260408083015161267881612037565b9082015260608281015161268b81612037565b9082015283529183019160800161263c565b509695505050505050565b80518015158114611f4957600080fd5b6000806000606084860312156126cd57600080fd5b83516001600160401b03808211156126e457600080fd5b9085019061016082880312156126f957600080fd5b6127016120e8565b61270a83612559565b815261271860208401612564565b602082015261272960408401612564565b604082015261273a60608401612578565b60608201526080830151608082015261275560a08401612583565b60a082015261276660c08401612559565b60c082015260e08301518281111561277d57600080fd5b6127898982860161259a565b60e08301525061010061279d818501612564565b9082015261012083810151838111156127b557600080fd5b6127c18a8287016125df565b9183019190915250610140838101519082015294506127e2602087016126a8565b935060408601519150808211156127f857600080fd5b506128058682870161259a565b9150509250925092565b634e487b7160e01b600052601160045260246000fd5b818103818111156128385761283861280f565b92915050565b80820281158282048414176128385761283861280f565b600061286182546123d7565b82601f8211156128775783600052602060002090505b549150602081101561240b5760001960209190910360031b1b16919050565b6000602082840312156128a857600080fd5b81516001600160401b03808211156128bf57600080fd5b9083019061018082860312156128d457600080fd5b6128dc61210b565b6128e583612578565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120808401518183015250610140808401518183015250610160808401518381111561296557600080fd5b6129718882870161259a565b918301919091525095945050505050565b6020815261299760208201835161ffff169052565b60208201516040820152600060408301516129bd60608401826001600160a01b03169052565b5060608301516001600160a01b03811660808401525060808301516001600160a01b03811660a08401525060a08301516001600160a01b03811660c08401525060c083015160e0838101919091528301516101008084019190915283015161012080840191909152830151610140612a3f818501836001600160a01b03169052565b84015161016084810152905061220f610180840182612398565b600060208284031215612a6b57600080fd5b5051919050565b63ffffffff84168152606060208201526000612a916060830185612398565b905060ff83166040830152949350505050565b600060208284031215612ab657600080fd5b61206382612583565b60208152612ad460208201835161ffff169052565b602082015160408201526040820151606082015260608201516080820152608082015160a082015260a082015160c082015260c082015160e0820152600060e083015161010081818501528085015191505061012081818501528085015191505061014081818501528085015191505061016081818501528085015191505061018080818501525061220f6101a084018261239856fe48617368666c6f77576f726d686f6c654d657373656e6765723a3a757064617448617368666c6f77576f726d686f6c654d657373656e6765723a3a776f726d68a264697066735822122018de9436877a602ff264a3f0b38674c4e4f1e91b0d8994d668be4a8c8d945c6264736f6c6343000812003348617368666c6f7758436861696e4d657373656e676572426173653a3a636f6e000000000000000000000000000000000000000000000000000000000000000100000000000000000000000055084ee0fef03f14a305cd24286359a35d735151
Deployed Bytecode
0x6080604052600436106101445760003560e01c8063ae4dd35d116100b6578063da118ff81161006f578063da118ff8146103cf578063e30c397814610400578063eed9214c1461041e578063f2fde38b14610431578063f310dfa814610451578063f887ea401461047e57600080fd5b8063ae4dd35d146102df578063af8dd410146102ff578063bd6f3d5714610320578063c07cddfc1461035b578063c60280271461038f578063cdf0ae76146103af57600080fd5b8063758cf42c11610108578063758cf42c146101f457806379ba50971461021457806381eae0a414610229578063885580e5146102495780638da5cb5b1461028d578063ad47f57d146102bf57600080fd5b8063230118481461015057806324600fc3146101725780632b447401146101875780636c4d3b96146101a7578063715018a6146101df57600080fd5b3661014b57005b600080fd5b34801561015c57600080fd5b5061017061016b366004611f4e565b6104b2565b005b34801561017e57600080fd5b50610170610519565b34801561019357600080fd5b506101706101a2366004611fd2565b61052d565b3480156101b357600080fd5b506004546101c890600160a01b900460ff1681565b60405160ff90911681526020015b60405180910390f35b3480156101eb57600080fd5b50610170610728565b34801561020057600080fd5b5061017061020f36600461200b565b6107b5565b34801561022057600080fd5b5061017061093c565b34801561023557600080fd5b50610170610244366004612046565b6109b6565b34801561025557600080fd5b5061027a61026436600461206a565b60066020526000908152604090205461ffff1681565b60405161ffff90911681526020016101d6565b34801561029957600080fd5b506000546001600160a01b03165b6040516001600160a01b0390911681526020016101d6565b3480156102cb57600080fd5b506101706102da366004612046565b610aa3565b3480156102eb57600080fd5b506004546102a7906001600160a01b031681565b34801561030b57600080fd5b506004546101c890600160a81b900460ff1681565b34801561032c57600080fd5b5061034d61033b36600461206a565b60076020526000908152604090205481565b6040519081526020016101d6565b34801561036757600080fd5b5061027a7f000000000000000000000000000000000000000000000000000000000000000181565b34801561039b57600080fd5b506101706103aa3660046121db565b610b89565b3480156103bb57600080fd5b506101706103ca36600461222e565b6113a0565b3480156103db57600080fd5b5061027a6103ea36600461206a565b60056020526000908152604090205461ffff1681565b34801561040c57600080fd5b506001546001600160a01b03166102a7565b61017061042c366004612249565b611494565b34801561043d57600080fd5b5061017061044c36600461222e565b6115e5565b34801561045d57600080fd5b5061047161046c36600461206a565b611656565b6040516101d691906123c4565b34801561048a57600080fd5b506102a77f00000000000000000000000055084ee0fef03f14a305cd24286359a35d73515181565b6104ba611740565b61ffff831660009081526002602052604090206104d882848361245f565b507fadbf43a98b12e14ff175a053f107b2637a94e9a262ea9222a4417141c7b069b783838360405161050c9392919061251f565b60405180910390a1505050565b610521611740565b61052b334761179a565b565b610535611740565b61ffff82161580159061054b575061ffff811615155b6105d65760405162461bcd60e51b81526020600482015260576024820152600080516020612b6b83398151915260448201527f65576f726d686f6c65436861696e4964466f7248617368666c6f77436861696e60648201527f496420636861696e49642063616e6e6f7420626520302e000000000000000000608482015260a4015b60405180910390fd5b61ffff80821660009081526006602052604090205416156106825760405162461bcd60e51b81526020600482015260666024820152600080516020612b6b83398151915260448201527f65576f726d686f6c65436861696e4964466f7248617368666c6f77436861696e60648201527f496420576f726d686f6c6520436861696e20494420616c72656164792061737360848201526534b3b732b21760d11b60a482015260c4016105cd565b61ffff8083166000908152600560205260409020541680156106bb5761ffff81166000908152600660205260409020805461ffff191690555b61ffff8381166000818152600560209081526040808320805495881661ffff19968716811790915580845260068352928190208054909516841790945583519283528201527f62b70d50d9a46e5f93d9a7c011107721ad2165202e8dc3dcdb29437331a7f6c2910161050c565b610730611740565b60405162461bcd60e51b815260206004820152604e60248201527f48617368666c6f77576f726d686f6c654d657373656e6765723a3a72656e6f7560448201527f6e63654f776e6572736869702052656e6f756e63696e67206f776e657273686960648201526d38103737ba1030b63637bbb2b21760911b608482015260a4016105cd565b6107bd611740565b7f000000000000000000000000000000000000000000000000000000000000000161ffff168261ffff160361086e5760405162461bcd60e51b815260206004820152605a6024820152600080516020612b6b83398151915260448201527f655065726d697373696f6e656452656c617965722043616e6e6f74207570646160648201527f74652072656c6179657220666f722073616d6520636861696e2e000000000000608482015260a4016105cd565b806108e95760405162461bcd60e51b81526020600482015260516024820152600080516020612b6b83398151915260448201527f655065726d697373696f6e656452656c617965722052656c61796572206164646064820152703932b9b99031b0b73737ba10313290181760791b608482015260a4016105cd565b61ffff8216600081815260076020908152604091829020849055815192835282018390527f4c30136e54c9530459b002e4388bc9574f7ad6129ce7eae27c5b284b6eff301a910160405180910390a15050565b60015433906001600160a01b031681146109aa5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016105cd565b6109b3816118b8565b50565b6109be611740565b8060ff16600003610a4b5760405162461bcd60e51b815260206004820152605c6024820152600080516020612b6b83398151915260448201527f65576f726d686f6c65436f6e73697374656e63794c6576656c4661737420436f60648201527f6e73697374656e6379206c6576656c2063616e6e6f7420626520302e00000000608482015260a4016105cd565b6004805460ff60a81b1916600160a81b60ff8481168202929092179283905560405192041681527f38710bc268b11f2d90804ed3e31fc26a9dfc388a69fcc101e14c2c0cf6856868906020015b60405180910390a150565b610aab611740565b8060ff16600003610b385760405162461bcd60e51b81526020600482015260586024820152600080516020612b6b83398151915260448201527f65576f726d686f6c65436f6e73697374656e63794c6576656c20436f6e73697360648201527f74656e6379206c6576656c2063616e6e6f7420626520302e0000000000000000608482015260a4016105cd565b6004805460ff60a01b1916600160a01b60ff8481168202929092179283905560405192041681527f08d353f374af01b976f218707acddbc799efd3730d4ae1a84e1b3288bb80000990602001610a98565b610b916118d1565b6004805460405163607ec5ef60e11b8152600092839283926001600160a01b039091169163c0fd8bde91610bc7918891016123c4565b600060405180830381865afa158015610be4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c0c91908101906126b8565b925092509250818190610c325760405162461bcd60e51b81526004016105cd91906123c4565b50606083015161ffff90811660009081526006602052604081205490911690819003610cb6576040805162461bcd60e51b8152602060048201526024810191909152600080516020612b8b83398151915260448201527f6f6c655265636569766520496e76616c696420736f7572636520636861696e2e60648201526084016105cd565b61ffff811660009081526002602052604081208054610cd4906123d7565b610ce091506020612825565b610ceb90600861283e565b61ffff83166000908152600260205260409020610d0790612855565b6080870151911c91508114610d725760405162461bcd60e51b815260206004820152603f6024820152600080516020612b8b83398151915260448201527f6f6c655265636569766520556e617574686f72697a65642072656d6f74652e0060648201526084016105cd565b60008560e00151806020019051810190610d8c9190612896565b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082018390526101208201929092526101408101919091529091507f000000000000000000000000000000000000000000000000000000000000000161ffff16826000015161ffff1614610e895760405162461bcd60e51b81526020600482015260476024820152600080516020612b8b83398151915260448201527f6f6c655265636569766520496e636f72726563742064657374696e6174696f6e6064820152661031b430b4b71760c91b608482015260a4016105cd565b61010082015115610f9c576101008201516001600160a01b03811614610f205760405162461bcd60e51b81526020600482015260526024820152600080516020612b8b83398151915260448201527f6f6c6552656365697665207065726d697373696f6e656452656c61796572206960648201527139903737ba1022ab269030b2323932b9b99760711b608482015260a4016105cd565b6101008201516001600160a01b03163314610f9c5760405162461bcd60e51b81526020600482015260426024820152600080516020612b8b83398151915260448201527f6f6c65526563656976652052656c61796572206e6f7420617574686f72697a65606482015261321760f11b608482015260a4016105cd565b60608201516001600160a01b0381161461101b5760405162461bcd60e51b81526020600482015260466024820152600080516020612b8b83398151915260448201527f6f6c655265636569766520647374506f6f6c206973206e6f742045564d206164606482015265323932b9b99760d11b608482015260a4016105cd565b60808201516001600160a01b038116146110a55760405162461bcd60e51b81526020600482015260516024820152600080516020612b8b83398151915260448201527f6f6c65526563656976652064737445787465726e616c4163636f756e74206973606482015270103737ba1022ab269030b2323932b9b99760791b608482015260a4016105cd565b60c08201516001600160a01b038116146111265760405162461bcd60e51b81526020600482015260486024820152600080516020612b8b83398151915260448201527f6f6c655265636569766520647374547261646572206973206e6f742045564d2060648201526730b2323932b9b99760c11b608482015260a4016105cd565b60a08201516001600160a01b038116146111a85760405162461bcd60e51b81526020600482015260496024820152600080516020612b8b83398151915260448201527f6f6c65526563656976652071756f7465546f6b656e206973206e6f742045564d6064820152681030b2323932b9b99760b91b608482015260a4016105cd565b61ffff841681526040808301516020808401919091526060808501516001600160a01b039081169385019390935260808086015184169185019190915260c08086015184169185019190915260a0808601519093169284019290925260e0808501519284019290925283015190820152610120820151610100820152610140820151156112d4576101408201516001600160a01b038116146112b35760405162461bcd60e51b815260206004820152604a6024820152600080516020612b8b83398151915260448201527f6f6c655265636569766520647374436f6e7472616374206973206e6f74204556606482015269269030b2323932b9b99760b11b608482015260a4016105cd565b610140808301516001600160a01b0316610120830152610160830151908201525b604051630c02799960e41b81526001600160a01b037f00000000000000000000000055084ee0fef03f14a305cd24286359a35d735151169063c027999090611320908490600401612982565b600060405180830381600087803b15801561133a57600080fd5b505af115801561134e573d6000803e3d6000fd5b505050507fdaa359c534878df499fed928ebd547efd9ab9cad42c0200a4deb8bec55dea0128160e0015160405161138791815260200190565b60405180910390a1505050505050506109b36001600355565b6113a8611740565b6001600160a01b0381163b61142b5760405162461bcd60e51b815260206004820152604f6024820152600080516020612b6b83398151915260448201527f65576f726d686f6c6520576f726d686f6c6520656e64706f696e74206d75737460648201526e10313290309031b7b73a3930b1ba1760891b608482015260a4016105cd565b600454604080516001600160a01b03808516825290921660208301527f41bc02113522bf9d1c5b2fa77fd65106307a6a90648c65230404710ce6d74c99910160405180910390a1600480546001600160a01b0319166001600160a01b0392909216919091179055565b337f00000000000000000000000055084ee0fef03f14a305cd24286359a35d7351516001600160a01b0316146115325760405162461bcd60e51b815260206004820152603d60248201527f48617368666c6f77576f726d686f6c654d657373656e6765723a3a747261646560448201527f58436861696e2053656e646572206d75737420626520726f757465722e00000060648201526084016105cd565b7f000000000000000000000000000000000000000000000000000000000000000161ffff16846000015161ffff16146115d35760405162461bcd60e51b815260206004820152603c60248201527f48617368666c6f77576f726d686f6c654d657373656e6765723a3a747261646560448201527f58436861696e20496e636f727265637420737263436861696e49642e0000000060648201526084016105cd565b6115df8484848461192a565b50505050565b6115ed611740565b600180546001600160a01b0383166001600160a01b0319909116811790915561161e6000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6002602052600090815260409020805461166f906123d7565b80601f016020809104026020016040519081016040528092919081815260200182805461169b906123d7565b80156116e85780601f106116bd576101008083540402835291602001916116e8565b820191906000526020600020905b8154815290600101906020018083116116cb57829003601f168201915b505050505081565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000546001600160a01b0316331461052b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105cd565b804710156117ea5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016105cd565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611837576040519150601f19603f3d011682016040523d82523d6000602084013e61183c565b606091505b50509050806118b35760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016105cd565b505050565b600180546001600160a01b03191690556109b3816116f0565b6002600354036119235760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016105cd565b6002600355565b6000600460009054906101000a90046001600160a01b03166001600160a01b0316631a90a2196040518163ffffffff1660e01b8152600401602060405180830381865afa15801561197f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a39190612a59565b6004549091508190600160a81b900460ff16158015906119da575060208087015161ffff1660009081526007909152604090205415155b156119ed576119ea81600261283e565b90505b80341015611a715760405162461bcd60e51b8152602060048201526044602482018190527f48617368666c6f77576f726d686f6c654d657373656e6765723a3a5f776f726d908201527f686f6c6553656e6420496e73756666696369656e7420576f726d686f6c65206660648201526332b2b99760e11b608482015260a4016105cd565b60208087015161ffff90811660009081526005909252604090912054168015801590611abf575060208088015161ffff1660009081526002909152604081208054611abb906123d7565b9050115b611b4f5760405162461bcd60e51b815260206004820152605560248201527f48617368666c6f77576f726d686f6c654d657373656e6765723a3a5f776f726d60448201527f686f6c6553656e6420576f726d686f6c652064657374696e6174696f6e206368606482015274185a5b881251081b9bdd0818dbdb999a59dd5c9959605a1b608482015260a4016105cd565b600454600160a01b900460ff16600003611bdd5760405162461bcd60e51b815260206004820152604360248201527f48617368666c6f77576f726d686f6c654d657373656e6765723a3a5f776f726d60448201527f686f6c6553656e6420436f6e73697374656e6379206c6576656c206e6f74207360648201526232ba1760e91b608482015260a4016105cd565b6000611bec8888838989611e21565b600480546040516358cd21bf60e11b81529293506000926001600160a01b0382169263b19a437e928992611c309287928992600160a01b90910460ff169101612a72565b60206040518083038185885af1158015611c4e573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611c739190612aa4565b6001600160401b031690507f5226e00d4650d3a00a0cc6446dfafdd1a8f825a3a6c7396eb5ccfcf737190d1a8961018001518534611cb19190612825565b604080519283526020830191909152810183905260600160405180910390a15050600454600160a81b900460ff1615801590611d04575060208088015161ffff1660009081526007909152604090205415155b15611e185760208088015161ffff16600090815260079091526040812054611d3190899089908989611e21565b600480546040516358cd21bf60e11b81529293506000926001600160a01b0382169263b19a437e928992611d759287928992600160a81b90910460ff169101612a72565b60206040518083038185885af1158015611d93573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611db89190612aa4565b6001600160401b031690507f4264a0964b8918276a33db4ae2c82c7a9a0a85f60afed61592141470235b88278961018001518534611df69190612825565b604080519283526020830191909152810183905260600160405180910390a150505b50505050505050565b604080516101808101825260008082526020820181905291810182905260608181018390526080820183905260a0820183905260c0820183905260e0820183905261010082018390526101208201839052610140820192909252610160810182905260208088015161ffff168252610180880151828201526040808901516001600160a01b03908116828501526060808b01519085015260a0808b01516080860152610120808c01519186019190915260e0808c015160c0870152610160808d01519187019190915261010086018a9052918a16908501526101408401879052830185905251611f1391839101612abf565b60405160208183030381529060405291505095945050505050565b61ffff811681146109b357600080fd5b8035611f4981611f2e565b919050565b600080600060408486031215611f6357600080fd5b8335611f6e81611f2e565b925060208401356001600160401b0380821115611f8a57600080fd5b818601915086601f830112611f9e57600080fd5b813581811115611fad57600080fd5b876020828501011115611fbf57600080fd5b6020830194508093505050509250925092565b60008060408385031215611fe557600080fd5b8235611ff081611f2e565b9150602083013561200081611f2e565b809150509250929050565b6000806040838503121561201e57600080fd5b823561202981611f2e565b946020939093013593505050565b60ff811681146109b357600080fd5b60006020828403121561205857600080fd5b813561206381612037565b9392505050565b60006020828403121561207c57600080fd5b813561206381611f2e565b634e487b7160e01b600052604160045260246000fd5b6040516101a081016001600160401b03811182821017156120c0576120c0612087565b60405290565b604051608081016001600160401b03811182821017156120c0576120c0612087565b60405161016081016001600160401b03811182821017156120c0576120c0612087565b60405161018081016001600160401b03811182821017156120c0576120c0612087565b604051601f8201601f191681016001600160401b038111828210171561215657612156612087565b604052919050565b60006001600160401b0382111561217757612177612087565b50601f01601f191660200190565b600082601f83011261219657600080fd5b81356121a96121a48261215e565b61212e565b8181528460208386010111156121be57600080fd5b816020850160208301376000918101602001919091529392505050565b6000602082840312156121ed57600080fd5b81356001600160401b0381111561220357600080fd5b61220f84828501612185565b949350505050565b80356001600160a01b0381168114611f4957600080fd5b60006020828403121561224057600080fd5b61206382612217565b60008060008084860361020081121561226157600080fd5b6101a08082121561227157600080fd5b61227961209d565b915061228487611f3e565b825261229260208801611f3e565b60208301526122a360408801612217565b6040830152606087013560608301526122be60808801612217565b608083015260a087013560a08301526122d960c08801612217565b60c083015260e087013560e08301526101006122f6818901612217565b9083015261012087810135908301526101408088013590830152610160808801359083015261018080880135908301529094508490612336818801612217565b945050506101c085013591506101e08501356001600160401b0381111561235c57600080fd5b61236887828801612185565b91505092959194509250565b60005b8381101561238f578181015183820152602001612377565b50506000910152565b600081518084526123b0816020860160208601612374565b601f01601f19169290920160200192915050565b6020815260006120636020830184612398565b600181811c908216806123eb57607f821691505b60208210810361240b57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156118b357600081815260208120601f850160051c810160208610156124385750805b601f850160051c820191505b8181101561245757828155600101612444565b505050505050565b6001600160401b0383111561247657612476612087565b61248a8361248483546123d7565b83612411565b6000601f8411600181146124be57600085156124a65750838201355b600019600387901b1c1916600186901b178355612518565b600083815260209020601f19861690835b828110156124ef57868501358255602094850194600190920191016124cf565b508682101561250c5760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b61ffff8416815260406020820152816040820152818360608301376000818301606090810191909152601f909201601f1916010192915050565b8051611f4981612037565b805163ffffffff81168114611f4957600080fd5b8051611f4981611f2e565b80516001600160401b0381168114611f4957600080fd5b600082601f8301126125ab57600080fd5b81516125b96121a48261215e565b8181528460208386010111156125ce57600080fd5b61220f826020830160208701612374565b600082601f8301126125f057600080fd5b815160206001600160401b0382111561260b5761260b612087565b612619818360051b0161212e565b82815260079290921b8401810191818101908684111561263857600080fd5b8286015b8481101561269d57608081890312156126555760008081fd5b61265d6120c6565b81518152848201518582015260408083015161267881612037565b9082015260608281015161268b81612037565b9082015283529183019160800161263c565b509695505050505050565b80518015158114611f4957600080fd5b6000806000606084860312156126cd57600080fd5b83516001600160401b03808211156126e457600080fd5b9085019061016082880312156126f957600080fd5b6127016120e8565b61270a83612559565b815261271860208401612564565b602082015261272960408401612564565b604082015261273a60608401612578565b60608201526080830151608082015261275560a08401612583565b60a082015261276660c08401612559565b60c082015260e08301518281111561277d57600080fd5b6127898982860161259a565b60e08301525061010061279d818501612564565b9082015261012083810151838111156127b557600080fd5b6127c18a8287016125df565b9183019190915250610140838101519082015294506127e2602087016126a8565b935060408601519150808211156127f857600080fd5b506128058682870161259a565b9150509250925092565b634e487b7160e01b600052601160045260246000fd5b818103818111156128385761283861280f565b92915050565b80820281158282048414176128385761283861280f565b600061286182546123d7565b82601f8211156128775783600052602060002090505b549150602081101561240b5760001960209190910360031b1b16919050565b6000602082840312156128a857600080fd5b81516001600160401b03808211156128bf57600080fd5b9083019061018082860312156128d457600080fd5b6128dc61210b565b6128e583612578565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120808401518183015250610140808401518183015250610160808401518381111561296557600080fd5b6129718882870161259a565b918301919091525095945050505050565b6020815261299760208201835161ffff169052565b60208201516040820152600060408301516129bd60608401826001600160a01b03169052565b5060608301516001600160a01b03811660808401525060808301516001600160a01b03811660a08401525060a08301516001600160a01b03811660c08401525060c083015160e0838101919091528301516101008084019190915283015161012080840191909152830151610140612a3f818501836001600160a01b03169052565b84015161016084810152905061220f610180840182612398565b600060208284031215612a6b57600080fd5b5051919050565b63ffffffff84168152606060208201526000612a916060830185612398565b905060ff83166040830152949350505050565b600060208284031215612ab657600080fd5b61206382612583565b60208152612ad460208201835161ffff169052565b602082015160408201526040820151606082015260608201516080820152608082015160a082015260a082015160c082015260c082015160e0820152600060e083015161010081818501528085015191505061012081818501528085015191505061014081818501528085015191505061016081818501528085015191505061018080818501525061220f6101a084018261239856fe48617368666c6f77576f726d686f6c654d657373656e6765723a3a757064617448617368666c6f77576f726d686f6c654d657373656e6765723a3a776f726d68a264697066735822122018de9436877a602ff264a3f0b38674c4e4f1e91b0d8994d668be4a8c8d945c6264736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000000100000000000000000000000055084ee0fef03f14a305cd24286359a35d735151
-----Decoded View---------------
Arg [0] : _hChainId (uint16): 1
Arg [1] : _router (address): 0x55084eE0fEf03f14a305cd24286359A35D735151
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [1] : 00000000000000000000000055084ee0fef03f14a305cd24286359a35d735151
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | Ether (ETH) | 100.00% | $3,399.03 | 0.00062483 | $2.12 |
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.