Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
OmniPortal
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-only pragma solidity =0.8.24; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import { ExcessivelySafeCall } from "@nomad-xyz/excessively-safe-call/src/ExcessivelySafeCall.sol"; import { IFeeOracle } from "../interfaces/IFeeOracle.sol"; import { IOmniPortal } from "../interfaces/IOmniPortal.sol"; import { IOmniPortalSys } from "../interfaces/IOmniPortalSys.sol"; import { IOmniPortalAdmin } from "../interfaces/IOmniPortalAdmin.sol"; import { XBlockMerkleProof } from "../libraries/XBlockMerkleProof.sol"; import { XTypes } from "../libraries/XTypes.sol"; import { Quorum } from "../libraries/Quorum.sol"; import { ConfLevel } from "../libraries/ConfLevel.sol"; import { PausableUpgradeable } from "../utils/Pausable.sol"; import { OmniPortalConstants } from "./OmniPortalConstants.sol"; import { OmniPortalStorage } from "./OmniPortalStorage.sol"; contract OmniPortal is IOmniPortal, IOmniPortalSys, IOmniPortalAdmin, OwnableUpgradeable, PausableUpgradeable, ReentrancyGuardUpgradeable, OmniPortalConstants, OmniPortalStorage { using ExcessivelySafeCall for address; /** * @notice Modifier the requires an action is not paused. An action is paused if: * - actionId is paused for all chains * - actionId is paused for chainId * - All actions are paused * Available actions are ActionXCall and ActionXSubmit, defined in OmniPortalConstants.sol. */ modifier whenNotPaused(bytes32 actionId, uint64 chainId_) { require(!_isPaused(actionId, _chainActionId(actionId, chainId_)), "OmniPortal: paused"); _; } /** * @notice Construct the OmniPortal contract */ constructor() { _disableInitializers(); } /** * @notice Initialization init params * @dev Used to reduce stack depth in initialize() * @custom:field owner The owner of the contract * @custom:field feeOracle Address of the fee oracle contract * @custom:field omniChainId Chain ID of Omni's EVM execution chain * @custom:field omniCChainId Chain ID of Omni's consensus chain * @custom:field xmsgMaxGasLimit Maximum gas limit for xmsg * @custom:field xmsgMinGasLimit Minimum gas limit for xmsg * @custom:field xmsgMaxDataSize Maximum size of xmsg data in bytes * @custom:field xreceiptMaxErrorSize Maximum size of xreceipt error in bytes * @custom:field xsubValsetCutoff Number of validator sets since the latest that validate an XSubmission * @custom:field cChainXMsgOffset Offset for xmsgs from the consensus chain * @custom:field cChainXBlockOffset Offset for xblocks from the consensus chain * @custom:field valSetId Initial validator set id * @custom:field validators Initial validator set */ struct InitParams { address owner; address feeOracle; uint64 omniChainId; uint64 omniCChainId; uint64 xmsgMaxGasLimit; uint64 xmsgMinGasLimit; uint16 xmsgMaxDataSize; uint16 xreceiptMaxErrorSize; uint8 xsubValsetCutoff; uint64 cChainXMsgOffset; uint64 cChainXBlockOffset; uint64 valSetId; XTypes.Validator[] validators; } /** * @notice Initialize the OmniPortal contract */ function initialize(InitParams calldata p) public initializer { __Ownable_init(p.owner); _setFeeOracle(p.feeOracle); _setXMsgMaxGasLimit(p.xmsgMaxGasLimit); _setXMsgMinGasLimit(p.xmsgMinGasLimit); _setXMsgMaxDataSize(p.xmsgMaxDataSize); _setXReceiptMaxErrorSize(p.xreceiptMaxErrorSize); _setXSubValsetCutoff(p.xsubValsetCutoff); _addValidatorSet(p.valSetId, p.validators); omniChainId = p.omniChainId; omniCChainId = p.omniCChainId; // omni consensus chain uses Finalised+Broadcast shard uint64 omniCShard = ConfLevel.toBroadcastShard(ConfLevel.Finalized); inXMsgOffset[p.omniCChainId][omniCShard] = p.cChainXMsgOffset; inXBlockOffset[p.omniCChainId][omniCShard] = p.cChainXBlockOffset; } function chainId() public view returns (uint64) { return uint64(block.chainid); } ////////////////////////////////////////////////////////////////////////////// // Outbound xcall functions // ////////////////////////////////////////////////////////////////////////////// /** * @notice Call a contract on another chain. * @param destChainId Destination chain ID * @param conf Confirmation level * @param to Address of contract to call on destination chain * @param data ABI Encoded function calldata * @param gasLimit Execution gas limit, enforced on destination chain */ function xcall(uint64 destChainId, uint8 conf, address to, bytes calldata data, uint64 gasLimit) external payable whenNotPaused(ActionXCall, destChainId) { require(isSupportedDest[destChainId], "OmniPortal: unsupported dest"); require(to != VirtualPortalAddress, "OmniPortal: no portal xcall"); require(gasLimit <= xmsgMaxGasLimit, "OmniPortal: gasLimit too high"); require(gasLimit >= xmsgMinGasLimit, "OmniPortal: gasLimit too low"); require(data.length <= xmsgMaxDataSize, "OmniPortal: data too large"); // conf level will always be first byte of shardId. for now, shardId is just conf level uint64 shardId = uint64(conf); require(isSupportedShard[shardId], "OmniPortal: unsupported shard"); uint256 fee = feeFor(destChainId, data, gasLimit); require(msg.value >= fee, "OmniPortal: insufficient fee"); outXMsgOffset[destChainId][shardId] += 1; emit XMsg(destChainId, shardId, outXMsgOffset[destChainId][shardId], msg.sender, to, data, gasLimit, fee); } /** * @notice Calculate the fee for calling a contract on another chain * Fees denominated in wei. * @param destChainId Destination chain ID * @param data Encoded function calldata * @param gasLimit Execution gas limit, enforced on destination chain */ function feeFor(uint64 destChainId, bytes calldata data, uint64 gasLimit) public view returns (uint256) { return IFeeOracle(feeOracle).feeFor(destChainId, data, gasLimit); } ////////////////////////////////////////////////////////////////////////////// // Inbound xcall functions // ////////////////////////////////////////////////////////////////////////////// /** * @notice Submit a batch of XMsgs to be executed on this chain * @param xsub An xchain submission, including an attestation root w/ validator signatures, * and a block header and message batch, proven against the attestation root. */ function xsubmit(XTypes.Submission calldata xsub) external whenNotPaused(ActionXSubmit, xsub.blockHeader.sourceChainId) nonReentrant { XTypes.Msg[] calldata xmsgs = xsub.msgs; XTypes.BlockHeader calldata xheader = xsub.blockHeader; uint64 valSetId = xsub.validatorSetId; require(xheader.consensusChainId == omniCChainId, "OmniPortal: wrong cchain ID"); require(xmsgs.length > 0, "OmniPortal: no xmsgs"); require(valSetTotalPower[valSetId] > 0, "OmniPortal: unknown val set"); require(valSetId >= _minValSet(), "OmniPortal: old val set"); // check that the attestationRoot is signed by a quorum of validators in xsub.validatorsSetId require( Quorum.verify( xsub.attestationRoot, xsub.signatures, valSet[valSetId], valSetTotalPower[valSetId], XSubQuorumNumerator, XSubQuorumDenominator ), "OmniPortal: no quorum" ); // check that blockHeader and xmsgs are included in attestationRoot require( XBlockMerkleProof.verify(xsub.attestationRoot, xheader, xmsgs, xsub.proof, xsub.proofFlags), "OmniPortal: invalid proof" ); // execute xmsgs for (uint256 i = 0; i < xmsgs.length; i++) { _exec(xheader, xmsgs[i]); } } /** * @notice Returns the current XMsg being executed via this portal. * - xmsg().sourceChainId Chain ID of the source xcall * - xmsg().sender msg.sender of the source xcall * If no XMsg is being executed, all fields will be zero. * - xmsg().sourceChainId == 0 * - xmsg().sender == address(0) */ function xmsg() external view returns (XTypes.MsgContext memory) { return _xmsg; } /** * @notice Returns true the current transaction is an xcall, false otherwise */ function isXCall() external view returns (bool) { return _xmsg.sourceChainId != 0; } /** * @notice Execute an xmsg. * @dev Verify if an XMsg is next in its XStream, execute it, increment inXMsgOffset, emit an XReceipt event */ function _exec(XTypes.BlockHeader memory xheader, XTypes.Msg calldata xmsg_) internal { uint64 sourceChainId = xheader.sourceChainId; uint64 destChainId = xmsg_.destChainId; uint64 shardId = xmsg_.shardId; uint64 offset = xmsg_.offset; require(destChainId == chainId() || destChainId == BroadcastChainId, "OmniPortal: wrong dest chain"); require(offset == inXMsgOffset[sourceChainId][shardId] + 1, "OmniPortal: wrong offset"); // verify xmsg conf level matches xheader conf level // allow finalized blocks to for any xmsg, so that finalized blocks may correct "fuzzy" xmsgs require( ConfLevel.Finalized == xheader.confLevel || xheader.confLevel == uint8(shardId), "OmniPortal: wrong conf level" ); if (inXBlockOffset[sourceChainId][shardId] < xheader.offset) { inXBlockOffset[sourceChainId][shardId] = xheader.offset; } inXMsgOffset[sourceChainId][shardId] += 1; // do not allow user xcalls to the portal // only sys xcalls (to _VIRTUAL_PORTAL_ADDRESS) are allowed to be executed on the portal if (xmsg_.to == address(this)) { emit XReceipt( sourceChainId, shardId, offset, 0, msg.sender, false, abi.encodeWithSignature("Error(string)", "OmniPortal: no xcall to portal") ); return; } // set _xmsg to the one we're executing, allowing external contracts to query the current xmsg via xmsg() _xmsg = XTypes.MsgContext(sourceChainId, xmsg_.sender); (bool success, bytes memory result, uint256 gasUsed) = xmsg_.to == VirtualPortalAddress // calls to VirtualPortalAddress are syscalls ? _syscall(xmsg_.data) : _call(xmsg_.to, xmsg_.gasLimit, xmsg_.data); // reset xmsg to zero delete _xmsg; bytes memory errorMsg = success ? bytes("") : result; emit XReceipt(sourceChainId, shardId, offset, gasUsed, msg.sender, success, errorMsg); } /** * @notice Call an external contract. * @dev Returns the result of the call, the gas used, and whether the call was successful. * @param to The address of the contract to call. * @param gasLimit Gas limit of the call. * @param data Calldata to send to the contract. */ function _call(address to, uint256 gasLimit, bytes calldata data) internal returns (bool, bytes memory, uint256) { uint256 gasLeftBefore = gasleft(); // use excessivelySafeCall for external calls to prevent large return bytes mem copy (bool success, bytes memory result) = to.excessivelySafeCall({ _gas: gasLimit, _value: 0, _maxCopy: xreceiptMaxErrorSize, _calldata: data }); uint256 gasLeftAfter = gasleft(); // Ensure relayer sent enough gas for the call // See https://github.com/OpenZeppelin/openzeppelin-contracts/blob/bd325d56b4c62c9c5c1aff048c37c6bb18ac0290/contracts/metatx/MinimalForwarder.sol#L58-L68 if (gasLeftAfter <= gasLimit / 63) { // We use invalid opcode to consume all gas and bubble-up the effects, to emulate an "OutOfGas" exception assembly { invalid() } } return (success, result, gasLeftBefore - gasLeftAfter); } /** * @notice Call a function on the current contract. * @dev Reverts on failure. We match _call() return signature for symmetry. * @param data Calldata to execute on the current contract. */ function _syscall(bytes calldata data) internal returns (bool, bytes memory, uint256) { uint256 gasUsed = gasleft(); (bool success, bytes memory result) = address(this).call(data); gasUsed = gasUsed - gasleft(); // if not success, revert with same reason if (!success) { assembly { revert(add(result, 32), mload(result)) } } return (success, result, gasUsed); } /** * @notice Returns the minimum validator set id that can be used for xsubmissions */ function _minValSet() internal view returns (uint64) { return latestValSetId > xsubValsetCutoff // plus 1, so the number of accepted valsets == XSubValsetCutoff ? (latestValSetId - xsubValsetCutoff + 1) : 1; } ////////////////////////////////////////////////////////////////////////////// // Syscall functions // ////////////////////////////////////////////////////////////////////////////// /** * @notice Add a new validator set. * @dev Only callable via xcall from Omni's consensus chain * @param valSetId Validator set id * @param validators Validator set */ function addValidatorSet(uint64 valSetId, XTypes.Validator[] calldata validators) external { require(msg.sender == address(this), "OmniPortal: only self"); require(_xmsg.sourceChainId == omniCChainId, "OmniPortal: only cchain"); require(_xmsg.sender == CChainSender, "OmniPortal: only cchain sender"); _addValidatorSet(valSetId, validators); } /** * @notice Add a new validator set * @param valSetId Validator set id * @param validators Validator set */ function _addValidatorSet(uint64 valSetId, XTypes.Validator[] calldata validators) internal { uint256 numVals = validators.length; require(numVals > 0, "OmniPortal: no validators"); require(valSetTotalPower[valSetId] == 0, "OmniPortal: duplicate val set"); uint64 totalPower; XTypes.Validator memory val; mapping(address => uint64) storage valSet = valSet[valSetId]; for (uint256 i = 0; i < numVals; i++) { val = validators[i]; require(val.addr != address(0), "OmniPortal: no zero validator"); require(val.power > 0, "OmniPortal: no zero power"); require(valSet[val.addr] == 0, "OmniPortal: duplicate validator"); totalPower += val.power; valSet[val.addr] = val.power; } valSetTotalPower[valSetId] = totalPower; if (valSetId > latestValSetId) latestValSetId = valSetId; emit ValidatorSetAdded(valSetId); } /** * @notice Set the network of supported chains & shards * @dev Only callable via xcall from Omni's consensus chain * @param network_ The new network */ function setNetwork(XTypes.Chain[] calldata network_) external { require(msg.sender == address(this), "OmniPortal: only self"); require(_xmsg.sourceChainId == omniCChainId, "OmniPortal: only cchain"); require(_xmsg.sender == CChainSender, "OmniPortal: only cchain sender"); _setNetwork(network_); } /** * @notice Set the network of supported chains & shards * @param network_ The new network */ function _setNetwork(XTypes.Chain[] calldata network_) internal { _clearNetwork(); XTypes.Chain calldata c; for (uint256 i = 0; i < network_.length; i++) { c = network_[i]; network.push(c); // if not this chain, mark as supported dest if (c.chainId != chainId()) { isSupportedDest[c.chainId] = true; continue; } // if this chain, mark shards as supported for (uint256 j = 0; j < c.shards.length; j++) { isSupportedShard[c.shards[j]] = true; } } } /** * @notice Clear the network of supported chains & shards */ function _clearNetwork() private { XTypes.Chain storage c; for (uint256 i = 0; i < network.length; i++) { c = network[i]; // if not this chain, mark as unsupported dest if (c.chainId != chainId()) { isSupportedDest[c.chainId] = false; continue; } // if this chain, mark shards as unsupported for (uint256 j = 0; j < c.shards.length; j++) { isSupportedShard[c.shards[j]] = false; } } delete network; } ////////////////////////////////////////////////////////////////////////////// // Admin functions // ////////////////////////////////////////////////////////////////////////////// /** * @notice Set the inbound xmsg offset for a chain and shard * @param sourceChainId Source chain ID * @param shardId Shard ID * @param offset New xmsg offset */ function setInXMsgOffset(uint64 sourceChainId, uint64 shardId, uint64 offset) external onlyOwner { inXMsgOffset[sourceChainId][shardId] = offset; emit InXMsgOffsetSet(sourceChainId, shardId, offset); } /** * @notice Set the inbound xblock offset for a chain and shard * @param sourceChainId Source chain ID * @param shardId Shard ID * @param offset New xblock offset */ function setInXBlockOffset(uint64 sourceChainId, uint64 shardId, uint64 offset) external onlyOwner { inXBlockOffset[sourceChainId][shardId] = offset; emit InXBlockOffsetSet(sourceChainId, shardId, offset); } /** * @notice Set the fee oracle */ function setFeeOracle(address feeOracle_) external onlyOwner { _setFeeOracle(feeOracle_); } /** * @notice Transfer all collected fees to the give address * @param to The address to transfer the fees to */ function collectFees(address to) external onlyOwner { uint256 amount = address(this).balance; // .transfer() is fine, owner should provide an EOA address that will not // consume more than 2300 gas on transfer, and we are okay .transfer() reverts payable(to).transfer(amount); emit FeesCollected(to, amount); } /** * @notice Set the minimum gas limit for xmsg */ function setXMsgMinGasLimit(uint64 gasLimit) external onlyOwner { _setXMsgMinGasLimit(gasLimit); } /** * @notice Set the maximum gas limit for xmsg */ function setXMsgMaxGasLimit(uint64 gasLimit) external onlyOwner { _setXMsgMaxGasLimit(gasLimit); } /** * @notice Set the maximum error bytes for xreceipt */ function setXMsgMaxDataSize(uint16 numBytes) external onlyOwner { _setXMsgMaxDataSize(numBytes); } /** * @notice Set the maximum error bytes for xreceipt */ function setXReceiptMaxErrorSize(uint16 numBytes) external onlyOwner { _setXReceiptMaxErrorSize(numBytes); } /** * @notice Set the number of validator sets since the latest that can validate an XSubmission */ function setXSubValsetCutoff(uint8 xsubValsetCutoff_) external onlyOwner { _setXSubValsetCutoff(xsubValsetCutoff_); } /** * @notice Pause xcalls and xsubissions from all chains */ function pause() external onlyOwner { _pauseAll(); emit Paused(); } /** * @notice Unpause xcalls and xsubissions from all chains */ function unpause() external onlyOwner { _unpauseAll(); emit Unpaused(); } /** * @notice Pause xcalls to all chains */ function pauseXCall() external onlyOwner { _pause(ActionXCall); emit XCallPaused(); } /** * @notice Unpause xcalls to all chains */ function unpauseXCall() external onlyOwner { _unpause(ActionXCall); emit XCallUnpaused(); } /** * @notice Pause xcalls to a specific chain * @param chainId_ Destination chain ID */ function pauseXCallTo(uint64 chainId_) external onlyOwner { _pause(_chainActionId(ActionXCall, chainId_)); emit XCallToPaused(chainId_); } /** * @notice Unpause xcalls to a specific chain * @param chainId_ Destination chain ID */ function unpauseXCallTo(uint64 chainId_) external onlyOwner { _unpause(_chainActionId(ActionXCall, chainId_)); emit XCallToUnpaused(chainId_); } /** * @notice Pause xsubmissions from all chains */ function pauseXSubmit() external onlyOwner { _pause(ActionXSubmit); emit XSubmitPaused(); } /** * @notice Unpause xsubmissions from all chains */ function unpauseXSubmit() external onlyOwner { _unpause(ActionXSubmit); emit XSubmitUnpaused(); } /** * @notice Pause xsubmissions from a specific chain * @param chainId_ Source chain ID */ function pauseXSubmitFrom(uint64 chainId_) external onlyOwner { _pause(_chainActionId(ActionXSubmit, chainId_)); emit XSubmitFromPaused(chainId_); } /** * @notice Unpause xsubmissions from a specific chain * @param chainId_ Source chain ID */ function unpauseXSubmitFrom(uint64 chainId_) external onlyOwner { _unpause(_chainActionId(ActionXSubmit, chainId_)); emit XSubmitFromUnpaused(chainId_); } /** * @notice Return true if actionId for is paused for the given chain */ function isPaused(bytes32 actionId, uint64 chainId_) external view returns (bool) { return _isPaused(actionId, _chainActionId(actionId, chainId_)); } /** * @notice Return true if actionId is paused for all chains */ function isPaused(bytes32 actionId) external view returns (bool) { return _isPaused(actionId); } /* * @notice Return true if all actions are paused */ function isPaused() external view returns (bool) { return _isAllPaused(); } /** * @notice An action id with a qualifiying chain id, used as pause keys. */ function _chainActionId(bytes32 actionId, uint64 chainId_) internal pure returns (bytes32) { return keccak256(abi.encodePacked(actionId, chainId_)); } /** * @notice Set the minimum gas limit for xmsg */ function _setXMsgMinGasLimit(uint64 gasLimit) internal { require(gasLimit > 0, "OmniPortal: no zero min gas"); xmsgMinGasLimit = gasLimit; emit XMsgMinGasLimitSet(gasLimit); } /** * @notice Set the maximum gas limit for xmsg */ function _setXMsgMaxGasLimit(uint64 gasLimit) internal { require(gasLimit > 0, "OmniPortal: no zero max gas"); xmsgMaxGasLimit = gasLimit; emit XMsgMaxGasLimitSet(gasLimit); } /** * @notice Set the maximum data bytes for xmsg */ function _setXMsgMaxDataSize(uint16 numBytes) internal { require(numBytes > 0, "OmniPortal: no zero max size"); xmsgMaxDataSize = numBytes; emit XMsgMaxDataSizeSet(numBytes); } /** * @notice Set the maximum error bytes for xreceipt */ function _setXReceiptMaxErrorSize(uint16 numBytes) internal { require(numBytes > 0, "OmniPortal: no zero max size"); xreceiptMaxErrorSize = numBytes; emit XReceiptMaxErrorSizeSet(numBytes); } /** * @notice Set the number of validator sets since the latest that can validate an XSubmission */ function _setXSubValsetCutoff(uint8 xsubValsetCutoff_) internal { require(xsubValsetCutoff_ > 0, "OmniPortal: no zero cutoff"); xsubValsetCutoff = xsubValsetCutoff_; emit XSubValsetCutoffSet(xsubValsetCutoff_); } /** * @notice Set the fee oracle */ function _setFeeOracle(address feeOracle_) internal { require(feeOracle_ != address(0), "OmniPortal: no zero feeOracle"); feeOracle = feeOracle_; emit FeeOracleSet(feeOracle_); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @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 ReentrancyGuardUpgradeable is Initializable { // 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; /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard struct ReentrancyGuardStorage { uint256 _status; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ReentrancyGuardStorageLocation = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00; function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) { assembly { $.slot := ReentrancyGuardStorageLocation } } /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); $._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 { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // On the first call to nonReentrant, _status will be NOT_ENTERED if ($._status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail $._status = ENTERED; } function _nonReentrantAfter() private { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // 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) { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); return $._status == ENTERED; } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.7.6; library ExcessivelySafeCall { uint256 constant LOW_28_MASK = 0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff; /// @notice Use when you _really_ really _really_ don't trust the called /// contract. This prevents the called contract from causing reversion of /// the caller in as many ways as we can. /// @dev The main difference between this and a solidity low-level call is /// that we limit the number of bytes that the callee can cause to be /// copied to caller memory. This prevents stupid things like malicious /// contracts returning 10,000,000 bytes causing a local OOG when copying /// to memory. /// @param _target The address to call /// @param _gas The amount of gas to forward to the remote contract /// @param _value The value in wei to send to the remote contract /// @param _maxCopy The maximum number of bytes of returndata to copy /// to memory. /// @param _calldata The data to send to the remote contract /// @return success and returndata, as `.call()`. Returndata is capped to /// `_maxCopy` bytes. function excessivelySafeCall( address _target, uint256 _gas, uint256 _value, uint16 _maxCopy, bytes memory _calldata ) internal returns (bool, bytes memory) { // set up for assembly call uint256 _toCopy; bool _success; bytes memory _returnData = new bytes(_maxCopy); // dispatch message to recipient // by assembly calling "handle" function // we call via assembly to avoid memcopying a very large returndata // returned by a malicious contract assembly { _success := call( _gas, // gas _target, // recipient _value, // ether value add(_calldata, 0x20), // inloc mload(_calldata), // inlen 0, // outloc 0 // outlen ) // limit our copy to 256 bytes _toCopy := returndatasize() if gt(_toCopy, _maxCopy) { _toCopy := _maxCopy } // Store the length of the copied bytes mstore(_returnData, _toCopy) // copy the bytes from returndata[0:_toCopy] returndatacopy(add(_returnData, 0x20), 0, _toCopy) } return (_success, _returnData); } /// @notice Use when you _really_ really _really_ don't trust the called /// contract. This prevents the called contract from causing reversion of /// the caller in as many ways as we can. /// @dev The main difference between this and a solidity low-level call is /// that we limit the number of bytes that the callee can cause to be /// copied to caller memory. This prevents stupid things like malicious /// contracts returning 10,000,000 bytes causing a local OOG when copying /// to memory. /// @param _target The address to call /// @param _gas The amount of gas to forward to the remote contract /// @param _maxCopy The maximum number of bytes of returndata to copy /// to memory. /// @param _calldata The data to send to the remote contract /// @return success and returndata, as `.call()`. Returndata is capped to /// `_maxCopy` bytes. function excessivelySafeStaticCall( address _target, uint256 _gas, uint16 _maxCopy, bytes memory _calldata ) internal view returns (bool, bytes memory) { // set up for assembly call uint256 _toCopy; bool _success; bytes memory _returnData = new bytes(_maxCopy); // dispatch message to recipient // by assembly calling "handle" function // we call via assembly to avoid memcopying a very large returndata // returned by a malicious contract assembly { _success := staticcall( _gas, // gas _target, // recipient add(_calldata, 0x20), // inloc mload(_calldata), // inlen 0, // outloc 0 // outlen ) // limit our copy to 256 bytes _toCopy := returndatasize() if gt(_toCopy, _maxCopy) { _toCopy := _maxCopy } // Store the length of the copied bytes mstore(_returnData, _toCopy) // copy the bytes from returndata[0:_toCopy] returndatacopy(add(_returnData, 0x20), 0, _toCopy) } return (_success, _returnData); } /** * @notice Swaps function selectors in encoded contract calls * @dev Allows reuse of encoded calldata for functions with identical * argument types but different names. It simply swaps out the first 4 bytes * for the new selector. This function modifies memory in place, and should * only be used with caution. * @param _newSelector The new 4-byte selector * @param _buf The encoded contract args */ function swapSelector(bytes4 _newSelector, bytes memory _buf) internal pure { require(_buf.length >= 4); uint256 _mask = LOW_28_MASK; assembly { // load the first word of let _word := mload(add(_buf, 0x20)) // mask out the top 4 bytes // /x _word := and(_word, _mask) _word := or(_newSelector, _word) mstore(add(_buf, 0x20), _word) } } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.12; /** * @title IFeeOracle * @notice Defines the interface expected of a fee oracle by the OmniPortal */ interface IFeeOracle { /** * @notice Calculate the fee for calling a contract on another chain * @dev Fees denominated in wei * @param destChainId Destination chain ID * @param data Encoded function calldata * @param gasLimit Execution gas limit, enforced on destination chain */ function feeFor(uint64 destChainId, bytes calldata data, uint64 gasLimit) external view returns (uint256); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.12; import { XTypes } from "../libraries/XTypes.sol"; /** * @title IOmniPortal * @notice The OmniPortal is the on-chain interface to Omni's cross-chain * messaging protocol. It is used to initiate and execute cross-chain calls. */ interface IOmniPortal { /** * @notice Emitted when an xcall is made to a contract on another chain * @param destChainId Destination chain ID * @param offset Offset this XMsg in the source -> dest XStream * @param sender msg.sender of the source xcall * @param to Address of the contract to call on the destination chain * @param data Encoded function calldata * @param gasLimit Gas limit for execution on destination chain * @param fees Fees paid for the xcall */ event XMsg( uint64 indexed destChainId, uint64 indexed shardId, uint64 indexed offset, address sender, address to, bytes data, uint64 gasLimit, uint256 fees ); /** * @notice Emitted when an XMsg is executed on its destination chain * @param sourceChainId Source chain ID * @param shardId Shard ID of the XStream (first byte is the confirmation level) * @param offset Offset the XMsg in the source -> dest XStream * @param gasUsed Gas used in execution of the XMsg * @param success Whether the execution succeeded * @param relayer Address of the relayer who submitted the XMsg * @param error Result of XMsg execution, if success == false. Limited to * xreceiptMaxErrorBytes(). Empty if success == true. */ event XReceipt( uint64 indexed sourceChainId, uint64 indexed shardId, uint64 indexed offset, uint256 gasUsed, address relayer, bool success, bytes error ); /** * @notice Maximum allowed xmsg gas limit */ function xmsgMaxGasLimit() external view returns (uint64); /** * @notice Minimum allowed xmsg gas limit */ function xmsgMinGasLimit() external view returns (uint64); /** * @notice Maximum number of bytes allowed in xmsg data */ function xmsgMaxDataSize() external view returns (uint16); /** * @notice Maxium number of bytes allowed in xreceipt result */ function xreceiptMaxErrorSize() external view returns (uint16); /** * @notice Returns the fee oracle address */ function feeOracle() external view returns (address); /** * @notice Returns the chain ID of the chain to which this portal is deployed */ function chainId() external view returns (uint64); /** * @notice Returns the chain ID of Omni's EVM execution chain */ function omniChainId() external view returns (uint64); /** * @notice Returns the offset of the last outbound XMsg sent to destChainId in shardId */ function outXMsgOffset(uint64 destChainId, uint64 shardId) external view returns (uint64); /** * @notice Returns the offset of the last inbound XMsg received from srcChainId in shardId */ function inXMsgOffset(uint64 srcChainId, uint64 shardId) external view returns (uint64); /** * @notice Returns the offset of the last inbound XBlock received from srcChainId in shardId */ function inXBlockOffset(uint64 srcChainId, uint64 shardId) external view returns (uint64); /** * @notice Returns the current XMsg being executed via this portal. * - xmsg().sourceChainId Chain ID of the source xcall * - xmsg().sender msg.sender of the source xcall * If no XMsg is being executed, all fields will be zero. * - xmsg().sourceChainId == 0 * - xmsg().sender == address(0) */ function xmsg() external view returns (XTypes.MsgContext memory); /** * @notice Returns true the current transaction is an xcall, false otherwise */ function isXCall() external view returns (bool); /** * @notice Returns the shard ID is supported by this portal */ function isSupportedShard(uint64 shardId) external view returns (bool); /** * @notice Returns the destination chain ID is supported by this portal */ function isSupportedDest(uint64 destChainId) external view returns (bool); /** * @notice Calculate the fee for calling a contract on another chain * Fees denominated in wei. * @param destChainId Destination chain ID * @param data Encoded function calldata * @param gasLimit Execution gas limit, enforced on destination chain */ function feeFor(uint64 destChainId, bytes calldata data, uint64 gasLimit) external view returns (uint256); /** * @notice Call a contract on another chain. * @param destChainId Destination chain ID * @param conf Confirmation level; * @param to Address of contract to call on destination chain * @param data ABI Encoded function calldata * @param gasLimit Execution gas limit, enforced on destination chain */ function xcall(uint64 destChainId, uint8 conf, address to, bytes calldata data, uint64 gasLimit) external payable; /** * @notice Submit a batch of XMsgs to be executed on this chain * @param xsub An xchain submisison, including an attestation root w/ validator signatures, * and a block header and message batch, proven against the attestation root. */ function xsubmit(XTypes.Submission calldata xsub) external; }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.12; import { XTypes } from "../libraries/XTypes.sol"; /** * @title IOmniPortalSys * @notice Defines syscall functions internal to Omni's cross-chain messaging protocol */ interface IOmniPortalSys { /** * @notice Emitted when a new validator set is added * @param setId Validator set ID */ event ValidatorSetAdded(uint64 indexed setId); /** * @notice Add a new validator set. * @dev Only callable via xcall from Omni's consensus chain * @param valSetId Validator set id * @param validators Validator set */ function addValidatorSet(uint64 valSetId, XTypes.Validator[] calldata validators) external; /** * @notice Set the network of supported chains & shards * @dev Only callable via xcall from Omni's consensus chain * @param network_ The new network */ function setNetwork(XTypes.Chain[] calldata network_) external; }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.12; /** * @title IOmniPortalAdmin * @notice Defines the OmniPortal admin interface */ interface IOmniPortalAdmin { /** * @notice Emitted when the fee oracle is updated. * @param oracle The new fee oracle address */ event FeeOracleSet(address oracle); /** * @notice Emited when fees are collected * @param to The address the fees are collected to * @param amount The amount of fees collected */ event FeesCollected(address indexed to, uint256 amount); /** * @notice Emitted when xmsgMinGasLimit is updated * @param gasLimit The new xmsgMinGasLimit */ event XMsgMinGasLimitSet(uint64 gasLimit); /** * @notice Emitted when xmsgMaxGasLimit is updated * @param gasLimit The new xmsgMaxGasLimit */ event XMsgMaxGasLimitSet(uint64 gasLimit); /** * @notice Emitted when xmsgMaxDataSize is updated * @param size The new max size */ event XMsgMaxDataSizeSet(uint16 size); /** * @notice Emitted when xreceiptMaxErrorSize is updated * @param size The new max size */ event XReceiptMaxErrorSizeSet(uint16 size); /** * @notice Emitted when the xsubValsetCutoff is updated * @param cutoff The new cutoff */ event XSubValsetCutoffSet(uint8 cutoff); /** * @notice Emitted the portal is paused, all xcalls and xsubmissions */ event Paused(); /** * @notice Emitted the portal is unpaused, all xcalls and xsubmissions */ event Unpaused(); /** * @notice Emitted when all xcalls are paused */ event XCallPaused(); /** * @notice Emitted when inbound xmsg offset is updated */ event InXMsgOffsetSet(uint64 indexed srcChainId, uint64 indexed shardId, uint64 offset); /** * @notice Emitted when all inbound xblock offset is updated */ event InXBlockOffsetSet(uint64 indexed srcChainId, uint64 indexed shardId, uint64 offset); /** * @notice Emitted when all xcalls are unpaused */ event XCallUnpaused(); /** * @notice Emitted when all xsubmissions are paused */ event XSubmitPaused(); /** * @notice Emitted when all xsubmissions are unpaused */ event XSubmitUnpaused(); /** * @notice Emitted when xcalls to a specific chain are paused * @param chainId The destination chain */ event XCallToPaused(uint64 indexed chainId); /** * @notice Emitted when xcalls to a specific chain are unpaused * @param chainId The destination chain */ event XCallToUnpaused(uint64 indexed chainId); /** * @notice Emitted when xsubmissions from a specific chain are paused * @param chainId The source chain */ event XSubmitFromPaused(uint64 indexed chainId); /** * @notice Emitted when xsubmissions from a specific chain are unpaused * @param chainId The source chain */ event XSubmitFromUnpaused(uint64 indexed chainId); /** * @notice Set the inbound xmsg offset for a chain and shard * @param sourceChainId Source chain ID * @param shardId Shard ID * @param offset New xmsg offset */ function setInXMsgOffset(uint64 sourceChainId, uint64 shardId, uint64 offset) external; /** * @notice Set the inbound xblock offset for a chain and shard * @param sourceChainId Source chain ID * @param shardId Shard ID * @param offset New xblock offset */ function setInXBlockOffset(uint64 sourceChainId, uint64 shardId, uint64 offset) external; /** * @notice Set the fee oracle */ function setFeeOracle(address feeOracle) external; /** * @notice Transfer all collected fees to the give address * @param to The address to transfer the fees to */ function collectFees(address to) external; /** * @notice Set the minimum gas limit for xmsg */ function setXMsgMinGasLimit(uint64 gasLimit) external; /** * @notice Set the maximum gas limit for xmsg */ function setXMsgMaxGasLimit(uint64 gasLimit) external; /** * @notice Set the maximum data bytes for xmsg */ function setXMsgMaxDataSize(uint16 numBytes) external; /** * @notice Set the maximum error bytes for xreceipt */ function setXReceiptMaxErrorSize(uint16 numBytes) external; /** * @notice Pause xcalls */ function pause() external; /** * @notice Unpause xcalls */ function unpause() external; }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity =0.8.24; import { MerkleProof } from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; import { XTypes } from "./XTypes.sol"; /** * @title XBlockMerkleProof * @dev Library for verifying XBlock merkle proofs */ library XBlockMerkleProof { /// @dev Domain separation tag for XBlockHeaders, prepended to leaves before hashing and signing. uint8 internal constant DST_XBLOCK_HEADER = 1; /// @dev Domain separation tag for XMsgs, prepended to leaves before hashing and signing. uint8 internal constant DST_XMSG = 2; /** * @notice Verifies that the provided xmsgs & multi proof produce an xmsg merkle root that, when * combined with the xblock header, produces the provided root. * @param root The root of the nested xblock merkle tree (xblock header + xmsg merkle root). * @param blockHeader Xblock header. * @param msgs Xmsgs to verify. * @param msgProof Xmsg merkle proof. * @param msgProofFlags Xmsg merkle proof flags. * @return True if the msgs, msg proof & block header are valid, agsinst the provided root. */ function verify( bytes32 root, XTypes.BlockHeader calldata blockHeader, XTypes.Msg[] calldata msgs, bytes32[] calldata msgProof, bool[] calldata msgProofFlags ) internal pure returns (bool) { bytes32[] memory rootProof = new bytes32[](1); rootProof[0] = MerkleProof.processMultiProofCalldata(msgProof, msgProofFlags, _msgLeaves(msgs)); return MerkleProof.verify(rootProof, root, _blockHeaderLeaf(blockHeader)); } /// @dev Convert xmsgs to leaf hashes function _msgLeaves(XTypes.Msg[] calldata msgs) private pure returns (bytes32[] memory) { bytes32[] memory leaves = new bytes32[](msgs.length); for (uint256 i = 0; i < msgs.length; i++) { leaves[i] = _leafHash(DST_XMSG, abi.encode(msgs[i])); } return leaves; } /// @dev Convert xblock header to leaf hash function _blockHeaderLeaf(XTypes.BlockHeader calldata blockHeader) private pure returns (bytes32) { return _leafHash(DST_XBLOCK_HEADER, abi.encode(blockHeader)); } /// @dev Double hash leaves, as recommended by OpenZeppelin, to prevent second preimage attacks /// Leaves must be double hashed in tree / proof construction /// Callers must specify the domain separation tag of the leaf, which will be hashed in function _leafHash(uint8 dst, bytes memory leaf) private pure returns (bytes32) { return keccak256(bytes.concat(keccak256(abi.encodePacked(dst, leaf)))); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.12; /** * @title XTypes * @dev Defines xchain types, core to Omni's xchain messaging protocol. These * types mirror those defined in omni/lib/xchain/types.go. */ library XTypes { /** * @notice A cross chain message - the product of an xcall. This matches the XMsg type used * throughout Omni's cross-chain messaging protocol. Msg is used to construct and verify * XSubmission merkle trees / proofs. * @custom:field destChainId Chain ID of the destination chain * @custom:field shardId Shard ID of the XStream (first byte is the confirmation level) * @custom:field offset Monotonically incremented offset of Msg in source -> dest Stream * @custom:field sender msg.sender of xcall on source chain * @custom:field to Target address to call on destination chain * @custom:field data Data to provide to call on destination chain * @custom:field gasLimit Gas limit to use for call execution on destination chain */ struct Msg { uint64 destChainId; uint64 shardId; uint64 offset; address sender; address to; bytes data; uint64 gasLimit; } /** * @notice Msg context exposed during its execution to consuming xapps. * @custom:field sourceChainId Chain ID of the source chain * @custom:field sender msg.sender of xcall on source chain */ struct MsgContext { uint64 sourceChainId; address sender; } /** * @notice BlockHeader of an XBlock. * @custom:field sourceChainId Chain ID of the source chain * @custom:field sourceChainId Chain ID of the Omni consensus chain * @custom:field confLevel Confirmation level of the cross chain block * @custom:field offset Offset of the cross chain block * @custom:field sourceBlockHeight Height of the source chain block * @custom:field sourceBlockHash Hash of the source chain block */ struct BlockHeader { uint64 sourceChainId; uint64 consensusChainId; uint8 confLevel; uint64 offset; uint64 sourceBlockHeight; bytes32 sourceBlockHash; } /** * @notice The required parameters to submit xmsgs to an OmniPortal. Constructed by the relayer * by watching Omni's consensus chain, and source chain blocks. * @custom:field attestationRoot Merkle root of xchain block (XBlockRoot), attested to and signed by validators * @custom:field validatorSetId Unique identifier of the validator set that attested to this root * @custom:field blockHeader Block header, identifies xchain block * @custom:field msgs Messages to execute * @custom:field proof Multi proof of block header and messages, proven against attestationRoot * @custom:field proofFlags Multi proof flags * @custom:field signatures Array of validator signatures of the attestationRoot, and their public keys */ struct Submission { bytes32 attestationRoot; uint64 validatorSetId; BlockHeader blockHeader; Msg[] msgs; bytes32[] proof; bool[] proofFlags; SigTuple[] signatures; } /** * @notice A tuple of a validator's ethereum address and signature over some digest. * @custom:field validatorAddr Validator ethereum address * @custom:field signature Validator signature over some digest; Ethereum 65 bytes [R || S || V] format. */ struct SigTuple { address validatorAddr; bytes signature; } /** * @notice An Omni validator, specified by their etheruem address and voting power. * @custom:field addr Validator ethereum address * @custom:field power Validator voting power */ struct Validator { address addr; uint64 power; } /** * @notice A chain in the "omni network" specified by its chain ID and supported shards. * @custom:field chainId Chain ID * @custom:field shards Supported shards */ struct Chain { uint64 chainId; uint64[] shards; } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity =0.8.24; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { XTypes } from "./XTypes.sol"; /** * @title Quorom * @dev Defines quorum verification logic. */ library Quorum { /** * @notice Verifies that the given percentage of the total power has signed the given digest. * @param digest Signed hash * @param sigs Signatures to verify, must be sorted by validator address * @param validators Maps validator addresses to their voting power * @param totalPower Total voting power * @param qNumerator Numerator of the quorum threshold. Ex: 2/3 -> 2 * @param qDenominator Denominator of the quorum threshold. Ex: 2/3 -> 3 */ function verify( bytes32 digest, XTypes.SigTuple[] calldata sigs, mapping(address => uint64) storage validators, uint64 totalPower, uint8 qNumerator, uint8 qDenominator ) internal view returns (bool) { uint64 votedPower; XTypes.SigTuple calldata sig; for (uint256 i = 0; i < sigs.length; i++) { sig = sigs[i]; if (i > 0) { XTypes.SigTuple memory prev = sigs[i - 1]; require(sig.validatorAddr != prev.validatorAddr, "Quorum: duplicate validator"); require(sig.validatorAddr > prev.validatorAddr, "Quorum: sigs not sorted"); } require(_isValidSig(sig, digest), "Quorum: invalid signature"); votedPower += validators[sig.validatorAddr]; if (_isQuorum(votedPower, totalPower, qNumerator, qDenominator)) return true; } return false; } /// @dev True if SigTuple.sig is a valid ECDSA signature over the given digest for SigTuple.addr, else false. function _isValidSig(XTypes.SigTuple calldata sig, bytes32 digest) internal pure returns (bool) { return ECDSA.recover(digest, sig.signature) == sig.validatorAddr; } /// @dev True if votedPower exceeds the quorum threshold of numerator/denominator, else false. function _isQuorum(uint64 votedPower, uint64 totalPower, uint8 numerator, uint8 denominator) private pure returns (bool) { return votedPower > (totalPower * numerator) / denominator; } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.12; /** * @title ConfLevel * @notice XMsg confirmation levels. Matches ConfLevels in lib/xchain/types.go * @dev We prefer explicit constants over Enums, because we want uint8 values to start at 1, not 0, as they do in * lib/xchain/types.go, such that 0 can represent "unset". Note only latest and finalized levels are supported * on-chain. */ library ConfLevel { /** * @notice XMsg confirmation level "latest", last byte of xmsg.shardId. */ uint8 internal constant Latest = 1; /** * @notice XMsg confirmation level "finalized", last byte of xmsg.shardId. */ uint8 internal constant Finalized = 4; /** * @notice Returns true if the given level is valid. */ function isValid(uint8 level) internal pure returns (bool) { return level == Latest || level == Finalized; } /** * @notice Returns broadcast shard version of the given level. */ function toBroadcastShard(uint8 level) internal pure returns (uint64) { return uint64(level) | 0x0100; } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity =0.8.24; /** * @title Pausable * @notice Contract module which provides a way to pause certain functions by key. * @dev We use a map of bytes32 key to bools, rather than uint256 bitmap, to allow keys to be generated dynamically. * This allows for flexible pausing, but at higher gas cost. */ contract PausableUpgradeable { /// @custom:storage-location erc7201:omni.storage.Pauseable struct PauseableStorage { mapping(bytes32 => bool) _paused; } // keccak256(abi.encode(uint256(keccak256("omni.storage.Pauseable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant PausableStorageSlot = 0xff37105740f03695c8f3597f3aff2b92fbe1c80abea3c28731ecff2efd693400; function _getPauseableStorage() internal pure returns (PauseableStorage storage $) { assembly { $.slot := PausableStorageSlot } } /** * @dev Special key for pausing all keys. */ bytes32 public constant KeyPauseAll = keccak256("PAUSE_ALL"); /** * @notice Pause by key. */ function _pause(bytes32 key) internal { PauseableStorage storage $ = _getPauseableStorage(); require(!$._paused[key], "Pausable: paused"); $._paused[key] = true; } /** * @notice Unpause by key. */ function _unpause(bytes32 key) internal { PauseableStorage storage $ = _getPauseableStorage(); require($._paused[key], "Pausable: not paused"); $._paused[key] = false; } /** * @notice Returns true if `key` is paused, or all keys are paused. */ function _isPaused(bytes32 key) internal view returns (bool) { PauseableStorage storage $ = _getPauseableStorage(); return $._paused[KeyPauseAll] || $._paused[key]; } /** * @notice Returns true if either `key1` or `key2` is paused, or all keys are paused. */ function _isPaused(bytes32 key1, bytes32 key2) internal view returns (bool) { PauseableStorage storage $ = _getPauseableStorage(); return $._paused[KeyPauseAll] || $._paused[key1] || $._paused[key2]; } /** * @notice Returns true if all keys are paused. */ function _isAllPaused() internal view returns (bool) { PauseableStorage storage $ = _getPauseableStorage(); return $._paused[KeyPauseAll]; } /** * @notice Pause all keys. */ function _pauseAll() internal { _pause(KeyPauseAll); } /** * @notice Unpause all keys. */ function _unpauseAll() internal { _unpause(KeyPauseAll); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.12; /** * @title OmniPortalConstants * @notice Constants used by the OmniPortal contract */ contract OmniPortalConstants { /** * @notice Numerator of the fraction of total validator power required to accept an XSubmission. Ex 2/3 -> 2 */ uint8 public constant XSubQuorumNumerator = 2; /** * @notice Denominator of the fraction of total validator power required to accept an XSubmission. Ex 2/3 -> 3 */ uint8 public constant XSubQuorumDenominator = 3; /** * @notice Action ID for xsubmissions, used as Pauseable key */ bytes32 public constant ActionXSubmit = keccak256("xsubmit"); /** * @notice Action ID for xcalls, used as Pauseable key */ bytes32 public constant ActionXCall = keccak256("xcall"); /** * @dev xmsg.destChainId for "broadcast" xcalls, intended for all portals */ uint64 internal constant BroadcastChainId = 0; /** * @dev xmg.sender for xmsgs from Omni's consensus chain */ address internal constant CChainSender = address(0); /** * @dev xmsg.to for xcalls to be executed on the portal itself */ address internal constant VirtualPortalAddress = address(0); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity =0.8.24; import { IOmniPortal } from "../interfaces/IOmniPortal.sol"; import { IOmniPortalAdmin } from "../interfaces/IOmniPortalAdmin.sol"; import { XTypes } from "../libraries/XTypes.sol"; /** * @title OmniPortalStorage * @notice Storage layout for OmniPortal */ abstract contract OmniPortalStorage is IOmniPortal, IOmniPortalAdmin { /** * @notice Number of validator sets since the latest that can be used to validate an XSubmission */ uint8 public xsubValsetCutoff; /** * @notice Maxium number of bytes allowed in xreceipt result */ uint16 public xreceiptMaxErrorSize; /** * @notice Maximum number of bytes allowed in xmsg data */ uint16 public xmsgMaxDataSize; /** * @notice Maximum allowed xmsg gas limit */ uint64 public xmsgMaxGasLimit; /** * @notice Minimum allowed xmsg gas limit */ uint64 public xmsgMinGasLimit; /** * @notice ID of the latest validator set relayed to this portal from the consensus chain. */ uint64 public latestValSetId; /** * @notice Chain ID of Omni's EVM execution chain */ uint64 public omniChainId; /** * @notice Virtual Chain ID of Omni's consensus chain */ uint64 public omniCChainId; /** * @notice The address of the fee oracle contract */ address public feeOracle; /** * @notice A list of supported chains & shards. */ XTypes.Chain[] public network; /** * @notice Maps shard ID to true, if the shard is supported. */ mapping(uint64 => bool) public isSupportedShard; /** * @notice Maps chain ID to true, if the chain is supported. */ mapping(uint64 => bool) public isSupportedDest; /** * @notice Offset of the last outbound XMsg that was sent to destChainId in shardId * Maps destChainId -> shardId -> offset. */ mapping(uint64 => mapping(uint64 => uint64)) public outXMsgOffset; /** * @notice Offset of the last outbound XMsg that was sent to destChainId in shardId * Maps destChainId -> shardId -> offset. */ mapping(uint64 => mapping(uint64 => uint64)) public inXMsgOffset; /** * @notice The xblock offset of the last inbound XMsg that was received from sourceChainId in shardIdj * Maps sourceChainId -> shardId -> xblockOffset. */ mapping(uint64 => mapping(uint64 => uint64)) public inXBlockOffset; /** * @notice Maps validator set id -> total power */ mapping(uint64 => uint64) public valSetTotalPower; /** * @notice Maps validator set id -> validator address -> power */ mapping(uint64 => mapping(address => uint64)) public valSet; /** * @notice The current XMsg being executed, exposed via xmsg() getter * @dev Internal state + public getter preferred over public state with default getter * so that we can use the XMsg struct type in the interface. */ XTypes.MsgContext internal _xmsg; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.20; /** * @dev These functions deal with verification of Merkle Tree proofs. * * The tree and the proofs can be generated using our * https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. * You will find a quickstart guide in the readme. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the Merkle tree could be reinterpreted as a leaf value. * OpenZeppelin's JavaScript library generates Merkle trees that are safe * against this attack out of the box. */ library MerkleProof { /** *@dev The multiproof provided is not valid. */ error MerkleProofInvalidMultiproof(); /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Calldata version of {verify} */ function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProofCalldata(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Calldata version of {processProof} */ function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details. */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProof(proof, proofFlags, leaves) == root; } /** * @dev Calldata version of {multiProofVerify} * * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details. */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false * respectively. * * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the Merkle tree. uint256 leavesLen = leaves.length; uint256 proofLen = proof.length; uint256 totalHashes = proofFlags.length; // Check proof validity. if (leavesLen + proofLen != totalHashes + 1) { revert MerkleProofInvalidMultiproof(); } // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { if (proofPos != proofLen) { revert MerkleProofInvalidMultiproof(); } unchecked { return hashes[totalHashes - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Calldata version of {processMultiProof}. * * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details. */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the Merkle tree. uint256 leavesLen = leaves.length; uint256 proofLen = proof.length; uint256 totalHashes = proofFlags.length; // Check proof validity. if (leavesLen + proofLen != totalHashes + 1) { revert MerkleProofInvalidMultiproof(); } // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { if (proofPos != proofLen) { revert MerkleProofInvalidMultiproof(); } unchecked { return hashes[totalHashes - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Sorts the pair (a, b) and hashes the result. */ function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _efficientHash(a, b) : _efficientHash(b, a); } /** * @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory. */ function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { /// @solidity memory-safe-assembly assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError, bytes32) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS, s); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } }
{ "remappings": [ "forge-std/=node_modules/forge-std/src/", "ds-test/=node_modules/ds-test/src/", "src/=src/", "test/=test/", "avs/=../avs/src/", "@openzeppelin-upgrades/contracts/=node_modules/@openzeppelin/contracts-upgradeable/", "@nomad-xyz/=node_modules/@nomad-xyz/", "@openzeppelin-v4/=node_modules/@openzeppelin-v4/", "@openzeppelin/=node_modules/@openzeppelin/", "eigenlayer-contracts/=node_modules/eigenlayer-contracts/", "eigenlayer-middleware/=node_modules/eigenlayer-middleware/", "solmate/=node_modules/solmate/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": false, "libraries": {} }
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"MerkleProofInvalidMultiproof","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oracle","type":"address"}],"name":"FeeOracleSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"srcChainId","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"shardId","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"offset","type":"uint64"}],"name":"InXBlockOffsetSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"srcChainId","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"shardId","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"offset","type":"uint64"}],"name":"InXMsgOffsetSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"setId","type":"uint64"}],"name":"ValidatorSetAdded","type":"event"},{"anonymous":false,"inputs":[],"name":"XCallPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"XCallToPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"XCallToUnpaused","type":"event"},{"anonymous":false,"inputs":[],"name":"XCallUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"destChainId","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"shardId","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"offset","type":"uint64"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"gasLimit","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"fees","type":"uint256"}],"name":"XMsg","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"size","type":"uint16"}],"name":"XMsgMaxDataSizeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"gasLimit","type":"uint64"}],"name":"XMsgMaxGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"gasLimit","type":"uint64"}],"name":"XMsgMinGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"sourceChainId","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"shardId","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"offset","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"address","name":"relayer","type":"address"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"bytes","name":"error","type":"bytes"}],"name":"XReceipt","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"size","type":"uint16"}],"name":"XReceiptMaxErrorSizeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"cutoff","type":"uint8"}],"name":"XSubValsetCutoffSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"XSubmitFromPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"XSubmitFromUnpaused","type":"event"},{"anonymous":false,"inputs":[],"name":"XSubmitPaused","type":"event"},{"anonymous":false,"inputs":[],"name":"XSubmitUnpaused","type":"event"},{"inputs":[],"name":"ActionXCall","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ActionXSubmit","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"KeyPauseAll","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XSubQuorumDenominator","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XSubQuorumNumerator","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"valSetId","type":"uint64"},{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"power","type":"uint64"}],"internalType":"struct XTypes.Validator[]","name":"validators","type":"tuple[]"}],"name":"addValidatorSet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chainId","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"collectFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"destChainId","type":"uint64"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint64","name":"gasLimit","type":"uint64"}],"name":"feeFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"inXBlockOffset","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"inXMsgOffset","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"feeOracle","type":"address"},{"internalType":"uint64","name":"omniChainId","type":"uint64"},{"internalType":"uint64","name":"omniCChainId","type":"uint64"},{"internalType":"uint64","name":"xmsgMaxGasLimit","type":"uint64"},{"internalType":"uint64","name":"xmsgMinGasLimit","type":"uint64"},{"internalType":"uint16","name":"xmsgMaxDataSize","type":"uint16"},{"internalType":"uint16","name":"xreceiptMaxErrorSize","type":"uint16"},{"internalType":"uint8","name":"xsubValsetCutoff","type":"uint8"},{"internalType":"uint64","name":"cChainXMsgOffset","type":"uint64"},{"internalType":"uint64","name":"cChainXBlockOffset","type":"uint64"},{"internalType":"uint64","name":"valSetId","type":"uint64"},{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"power","type":"uint64"}],"internalType":"struct XTypes.Validator[]","name":"validators","type":"tuple[]"}],"internalType":"struct OmniPortal.InitParams","name":"p","type":"tuple"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"actionId","type":"bytes32"}],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"actionId","type":"bytes32"},{"internalType":"uint64","name":"chainId_","type":"uint64"}],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"isSupportedDest","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"isSupportedShard","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isXCall","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestValSetId","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"network","outputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"omniCChainId","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"omniChainId","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"outXMsgOffset","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseXCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId_","type":"uint64"}],"name":"pauseXCallTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseXSubmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId_","type":"uint64"}],"name":"pauseXSubmitFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"feeOracle_","type":"address"}],"name":"setFeeOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"sourceChainId","type":"uint64"},{"internalType":"uint64","name":"shardId","type":"uint64"},{"internalType":"uint64","name":"offset","type":"uint64"}],"name":"setInXBlockOffset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"sourceChainId","type":"uint64"},{"internalType":"uint64","name":"shardId","type":"uint64"},{"internalType":"uint64","name":"offset","type":"uint64"}],"name":"setInXMsgOffset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint64[]","name":"shards","type":"uint64[]"}],"internalType":"struct XTypes.Chain[]","name":"network_","type":"tuple[]"}],"name":"setNetwork","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"numBytes","type":"uint16"}],"name":"setXMsgMaxDataSize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"gasLimit","type":"uint64"}],"name":"setXMsgMaxGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"gasLimit","type":"uint64"}],"name":"setXMsgMinGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"numBytes","type":"uint16"}],"name":"setXReceiptMaxErrorSize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"xsubValsetCutoff_","type":"uint8"}],"name":"setXSubValsetCutoff","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseXCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId_","type":"uint64"}],"name":"unpauseXCallTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseXSubmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId_","type":"uint64"}],"name":"unpauseXSubmitFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"},{"internalType":"address","name":"","type":"address"}],"name":"valSet","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"valSetTotalPower","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"destChainId","type":"uint64"},{"internalType":"uint8","name":"conf","type":"uint8"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint64","name":"gasLimit","type":"uint64"}],"name":"xcall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"xmsg","outputs":[{"components":[{"internalType":"uint64","name":"sourceChainId","type":"uint64"},{"internalType":"address","name":"sender","type":"address"}],"internalType":"struct XTypes.MsgContext","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xmsgMaxDataSize","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xmsgMaxGasLimit","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xmsgMinGasLimit","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xreceiptMaxErrorSize","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xsubValsetCutoff","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"attestationRoot","type":"bytes32"},{"internalType":"uint64","name":"validatorSetId","type":"uint64"},{"components":[{"internalType":"uint64","name":"sourceChainId","type":"uint64"},{"internalType":"uint64","name":"consensusChainId","type":"uint64"},{"internalType":"uint8","name":"confLevel","type":"uint8"},{"internalType":"uint64","name":"offset","type":"uint64"},{"internalType":"uint64","name":"sourceBlockHeight","type":"uint64"},{"internalType":"bytes32","name":"sourceBlockHash","type":"bytes32"}],"internalType":"struct XTypes.BlockHeader","name":"blockHeader","type":"tuple"},{"components":[{"internalType":"uint64","name":"destChainId","type":"uint64"},{"internalType":"uint64","name":"shardId","type":"uint64"},{"internalType":"uint64","name":"offset","type":"uint64"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint64","name":"gasLimit","type":"uint64"}],"internalType":"struct XTypes.Msg[]","name":"msgs","type":"tuple[]"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"bool[]","name":"proofFlags","type":"bool[]"},{"components":[{"internalType":"address","name":"validatorAddr","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct XTypes.SigTuple[]","name":"signatures","type":"tuple[]"}],"internalType":"struct XTypes.Submission","name":"xsub","type":"tuple"}],"name":"xsubmit","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b506200001c62000022565b620000d6565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff1615620000735760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b0390811614620000d35780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b614b8b80620000e66000396000f3fe60806040526004361061036b5760003560e01c80638532eb9f116101c6578063b4d5afd1116100f7578063c3d8ad6711610095578063d051c97d1161006f578063d051c97d14610af6578063d533b44514610b37578063f2fde38b14610b57578063f45cc7b814610b7757600080fd5b8063c3d8ad6714610a98578063c4ab80bc14610aad578063cf84c81814610acd57600080fd5b8063bff0e84d116100d1578063bff0e84d14610a25578063c21dda4f14610a45578063c26dfc0514610a58578063c2f9b96814610a7857600080fd5b8063b4d5afd1146109b0578063b521466d146109e5578063bb8590ad14610a0557600080fd5b8063a480ca7911610164578063afe821981161013e578063afe8219814610923578063afe8af9c14610943578063b187bd2614610979578063b2b2f5bd1461098e57600080fd5b8063a480ca79146108b3578063a8a98962146108d3578063aaf1bc97146108f357600080fd5b806397b52062116101a057806397b520621461083c5780639a8a05921461085c578063a10ac97a1461086f578063a32eb7c61461089157600080fd5b80638532eb9f146107b15780638da5cb5b146107d15780638dd9523c1461080e57600080fd5b80633f4ba83a116102a0578063575420501161023e57806374eba9391161021857806374eba9391461074057806378fe53071461076057806383d0cbd9146107875780638456cb591461079c57600080fd5b806357542050146106ca57806366a1eaf31461070b578063715018a61461072b57600080fd5b806349cc3bf61161027a57806349cc3bf614610643578063500b19e71461065d57806354d26bba1461069557806355e2448e146106aa57600080fd5b80633f4ba83a146105cd5780633fd3b15e146105e2578063461ab4881461062357600080fd5b8063241b71bb1161030d57806330632e8b116102e757806330632e8b1461052557806336d219121461054557806336d853f91461056c5780633aa873301461058c57600080fd5b8063241b71bb1461046057806324278bbe146104905780632f32700e146104c057600080fd5b806310a5a7f71161034957806310a5a7f7146103d3578063110ff5f1146103f35780631d3eb6e31461042b57806323dbce501461044b57600080fd5b80630360d20f1461037057806306c3dc5f1461039c578063103ba701146103b1575b600080fd5b34801561037c57600080fd5b50610385600281565b60405160ff90911681526020015b60405180910390f35b3480156103a857600080fd5b50610385600381565b3480156103bd57600080fd5b506103d16103cc366004613d44565b610b9e565b005b3480156103df57600080fd5b506103d16103ee366004613d7f565b610bb2565b3480156103ff57600080fd5b50600154610413906001600160401b031681565b6040516001600160401b039091168152602001610393565b34801561043757600080fd5b506103d1610446366004613d9c565b610c11565b34801561045757600080fd5b506103d1610d2c565b34801561046c57600080fd5b5061048061047b366004613e10565b610d76565b6040519015158152602001610393565b34801561049c57600080fd5b506104806104ab366004613d7f565b60056020526000908152604090205460ff1681565b3480156104cc57600080fd5b50604080518082018252600080825260209182015281518083018352600b546001600160401b0381168083526001600160a01b03600160401b909204821692840192835284519081529151169181019190915201610393565b34801561053157600080fd5b506103d1610540366004613e29565b610d87565b34801561055157600080fd5b5060015461041390600160401b90046001600160401b031681565b34801561057857600080fd5b506103d1610587366004613d7f565b61109e565b34801561059857600080fd5b506104136105a7366004613e64565b60066020908152600092835260408084209091529082529020546001600160401b031681565b3480156105d957600080fd5b506103d16110af565b3480156105ee57600080fd5b506104136105fd366004613e64565b60086020908152600092835260408084209091529082529020546001600160401b031681565b34801561062f57600080fd5b5061048061063e366004613e9d565b6110ea565b34801561064f57600080fd5b506000546103859060ff1681565b34801561066957600080fd5b5060025461067d906001600160a01b031681565b6040516001600160a01b039091168152602001610393565b3480156106a157600080fd5b506103d1611106565b3480156106b657600080fd5b50600b546001600160401b03161515610480565b3480156106d657600080fd5b506104136106e5366004613ed9565b600a6020908152600092835260408084209091529082529020546001600160401b031681565b34801561071757600080fd5b506103d1610726366004613f0e565b611150565b34801561073757600080fd5b506103d16114fe565b34801561074c57600080fd5b5061041361075b366004613e10565b611512565b34801561076c57600080fd5b5060005461041390600160681b90046001600160401b031681565b34801561079357600080fd5b506103d1611541565b3480156107a857600080fd5b506103d161158b565b3480156107bd57600080fd5b506103d16107cc366004613f49565b6115c6565b3480156107dd57600080fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031661067d565b34801561081a57600080fd5b5061082e610829366004614018565b6116d9565b604051908152602001610393565b34801561084857600080fd5b506103d161085736600461407f565b61175a565b34801561086857600080fd5b5046610413565b34801561087b57600080fd5b5061082e600080516020614af683398151915281565b34801561089d57600080fd5b5061082e600080516020614b3683398151915281565b3480156108bf57600080fd5b506103d16108ce3660046140ca565b6117d7565b3480156108df57600080fd5b506103d16108ee3660046140ca565b61185f565b3480156108ff57600080fd5b5061048061090e366004613d7f565b60046020526000908152604090205460ff1681565b34801561092f57600080fd5b506103d161093e366004613d7f565b611870565b34801561094f57600080fd5b5061041361095e366004613d7f565b6009602052600090815260409020546001600160401b031681565b34801561098557600080fd5b506104806118ca565b34801561099a57600080fd5b5061082e600080516020614ad683398151915281565b3480156109bc57600080fd5b506000546109d2906301000000900461ffff1681565b60405161ffff9091168152602001610393565b3480156109f157600080fd5b506103d1610a003660046140e5565b611920565b348015610a1157600080fd5b506103d1610a20366004613d7f565b611931565b348015610a3157600080fd5b506103d1610a403660046140e5565b611942565b6103d1610a53366004614109565b611953565b348015610a6457600080fd5b506000546109d290610100900461ffff1681565b348015610a8457600080fd5b506103d1610a93366004613d7f565b611d2d565b348015610aa457600080fd5b506103d1611d8c565b348015610ab957600080fd5b506103d1610ac836600461407f565b611dd6565b348015610ad957600080fd5b50600054610413906501000000000090046001600160401b031681565b348015610b0257600080fd5b50610413610b11366004613e64565b60076020908152600092835260408084209091529082529020546001600160401b031681565b348015610b4357600080fd5b506103d1610b52366004613d7f565b611e4a565b348015610b6357600080fd5b506103d1610b723660046140ca565b611ea4565b348015610b8357600080fd5b5060005461041390600160a81b90046001600160401b031681565b610ba6611edf565b610baf81611f3a565b50565b610bba611edf565b610bda610bd5600080516020614ad683398151915283611fd6565b61201f565b6040516001600160401b038216907fcd7910e1c5569d8433ce4ef8e5d51c1bdc03168f614b576da47dc3d2b51d033a90600090a250565b333014610c5d5760405162461bcd60e51b815260206004820152601560248201527427b6b734a837b93a30b61d1037b7363c9039b2b63360591b60448201526064015b60405180910390fd5b600154600b546001600160401b03908116600160401b9092041614610cbe5760405162461bcd60e51b815260206004820152601760248201527627b6b734a837b93a30b61d1037b7363c9031b1b430b4b760491b6044820152606401610c54565b600b54600160401b90046001600160a01b031615610d1e5760405162461bcd60e51b815260206004820152601e60248201527f4f6d6e69506f7274616c3a206f6e6c792063636861696e2073656e64657200006044820152606401610c54565b610d28828261209a565b5050565b610d34611edf565b610d4b600080516020614b3683398151915261201f565b6040517f3d0f9c56dac46156a2db0aa09ee7804770ad9fc9549d21023164f22d69475ed890600090a1565b6000610d8182612214565b92915050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b0316600081158015610dcc5750825b90506000826001600160401b03166001148015610de85750303b155b905081158015610df6575080155b15610e145760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610e3e57845460ff60401b1916600160401b1785555b610e53610e4e60208801886140ca565b61227b565b610e6b610e6660408801602089016140ca565b61228c565b610e83610e7e60a0880160808901613d7f565b612330565b610e9b610e9660c0880160a08901613d7f565b6123e8565b610eb3610eae60e0880160c089016140e5565b61249c565b610ecc610ec7610100880160e089016140e5565b612540565b610ee6610ee161012088016101008901613d44565b611f3a565b610f0e610efb61018088016101608901613d7f565b610f09610180890189614192565b6125e0565b610f1e6060870160408801613d7f565b6001805467ffffffffffffffff19166001600160401b0392909216919091179055610f4f6080870160608801613d7f565b600180546001600160401b0392909216600160401b026fffffffffffffffff000000000000000019909216919091179055610104610f9561014088016101208901613d7f565b60076000610fa960808b0160608c01613d7f565b6001600160401b0390811682526020808301939093526040918201600090812086831682529093529120805467ffffffffffffffff191692909116919091179055610ffc61016088016101408901613d7f565b6008600061101060808b0160608c01613d7f565b6001600160401b03908116825260208083019390935260409182016000908120958216815294909252909220805467ffffffffffffffff191691909216179055831561109657845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b6110a6611edf565b610baf81612330565b6110b7611edf565b6110bf61290f565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b60006110ff836110fa8585611fd6565b612926565b9392505050565b61110e611edf565b611125600080516020614ad68339815191526129ad565b6040517f4c48c7b71557216a3192842746bdfc381f98d7536d9eb1c6764f3b45e679482790600090a1565b600080516020614b3683398151915261116f6060830160408401613d7f565b61117d826110fa8484611fd6565b156111bf5760405162461bcd60e51b815260206004820152601260248201527113db5b9a541bdc9d185b0e881c185d5cd95960721b6044820152606401610c54565b6111c7612a28565b3660006111d86101008601866141db565b90925090506040850160006111f08260208901613d7f565b600154909150600160401b90046001600160401b03166112166040840160208501613d7f565b6001600160401b03161461126c5760405162461bcd60e51b815260206004820152601b60248201527f4f6d6e69506f7274616c3a2077726f6e672063636861696e20494400000000006044820152606401610c54565b826112b05760405162461bcd60e51b81526020600482015260146024820152734f6d6e69506f7274616c3a206e6f20786d73677360601b6044820152606401610c54565b6001600160401b03808216600090815260096020526040902054166113175760405162461bcd60e51b815260206004820152601b60248201527f4f6d6e69506f7274616c3a20756e6b6e6f776e2076616c2073657400000000006044820152606401610c54565b61131f612a72565b6001600160401b0316816001600160401b031610156113805760405162461bcd60e51b815260206004820152601760248201527f4f6d6e69506f7274616c3a206f6c642076616c207365740000000000000000006044820152606401610c54565b6113c487356113936101608a018a6141db565b6001600160401b038086166000908152600a6020908152604080832060099092529091205490911660026003612ac2565b6114085760405162461bcd60e51b81526020600482015260156024820152744f6d6e69506f7274616c3a206e6f2071756f72756d60581b6044820152606401610c54565b611431873583868661141e6101208d018d6141db565b61142c6101408f018f6141db565b612ce4565b61147d5760405162461bcd60e51b815260206004820152601960248201527f4f6d6e69506f7274616c3a20696e76616c69642070726f6f66000000000000006044820152606401610c54565b60005b838110156114cb576114c361149a36859003850185614292565b8686848181106114ac576114ac614333565b90506020028101906114be9190614349565b612d5f565b600101611480565b50505050506114f960017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b505050565b611506611edf565b611510600061324a565b565b6003818154811061152257600080fd5b60009182526020909120600290910201546001600160401b0316905081565b611549611edf565b611560600080516020614ad683398151915261201f565b6040517f5f335a4032d4cfb6aca7835b0c2225f36d4d9eaa4ed43ee59ed537e02dff6b3990600090a1565b611593611edf565b61159b6132bb565b6040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75290600090a1565b33301461160d5760405162461bcd60e51b815260206004820152601560248201527427b6b734a837b93a30b61d1037b7363c9039b2b63360591b6044820152606401610c54565b600154600b546001600160401b03908116600160401b909204161461166e5760405162461bcd60e51b815260206004820152601760248201527627b6b734a837b93a30b61d1037b7363c9031b1b430b4b760491b6044820152606401610c54565b600b54600160401b90046001600160a01b0316156116ce5760405162461bcd60e51b815260206004820152601e60248201527f4f6d6e69506f7274616c3a206f6e6c792063636861696e2073656e64657200006044820152606401610c54565b6114f98383836125e0565b600254604051632376548f60e21b81526000916001600160a01b031690638dd9523c90611710908890889088908890600401614392565b602060405180830381865afa15801561172d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061175191906143ca565b95945050505050565b611762611edf565b6001600160401b03838116600081815260086020908152604080832087861680855290835292819020805467ffffffffffffffff191695871695861790555193845290927fe070f08cae8464c91238e8cbea64ccee5e7b48dd79a843f144e3721ee6bdd9b591015b60405180910390a3505050565b6117df611edf565b60405147906001600160a01b0383169082156108fc029083906000818181858888f19350505050158015611817573d6000803e3d6000fd5b50816001600160a01b03167f9dc46f23cfb5ddcad0ae7ea2be38d47fec07bb9382ec7e564efc69e036dd66ce8260405161185391815260200190565b60405180910390a25050565b611867611edf565b610baf8161228c565b611878611edf565b611893610bd5600080516020614b3683398151915283611fd6565b6040516001600160401b038216907fab78810a0515df65f9f10bfbcb92d03d5df71d9fd3b9414e9ad831a5117d6daa90600090a250565b600061191b600080516020614af6833981519152600052600080516020614b168339815191526020527ffae9838a178d7f201aa98e2ce5340158edda60bb1e8f168f46503bf3e99f13be5460ff1690565b905090565b611928611edf565b610baf8161249c565b611939611edf565b610baf816123e8565b61194a611edf565b610baf81612540565b600080516020614ad683398151915286611971826110fa8484611fd6565b156119b35760405162461bcd60e51b815260206004820152601260248201527113db5b9a541bdc9d185b0e881c185d5cd95960721b6044820152606401610c54565b6001600160401b03881660009081526005602052604090205460ff16611a1b5760405162461bcd60e51b815260206004820152601c60248201527f4f6d6e69506f7274616c3a20756e737570706f727465642064657374000000006044820152606401610c54565b6001600160a01b038616611a715760405162461bcd60e51b815260206004820152601b60248201527f4f6d6e69506f7274616c3a206e6f20706f7274616c207863616c6c00000000006044820152606401610c54565b6000546001600160401b036501000000000090910481169084161115611ad95760405162461bcd60e51b815260206004820152601d60248201527f4f6d6e69506f7274616c3a206761734c696d697420746f6f20686967680000006044820152606401610c54565b6000546001600160401b03600160681b90910481169084161015611b3f5760405162461bcd60e51b815260206004820152601c60248201527f4f6d6e69506f7274616c3a206761734c696d697420746f6f206c6f77000000006044820152606401610c54565b6000546301000000900461ffff16841115611b9c5760405162461bcd60e51b815260206004820152601a60248201527f4f6d6e69506f7274616c3a206461746120746f6f206c617267650000000000006044820152606401610c54565b60ff808816600081815260046020526040902054909116611bff5760405162461bcd60e51b815260206004820152601d60248201527f4f6d6e69506f7274616c3a20756e737570706f727465642073686172640000006044820152606401610c54565b6000611c0d8a8888886116d9565b905080341015611c5f5760405162461bcd60e51b815260206004820152601c60248201527f4f6d6e69506f7274616c3a20696e73756666696369656e7420666565000000006044820152606401610c54565b6001600160401b03808b166000908152600660209081526040808320868516845290915281208054600193919291611c99918591166143f9565b82546101009290920a6001600160401b038181021990931691831602179091558b811660008181526006602090815260408083208886168085529252918290205491519190931693507fb7c8eb9d7a7fbcdab809ab7b8a7c41701eb3115e3fe99d30ff490d8552f72bfa90611d199033908e908e908e908e908b90614420565b60405180910390a450505050505050505050565b611d35611edf565b611d55611d50600080516020614b3683398151915283611fd6565b6129ad565b6040516001600160401b038216907fc551305d9bd408be4327b7f8aba28b04ccf6b6c76925392d195ecf9cc764294d90600090a250565b611d94611edf565b611dab600080516020614b368339815191526129ad565b6040517f2cb9d71d4c31860b70e9b707c69aa2f5953e03474f00cfcfff205c4745f8287590600090a1565b611dde611edf565b6001600160401b03838116600081815260076020908152604080832087861680855290835292819020805467ffffffffffffffff191695871695861790555193845290927f8647aae68c8456a1dcbfaf5eaadc94278ae423526d3f09c7b972bff7355d55c791016117ca565b611e52611edf565b611e6d611d50600080516020614ad683398151915283611fd6565b6040516001600160401b038216907f1ed9223556fb0971076c30172f1f00630efd313b6a05290a562aef95928e712590600090a250565b611eac611edf565b6001600160a01b038116611ed657604051631e4fbdf760e01b815260006004820152602401610c54565b610baf8161324a565b33611f117f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146115105760405163118cdaa760e01b8152336004820152602401610c54565b60008160ff1611611f8d5760405162461bcd60e51b815260206004820152601a60248201527f4f6d6e69506f7274616c3a206e6f207a65726f206375746f66660000000000006044820152606401610c54565b6000805460ff191660ff83169081179091556040519081527f1683dc51426224f6e37a3b41dd5849e2db1bfe22366d1d913fa0ef6f757e828f906020015b60405180910390a150565b6000828260405160200161200192919091825260c01b6001600160c01b031916602082015260280190565b60405160208183030381529060405280519060200120905092915050565b6000818152600080516020614b16833981519152602081905260409091205460ff16156120815760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610c54565b600091825260205260409020805460ff19166001179055565b6120a26132d2565b3660005b8281101561220e578383828181106120c0576120c0614333565b90506020028101906120d2919061446b565b6003805460018101825560009190915290925082906002027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b016121168282614507565b505061211f4690565b6001600160401b03166121356020840184613d7f565b6001600160401b031614612183576001600560006121566020860186613d7f565b6001600160401b031681526020810191909152604001600020805460ff1916911515919091179055612206565b60005b61219360208401846141db565b9050811015612204576001600460006121af60208701876141db565b858181106121bf576121bf614333565b90506020020160208101906121d49190613d7f565b6001600160401b031681526020810191909152604001600020805460ff1916911515919091179055600101612186565b505b6001016120a6565b50505050565b600080516020614af68339815191526000908152600080516020614b1683398151915260208190527ffae9838a178d7f201aa98e2ce5340158edda60bb1e8f168f46503bf3e99f13be5460ff16806110ff5750600092835260205250604090205460ff1690565b6122836133d1565b610baf8161341a565b6001600160a01b0381166122e25760405162461bcd60e51b815260206004820152601d60248201527f4f6d6e69506f7274616c3a206e6f207a65726f206665654f7261636c650000006044820152606401610c54565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd97bdb0db82b52a85aa07f8da78033b1d6e159d94f1e3cbd4109d946c3bcfd3290602001611fcb565b6000816001600160401b0316116123895760405162461bcd60e51b815260206004820152601b60248201527f4f6d6e69506f7274616c3a206e6f207a65726f206d61782067617300000000006044820152606401610c54565b600080546cffffffffffffffff00000000001916650100000000006001600160401b038416908102919091179091556040519081527f1153561ac5effc2926ba6c612f86a397c997bc43dfbfc718da08065be0c5fe4d90602001611fcb565b6000816001600160401b0316116124415760405162461bcd60e51b815260206004820152601b60248201527f4f6d6e69506f7274616c3a206e6f207a65726f206d696e2067617300000000006044820152606401610c54565b6000805467ffffffffffffffff60681b1916600160681b6001600160401b038416908102919091179091556040519081527f8c852a6291aa436654b167353bca4a4b0c3d024c7562cb5082e7c869bddabf3e90602001611fcb565b60008161ffff16116124f05760405162461bcd60e51b815260206004820152601c60248201527f4f6d6e69506f7274616c3a206e6f207a65726f206d61782073697a65000000006044820152606401610c54565b6000805464ffff0000001916630100000061ffff8416908102919091179091556040519081527f65923e04419dc810d0ea08a94a7f608d4c4d949818d95c3788f895e575dd206490602001611fcb565b60008161ffff16116125945760405162461bcd60e51b815260206004820152601c60248201527f4f6d6e69506f7274616c3a206e6f207a65726f206d61782073697a65000000006044820152606401610c54565b6000805462ffff00191661010061ffff8416908102919091179091556040519081527f620bbea084306b66a8cc6b5b63830d6b3874f9d2438914e259ffd5065c33f7b090602001611fcb565b808061262e5760405162461bcd60e51b815260206004820152601960248201527f4f6d6e69506f7274616c3a206e6f2076616c696461746f7273000000000000006044820152606401610c54565b6001600160401b0380851660009081526009602052604090205416156126965760405162461bcd60e51b815260206004820152601d60248201527f4f6d6e69506f7274616c3a206475706c69636174652076616c207365740000006044820152606401610c54565b604080518082018252600080825260208083018290526001600160401b0388168252600a9052918220825b8481101561286e578686828181106126db576126db614333565b9050604002018036038101906126f1919061462f565b80519093506001600160a01b031661274b5760405162461bcd60e51b815260206004820152601d60248201527f4f6d6e69506f7274616c3a206e6f207a65726f2076616c696461746f720000006044820152606401610c54565b600083602001516001600160401b0316116127a85760405162461bcd60e51b815260206004820152601960248201527f4f6d6e69506f7274616c3a206e6f207a65726f20706f776572000000000000006044820152606401610c54565b82516001600160a01b03166000908152602083905260409020546001600160401b0316156128185760405162461bcd60e51b815260206004820152601f60248201527f4f6d6e69506f7274616c3a206475706c69636174652076616c696461746f72006044820152606401610c54565b602083015161282790856143f9565b60208481015185516001600160a01b03166000908152918590526040909120805467ffffffffffffffff19166001600160401b0390921691909117905593506001016126c1565b506001600160401b038781166000818152600960205260408120805467ffffffffffffffff191687851617905554600160a81b900490911610156128d2576000805467ffffffffffffffff60a81b1916600160a81b6001600160401b038a16021790555b6040516001600160401b038816907f3a7c2f997a87ba92aedaecd1127f4129cae1283e2809ebf5304d321b943fd10790600090a250505050505050565b611510600080516020614af68339815191526129ad565b600080516020614af68339815191526000908152600080516020614b1683398151915260208190527ffae9838a178d7f201aa98e2ce5340158edda60bb1e8f168f46503bf3e99f13be5460ff168061298c575060008481526020829052604090205460ff165b806129a5575060008381526020829052604090205460ff165b949350505050565b6000818152600080516020614b16833981519152602081905260409091205460ff16612a125760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610c54565b600091825260205260409020805460ff19169055565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00805460011901612a6c57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b6000805460ff8116600160a81b9091046001600160401b031611612a965750600190565b600054612ab79060ff811690600160a81b90046001600160401b031661466e565b61191b9060016143f9565b6000803660005b88811015612cd157898982818110612ae357612ae3614333565b9050602002810190612af5919061446b565b91508015612c175760008a8a612b0c60018561468e565b818110612b1b57612b1b614333565b9050602002810190612b2d919061446b565b612b36906146a1565b80519091506001600160a01b0316612b5160208501856140ca565b6001600160a01b031603612ba75760405162461bcd60e51b815260206004820152601b60248201527f51756f72756d3a206475706c69636174652076616c696461746f7200000000006044820152606401610c54565b80516001600160a01b0316612bbf60208501856140ca565b6001600160a01b031611612c155760405162461bcd60e51b815260206004820152601760248201527f51756f72756d3a2073696773206e6f7420736f727465640000000000000000006044820152606401610c54565b505b612c21828c613422565b612c6d5760405162461bcd60e51b815260206004820152601960248201527f51756f72756d3a20696e76616c6964207369676e6174757265000000000000006044820152606401610c54565b876000612c7d60208501856140ca565b6001600160a01b03168152602081019190915260400160002054612caa906001600160401b0316846143f9565b9250612cb883888888613496565b15612cc95760019350505050612cd9565b600101612ac9565b506000925050505b979650505050505050565b60408051600180825281830190925260009182919060208083019080368337019050509050612d1f86868686612d1a8d8d6134d3565b6135a0565b81600081518110612d3257612d32614333565b602002602001018181525050612d51818b612d4c8c613801565b613819565b9a9950505050505050505050565b81516000612d706020840184613d7f565b90506000612d846040850160208601613d7f565b90506000612d986060860160408701613d7f565b9050466001600160401b0316836001600160401b03161480612dc157506001600160401b038316155b612e0d5760405162461bcd60e51b815260206004820152601c60248201527f4f6d6e69506f7274616c3a2077726f6e67206465737420636861696e000000006044820152606401610c54565b6001600160401b0380851660009081526007602090815260408083208685168452909152902054612e40911660016143f9565b6001600160401b0316816001600160401b031614612ea05760405162461bcd60e51b815260206004820152601860248201527f4f6d6e69506f7274616c3a2077726f6e67206f666673657400000000000000006044820152606401610c54565b856040015160ff16600460ff161480612ec257508160ff16866040015160ff16145b612f0e5760405162461bcd60e51b815260206004820152601c60248201527f4f6d6e69506f7274616c3a2077726f6e6720636f6e66206c6576656c000000006044820152606401610c54565b60608601516001600160401b038581166000908152600860209081526040808320878516845290915290205491811691161015612f855760608601516001600160401b03858116600090815260086020908152604080832087851684529091529020805467ffffffffffffffff1916919092161790555b6001600160401b038085166000908152600760209081526040808320868516845290915281208054600193919291612fbf918591166143f9565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550306001600160a01b031685608001602081019061300091906140ca565b6001600160a01b0316036130da57806001600160401b0316826001600160401b0316856001600160401b03167f8277cab1f0fa69b34674f64a7d43f242b0bacece6f5b7e8652f1e0d88a9b873b6000336000604051602401613093906020808252601e908201527f4f6d6e69506f7274616c3a206e6f207863616c6c20746f20706f7274616c0000604082015260600190565b60408051601f198184030181529181526020820180516001600160e01b031662461bcd60e51b179052516130ca949392919061479c565b60405180910390a4505050505050565b604080518082019091526001600160401b03851681526020810161310460808801606089016140ca565b6001600160a01b039081169091528151600b8054602090940151909216600160401b026001600160e01b03199093166001600160401b0390911617919091179055600080808061315a60a08a0160808b016140ca565b6001600160a01b0316146131ab576131a661317b60a08a0160808b016140ca565b61318b60e08b0160c08c01613d7f565b6001600160401b03166131a160a08c018c6147d8565b61382f565b6131c0565b6131c06131bb60a08a018a6147d8565b6138ef565b600b80546001600160e01b0319169055919450925090506000836131e457826131f5565b604051806020016040528060008152505b9050846001600160401b0316866001600160401b0316896001600160401b03167f8277cab1f0fa69b34674f64a7d43f242b0bacece6f5b7e8652f1e0d88a9b873b85338987604051611d19949392919061479c565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b611510600080516020614af683398151915261201f565b6000805b6003548110156133c457600381815481106132f3576132f3614333565b9060005260206000209060020201915061330a4690565b82546001600160401b039081169116146133445781546001600160401b03166000908152600560205260409020805460ff191690556133bc565b60005b60018301548110156133ba5760006004600085600101848154811061336e5761336e614333565b6000918252602080832060048304015460039092166008026101000a9091046001600160401b031683528201929092526040019020805460ff1916911515919091179055600101613347565b505b6001016132d6565b50610baf60036000613ca9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661151057604051631afcd79f60e31b815260040160405180910390fd5b611eac6133d1565b600061343160208401846140ca565b6001600160a01b03166134858361344b60208701876147d8565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061398692505050565b6001600160a01b0316149392505050565b60008160ff168360ff16856134ab919061481e565b6134b5919061485f565b6001600160401b0316856001600160401b0316119050949350505050565b60606000826001600160401b038111156134ef576134ef614224565b604051908082528060200260200182016040528015613518578160200160208202803683370190505b50905060005b8381101561359857613573600286868481811061353d5761353d614333565b905060200281019061354f9190614349565b60405160200161355f91906148ca565b6040516020818303038152906040526139b0565b82828151811061358557613585614333565b602090810291909101015260010161351e565b509392505050565b805160009085846135b2816001614999565b6135bc8385614999565b146135da57604051631a8a024960e11b815260040160405180910390fd5b6000816001600160401b038111156135f4576135f4614224565b60405190808252806020026020018201604052801561361d578160200160208202803683370190505b5090506000806000805b8581101561376a576000888510613662578584613643816149ac565b95508151811061365557613655614333565b6020026020010151613688565b8a8561366d816149ac565b96508151811061367f5761367f614333565b60200260200101515b905060008d8d8481811061369e5761369e614333565b90506020020160208101906136b391906149c5565b6136e0578f8f856136c3816149ac565b96508181106136d4576136d4614333565b90506020020135613737565b8986106137115786856136f2816149ac565b96508151811061370457613704614333565b6020026020010151613737565b8b8661371c816149ac565b97508151811061372e5761372e614333565b60200260200101515b905061374382826139e7565b87848151811061375557613755614333565b60209081029190910101525050600101613627565b5084156137bc5785811461379157604051631a8a024960e11b815260040160405180910390fd5b8360018603815181106137a6576137a6614333565b6020026020010151975050505050505050611751565b86156137d557886000815181106137a6576137a6614333565b8c8c60008181106137e8576137e8614333565b9050602002013597505050505050505095945050505050565b6000610d8160018360405160200161355f91906149e7565b6000826138268584613a16565b14949350505050565b600060606000805a90506000806138b28960008060019054906101000a900461ffff168b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e6001600160a01b0316613a5190949392919063ffffffff16565b9150915060005a90506138c6603f8b614a6c565b81116138ce57fe5b82826138da838761468e565b965096509650505050505b9450945094915050565b600060606000805a9050600080306001600160a01b03168888604051613916929190614a80565b6000604051808303816000865af19150503d8060008114613953576040519150601f19603f3d011682016040523d82523d6000602084013e613958565b606091505b50915091505a613968908461468e565b92508161397757805160208201fd5b909450925090505b9250925092565b6000806000806139968686613adb565b9250925092506139a68282613b25565b5090949350505050565b600082826040516020016139c5929190614a90565b60408051601f1981840301815282825280516020918201209083015201612001565b6000818310613a035760008281526020849052604090206110ff565b60008381526020839052604090206110ff565b600081815b845181101561359857613a4782868381518110613a3a57613a3a614333565b60200260200101516139e7565b9150600101613a1b565b6000606060008060008661ffff166001600160401b03811115613a7657613a76614224565b6040519080825280601f01601f191660200182016040528015613aa0576020820181803683370190505b5090506000808751602089018b8e8ef191503d925086831115613ac1578692505b828152826000602083013e90999098509650505050505050565b60008060008351604103613b155760208401516040850151606086015160001a613b0788828585613bde565b95509550955050505061397f565b505081516000915060029061397f565b6000826003811115613b3957613b39614abf565b03613b42575050565b6001826003811115613b5657613b56614abf565b03613b745760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115613b8857613b88614abf565b03613ba95760405163fce698f760e01b815260048101829052602401610c54565b6003826003811115613bbd57613bbd614abf565b03610d28576040516335e2f38360e21b815260048101829052602401610c54565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115613c1957506000915060039050826138e5565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015613c6d573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613c99575060009250600191508290506138e5565b9760009750879650945050505050565b5080546000825560020290600052602060002090810190610baf91905b80821115613cf557805467ffffffffffffffff191681556000613cec6001830182613cf9565b50600201613cc6565b5090565b508054600082556003016004900490600052602060002090810190610baf91905b80821115613cf55760008155600101613d1a565b803560ff81168114613d3f57600080fd5b919050565b600060208284031215613d5657600080fd5b6110ff82613d2e565b6001600160401b0381168114610baf57600080fd5b8035613d3f81613d5f565b600060208284031215613d9157600080fd5b81356110ff81613d5f565b60008060208385031215613daf57600080fd5b82356001600160401b0380821115613dc657600080fd5b818501915085601f830112613dda57600080fd5b813581811115613de957600080fd5b8660208260051b8501011115613dfe57600080fd5b60209290920196919550909350505050565b600060208284031215613e2257600080fd5b5035919050565b600060208284031215613e3b57600080fd5b81356001600160401b03811115613e5157600080fd5b82016101a081850312156110ff57600080fd5b60008060408385031215613e7757600080fd5b8235613e8281613d5f565b91506020830135613e9281613d5f565b809150509250929050565b60008060408385031215613eb057600080fd5b823591506020830135613e9281613d5f565b80356001600160a01b0381168114613d3f57600080fd5b60008060408385031215613eec57600080fd5b8235613ef781613d5f565b9150613f0560208401613ec2565b90509250929050565b600060208284031215613f2057600080fd5b81356001600160401b03811115613f3657600080fd5b820161018081850312156110ff57600080fd5b600080600060408486031215613f5e57600080fd5b8335613f6981613d5f565b925060208401356001600160401b0380821115613f8557600080fd5b818601915086601f830112613f9957600080fd5b813581811115613fa857600080fd5b8760208260061b8501011115613fbd57600080fd5b6020830194508093505050509250925092565b60008083601f840112613fe257600080fd5b5081356001600160401b03811115613ff957600080fd5b60208301915083602082850101111561401157600080fd5b9250929050565b6000806000806060858703121561402e57600080fd5b843561403981613d5f565b935060208501356001600160401b0381111561405457600080fd5b61406087828801613fd0565b909450925050604085013561407481613d5f565b939692955090935050565b60008060006060848603121561409457600080fd5b833561409f81613d5f565b925060208401356140af81613d5f565b915060408401356140bf81613d5f565b809150509250925092565b6000602082840312156140dc57600080fd5b6110ff82613ec2565b6000602082840312156140f757600080fd5b813561ffff811681146110ff57600080fd5b60008060008060008060a0878903121561412257600080fd5b863561412d81613d5f565b955061413b60208801613d2e565b945061414960408801613ec2565b935060608701356001600160401b0381111561416457600080fd5b61417089828a01613fd0565b909450925050608087013561418481613d5f565b809150509295509295509295565b6000808335601e198436030181126141a957600080fd5b8301803591506001600160401b038211156141c357600080fd5b6020019150600681901b360382131561401157600080fd5b6000808335601e198436030181126141f257600080fd5b8301803591506001600160401b0382111561420c57600080fd5b6020019150600581901b360382131561401157600080fd5b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561425c5761425c614224565b60405290565b604051601f8201601f191681016001600160401b038111828210171561428a5761428a614224565b604052919050565b600060c082840312156142a457600080fd5b60405160c081018181106001600160401b03821117156142c6576142c6614224565b60405282356142d481613d5f565b815260208301356142e481613d5f565b60208201526142f560408401613d2e565b6040820152606083013561430881613d5f565b6060820152608083013561431b81613d5f565b608082015260a0928301359281019290925250919050565b634e487b7160e01b600052603260045260246000fd5b6000823560de1983360301811261435f57600080fd5b9190910192915050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60006001600160401b038087168352606060208401526143b6606084018688614369565b915080841660408401525095945050505050565b6000602082840312156143dc57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6001600160401b03818116838216019080821115614419576144196143e3565b5092915050565b6001600160a01b0387811682528616602082015260a06040820181905260009061444d9083018688614369565b6001600160401b039490941660608301525060800152949350505050565b60008235603e1983360301811261435f57600080fd5b60008135610d8181613d5f565b600160401b8211156144a2576144a2614224565b8054828255808310156114f95760008260005260206000206003850160021c81016003840160021c8201915060188660031b1680156144f2576000198083018054828460200360031b1c16815550505b505b81811015611096578281556001016144f4565b813561451281613d5f565b815467ffffffffffffffff19166001600160401b0391821617825560019081830160208581013536879003601e1901811261454c57600080fd5b860180358481111561455d57600080fd5b6020820194508060051b360385131561457557600080fd5b61457f818561448e565b60009384526020842093600282901c92505b828110156145e8576000805b60048110156145dc576145cf6145b289614481565b6001600160401b03908116600684901b90811b91901b1984161790565b978601979150880161459d565b50858201558601614591565b506003198116808203818314614623576000805b8281101561461d576146106145b28a614481565b98870198915089016145fc565b50868501555b50505050505050505050565b60006040828403121561464157600080fd5b61464961423a565b61465283613ec2565b8152602083013561466281613d5f565b60208201529392505050565b6001600160401b03828116828216039080821115614419576144196143e3565b81810381811115610d8157610d816143e3565b6000604082360312156146b357600080fd5b6146bb61423a565b6146c483613ec2565b81526020808401356001600160401b03808211156146e157600080fd5b9085019036601f8301126146f457600080fd5b81358181111561470657614706614224565b614718601f8201601f19168501614262565b9150808252368482850101111561472e57600080fd5b80848401858401376000908201840152918301919091525092915050565b60005b8381101561476757818101518382015260200161474f565b50506000910152565b6000815180845261478881602086016020860161474c565b601f01601f19169290920160200192915050565b8481526001600160a01b038416602082015282151560408201526080606082018190526000906147ce90830184614770565b9695505050505050565b6000808335601e198436030181126147ef57600080fd5b8301803591506001600160401b0382111561480957600080fd5b60200191503681900382131561401157600080fd5b6001600160401b03818116838216028082169190828114614841576148416143e3565b505092915050565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b038084168061487957614879614849565b92169190910492915050565b6000808335601e1984360301811261489c57600080fd5b83016020810192503590506001600160401b038111156148bb57600080fd5b80360382131561401157600080fd5b60208152600082356148db81613d5f565b6001600160401b038082166020850152602085013591506148fb82613d5f565b80821660408501526040850135915061491382613d5f565b166060838101919091526001600160a01b0390614931908501613ec2565b16608083015261494360808401613ec2565b6001600160a01b03811660a08401525061496060a0840184614885565b60e060c085015261497661010085018284614369565b91505061498560c08501613d74565b6001600160401b03811660e0850152613598565b80820180821115610d8157610d816143e3565b6000600182016149be576149be6143e3565b5060010190565b6000602082840312156149d757600080fd5b813580151581146110ff57600080fd5b60c0810182356149f681613d5f565b6001600160401b039081168352602084013590614a1282613d5f565b808216602085015260ff614a2860408701613d2e565b16604085015260608501359150614a3e82613d5f565b9081166060840152608084013590614a5582613d5f565b16608083015260a092830135929091019190915290565b600082614a7b57614a7b614849565b500490565b8183823760009101908152919050565b60ff60f81b8360f81b16815260008251614ab181600185016020870161474c565b919091016001019392505050565b634e487b7160e01b600052602160045260246000fdfea06a0c1264badca141841b5f52470407dac9adaaa539dd445540986341b73a6876e8952e4b09b8d505aa08998d716721a1dbf0884ac74202e33985da1ed005e9ff37105740f03695c8f3597f3aff2b92fbe1c80abea3c28731ecff2efd693400feccba1cfc4544bf9cd83b76f36ae5c464750b6c43f682e26744ee21ec31fc1ea264697066735822122082007a797748fabc04818a77901716e59f82472d3f9ab0e18d0fe1956de8602a64736f6c63430008180033
Deployed Bytecode
0x60806040526004361061036b5760003560e01c80638532eb9f116101c6578063b4d5afd1116100f7578063c3d8ad6711610095578063d051c97d1161006f578063d051c97d14610af6578063d533b44514610b37578063f2fde38b14610b57578063f45cc7b814610b7757600080fd5b8063c3d8ad6714610a98578063c4ab80bc14610aad578063cf84c81814610acd57600080fd5b8063bff0e84d116100d1578063bff0e84d14610a25578063c21dda4f14610a45578063c26dfc0514610a58578063c2f9b96814610a7857600080fd5b8063b4d5afd1146109b0578063b521466d146109e5578063bb8590ad14610a0557600080fd5b8063a480ca7911610164578063afe821981161013e578063afe8219814610923578063afe8af9c14610943578063b187bd2614610979578063b2b2f5bd1461098e57600080fd5b8063a480ca79146108b3578063a8a98962146108d3578063aaf1bc97146108f357600080fd5b806397b52062116101a057806397b520621461083c5780639a8a05921461085c578063a10ac97a1461086f578063a32eb7c61461089157600080fd5b80638532eb9f146107b15780638da5cb5b146107d15780638dd9523c1461080e57600080fd5b80633f4ba83a116102a0578063575420501161023e57806374eba9391161021857806374eba9391461074057806378fe53071461076057806383d0cbd9146107875780638456cb591461079c57600080fd5b806357542050146106ca57806366a1eaf31461070b578063715018a61461072b57600080fd5b806349cc3bf61161027a57806349cc3bf614610643578063500b19e71461065d57806354d26bba1461069557806355e2448e146106aa57600080fd5b80633f4ba83a146105cd5780633fd3b15e146105e2578063461ab4881461062357600080fd5b8063241b71bb1161030d57806330632e8b116102e757806330632e8b1461052557806336d219121461054557806336d853f91461056c5780633aa873301461058c57600080fd5b8063241b71bb1461046057806324278bbe146104905780632f32700e146104c057600080fd5b806310a5a7f71161034957806310a5a7f7146103d3578063110ff5f1146103f35780631d3eb6e31461042b57806323dbce501461044b57600080fd5b80630360d20f1461037057806306c3dc5f1461039c578063103ba701146103b1575b600080fd5b34801561037c57600080fd5b50610385600281565b60405160ff90911681526020015b60405180910390f35b3480156103a857600080fd5b50610385600381565b3480156103bd57600080fd5b506103d16103cc366004613d44565b610b9e565b005b3480156103df57600080fd5b506103d16103ee366004613d7f565b610bb2565b3480156103ff57600080fd5b50600154610413906001600160401b031681565b6040516001600160401b039091168152602001610393565b34801561043757600080fd5b506103d1610446366004613d9c565b610c11565b34801561045757600080fd5b506103d1610d2c565b34801561046c57600080fd5b5061048061047b366004613e10565b610d76565b6040519015158152602001610393565b34801561049c57600080fd5b506104806104ab366004613d7f565b60056020526000908152604090205460ff1681565b3480156104cc57600080fd5b50604080518082018252600080825260209182015281518083018352600b546001600160401b0381168083526001600160a01b03600160401b909204821692840192835284519081529151169181019190915201610393565b34801561053157600080fd5b506103d1610540366004613e29565b610d87565b34801561055157600080fd5b5060015461041390600160401b90046001600160401b031681565b34801561057857600080fd5b506103d1610587366004613d7f565b61109e565b34801561059857600080fd5b506104136105a7366004613e64565b60066020908152600092835260408084209091529082529020546001600160401b031681565b3480156105d957600080fd5b506103d16110af565b3480156105ee57600080fd5b506104136105fd366004613e64565b60086020908152600092835260408084209091529082529020546001600160401b031681565b34801561062f57600080fd5b5061048061063e366004613e9d565b6110ea565b34801561064f57600080fd5b506000546103859060ff1681565b34801561066957600080fd5b5060025461067d906001600160a01b031681565b6040516001600160a01b039091168152602001610393565b3480156106a157600080fd5b506103d1611106565b3480156106b657600080fd5b50600b546001600160401b03161515610480565b3480156106d657600080fd5b506104136106e5366004613ed9565b600a6020908152600092835260408084209091529082529020546001600160401b031681565b34801561071757600080fd5b506103d1610726366004613f0e565b611150565b34801561073757600080fd5b506103d16114fe565b34801561074c57600080fd5b5061041361075b366004613e10565b611512565b34801561076c57600080fd5b5060005461041390600160681b90046001600160401b031681565b34801561079357600080fd5b506103d1611541565b3480156107a857600080fd5b506103d161158b565b3480156107bd57600080fd5b506103d16107cc366004613f49565b6115c6565b3480156107dd57600080fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031661067d565b34801561081a57600080fd5b5061082e610829366004614018565b6116d9565b604051908152602001610393565b34801561084857600080fd5b506103d161085736600461407f565b61175a565b34801561086857600080fd5b5046610413565b34801561087b57600080fd5b5061082e600080516020614af683398151915281565b34801561089d57600080fd5b5061082e600080516020614b3683398151915281565b3480156108bf57600080fd5b506103d16108ce3660046140ca565b6117d7565b3480156108df57600080fd5b506103d16108ee3660046140ca565b61185f565b3480156108ff57600080fd5b5061048061090e366004613d7f565b60046020526000908152604090205460ff1681565b34801561092f57600080fd5b506103d161093e366004613d7f565b611870565b34801561094f57600080fd5b5061041361095e366004613d7f565b6009602052600090815260409020546001600160401b031681565b34801561098557600080fd5b506104806118ca565b34801561099a57600080fd5b5061082e600080516020614ad683398151915281565b3480156109bc57600080fd5b506000546109d2906301000000900461ffff1681565b60405161ffff9091168152602001610393565b3480156109f157600080fd5b506103d1610a003660046140e5565b611920565b348015610a1157600080fd5b506103d1610a20366004613d7f565b611931565b348015610a3157600080fd5b506103d1610a403660046140e5565b611942565b6103d1610a53366004614109565b611953565b348015610a6457600080fd5b506000546109d290610100900461ffff1681565b348015610a8457600080fd5b506103d1610a93366004613d7f565b611d2d565b348015610aa457600080fd5b506103d1611d8c565b348015610ab957600080fd5b506103d1610ac836600461407f565b611dd6565b348015610ad957600080fd5b50600054610413906501000000000090046001600160401b031681565b348015610b0257600080fd5b50610413610b11366004613e64565b60076020908152600092835260408084209091529082529020546001600160401b031681565b348015610b4357600080fd5b506103d1610b52366004613d7f565b611e4a565b348015610b6357600080fd5b506103d1610b723660046140ca565b611ea4565b348015610b8357600080fd5b5060005461041390600160a81b90046001600160401b031681565b610ba6611edf565b610baf81611f3a565b50565b610bba611edf565b610bda610bd5600080516020614ad683398151915283611fd6565b61201f565b6040516001600160401b038216907fcd7910e1c5569d8433ce4ef8e5d51c1bdc03168f614b576da47dc3d2b51d033a90600090a250565b333014610c5d5760405162461bcd60e51b815260206004820152601560248201527427b6b734a837b93a30b61d1037b7363c9039b2b63360591b60448201526064015b60405180910390fd5b600154600b546001600160401b03908116600160401b9092041614610cbe5760405162461bcd60e51b815260206004820152601760248201527627b6b734a837b93a30b61d1037b7363c9031b1b430b4b760491b6044820152606401610c54565b600b54600160401b90046001600160a01b031615610d1e5760405162461bcd60e51b815260206004820152601e60248201527f4f6d6e69506f7274616c3a206f6e6c792063636861696e2073656e64657200006044820152606401610c54565b610d28828261209a565b5050565b610d34611edf565b610d4b600080516020614b3683398151915261201f565b6040517f3d0f9c56dac46156a2db0aa09ee7804770ad9fc9549d21023164f22d69475ed890600090a1565b6000610d8182612214565b92915050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b0316600081158015610dcc5750825b90506000826001600160401b03166001148015610de85750303b155b905081158015610df6575080155b15610e145760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610e3e57845460ff60401b1916600160401b1785555b610e53610e4e60208801886140ca565b61227b565b610e6b610e6660408801602089016140ca565b61228c565b610e83610e7e60a0880160808901613d7f565b612330565b610e9b610e9660c0880160a08901613d7f565b6123e8565b610eb3610eae60e0880160c089016140e5565b61249c565b610ecc610ec7610100880160e089016140e5565b612540565b610ee6610ee161012088016101008901613d44565b611f3a565b610f0e610efb61018088016101608901613d7f565b610f09610180890189614192565b6125e0565b610f1e6060870160408801613d7f565b6001805467ffffffffffffffff19166001600160401b0392909216919091179055610f4f6080870160608801613d7f565b600180546001600160401b0392909216600160401b026fffffffffffffffff000000000000000019909216919091179055610104610f9561014088016101208901613d7f565b60076000610fa960808b0160608c01613d7f565b6001600160401b0390811682526020808301939093526040918201600090812086831682529093529120805467ffffffffffffffff191692909116919091179055610ffc61016088016101408901613d7f565b6008600061101060808b0160608c01613d7f565b6001600160401b03908116825260208083019390935260409182016000908120958216815294909252909220805467ffffffffffffffff191691909216179055831561109657845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b6110a6611edf565b610baf81612330565b6110b7611edf565b6110bf61290f565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b60006110ff836110fa8585611fd6565b612926565b9392505050565b61110e611edf565b611125600080516020614ad68339815191526129ad565b6040517f4c48c7b71557216a3192842746bdfc381f98d7536d9eb1c6764f3b45e679482790600090a1565b600080516020614b3683398151915261116f6060830160408401613d7f565b61117d826110fa8484611fd6565b156111bf5760405162461bcd60e51b815260206004820152601260248201527113db5b9a541bdc9d185b0e881c185d5cd95960721b6044820152606401610c54565b6111c7612a28565b3660006111d86101008601866141db565b90925090506040850160006111f08260208901613d7f565b600154909150600160401b90046001600160401b03166112166040840160208501613d7f565b6001600160401b03161461126c5760405162461bcd60e51b815260206004820152601b60248201527f4f6d6e69506f7274616c3a2077726f6e672063636861696e20494400000000006044820152606401610c54565b826112b05760405162461bcd60e51b81526020600482015260146024820152734f6d6e69506f7274616c3a206e6f20786d73677360601b6044820152606401610c54565b6001600160401b03808216600090815260096020526040902054166113175760405162461bcd60e51b815260206004820152601b60248201527f4f6d6e69506f7274616c3a20756e6b6e6f776e2076616c2073657400000000006044820152606401610c54565b61131f612a72565b6001600160401b0316816001600160401b031610156113805760405162461bcd60e51b815260206004820152601760248201527f4f6d6e69506f7274616c3a206f6c642076616c207365740000000000000000006044820152606401610c54565b6113c487356113936101608a018a6141db565b6001600160401b038086166000908152600a6020908152604080832060099092529091205490911660026003612ac2565b6114085760405162461bcd60e51b81526020600482015260156024820152744f6d6e69506f7274616c3a206e6f2071756f72756d60581b6044820152606401610c54565b611431873583868661141e6101208d018d6141db565b61142c6101408f018f6141db565b612ce4565b61147d5760405162461bcd60e51b815260206004820152601960248201527f4f6d6e69506f7274616c3a20696e76616c69642070726f6f66000000000000006044820152606401610c54565b60005b838110156114cb576114c361149a36859003850185614292565b8686848181106114ac576114ac614333565b90506020028101906114be9190614349565b612d5f565b600101611480565b50505050506114f960017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b505050565b611506611edf565b611510600061324a565b565b6003818154811061152257600080fd5b60009182526020909120600290910201546001600160401b0316905081565b611549611edf565b611560600080516020614ad683398151915261201f565b6040517f5f335a4032d4cfb6aca7835b0c2225f36d4d9eaa4ed43ee59ed537e02dff6b3990600090a1565b611593611edf565b61159b6132bb565b6040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75290600090a1565b33301461160d5760405162461bcd60e51b815260206004820152601560248201527427b6b734a837b93a30b61d1037b7363c9039b2b63360591b6044820152606401610c54565b600154600b546001600160401b03908116600160401b909204161461166e5760405162461bcd60e51b815260206004820152601760248201527627b6b734a837b93a30b61d1037b7363c9031b1b430b4b760491b6044820152606401610c54565b600b54600160401b90046001600160a01b0316156116ce5760405162461bcd60e51b815260206004820152601e60248201527f4f6d6e69506f7274616c3a206f6e6c792063636861696e2073656e64657200006044820152606401610c54565b6114f98383836125e0565b600254604051632376548f60e21b81526000916001600160a01b031690638dd9523c90611710908890889088908890600401614392565b602060405180830381865afa15801561172d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061175191906143ca565b95945050505050565b611762611edf565b6001600160401b03838116600081815260086020908152604080832087861680855290835292819020805467ffffffffffffffff191695871695861790555193845290927fe070f08cae8464c91238e8cbea64ccee5e7b48dd79a843f144e3721ee6bdd9b591015b60405180910390a3505050565b6117df611edf565b60405147906001600160a01b0383169082156108fc029083906000818181858888f19350505050158015611817573d6000803e3d6000fd5b50816001600160a01b03167f9dc46f23cfb5ddcad0ae7ea2be38d47fec07bb9382ec7e564efc69e036dd66ce8260405161185391815260200190565b60405180910390a25050565b611867611edf565b610baf8161228c565b611878611edf565b611893610bd5600080516020614b3683398151915283611fd6565b6040516001600160401b038216907fab78810a0515df65f9f10bfbcb92d03d5df71d9fd3b9414e9ad831a5117d6daa90600090a250565b600061191b600080516020614af6833981519152600052600080516020614b168339815191526020527ffae9838a178d7f201aa98e2ce5340158edda60bb1e8f168f46503bf3e99f13be5460ff1690565b905090565b611928611edf565b610baf8161249c565b611939611edf565b610baf816123e8565b61194a611edf565b610baf81612540565b600080516020614ad683398151915286611971826110fa8484611fd6565b156119b35760405162461bcd60e51b815260206004820152601260248201527113db5b9a541bdc9d185b0e881c185d5cd95960721b6044820152606401610c54565b6001600160401b03881660009081526005602052604090205460ff16611a1b5760405162461bcd60e51b815260206004820152601c60248201527f4f6d6e69506f7274616c3a20756e737570706f727465642064657374000000006044820152606401610c54565b6001600160a01b038616611a715760405162461bcd60e51b815260206004820152601b60248201527f4f6d6e69506f7274616c3a206e6f20706f7274616c207863616c6c00000000006044820152606401610c54565b6000546001600160401b036501000000000090910481169084161115611ad95760405162461bcd60e51b815260206004820152601d60248201527f4f6d6e69506f7274616c3a206761734c696d697420746f6f20686967680000006044820152606401610c54565b6000546001600160401b03600160681b90910481169084161015611b3f5760405162461bcd60e51b815260206004820152601c60248201527f4f6d6e69506f7274616c3a206761734c696d697420746f6f206c6f77000000006044820152606401610c54565b6000546301000000900461ffff16841115611b9c5760405162461bcd60e51b815260206004820152601a60248201527f4f6d6e69506f7274616c3a206461746120746f6f206c617267650000000000006044820152606401610c54565b60ff808816600081815260046020526040902054909116611bff5760405162461bcd60e51b815260206004820152601d60248201527f4f6d6e69506f7274616c3a20756e737570706f727465642073686172640000006044820152606401610c54565b6000611c0d8a8888886116d9565b905080341015611c5f5760405162461bcd60e51b815260206004820152601c60248201527f4f6d6e69506f7274616c3a20696e73756666696369656e7420666565000000006044820152606401610c54565b6001600160401b03808b166000908152600660209081526040808320868516845290915281208054600193919291611c99918591166143f9565b82546101009290920a6001600160401b038181021990931691831602179091558b811660008181526006602090815260408083208886168085529252918290205491519190931693507fb7c8eb9d7a7fbcdab809ab7b8a7c41701eb3115e3fe99d30ff490d8552f72bfa90611d199033908e908e908e908e908b90614420565b60405180910390a450505050505050505050565b611d35611edf565b611d55611d50600080516020614b3683398151915283611fd6565b6129ad565b6040516001600160401b038216907fc551305d9bd408be4327b7f8aba28b04ccf6b6c76925392d195ecf9cc764294d90600090a250565b611d94611edf565b611dab600080516020614b368339815191526129ad565b6040517f2cb9d71d4c31860b70e9b707c69aa2f5953e03474f00cfcfff205c4745f8287590600090a1565b611dde611edf565b6001600160401b03838116600081815260076020908152604080832087861680855290835292819020805467ffffffffffffffff191695871695861790555193845290927f8647aae68c8456a1dcbfaf5eaadc94278ae423526d3f09c7b972bff7355d55c791016117ca565b611e52611edf565b611e6d611d50600080516020614ad683398151915283611fd6565b6040516001600160401b038216907f1ed9223556fb0971076c30172f1f00630efd313b6a05290a562aef95928e712590600090a250565b611eac611edf565b6001600160a01b038116611ed657604051631e4fbdf760e01b815260006004820152602401610c54565b610baf8161324a565b33611f117f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146115105760405163118cdaa760e01b8152336004820152602401610c54565b60008160ff1611611f8d5760405162461bcd60e51b815260206004820152601a60248201527f4f6d6e69506f7274616c3a206e6f207a65726f206375746f66660000000000006044820152606401610c54565b6000805460ff191660ff83169081179091556040519081527f1683dc51426224f6e37a3b41dd5849e2db1bfe22366d1d913fa0ef6f757e828f906020015b60405180910390a150565b6000828260405160200161200192919091825260c01b6001600160c01b031916602082015260280190565b60405160208183030381529060405280519060200120905092915050565b6000818152600080516020614b16833981519152602081905260409091205460ff16156120815760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610c54565b600091825260205260409020805460ff19166001179055565b6120a26132d2565b3660005b8281101561220e578383828181106120c0576120c0614333565b90506020028101906120d2919061446b565b6003805460018101825560009190915290925082906002027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b016121168282614507565b505061211f4690565b6001600160401b03166121356020840184613d7f565b6001600160401b031614612183576001600560006121566020860186613d7f565b6001600160401b031681526020810191909152604001600020805460ff1916911515919091179055612206565b60005b61219360208401846141db565b9050811015612204576001600460006121af60208701876141db565b858181106121bf576121bf614333565b90506020020160208101906121d49190613d7f565b6001600160401b031681526020810191909152604001600020805460ff1916911515919091179055600101612186565b505b6001016120a6565b50505050565b600080516020614af68339815191526000908152600080516020614b1683398151915260208190527ffae9838a178d7f201aa98e2ce5340158edda60bb1e8f168f46503bf3e99f13be5460ff16806110ff5750600092835260205250604090205460ff1690565b6122836133d1565b610baf8161341a565b6001600160a01b0381166122e25760405162461bcd60e51b815260206004820152601d60248201527f4f6d6e69506f7274616c3a206e6f207a65726f206665654f7261636c650000006044820152606401610c54565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd97bdb0db82b52a85aa07f8da78033b1d6e159d94f1e3cbd4109d946c3bcfd3290602001611fcb565b6000816001600160401b0316116123895760405162461bcd60e51b815260206004820152601b60248201527f4f6d6e69506f7274616c3a206e6f207a65726f206d61782067617300000000006044820152606401610c54565b600080546cffffffffffffffff00000000001916650100000000006001600160401b038416908102919091179091556040519081527f1153561ac5effc2926ba6c612f86a397c997bc43dfbfc718da08065be0c5fe4d90602001611fcb565b6000816001600160401b0316116124415760405162461bcd60e51b815260206004820152601b60248201527f4f6d6e69506f7274616c3a206e6f207a65726f206d696e2067617300000000006044820152606401610c54565b6000805467ffffffffffffffff60681b1916600160681b6001600160401b038416908102919091179091556040519081527f8c852a6291aa436654b167353bca4a4b0c3d024c7562cb5082e7c869bddabf3e90602001611fcb565b60008161ffff16116124f05760405162461bcd60e51b815260206004820152601c60248201527f4f6d6e69506f7274616c3a206e6f207a65726f206d61782073697a65000000006044820152606401610c54565b6000805464ffff0000001916630100000061ffff8416908102919091179091556040519081527f65923e04419dc810d0ea08a94a7f608d4c4d949818d95c3788f895e575dd206490602001611fcb565b60008161ffff16116125945760405162461bcd60e51b815260206004820152601c60248201527f4f6d6e69506f7274616c3a206e6f207a65726f206d61782073697a65000000006044820152606401610c54565b6000805462ffff00191661010061ffff8416908102919091179091556040519081527f620bbea084306b66a8cc6b5b63830d6b3874f9d2438914e259ffd5065c33f7b090602001611fcb565b808061262e5760405162461bcd60e51b815260206004820152601960248201527f4f6d6e69506f7274616c3a206e6f2076616c696461746f7273000000000000006044820152606401610c54565b6001600160401b0380851660009081526009602052604090205416156126965760405162461bcd60e51b815260206004820152601d60248201527f4f6d6e69506f7274616c3a206475706c69636174652076616c207365740000006044820152606401610c54565b604080518082018252600080825260208083018290526001600160401b0388168252600a9052918220825b8481101561286e578686828181106126db576126db614333565b9050604002018036038101906126f1919061462f565b80519093506001600160a01b031661274b5760405162461bcd60e51b815260206004820152601d60248201527f4f6d6e69506f7274616c3a206e6f207a65726f2076616c696461746f720000006044820152606401610c54565b600083602001516001600160401b0316116127a85760405162461bcd60e51b815260206004820152601960248201527f4f6d6e69506f7274616c3a206e6f207a65726f20706f776572000000000000006044820152606401610c54565b82516001600160a01b03166000908152602083905260409020546001600160401b0316156128185760405162461bcd60e51b815260206004820152601f60248201527f4f6d6e69506f7274616c3a206475706c69636174652076616c696461746f72006044820152606401610c54565b602083015161282790856143f9565b60208481015185516001600160a01b03166000908152918590526040909120805467ffffffffffffffff19166001600160401b0390921691909117905593506001016126c1565b506001600160401b038781166000818152600960205260408120805467ffffffffffffffff191687851617905554600160a81b900490911610156128d2576000805467ffffffffffffffff60a81b1916600160a81b6001600160401b038a16021790555b6040516001600160401b038816907f3a7c2f997a87ba92aedaecd1127f4129cae1283e2809ebf5304d321b943fd10790600090a250505050505050565b611510600080516020614af68339815191526129ad565b600080516020614af68339815191526000908152600080516020614b1683398151915260208190527ffae9838a178d7f201aa98e2ce5340158edda60bb1e8f168f46503bf3e99f13be5460ff168061298c575060008481526020829052604090205460ff165b806129a5575060008381526020829052604090205460ff165b949350505050565b6000818152600080516020614b16833981519152602081905260409091205460ff16612a125760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610c54565b600091825260205260409020805460ff19169055565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00805460011901612a6c57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b6000805460ff8116600160a81b9091046001600160401b031611612a965750600190565b600054612ab79060ff811690600160a81b90046001600160401b031661466e565b61191b9060016143f9565b6000803660005b88811015612cd157898982818110612ae357612ae3614333565b9050602002810190612af5919061446b565b91508015612c175760008a8a612b0c60018561468e565b818110612b1b57612b1b614333565b9050602002810190612b2d919061446b565b612b36906146a1565b80519091506001600160a01b0316612b5160208501856140ca565b6001600160a01b031603612ba75760405162461bcd60e51b815260206004820152601b60248201527f51756f72756d3a206475706c69636174652076616c696461746f7200000000006044820152606401610c54565b80516001600160a01b0316612bbf60208501856140ca565b6001600160a01b031611612c155760405162461bcd60e51b815260206004820152601760248201527f51756f72756d3a2073696773206e6f7420736f727465640000000000000000006044820152606401610c54565b505b612c21828c613422565b612c6d5760405162461bcd60e51b815260206004820152601960248201527f51756f72756d3a20696e76616c6964207369676e6174757265000000000000006044820152606401610c54565b876000612c7d60208501856140ca565b6001600160a01b03168152602081019190915260400160002054612caa906001600160401b0316846143f9565b9250612cb883888888613496565b15612cc95760019350505050612cd9565b600101612ac9565b506000925050505b979650505050505050565b60408051600180825281830190925260009182919060208083019080368337019050509050612d1f86868686612d1a8d8d6134d3565b6135a0565b81600081518110612d3257612d32614333565b602002602001018181525050612d51818b612d4c8c613801565b613819565b9a9950505050505050505050565b81516000612d706020840184613d7f565b90506000612d846040850160208601613d7f565b90506000612d986060860160408701613d7f565b9050466001600160401b0316836001600160401b03161480612dc157506001600160401b038316155b612e0d5760405162461bcd60e51b815260206004820152601c60248201527f4f6d6e69506f7274616c3a2077726f6e67206465737420636861696e000000006044820152606401610c54565b6001600160401b0380851660009081526007602090815260408083208685168452909152902054612e40911660016143f9565b6001600160401b0316816001600160401b031614612ea05760405162461bcd60e51b815260206004820152601860248201527f4f6d6e69506f7274616c3a2077726f6e67206f666673657400000000000000006044820152606401610c54565b856040015160ff16600460ff161480612ec257508160ff16866040015160ff16145b612f0e5760405162461bcd60e51b815260206004820152601c60248201527f4f6d6e69506f7274616c3a2077726f6e6720636f6e66206c6576656c000000006044820152606401610c54565b60608601516001600160401b038581166000908152600860209081526040808320878516845290915290205491811691161015612f855760608601516001600160401b03858116600090815260086020908152604080832087851684529091529020805467ffffffffffffffff1916919092161790555b6001600160401b038085166000908152600760209081526040808320868516845290915281208054600193919291612fbf918591166143f9565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550306001600160a01b031685608001602081019061300091906140ca565b6001600160a01b0316036130da57806001600160401b0316826001600160401b0316856001600160401b03167f8277cab1f0fa69b34674f64a7d43f242b0bacece6f5b7e8652f1e0d88a9b873b6000336000604051602401613093906020808252601e908201527f4f6d6e69506f7274616c3a206e6f207863616c6c20746f20706f7274616c0000604082015260600190565b60408051601f198184030181529181526020820180516001600160e01b031662461bcd60e51b179052516130ca949392919061479c565b60405180910390a4505050505050565b604080518082019091526001600160401b03851681526020810161310460808801606089016140ca565b6001600160a01b039081169091528151600b8054602090940151909216600160401b026001600160e01b03199093166001600160401b0390911617919091179055600080808061315a60a08a0160808b016140ca565b6001600160a01b0316146131ab576131a661317b60a08a0160808b016140ca565b61318b60e08b0160c08c01613d7f565b6001600160401b03166131a160a08c018c6147d8565b61382f565b6131c0565b6131c06131bb60a08a018a6147d8565b6138ef565b600b80546001600160e01b0319169055919450925090506000836131e457826131f5565b604051806020016040528060008152505b9050846001600160401b0316866001600160401b0316896001600160401b03167f8277cab1f0fa69b34674f64a7d43f242b0bacece6f5b7e8652f1e0d88a9b873b85338987604051611d19949392919061479c565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b611510600080516020614af683398151915261201f565b6000805b6003548110156133c457600381815481106132f3576132f3614333565b9060005260206000209060020201915061330a4690565b82546001600160401b039081169116146133445781546001600160401b03166000908152600560205260409020805460ff191690556133bc565b60005b60018301548110156133ba5760006004600085600101848154811061336e5761336e614333565b6000918252602080832060048304015460039092166008026101000a9091046001600160401b031683528201929092526040019020805460ff1916911515919091179055600101613347565b505b6001016132d6565b50610baf60036000613ca9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661151057604051631afcd79f60e31b815260040160405180910390fd5b611eac6133d1565b600061343160208401846140ca565b6001600160a01b03166134858361344b60208701876147d8565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061398692505050565b6001600160a01b0316149392505050565b60008160ff168360ff16856134ab919061481e565b6134b5919061485f565b6001600160401b0316856001600160401b0316119050949350505050565b60606000826001600160401b038111156134ef576134ef614224565b604051908082528060200260200182016040528015613518578160200160208202803683370190505b50905060005b8381101561359857613573600286868481811061353d5761353d614333565b905060200281019061354f9190614349565b60405160200161355f91906148ca565b6040516020818303038152906040526139b0565b82828151811061358557613585614333565b602090810291909101015260010161351e565b509392505050565b805160009085846135b2816001614999565b6135bc8385614999565b146135da57604051631a8a024960e11b815260040160405180910390fd5b6000816001600160401b038111156135f4576135f4614224565b60405190808252806020026020018201604052801561361d578160200160208202803683370190505b5090506000806000805b8581101561376a576000888510613662578584613643816149ac565b95508151811061365557613655614333565b6020026020010151613688565b8a8561366d816149ac565b96508151811061367f5761367f614333565b60200260200101515b905060008d8d8481811061369e5761369e614333565b90506020020160208101906136b391906149c5565b6136e0578f8f856136c3816149ac565b96508181106136d4576136d4614333565b90506020020135613737565b8986106137115786856136f2816149ac565b96508151811061370457613704614333565b6020026020010151613737565b8b8661371c816149ac565b97508151811061372e5761372e614333565b60200260200101515b905061374382826139e7565b87848151811061375557613755614333565b60209081029190910101525050600101613627565b5084156137bc5785811461379157604051631a8a024960e11b815260040160405180910390fd5b8360018603815181106137a6576137a6614333565b6020026020010151975050505050505050611751565b86156137d557886000815181106137a6576137a6614333565b8c8c60008181106137e8576137e8614333565b9050602002013597505050505050505095945050505050565b6000610d8160018360405160200161355f91906149e7565b6000826138268584613a16565b14949350505050565b600060606000805a90506000806138b28960008060019054906101000a900461ffff168b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e6001600160a01b0316613a5190949392919063ffffffff16565b9150915060005a90506138c6603f8b614a6c565b81116138ce57fe5b82826138da838761468e565b965096509650505050505b9450945094915050565b600060606000805a9050600080306001600160a01b03168888604051613916929190614a80565b6000604051808303816000865af19150503d8060008114613953576040519150601f19603f3d011682016040523d82523d6000602084013e613958565b606091505b50915091505a613968908461468e565b92508161397757805160208201fd5b909450925090505b9250925092565b6000806000806139968686613adb565b9250925092506139a68282613b25565b5090949350505050565b600082826040516020016139c5929190614a90565b60408051601f1981840301815282825280516020918201209083015201612001565b6000818310613a035760008281526020849052604090206110ff565b60008381526020839052604090206110ff565b600081815b845181101561359857613a4782868381518110613a3a57613a3a614333565b60200260200101516139e7565b9150600101613a1b565b6000606060008060008661ffff166001600160401b03811115613a7657613a76614224565b6040519080825280601f01601f191660200182016040528015613aa0576020820181803683370190505b5090506000808751602089018b8e8ef191503d925086831115613ac1578692505b828152826000602083013e90999098509650505050505050565b60008060008351604103613b155760208401516040850151606086015160001a613b0788828585613bde565b95509550955050505061397f565b505081516000915060029061397f565b6000826003811115613b3957613b39614abf565b03613b42575050565b6001826003811115613b5657613b56614abf565b03613b745760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115613b8857613b88614abf565b03613ba95760405163fce698f760e01b815260048101829052602401610c54565b6003826003811115613bbd57613bbd614abf565b03610d28576040516335e2f38360e21b815260048101829052602401610c54565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115613c1957506000915060039050826138e5565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015613c6d573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613c99575060009250600191508290506138e5565b9760009750879650945050505050565b5080546000825560020290600052602060002090810190610baf91905b80821115613cf557805467ffffffffffffffff191681556000613cec6001830182613cf9565b50600201613cc6565b5090565b508054600082556003016004900490600052602060002090810190610baf91905b80821115613cf55760008155600101613d1a565b803560ff81168114613d3f57600080fd5b919050565b600060208284031215613d5657600080fd5b6110ff82613d2e565b6001600160401b0381168114610baf57600080fd5b8035613d3f81613d5f565b600060208284031215613d9157600080fd5b81356110ff81613d5f565b60008060208385031215613daf57600080fd5b82356001600160401b0380821115613dc657600080fd5b818501915085601f830112613dda57600080fd5b813581811115613de957600080fd5b8660208260051b8501011115613dfe57600080fd5b60209290920196919550909350505050565b600060208284031215613e2257600080fd5b5035919050565b600060208284031215613e3b57600080fd5b81356001600160401b03811115613e5157600080fd5b82016101a081850312156110ff57600080fd5b60008060408385031215613e7757600080fd5b8235613e8281613d5f565b91506020830135613e9281613d5f565b809150509250929050565b60008060408385031215613eb057600080fd5b823591506020830135613e9281613d5f565b80356001600160a01b0381168114613d3f57600080fd5b60008060408385031215613eec57600080fd5b8235613ef781613d5f565b9150613f0560208401613ec2565b90509250929050565b600060208284031215613f2057600080fd5b81356001600160401b03811115613f3657600080fd5b820161018081850312156110ff57600080fd5b600080600060408486031215613f5e57600080fd5b8335613f6981613d5f565b925060208401356001600160401b0380821115613f8557600080fd5b818601915086601f830112613f9957600080fd5b813581811115613fa857600080fd5b8760208260061b8501011115613fbd57600080fd5b6020830194508093505050509250925092565b60008083601f840112613fe257600080fd5b5081356001600160401b03811115613ff957600080fd5b60208301915083602082850101111561401157600080fd5b9250929050565b6000806000806060858703121561402e57600080fd5b843561403981613d5f565b935060208501356001600160401b0381111561405457600080fd5b61406087828801613fd0565b909450925050604085013561407481613d5f565b939692955090935050565b60008060006060848603121561409457600080fd5b833561409f81613d5f565b925060208401356140af81613d5f565b915060408401356140bf81613d5f565b809150509250925092565b6000602082840312156140dc57600080fd5b6110ff82613ec2565b6000602082840312156140f757600080fd5b813561ffff811681146110ff57600080fd5b60008060008060008060a0878903121561412257600080fd5b863561412d81613d5f565b955061413b60208801613d2e565b945061414960408801613ec2565b935060608701356001600160401b0381111561416457600080fd5b61417089828a01613fd0565b909450925050608087013561418481613d5f565b809150509295509295509295565b6000808335601e198436030181126141a957600080fd5b8301803591506001600160401b038211156141c357600080fd5b6020019150600681901b360382131561401157600080fd5b6000808335601e198436030181126141f257600080fd5b8301803591506001600160401b0382111561420c57600080fd5b6020019150600581901b360382131561401157600080fd5b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561425c5761425c614224565b60405290565b604051601f8201601f191681016001600160401b038111828210171561428a5761428a614224565b604052919050565b600060c082840312156142a457600080fd5b60405160c081018181106001600160401b03821117156142c6576142c6614224565b60405282356142d481613d5f565b815260208301356142e481613d5f565b60208201526142f560408401613d2e565b6040820152606083013561430881613d5f565b6060820152608083013561431b81613d5f565b608082015260a0928301359281019290925250919050565b634e487b7160e01b600052603260045260246000fd5b6000823560de1983360301811261435f57600080fd5b9190910192915050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60006001600160401b038087168352606060208401526143b6606084018688614369565b915080841660408401525095945050505050565b6000602082840312156143dc57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6001600160401b03818116838216019080821115614419576144196143e3565b5092915050565b6001600160a01b0387811682528616602082015260a06040820181905260009061444d9083018688614369565b6001600160401b039490941660608301525060800152949350505050565b60008235603e1983360301811261435f57600080fd5b60008135610d8181613d5f565b600160401b8211156144a2576144a2614224565b8054828255808310156114f95760008260005260206000206003850160021c81016003840160021c8201915060188660031b1680156144f2576000198083018054828460200360031b1c16815550505b505b81811015611096578281556001016144f4565b813561451281613d5f565b815467ffffffffffffffff19166001600160401b0391821617825560019081830160208581013536879003601e1901811261454c57600080fd5b860180358481111561455d57600080fd5b6020820194508060051b360385131561457557600080fd5b61457f818561448e565b60009384526020842093600282901c92505b828110156145e8576000805b60048110156145dc576145cf6145b289614481565b6001600160401b03908116600684901b90811b91901b1984161790565b978601979150880161459d565b50858201558601614591565b506003198116808203818314614623576000805b8281101561461d576146106145b28a614481565b98870198915089016145fc565b50868501555b50505050505050505050565b60006040828403121561464157600080fd5b61464961423a565b61465283613ec2565b8152602083013561466281613d5f565b60208201529392505050565b6001600160401b03828116828216039080821115614419576144196143e3565b81810381811115610d8157610d816143e3565b6000604082360312156146b357600080fd5b6146bb61423a565b6146c483613ec2565b81526020808401356001600160401b03808211156146e157600080fd5b9085019036601f8301126146f457600080fd5b81358181111561470657614706614224565b614718601f8201601f19168501614262565b9150808252368482850101111561472e57600080fd5b80848401858401376000908201840152918301919091525092915050565b60005b8381101561476757818101518382015260200161474f565b50506000910152565b6000815180845261478881602086016020860161474c565b601f01601f19169290920160200192915050565b8481526001600160a01b038416602082015282151560408201526080606082018190526000906147ce90830184614770565b9695505050505050565b6000808335601e198436030181126147ef57600080fd5b8301803591506001600160401b0382111561480957600080fd5b60200191503681900382131561401157600080fd5b6001600160401b03818116838216028082169190828114614841576148416143e3565b505092915050565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b038084168061487957614879614849565b92169190910492915050565b6000808335601e1984360301811261489c57600080fd5b83016020810192503590506001600160401b038111156148bb57600080fd5b80360382131561401157600080fd5b60208152600082356148db81613d5f565b6001600160401b038082166020850152602085013591506148fb82613d5f565b80821660408501526040850135915061491382613d5f565b166060838101919091526001600160a01b0390614931908501613ec2565b16608083015261494360808401613ec2565b6001600160a01b03811660a08401525061496060a0840184614885565b60e060c085015261497661010085018284614369565b91505061498560c08501613d74565b6001600160401b03811660e0850152613598565b80820180821115610d8157610d816143e3565b6000600182016149be576149be6143e3565b5060010190565b6000602082840312156149d757600080fd5b813580151581146110ff57600080fd5b60c0810182356149f681613d5f565b6001600160401b039081168352602084013590614a1282613d5f565b808216602085015260ff614a2860408701613d2e565b16604085015260608501359150614a3e82613d5f565b9081166060840152608084013590614a5582613d5f565b16608083015260a092830135929091019190915290565b600082614a7b57614a7b614849565b500490565b8183823760009101908152919050565b60ff60f81b8360f81b16815260008251614ab181600185016020870161474c565b919091016001019392505050565b634e487b7160e01b600052602160045260246000fdfea06a0c1264badca141841b5f52470407dac9adaaa539dd445540986341b73a6876e8952e4b09b8d505aa08998d716721a1dbf0884ac74202e33985da1ed005e9ff37105740f03695c8f3597f3aff2b92fbe1c80abea3c28731ecff2efd693400feccba1cfc4544bf9cd83b76f36ae5c464750b6c43f682e26744ee21ec31fc1ea264697066735822122082007a797748fabc04818a77901716e59f82472d3f9ab0e18d0fe1956de8602a64736f6c63430008180033
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.