Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
PacketConsumer
Compiler Version
v0.8.27+commit.40a35a09
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import "@openzeppelin/contracts/access/Ownable2Step.sol"; import "./interfaces/IDataConsumer.sol"; import "./interfaces/ITunnelRouter.sol"; import "./interfaces/IVault.sol"; import "./libraries/PacketDecoder.sol"; import "./libraries/Address.sol"; import "./TssVerifier.sol"; contract PacketConsumer is IDataConsumer, Ownable2Step { // An object that contains the price of a signal Id. struct Price { uint64 price; int64 timestamp; } // The tunnel router contract. address public immutable tunnelRouter; // The hashed source chain Id that this contract is consuming from. bytes32 public immutable hashedSourceChainId; // The hashed target chain Id that this contract is at. bytes32 public immutable hashedTargetChainId; // The tunnel Id that this contract is consuming; cannot be immutable or else the create2 // will result in different address. uint64 public tunnelId; // Mapping between a signal Id and its corresponding latest price object. mapping(bytes32 => Price) public prices; modifier onlyTunnelRouter() { if (msg.sender != tunnelRouter) { revert UnauthorizedTunnelRouter(); } _; } constructor( address tunnelRouter_, bytes32 hashedSourceChainId_, bytes32 hashedTargetChainId_, address initialOwner ) Ownable(initialOwner) { hashedSourceChainId = hashedSourceChainId_; hashedTargetChainId = hashedTargetChainId_; tunnelRouter = tunnelRouter_; } /** * @dev See {IDataConsumer-process}. */ function process( PacketDecoder.TssMessage memory data ) external onlyTunnelRouter { if (data.hashOriginator != hashOriginator()) { revert InvalidHashOriginator(); } PacketDecoder.Packet memory packet = data.packet; for (uint256 i = 0; i < packet.signals.length; i++) { prices[packet.signals[i].signal] = Price({ price: packet.signals[i].price, timestamp: packet.timestamp }); emit SignalPriceUpdated( packet.signals[i].signal, packet.signals[i].price, packet.timestamp ); } } /** * @dev See {IDataConsumer-activate}. */ function activate(uint64 latestSeq) external payable onlyOwner { ITunnelRouter(tunnelRouter).activate{value: msg.value}( tunnelId, latestSeq ); } /** * @dev See {IDataConsumer-deactivate}. */ function deactivate() external onlyOwner { ITunnelRouter(tunnelRouter).deactivate(tunnelId); } /** * @dev See {IDataConsumer-deposit}. */ function deposit() external payable { IVault vault = ITunnelRouter(tunnelRouter).vault(); vault.deposit{value: msg.value}(tunnelId, address(this)); } /** * @dev See {IDataConsumer-withdraw}. */ function withdraw(uint256 amount) external onlyOwner { IVault vault = ITunnelRouter(tunnelRouter).vault(); vault.withdraw(tunnelId, amount); // send the remaining balance to the caller. uint256 balance = address(this).balance; (bool ok, ) = payable(msg.sender).call{value: balance}(""); if (!ok) { revert TokenTransferFailed(msg.sender); } } /** * @dev See {IDataConsumer-withdrawAll}. */ function withdrawAll() external onlyOwner { IVault vault = ITunnelRouter(tunnelRouter).vault(); vault.withdrawAll(tunnelId); // send the remaining balance to the caller. uint256 balance = address(this).balance; (bool ok, ) = payable(msg.sender).call{value: balance}(""); if (!ok) { revert TokenTransferFailed(msg.sender); } } ///@dev Sets the tunnel Id of the contract. function setTunnelId(uint64 tunnelId_) external onlyOwner { tunnelId = tunnelId_; } ///@dev Returns the hash of the originator of the packet. function hashOriginator() public view returns (bytes32) { return keccak256( abi.encodePacked( bytes4(0xa466d313), // keccak("tunnelOriginatorPrefix")[:4] hashedSourceChainId, tunnelId, keccak256(bytes(Address.toChecksumString(address(this)))), hashedTargetChainId ) ); } ///@dev The contract receive eth from the vault contract when user call withdraw. receive() external payable {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol) pragma solidity ^0.8.20; import {Ownable} from "./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. * * The initial owner is specified at deployment time in the constructor for `Ownable`. 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(); if (pendingOwner() != sender) { revert OwnableUnauthorizedAccount(sender); } _transferOwnership(sender); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import "../libraries/PacketDecoder.sol"; interface IDataConsumer { // ======================================== // Events // ======================================== /** * @notice Emitted when the signal price is updated. * * @param signalId The Id of the signal whose price is updated. * @param price The new price of the signal. * @param timestamp The timestamp of the updated prices. */ event SignalPriceUpdated( bytes32 indexed signalId, uint64 price, int64 timestamp ); // ======================================== // Custom Errors // ======================================== /** * @notice Reverts if the caller is not the tunnelRouter contract. */ error UnauthorizedTunnelRouter(); /** * @notice Reverts if the hashed originator is not matched. */ error InvalidHashOriginator(); /** * @notice Reverts if the program fails to send tokens to the specified address. * * @param addr The address to which the token transfer failed. */ error TokenTransferFailed(address addr); /** * @notice Reverts if the caller is not the factory contract. */ error UnauthorizedFactory(address addr); // ======================================== // Functions // ======================================== /** * @dev Processes the relayed message. * * The relayed message must be evaluated from the tunnelRouter contract and * verified by the tssVerifier contract before forwarding to the target contract. * * @param data The decoded tss message that is relayed from the tunnelRouter contract. */ function process(PacketDecoder.TssMessage memory data) external; /** * @dev Activates the tunnel and set the sequence on tunnelRouter contract. * * This function deposits tokens into the vault and sets the latest sequence on the * tunnelRouter contract if the current deposit in the vault contract exceeds a threshold. * The transaction is reverted if the threshold is not met. * * This function should be called by the contract owner. * * @param latestSeq The new sequence of the tunnel. */ function activate(uint64 latestSeq) external payable; /** * @dev Deactivates the tunnel on tunnelRouter contract. * * This function should be called by the contract owner. */ function deactivate() external; /** * @dev Deposits the native tokens into the vault on behalf of the given account and tunnelId. * The amount of tokens to be deposited is provided as msg.value in the transaction. * * The contract calls the vault to deposit the tokens. */ function deposit() external payable; /** * @dev Withdraws the native tokens from the vault contract with specific amount. * * This function should be called by the contract owner. */ function withdraw(uint256 amount) external; /** * @dev Withdraws all native tokens from the vault contract. * * This function should be called by the contract owner. */ function withdrawAll() external; /** * @dev Returns The tunnelRouter contract address. */ function tunnelRouter() external view returns (address); /** * @dev Returns The tunnelId of the contract address. */ function tunnelId() external view returns (uint64); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import "./IVault.sol"; interface ITunnelRouter { // ======================================== // Events // ======================================== /** * @notice Emitted when the maximum allowable callback gas limit is set. * * @param maxAllowableCallbackGasLimit The maximum gas limit to be used * when calling the target contract. */ event MaxAllowableCallbackGasLimitSet(uint256 maxAllowableCallbackGasLimit); /** * @notice Emitted when the additional gas used is set. * * @param additionalGasUsed The additional gas estimated for relaying the message; * does not include the gas cost for executing the target contract. */ event AdditionalGasUsedSet(uint256 additionalGasUsed); /** * @notice Emitted after the message is relayed to the target contract * to indicate the result of the process. * * @param tunnelId The tunnel ID that the message is relayed. * @param targetAddr The target address that the message is relayed. * @param sequence The sequence of the message. * @param isReverted The flag indicating whether the message is reverted. */ event MessageProcessed( uint64 indexed tunnelId, address indexed targetAddr, uint64 indexed sequence, bool isReverted ); /** * @notice Emitted when the target address is activated. * * @param tunnelId The tunnel ID that the sender is activating. * @param targetAddr The target address that the sender is activating. * @param latestNonce The latest nonce of the sender. */ event Activated( uint64 indexed tunnelId, address indexed targetAddr, uint64 latestNonce ); /** * @notice Emitted when the target address is deactivated. * * @param tunnelId The tunnel ID that the sender is deactivating. * @param targetAddr The target address that the sender is deactivating. * @param latestNonce The latest nonce of the sender. */ event Deactivated( uint64 indexed tunnelId, address indexed targetAddr, uint64 latestNonce ); // ======================================== // Custom Errors // ======================================== /** * @notice Reverts if the target contract is inactive. * * @param targetAddr The target address that is inactive. */ error InactiveTargetContract(address targetAddr); /** * @notice Reverts if the target contract is active. * * @param targetAddr The target address that is active. */ error ActiveTargetContract(address targetAddr); /** * @notice Reverts if the sequence is incorrect. * * @param expected The expected sequence of the tunnel. * @param input The input sequence of the tunnel. */ error InvalidSequence(uint64 expected, uint64 input); /** * @notice Reverts if the chain ID is incorrect. * * @param chainId The chain ID of the tunnel. */ error InvalidChain(string chainId); /** * @notice Reverts if the message and its signature doesn't match. */ error InvalidSignature(); /** * @notice Reverts if the contract cannot send fee to the specific address. */ error TokenTransferFailed(address addr); /** * @notice Reverts if the remaining balance is insufficient to withdraw. * * @param tunnelId The tunnel ID that the sender is withdrawing tokens. * @param addr The account from which the sender is withdrawing tokens. */ error InsufficientRemainingBalance(uint64 tunnelId, address addr); // ======================================== // Functions // ======================================== ///@dev Tunnel information struct TunnelInfo { bool isActive; // whether the tunnel is active or not uint64 latestSequence; // the latest sequence of the tunnel uint256 balance; // the remaining balance of the tunnel } /** * @dev Relays the message to the target contract. * * Verifies the message's sequence and signature before forwarding it to * the data consumer contract. The sender is entitled to a reward from the * vault contract, even if the data consumer contract fails to process the * message. The reward is based on the gas consumed during processing plus * a predefined additional gas estimate. * * @param message The message to be relayed. * @param randomAddr The random address used in signature. * @param signature The signature of the message. */ function relay( bytes calldata message, address randomAddr, uint256 signature ) external; /** * @dev Activates the sender and associated tunnel ID. * * @param tunnelId The tunnel ID that the sender contract is activating. * @param latestSeq The new sequence of the tunnelID. */ function activate(uint64 tunnelId, uint64 latestSeq) external payable; /** * @dev Deactivates the sender and associated tunnel ID. * * @param tunnelId The tunnel ID being deactivated. */ function deactivate(uint64 tunnelId) external; /** * @dev Returns the minimum balance required to keep the tunnel active. * * @return uint256 The minimum balance threshold. */ function minimumBalanceThreshold() external view returns (uint256); /** * @dev Returns whether the tunnel is active or not. * * @param tunnelId The ID of the tunnel. * @param addr The target contract address. * * @return bool True if the tunnel is active, false otherwise. */ function isActive( uint64 tunnelId, address addr ) external view returns (bool); /** * @dev Returns the tunnel information. * * @param tunnelId The ID of the tunnel. * @param addr The target contract address. * * @return bool True if the tunnel is active, false otherwise. */ function tunnelInfo( uint64 tunnelId, address addr ) external view returns (TunnelInfo memory); /** * @dev Returns the vault contract address. */ function vault() external view returns (IVault); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; interface IVault { // ======================================== // Events // ======================================== /** * @notice Emitted when the tunnel router contract address is set. * * @param tunnelRouter The new tunnel router contract address. */ event TunnelRouterSet(address tunnelRouter); /** * @notice Emitted when the caller deposit native token into the contract. * * @param tunnelId The ID of the tunnel into which the sender is depositing tokens.. * @param from The account from which the token is deposited. * @param to The account into which the token is deposited. * @param amount The amount of tokens deposited. */ event Deposited( uint256 indexed tunnelId, address indexed from, address indexed to, uint256 amount ); /** * @notice Emitted when the caller withdraw native token from the contract. * * @param tunnelId The ID of the tunnel from which the sender is withdrawing tokens. * @param from The account from which the token is withdrawn. * @param to The account to which the token is withdrawn. * @param amount The amount of tokens withdrawn. */ event Withdrawn( uint256 indexed tunnelId, address indexed from, address indexed to, uint256 amount ); // ======================================== // Custom Errors // ======================================== /** * @notice The caller is not the tunnelRouter contract. */ error UnauthorizedTunnelRouter(); /** * @notice Reverts if the remaining balance is insufficient. */ error InsufficientRemainingBalance(); /** * @notice Reverts if contract cannot send fee to the specific address. * * @param addr The address to which the token transfer failed. */ error TokenTransferFailed(address addr); // ======================================== // Functions // ======================================== /** * @dev Deposits the native tokens into the vault on behalf of the given account and tunnelID. * The deposit amount is provided via `msg.value`. * * @param tunnelId The ID of the tunnel into which the sender is depositing tokens. * @param account The account into which the sender is depositing tokens. */ function deposit(uint64 tunnelId, address account) external payable; /** * @dev Withdraws native tokens from the sender's account associated with the given tunnelID. * * @param tunnelId the ID of the tunnel from which the sender is withdrawing tokens. * @param amount the amount of tokens to withdraw. */ function withdraw(uint64 tunnelId, uint256 amount) external; /** * @dev Withdraws the entire deposit from the sender's account for the specified tunnel ID. * * @param tunnelId the ID of the tunnel from which the sender is withdrawing tokens. */ function withdrawAll(uint64 tunnelId) external; /** * @dev Collects the fee from the account and the given tunnel ID. * * This function should be called by the tunnelRouter contract only. * * @param tunnelId the ID of the tunnel from which the caller is withdrawing tokens. * @param account The account from which the caller is withdrawing tokens. * @param amount the amount of tokens to withdraw. */ function collectFee( uint64 tunnelId, address account, uint256 amount ) external; /** * @dev Returns the balance of the account. * * @param tunnelId The ID of the tunnel to check the balance. * @param account The account to check the balance. */ function balance( uint64 tunnelId, address account ) external view returns (uint256); /** * @dev Returns the tunnel router contract address. */ function tunnelRouter() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; library PacketDecoder { bytes4 private constant _FIXED_POINT_ENCODER_SELECTOR = 0xcba0ad5a; // keccak256("FixedPointABI"); bytes4 private constant _TICK_ENCODER_SELECTOR = 0xdb99b2b3; // keccak256("TickABI"); enum EncoderType { Unidentified, FixedPoint, Tick } // info of signals being published in the packet. struct SignalPrice { bytes32 signal; uint64 price; } // the packet information generated from the tunnel. struct Packet { uint64 tunnelId; uint64 sequence; string chainId; string targetAddr; SignalPrice[] signals; int64 timestamp; } // the TSS message structure that is generated by the tunnel and is signed by the tss module. struct TssMessage { bytes32 hashOriginator; uint64 sourceBlocktimestamp; uint64 signingId; EncoderType encoderType; Packet packet; } /** * @dev Decode the TSS message from the encoded message. * @param message The encoded message. * @return TssMessage The decoded TSS message object. */ function decodeTssMessage( bytes calldata message ) internal pure returns (TssMessage memory) { EncoderType encoder = _toEncoderType(bytes4(message[52:56])); Packet memory packet = _decodePacket(message); TssMessage memory tssMessage = TssMessage( bytes32(message[0:32]), uint64(bytes8(message[32:40])), uint64(bytes8(message[40:48])), encoder, packet ); return tssMessage; } /** * @dev Decode the TSS message from the encoded message. * @param message The encoded message. * @return TssMessage The decoded TSS message object. */ function _decodePacket( bytes calldata message ) internal pure returns (Packet memory) { Packet memory packet = abi.decode(message[56:], (Packet)); return packet; } /** * @dev Convert the selector to the encoder type. * @param selector The selector to be converted. * @return EncoderType The encoder type. */ function _toEncoderType( bytes4 selector ) internal pure returns (EncoderType) { if (selector == _FIXED_POINT_ENCODER_SELECTOR) { return EncoderType.FixedPoint; } else if (selector == _TICK_ENCODER_SELECTOR) { return EncoderType.Tick; } else { return EncoderType.Unidentified; } } }
// SPDX-License-Identifier: MIT // ref: https://gist.github.com/Y5Yash/721a5f5c3e392a6a28f47db1d3114501 // ref: https://github.com/ethereum/ercs/blob/master/ERCS/erc-55.md pragma solidity ^0.8.23; library Address { bytes16 private constant _LOWER = "0123456789abcdef"; bytes16 private constant _CAPITAL = "0123456789ABCDEF"; ///@dev convert address to checksum address string. function toChecksumString( address addr ) internal pure returns (string memory) { // get the hash of the lowercase address bytes memory lowercaseAddr = ToLowercaseBytes(addr); bytes32 hashedAddr = keccak256(abi.encodePacked(lowercaseAddr)); // store checksum address with '0x' prepended in this. bytes memory result = new bytes(42); result[0] = "0"; result[1] = "x"; uint160 addrValue = uint160(addr); uint160 hashValue = uint160(bytes20(hashedAddr)); // checksum logic from EIP-55 for (uint i = 41; i > 1; --i) { uint b = addrValue & 0xf; if (hashValue & 0xf > 7) { result[i] = _CAPITAL[b]; } else { result[i] = _LOWER[b]; } addrValue >>= 4; hashValue >>= 4; } return string(abi.encodePacked(result)); } ///@dev get convert address bytes to lowercase char hex bytes (without '0x'). function ToLowercaseBytes( address addr ) internal pure returns (bytes memory) { bytes memory s = new bytes(40); uint160 x = uint160(addr); for (uint i = 0; i < 20; i++) { uint8 b = uint8(x) & 0xff; s[39 - 2 * i - 1] = _LOWER[b >> 4]; // higher index s[39 - 2 * i] = _LOWER[b & 0xf]; // lower index x >>= 8; } return s; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import "@openzeppelin/contracts/access/Ownable2Step.sol"; import "@openzeppelin/contracts/utils/Pausable.sol"; import "./interfaces/ITssVerifier.sol"; contract TssVerifier is Pausable, Ownable2Step, ITssVerifier { struct PublicKey { uint64 activeTime; // The timestamp that the public key is activated. uint8 parity; // The parity value of the public key. uint256 px; // The x-coordinate value of the public key. } // The group order of secp256k1. uint256 constant _ORDER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141; // The grace period for the public key. uint64 immutable transitionPeriod; // The prefix for the hashing process in bandchain. string constant _CONTEXT = "BAND-TSS-secp256k1-v0"; // The prefix for the challenging hash message. string constant _CHALLENGE_PREFIX = "challenge"; // The list of public keys that are used for the verification process. PublicKey[] public publicKeys; constructor( uint64 transitionPeriod_, address initialAddr ) Ownable(initialAddr) { transitionPeriod = transitionPeriod_; } /** * @dev See {ITssVerifier-addPubKeyWithProof}. */ function addPubKeyWithProof( bytes calldata message, address randomAddr, uint256 s ) external whenNotPaused { if (!verify(keccak256(message), randomAddr, s)) { revert InvalidSignature(); } // Extract the public key from the message. The message is in the form of // hashedOrignator (32 bytes) || timestamp (uint64; 8-bytes) || signingId (uint64; 8 bytes) // || modulePrefix (8 bytes) || parity (1 byte) || px (32 bytes) || timestamp (8 bytes) uint8 parity = uint8(bytes1(message[56:57])); uint256 px = uint(bytes32(message[57:89])); uint64 timestamp = uint64(bytes8(message[89:97])); _updatePublicKey(timestamp, parity, px); } /** * @dev See {ITssVerifier-addPubKeyByOwner}. */ function addPubKeyByOwner( uint64 timestamp, uint8 parity, uint256 px ) external onlyOwner { _updatePublicKey(timestamp, parity, px); } /** * @dev See {ITssVerifier-verify}. */ function verify( bytes32 hashedMessage, address randomAddr, uint256 signature ) public view whenNotPaused returns (bool result) { if (randomAddr == address(0)) { return false; } // Get the public key that is valid at the given timestamp. uint256 pubKeyIdx = _getPubKeyIndexByTimestamp(uint64(block.timestamp)); // if the active time of the public key is in the transition period, then // we need to check the previous public key as it may be the signature from // the previous group. bool isInTransitionPeriod = publicKeys[pubKeyIdx].activeTime + transitionPeriod >= block.timestamp; if ( pubKeyIdx > 0 && isInTransitionPeriod && _verifyWithPublickKey( hashedMessage, randomAddr, signature, publicKeys[pubKeyIdx - 1] ) ) { return true; } return _verifyWithPublickKey( hashedMessage, randomAddr, signature, publicKeys[pubKeyIdx] ); } /// @dev Pauses the contract to prevent any further updates. function pause() external onlyOwner { _pause(); } /// @dev Unpauses the contract to prevent any further updates. function unpause() external onlyOwner { _unpause(); } /// @dev Returns the number of public keys. function publicKeysLength() public view returns (uint256 length) { length = publicKeys.length; } /// @dev returns true if the signature is valid against the given public key. function _verifyWithPublickKey( bytes32 hashedMessage, address randomAddr, uint256 signature, PublicKey memory publicKey ) internal pure returns (bool) { uint256 content = uint256( keccak256( abi.encodePacked( _CONTEXT, bytes1(0x00), _CHALLENGE_PREFIX, bytes1(0x00), randomAddr, publicKey.parity, publicKey.px, hashedMessage ) ) ); uint256 spx = _ORDER - mulmod(signature, publicKey.px, _ORDER); uint256 cpx = _ORDER - mulmod(content, publicKey.px, _ORDER); // Because the ecrecover precompile implementation verifies that the 'r' and's' // input positions must be non-zero // So in this case, there is no need to verify them('px' > 0 and 'cpx' > 0). if (spx == 0) { revert ProcessingSignatureFailed(); } address addr = ecrecover( bytes32(spx), publicKey.parity, bytes32(publicKey.px), bytes32(cpx) ); return randomAddr == addr; } /// @dev push the public key to the list. function _updatePublicKey( uint64 timestamp, uint8 parity, uint256 px ) internal { // Note: Offset parity by 25 to match with the calculation in TSS module // In etheruem, the parity is typically 27 or 28. PublicKey memory pubKey = PublicKey({ activeTime: timestamp, parity: parity + 25, px: px }); publicKeys.push(pubKey); emit GroupPubKeyUpdated(publicKeys.length, timestamp, parity, px, true); } ///@dev get the public key index that is valid at th given timestamp. function _getPubKeyIndexByTimestamp( uint64 timestamp ) internal view returns (uint256) { for (uint256 i = publicKeys.length; i > 0; i--) { if (publicKeys[i - 1].activeTime <= timestamp) { return i - 1; } } revert PublicKeyNotFound(timestamp); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { bool private _paused; /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); /** * @dev The operation failed because the contract is paused. */ error EnforcedPause(); /** * @dev The operation failed because the contract is not paused. */ error ExpectedPause(); /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { if (paused()) { revert EnforcedPause(); } } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { if (!paused()) { revert ExpectedPause(); } } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; interface ITssVerifier { // ======================================== // Events // ======================================== /** * @dev Emitted when the group public key is updated. * @param index The index of the public key in the group. * @param timestamp The timestamp of the update. * @param parity The parity value of the public key. * @param px The x-coordinate value of the public key. * @param isByAdmin True if the public key is updated by the admin, false otherwise. */ event GroupPubKeyUpdated( uint256 index, uint256 timestamp, uint8 parity, uint256 px, bool isByAdmin ); // ======================================== // Custom Errors // ======================================== /** * @notice Reverts if the message and its signature doesn't match. */ error InvalidSignature(); /** * @notice Reverts if the contract fails to processes the signature. */ error ProcessingSignatureFailed(); /** * @notice Reverts if there is no valid public key. * * @param timestamp The given timestamp of the message. */ error PublicKeyNotFound(uint256 timestamp); // ======================================== // Functions // ======================================== /** * @dev Verifies the signature of the message against the given signature. * * The contract is not allowed to verify the message with obsolete public key. * * @param hashedMessage The hashed message to be verified. * @param randomAddr The random address that is generated during the processing tss signature. * @param signature The tss signature. * @return true If the signature is valid, false otherwise. */ function verify( bytes32 hashedMessage, address randomAddr, uint256 signature ) external view returns (bool); /** * @dev Adds a new public key with proof from the current group. * * @param message The message being used for updating public key. * @param randomAddr The address form of the commitment R. * @param s The Schnorr signature. */ function addPubKeyWithProof( bytes calldata message, address randomAddr, uint256 s ) external; /** * @dev Adds the new public key by the owner. * * @param timestamp The timestamp of the new public key. * @param parity The parity value of the new public key. * @param px The x-coordinate value of the new public key. */ function addPubKeyByOwner( uint64 timestamp, uint8 parity, uint256 px ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src/", "@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src/", "solidity-stringutils/=lib/openzeppelin-foundry-upgrades/lib/solidity-stringutils/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": false, "libraries": {} }
Contract ABI
API[{"inputs":[{"internalType":"address","name":"tunnelRouter_","type":"address"},{"internalType":"bytes32","name":"hashedSourceChainId_","type":"bytes32"},{"internalType":"bytes32","name":"hashedTargetChainId_","type":"bytes32"},{"internalType":"address","name":"initialOwner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidHashOriginator","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"TokenTransferFailed","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"UnauthorizedFactory","type":"error"},{"inputs":[],"name":"UnauthorizedTunnelRouter","type":"error"},{"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":true,"internalType":"bytes32","name":"signalId","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"price","type":"uint64"},{"indexed":false,"internalType":"int64","name":"timestamp","type":"int64"}],"name":"SignalPriceUpdated","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"latestSeq","type":"uint64"}],"name":"activate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"deactivate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"hashOriginator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hashedSourceChainId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hashedTargetChainId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"bytes32","name":"","type":"bytes32"}],"name":"prices","outputs":[{"internalType":"uint64","name":"price","type":"uint64"},{"internalType":"int64","name":"timestamp","type":"int64"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"hashOriginator","type":"bytes32"},{"internalType":"uint64","name":"sourceBlocktimestamp","type":"uint64"},{"internalType":"uint64","name":"signingId","type":"uint64"},{"internalType":"enum PacketDecoder.EncoderType","name":"encoderType","type":"uint8"},{"components":[{"internalType":"uint64","name":"tunnelId","type":"uint64"},{"internalType":"uint64","name":"sequence","type":"uint64"},{"internalType":"string","name":"chainId","type":"string"},{"internalType":"string","name":"targetAddr","type":"string"},{"components":[{"internalType":"bytes32","name":"signal","type":"bytes32"},{"internalType":"uint64","name":"price","type":"uint64"}],"internalType":"struct PacketDecoder.SignalPrice[]","name":"signals","type":"tuple[]"},{"internalType":"int64","name":"timestamp","type":"int64"}],"internalType":"struct PacketDecoder.Packet","name":"packet","type":"tuple"}],"internalType":"struct PacketDecoder.TssMessage","name":"data","type":"tuple"}],"name":"process","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"tunnelId_","type":"uint64"}],"name":"setTunnelId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tunnelId","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tunnelRouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60e060405234801561000f575f5ffd5b5060405161160238038061160283398101604081905261002e91610107565b806001600160a01b03811661005c57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61006581610081565b505060a09190915260c0526001600160a01b031660805261014b565b600180546001600160a01b031916905561009a8161009d565b50565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b0381168114610102575f5ffd5b919050565b5f5f5f5f6080858703121561011a575f5ffd5b610123856100ec565b6020860151604087015191955093509150610140606086016100ec565b905092959194509250565b60805160a05160c0516114556101ad5f395f818161033c01526109f701525f8181610309015261097e01525f81816101df015281816103b8015281816105960152818161072a0152818161081c01528181610a3c0152610bda01526114555ff3fe608060405260043610610108575f3560e01c80638da5cb5b11610092578063d366747f11610062578063d366747f146102f8578063e2bd914c1461032b578063e30c39781461035e578063f2fde38b1461037b578063fc7e47461461039a575f5ffd5b80638da5cb5b14610274578063a0e062fa14610290578063a79c8c09146102b2578063d0e30db0146102f0575f5ffd5b80636a5d9b59116100d85780636a5d9b59146101ce578063715018a61461021957806379ba50971461022d5780637b30d81314610241578063853828b614610260575f5ffd5b806317b7ee4f146101135780632e1a7d4d1461013457806351b42b001461015357806360846bc614610167575f5ffd5b3661010f57005b5f5ffd5b34801561011e575f5ffd5b5061013261012d3660046111b5565b6103ad565b005b34801561013f575f5ffd5b5061013261014e36600461131b565b61058b565b34801561015e575f5ffd5b506101326106fa565b348015610172575f5ffd5b506101a761018136600461131b565b60026020525f90815260409020546001600160401b03811690600160401b900460070b82565b604080516001600160401b03909316835260079190910b6020830152015b60405180910390f35b3480156101d9575f5ffd5b506102017f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101c5565b348015610224575f5ffd5b50610132610785565b348015610238575f5ffd5b50610132610798565b34801561024c575f5ffd5b5061013261025b366004611332565b6107dc565b34801561026b575f5ffd5b50610132610811565b34801561027f575f5ffd5b505f546001600160a01b0316610201565b34801561029b575f5ffd5b506102a461096e565b6040519081526020016101c5565b3480156102bd575f5ffd5b506001546102d890600160a01b90046001600160401b031681565b6040516001600160401b0390911681526020016101c5565b610132610a39565b348015610303575f5ffd5b506102a47f000000000000000000000000000000000000000000000000000000000000000081565b348015610336575f5ffd5b506102a47f000000000000000000000000000000000000000000000000000000000000000081565b348015610369575f5ffd5b506001546001600160a01b0316610201565b348015610386575f5ffd5b50610132610395366004611366565b610b31565b6101326103a8366004611332565b610ba1565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103f657604051636e96d7e160e11b815260040160405180910390fd5b6103fe61096e565b81511461041e576040516397946a9d60e01b815260040160405180910390fd5b60808101515f5b8160800151518110156105865760405180604001604052808360800151838151811061045357610453611381565b6020026020010151602001516001600160401b031681526020018360a0015160070b81525060025f8460800151848151811061049157610491611381565b602090810291909101810151518252818101929092526040015f208251815493909201516001600160401b03908116600160401b026fffffffffffffffffffffffffffffffff1990941692169190911791909117905560808201518051829081106104fe576104fe611381565b60200260200101515f01517fa623627c34311a71b36da152b44076ede51861d701868671c9a6dfdd0f5da00a8360800151838151811061054057610540611381565b6020026020010151602001518460a001516040516105769291906001600160401b0392909216825260070b602082015260400190565b60405180910390a2600101610425565b505050565b610593610c13565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fbfa77cf6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105f0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106149190611395565b600154604051634338798360e01b8152600160a01b9091046001600160401b03166004820152602481018490529091506001600160a01b038216906343387983906044015f604051808303815f87803b15801561066f575f5ffd5b505af1158015610681573d5f5f3e3d5ffd5b50506040514792505f9150339083908381818185875af1925050503d805f81146106c6576040519150601f19603f3d011682016040523d82523d5f602084013e6106cb565b606091505b50509050806106f457604051632b596cb760e01b81523360048201526024015b60405180910390fd5b50505050565b610702610c13565b6001546040516343ba231760e11b8152600160a01b9091046001600160401b031660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638774462e906024015f604051808303815f87803b158015610773575f5ffd5b505af11580156106f4573d5f5f3e3d5ffd5b61078d610c13565b6107965f610c3f565b565b60015433906001600160a01b031681146107d05760405163118cdaa760e01b81526001600160a01b03821660048201526024016106eb565b6107d981610c3f565b50565b6107e4610c13565b600180546001600160401b03909216600160a01b0267ffffffffffffffff60a01b19909216919091179055565b610819610c13565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fbfa77cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610876573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061089a9190611395565b60015460405163f4465fd560e01b8152600160a01b9091046001600160401b031660048201529091506001600160a01b0382169063f4465fd5906024015f604051808303815f87803b1580156108ee575f5ffd5b505af1158015610900573d5f5f3e3d5ffd5b50506040514792505f9150339083908381818185875af1925050503d805f8114610945576040519150601f19603f3d011682016040523d82523d5f602084013e61094a565b606091505b505090508061058657604051632b596cb760e01b81523360048201526024016106eb565b6001545f9063a466d31360e01b907f000000000000000000000000000000000000000000000000000000000000000090600160a01b90046001600160401b03166109b730610c58565b80516020918201206040516001600160e01b03199590951691850191909152602484019290925260c01b6001600160c01b0319166044830152604c8201527f0000000000000000000000000000000000000000000000000000000000000000606c820152608c0160405160208183030381529060405280519060200120905090565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fbfa77cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a96573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aba9190611395565b60015460405163576bcd2f60e01b8152600160a01b9091046001600160401b031660048201523060248201529091506001600160a01b0382169063576bcd2f9034906044015b5f604051808303818588803b158015610b17575f5ffd5b505af1158015610b29573d5f5f3e3d5ffd5b505050505050565b610b39610c13565b600180546001600160a01b0383166001600160a01b03199091168117909155610b695f546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b610ba9610c13565b60015460405163ba1b5f2360e01b8152600160a01b9091046001600160401b039081166004830152821660248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ba1b5f23903490604401610b00565b5f546001600160a01b031633146107965760405163118cdaa760e01b81523360048201526024016106eb565b600180546001600160a01b03191690556107d981610e2c565b60605f610c6483610e7b565b90505f81604051602001610c7891906113b0565b60408051808303601f190181528282528051602090910120602a8084526060840190925292505f9190602082018180368337019050509050600360fc1b815f81518110610cc757610cc7611381565b60200101906001600160f81b03191690815f1a905350600f60fb1b81600181518110610cf557610cf5611381565b60200101906001600160f81b03191690815f1a90535084606083901c60295b6001811115610dff57600f8084169060079084161115610d84576f181899199a1a9b1b9c1ca0a121a222a360811b8160108110610d5357610d53611381565b1a60f81b858381518110610d6957610d69611381565b60200101906001600160f81b03191690815f1a905350610dd6565b6f181899199a1a9b1b9c1cb0b131b232b360811b8160108110610da957610da9611381565b1a60f81b858381518110610dbf57610dbf611381565b60200101906001600160f81b03191690815f1a9053505b5060016001609c1b03600493841c8116939290921c90911690610df8816113da565b9050610d14565b5082604051602001610e1191906113b0565b60405160208183030381529060405295505050505050919050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60408051602880825260608281019093525f9190602082018180368337019050509050825f5b6014811015610fb55760ff82166f181899199a1a9b1b9c1cb0b131b232b360811b600f600485901c1660108110610eda57610eda611381565b1a60f81b846001610eec8560026113ef565b610ef790602761140c565b610f01919061140c565b81518110610f1157610f11611381565b60200101906001600160f81b03191690815f1a9053506f181899199a1a9b1b9c1cb0b131b232b360811b600f821660108110610f4f57610f4f611381565b1a60f81b84610f5f8460026113ef565b610f6a90602761140c565b81518110610f7a57610f7a611381565b60200101906001600160f81b03191690815f1a9053505060089190911c72ffffffffffffffffffffffffffffffffffffff1690600101610ea1565b50909392505050565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b0381118282101715610ff457610ff4610fbe565b60405290565b60405160a081016001600160401b0381118282101715610ff457610ff4610fbe565b60405160c081016001600160401b0381118282101715610ff457610ff4610fbe565b604051601f8201601f191681016001600160401b038111828210171561106657611066610fbe565b604052919050565b80356001600160401b0381168114611084575f5ffd5b919050565b5f82601f830112611098575f5ffd5b81356001600160401b038111156110b1576110b1610fbe565b6110c4601f8201601f191660200161103e565b8181528460208386010111156110d8575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f82601f830112611103575f5ffd5b81356001600160401b0381111561111c5761111c610fbe565b61112b60208260051b0161103e565b8082825260208201915060208360061b86010192508583111561114c575f5ffd5b602085015b8381101561119a5760408188031215611168575f5ffd5b611170610fd2565b813581526111806020830161106e565b602082015280845250602083019250604081019050611151565b5095945050505050565b8035600781900b8114611084575f5ffd5b5f602082840312156111c5575f5ffd5b81356001600160401b038111156111da575f5ffd5b820160a081850312156111eb575f5ffd5b6111f3610ffa565b813581526112036020830161106e565b60208201526112146040830161106e565b604082015260608201356003811061122a575f5ffd5b606082015260808201356001600160401b03811115611247575f5ffd5b919091019060c0828603121561125b575f5ffd5b61126361101c565b61126c8361106e565b815261127a6020840161106e565b602082015260408301356001600160401b03811115611297575f5ffd5b6112a387828601611089565b60408301525060608301356001600160401b038111156112c1575f5ffd5b6112cd87828601611089565b60608301525060808301356001600160401b038111156112eb575f5ffd5b6112f7878286016110f4565b60808301525061130960a084016111a4565b60a08201526080820152949350505050565b5f6020828403121561132b575f5ffd5b5035919050565b5f60208284031215611342575f5ffd5b61134b8261106e565b9392505050565b6001600160a01b03811681146107d9575f5ffd5b5f60208284031215611376575f5ffd5b813561134b81611352565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156113a5575f5ffd5b815161134b81611352565b5f82518060208501845e5f920191825250919050565b634e487b7160e01b5f52601160045260245ffd5b5f816113e8576113e86113c6565b505f190190565b8082028115828204841417611406576114066113c6565b92915050565b81810381811115611406576114066113c656fea26469706673582212206b015543a79287239e49636728761f1308bdef4983c2b851fe1fa9eea9531b0764736f6c634300081b00330000000000000000000000006986c48e7ea039acc415ab2df4d3c0d36db40609ec3611e361c61412ffb6b15662be2ac6cd9bdcfa9227177b218f80700f1c6a4f5af6d81c929088b10c1f0eec52fd2ce69844fa9be1d417a4d7bda2928581dbd200000000000000000000000086fda4ed3492d1f1da4ff52cf0c2352b64922fc3
Deployed Bytecode
0x608060405260043610610108575f3560e01c80638da5cb5b11610092578063d366747f11610062578063d366747f146102f8578063e2bd914c1461032b578063e30c39781461035e578063f2fde38b1461037b578063fc7e47461461039a575f5ffd5b80638da5cb5b14610274578063a0e062fa14610290578063a79c8c09146102b2578063d0e30db0146102f0575f5ffd5b80636a5d9b59116100d85780636a5d9b59146101ce578063715018a61461021957806379ba50971461022d5780637b30d81314610241578063853828b614610260575f5ffd5b806317b7ee4f146101135780632e1a7d4d1461013457806351b42b001461015357806360846bc614610167575f5ffd5b3661010f57005b5f5ffd5b34801561011e575f5ffd5b5061013261012d3660046111b5565b6103ad565b005b34801561013f575f5ffd5b5061013261014e36600461131b565b61058b565b34801561015e575f5ffd5b506101326106fa565b348015610172575f5ffd5b506101a761018136600461131b565b60026020525f90815260409020546001600160401b03811690600160401b900460070b82565b604080516001600160401b03909316835260079190910b6020830152015b60405180910390f35b3480156101d9575f5ffd5b506102017f0000000000000000000000006986c48e7ea039acc415ab2df4d3c0d36db4060981565b6040516001600160a01b0390911681526020016101c5565b348015610224575f5ffd5b50610132610785565b348015610238575f5ffd5b50610132610798565b34801561024c575f5ffd5b5061013261025b366004611332565b6107dc565b34801561026b575f5ffd5b50610132610811565b34801561027f575f5ffd5b505f546001600160a01b0316610201565b34801561029b575f5ffd5b506102a461096e565b6040519081526020016101c5565b3480156102bd575f5ffd5b506001546102d890600160a01b90046001600160401b031681565b6040516001600160401b0390911681526020016101c5565b610132610a39565b348015610303575f5ffd5b506102a47fec3611e361c61412ffb6b15662be2ac6cd9bdcfa9227177b218f80700f1c6a4f81565b348015610336575f5ffd5b506102a47f5af6d81c929088b10c1f0eec52fd2ce69844fa9be1d417a4d7bda2928581dbd281565b348015610369575f5ffd5b506001546001600160a01b0316610201565b348015610386575f5ffd5b50610132610395366004611366565b610b31565b6101326103a8366004611332565b610ba1565b336001600160a01b037f0000000000000000000000006986c48e7ea039acc415ab2df4d3c0d36db4060916146103f657604051636e96d7e160e11b815260040160405180910390fd5b6103fe61096e565b81511461041e576040516397946a9d60e01b815260040160405180910390fd5b60808101515f5b8160800151518110156105865760405180604001604052808360800151838151811061045357610453611381565b6020026020010151602001516001600160401b031681526020018360a0015160070b81525060025f8460800151848151811061049157610491611381565b602090810291909101810151518252818101929092526040015f208251815493909201516001600160401b03908116600160401b026fffffffffffffffffffffffffffffffff1990941692169190911791909117905560808201518051829081106104fe576104fe611381565b60200260200101515f01517fa623627c34311a71b36da152b44076ede51861d701868671c9a6dfdd0f5da00a8360800151838151811061054057610540611381565b6020026020010151602001518460a001516040516105769291906001600160401b0392909216825260070b602082015260400190565b60405180910390a2600101610425565b505050565b610593610c13565b5f7f0000000000000000000000006986c48e7ea039acc415ab2df4d3c0d36db406096001600160a01b031663fbfa77cf6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105f0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106149190611395565b600154604051634338798360e01b8152600160a01b9091046001600160401b03166004820152602481018490529091506001600160a01b038216906343387983906044015f604051808303815f87803b15801561066f575f5ffd5b505af1158015610681573d5f5f3e3d5ffd5b50506040514792505f9150339083908381818185875af1925050503d805f81146106c6576040519150601f19603f3d011682016040523d82523d5f602084013e6106cb565b606091505b50509050806106f457604051632b596cb760e01b81523360048201526024015b60405180910390fd5b50505050565b610702610c13565b6001546040516343ba231760e11b8152600160a01b9091046001600160401b031660048201527f0000000000000000000000006986c48e7ea039acc415ab2df4d3c0d36db406096001600160a01b031690638774462e906024015f604051808303815f87803b158015610773575f5ffd5b505af11580156106f4573d5f5f3e3d5ffd5b61078d610c13565b6107965f610c3f565b565b60015433906001600160a01b031681146107d05760405163118cdaa760e01b81526001600160a01b03821660048201526024016106eb565b6107d981610c3f565b50565b6107e4610c13565b600180546001600160401b03909216600160a01b0267ffffffffffffffff60a01b19909216919091179055565b610819610c13565b5f7f0000000000000000000000006986c48e7ea039acc415ab2df4d3c0d36db406096001600160a01b031663fbfa77cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610876573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061089a9190611395565b60015460405163f4465fd560e01b8152600160a01b9091046001600160401b031660048201529091506001600160a01b0382169063f4465fd5906024015f604051808303815f87803b1580156108ee575f5ffd5b505af1158015610900573d5f5f3e3d5ffd5b50506040514792505f9150339083908381818185875af1925050503d805f8114610945576040519150601f19603f3d011682016040523d82523d5f602084013e61094a565b606091505b505090508061058657604051632b596cb760e01b81523360048201526024016106eb565b6001545f9063a466d31360e01b907fec3611e361c61412ffb6b15662be2ac6cd9bdcfa9227177b218f80700f1c6a4f90600160a01b90046001600160401b03166109b730610c58565b80516020918201206040516001600160e01b03199590951691850191909152602484019290925260c01b6001600160c01b0319166044830152604c8201527f5af6d81c929088b10c1f0eec52fd2ce69844fa9be1d417a4d7bda2928581dbd2606c820152608c0160405160208183030381529060405280519060200120905090565b5f7f0000000000000000000000006986c48e7ea039acc415ab2df4d3c0d36db406096001600160a01b031663fbfa77cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a96573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aba9190611395565b60015460405163576bcd2f60e01b8152600160a01b9091046001600160401b031660048201523060248201529091506001600160a01b0382169063576bcd2f9034906044015b5f604051808303818588803b158015610b17575f5ffd5b505af1158015610b29573d5f5f3e3d5ffd5b505050505050565b610b39610c13565b600180546001600160a01b0383166001600160a01b03199091168117909155610b695f546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b610ba9610c13565b60015460405163ba1b5f2360e01b8152600160a01b9091046001600160401b039081166004830152821660248201527f0000000000000000000000006986c48e7ea039acc415ab2df4d3c0d36db406096001600160a01b03169063ba1b5f23903490604401610b00565b5f546001600160a01b031633146107965760405163118cdaa760e01b81523360048201526024016106eb565b600180546001600160a01b03191690556107d981610e2c565b60605f610c6483610e7b565b90505f81604051602001610c7891906113b0565b60408051808303601f190181528282528051602090910120602a8084526060840190925292505f9190602082018180368337019050509050600360fc1b815f81518110610cc757610cc7611381565b60200101906001600160f81b03191690815f1a905350600f60fb1b81600181518110610cf557610cf5611381565b60200101906001600160f81b03191690815f1a90535084606083901c60295b6001811115610dff57600f8084169060079084161115610d84576f181899199a1a9b1b9c1ca0a121a222a360811b8160108110610d5357610d53611381565b1a60f81b858381518110610d6957610d69611381565b60200101906001600160f81b03191690815f1a905350610dd6565b6f181899199a1a9b1b9c1cb0b131b232b360811b8160108110610da957610da9611381565b1a60f81b858381518110610dbf57610dbf611381565b60200101906001600160f81b03191690815f1a9053505b5060016001609c1b03600493841c8116939290921c90911690610df8816113da565b9050610d14565b5082604051602001610e1191906113b0565b60405160208183030381529060405295505050505050919050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60408051602880825260608281019093525f9190602082018180368337019050509050825f5b6014811015610fb55760ff82166f181899199a1a9b1b9c1cb0b131b232b360811b600f600485901c1660108110610eda57610eda611381565b1a60f81b846001610eec8560026113ef565b610ef790602761140c565b610f01919061140c565b81518110610f1157610f11611381565b60200101906001600160f81b03191690815f1a9053506f181899199a1a9b1b9c1cb0b131b232b360811b600f821660108110610f4f57610f4f611381565b1a60f81b84610f5f8460026113ef565b610f6a90602761140c565b81518110610f7a57610f7a611381565b60200101906001600160f81b03191690815f1a9053505060089190911c72ffffffffffffffffffffffffffffffffffffff1690600101610ea1565b50909392505050565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b0381118282101715610ff457610ff4610fbe565b60405290565b60405160a081016001600160401b0381118282101715610ff457610ff4610fbe565b60405160c081016001600160401b0381118282101715610ff457610ff4610fbe565b604051601f8201601f191681016001600160401b038111828210171561106657611066610fbe565b604052919050565b80356001600160401b0381168114611084575f5ffd5b919050565b5f82601f830112611098575f5ffd5b81356001600160401b038111156110b1576110b1610fbe565b6110c4601f8201601f191660200161103e565b8181528460208386010111156110d8575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f82601f830112611103575f5ffd5b81356001600160401b0381111561111c5761111c610fbe565b61112b60208260051b0161103e565b8082825260208201915060208360061b86010192508583111561114c575f5ffd5b602085015b8381101561119a5760408188031215611168575f5ffd5b611170610fd2565b813581526111806020830161106e565b602082015280845250602083019250604081019050611151565b5095945050505050565b8035600781900b8114611084575f5ffd5b5f602082840312156111c5575f5ffd5b81356001600160401b038111156111da575f5ffd5b820160a081850312156111eb575f5ffd5b6111f3610ffa565b813581526112036020830161106e565b60208201526112146040830161106e565b604082015260608201356003811061122a575f5ffd5b606082015260808201356001600160401b03811115611247575f5ffd5b919091019060c0828603121561125b575f5ffd5b61126361101c565b61126c8361106e565b815261127a6020840161106e565b602082015260408301356001600160401b03811115611297575f5ffd5b6112a387828601611089565b60408301525060608301356001600160401b038111156112c1575f5ffd5b6112cd87828601611089565b60608301525060808301356001600160401b038111156112eb575f5ffd5b6112f7878286016110f4565b60808301525061130960a084016111a4565b60a08201526080820152949350505050565b5f6020828403121561132b575f5ffd5b5035919050565b5f60208284031215611342575f5ffd5b61134b8261106e565b9392505050565b6001600160a01b03811681146107d9575f5ffd5b5f60208284031215611376575f5ffd5b813561134b81611352565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156113a5575f5ffd5b815161134b81611352565b5f82518060208501845e5f920191825250919050565b634e487b7160e01b5f52601160045260245ffd5b5f816113e8576113e86113c6565b505f190190565b8082028115828204841417611406576114066113c6565b92915050565b81810381811115611406576114066113c656fea26469706673582212206b015543a79287239e49636728761f1308bdef4983c2b851fe1fa9eea9531b0764736f6c634300081b0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000006986c48e7ea039acc415ab2df4d3c0d36db40609ec3611e361c61412ffb6b15662be2ac6cd9bdcfa9227177b218f80700f1c6a4f5af6d81c929088b10c1f0eec52fd2ce69844fa9be1d417a4d7bda2928581dbd200000000000000000000000086fda4ed3492d1f1da4ff52cf0c2352b64922fc3
-----Decoded View---------------
Arg [0] : tunnelRouter_ (address): 0x6986C48e7EA039acc415Ab2Df4d3c0D36DB40609
Arg [1] : hashedSourceChainId_ (bytes32): 0xec3611e361c61412ffb6b15662be2ac6cd9bdcfa9227177b218f80700f1c6a4f
Arg [2] : hashedTargetChainId_ (bytes32): 0x5af6d81c929088b10c1f0eec52fd2ce69844fa9be1d417a4d7bda2928581dbd2
Arg [3] : initialOwner (address): 0x86FdA4Ed3492D1F1Da4Ff52Cf0c2352b64922fC3
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000006986c48e7ea039acc415ab2df4d3c0d36db40609
Arg [1] : ec3611e361c61412ffb6b15662be2ac6cd9bdcfa9227177b218f80700f1c6a4f
Arg [2] : 5af6d81c929088b10c1f0eec52fd2ce69844fa9be1d417a4d7bda2928581dbd2
Arg [3] : 00000000000000000000000086fda4ed3492d1f1da4ff52cf0c2352b64922fc3
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.