Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60a06040 | 20317699 | 130 days ago | IN | 0 ETH | 0.0326716 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
MainnetSignalService
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "../signal/SignalService.sol"; import "./LibSharedAddressCache.sol"; /// @title MainnetSignalService /// @dev This contract shall be deployed to replace its parent contract on Ethereum for Taiko /// mainnet to reduce gas cost. In theory, the contract can also be deplyed on Taiko L2 but this is /// not well testee nor necessary. /// @notice See the documentation in {SignalService}. /// @custom:security-contact [email protected] contract MainnetSignalService is SignalService { function _getAddress(uint64 _chainId, bytes32 _name) internal view override returns (address) { (bool found, address addr) = LibSharedAddressCache.getAddress(_chainId, _name); return found ? addr : super._getAddress(_chainId, _name); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "../common/EssentialContract.sol"; import "../common/LibStrings.sol"; import "../libs/LibTrieProof.sol"; import "./ISignalService.sol"; /// @title SignalService /// @notice See the documentation in {ISignalService} for more details. /// @dev Labeled in AddressResolver as "signal_service". /// @custom:security-contact [email protected] contract SignalService is EssentialContract, ISignalService { /// @notice Mapping to store the top blockId. /// @dev Slot 1. mapping(uint64 chainId => mapping(bytes32 kind => uint64 blockId)) public topBlockId; /// @notice Mapping to store the authorized addresses. /// @dev Slot 2. mapping(address addr => bool authorized) public isAuthorized; uint256[48] private __gap; struct CacheAction { bytes32 rootHash; bytes32 signalRoot; uint64 chainId; uint64 blockId; bool isFullProof; bool isLastHop; CacheOption option; } error SS_EMPTY_PROOF(); error SS_INVALID_HOPS_WITH_LOOP(); error SS_INVALID_LAST_HOP_CHAINID(); error SS_INVALID_MID_HOP_CHAINID(); error SS_INVALID_STATE(); error SS_SIGNAL_NOT_FOUND(); error SS_UNAUTHORIZED(); /// @notice Initializes the contract. /// @param _owner The owner of this contract. msg.sender will be used if this value is zero. /// @param _addressManager The address of the {AddressManager} contract. function init(address _owner, address _addressManager) external initializer { __Essential_init(_owner, _addressManager); } /// @dev Authorize or deauthorize an address for calling syncChainData. /// @dev Note that addr is supposed to be TaikoL1 and TaikoL1 contracts deployed locally. /// @param _addr The address to be authorized or deauthorized. /// @param _authorize True if authorize, false otherwise. function authorize(address _addr, bool _authorize) external onlyOwner { if (isAuthorized[_addr] == _authorize) revert SS_INVALID_STATE(); isAuthorized[_addr] = _authorize; emit Authorized(_addr, _authorize); } /// @inheritdoc ISignalService function sendSignal(bytes32 _signal) external returns (bytes32) { return _sendSignal(msg.sender, _signal, _signal); } /// @inheritdoc ISignalService function syncChainData( uint64 _chainId, bytes32 _kind, uint64 _blockId, bytes32 _chainData ) external returns (bytes32) { if (!isAuthorized[msg.sender]) revert SS_UNAUTHORIZED(); return _syncChainData(_chainId, _kind, _blockId, _chainData); } /// @inheritdoc ISignalService /// @dev This function may revert. function proveSignalReceived( uint64 _chainId, address _app, bytes32 _signal, bytes calldata _proof ) external virtual whenNotPaused nonReentrant returns (uint256 numCacheOps_) { CacheAction[] memory actions = // actions for caching _verifySignalReceived(_chainId, _app, _signal, _proof, true); for (uint256 i; i < actions.length; ++i) { numCacheOps_ += _cache(actions[i]); } } /// @inheritdoc ISignalService /// @dev This function may revert. function verifySignalReceived( uint64 _chainId, address _app, bytes32 _signal, bytes calldata _proof ) external view { _verifySignalReceived(_chainId, _app, _signal, _proof, false); } /// @inheritdoc ISignalService function isChainDataSynced( uint64 _chainId, bytes32 _kind, uint64 _blockId, bytes32 _chainData ) public view nonZeroValue(_chainData) returns (bool) { bytes32 signal = signalForChainData(_chainId, _kind, _blockId); return _loadSignalValue(address(this), signal) == _chainData; } /// @inheritdoc ISignalService function isSignalSent(address _app, bytes32 _signal) public view returns (bool) { return _loadSignalValue(_app, _signal) != 0; } /// @inheritdoc ISignalService function getSyncedChainData( uint64 _chainId, bytes32 _kind, uint64 _blockId ) public view returns (uint64 blockId_, bytes32 chainData_) { blockId_ = _blockId != 0 ? _blockId : topBlockId[_chainId][_kind]; if (blockId_ != 0) { bytes32 signal = signalForChainData(_chainId, _kind, blockId_); chainData_ = _loadSignalValue(address(this), signal); if (chainData_ == 0) revert SS_SIGNAL_NOT_FOUND(); } } /// @inheritdoc ISignalService function signalForChainData( uint64 _chainId, bytes32 _kind, uint64 _blockId ) public pure returns (bytes32) { return keccak256(abi.encode(_chainId, _kind, _blockId)); } /// @notice Returns the slot for a signal. /// @param _chainId The chainId of the signal. /// @param _app The address that initiated the signal. /// @param _signal The signal (message) that was sent. /// @return The slot for the signal. function getSignalSlot( uint64 _chainId, address _app, bytes32 _signal ) public pure returns (bytes32) { return keccak256(abi.encodePacked("SIGNAL", _chainId, _app, _signal)); } function _verifyHopProof( uint64 _chainId, address _app, bytes32 _signal, bytes32 _value, HopProof memory _hop, address _signalService ) internal view virtual nonZeroAddr(_app) nonZeroValue(_signal) nonZeroValue(_value) returns (bytes32) { return LibTrieProof.verifyMerkleProof( _hop.rootHash, _signalService, getSignalSlot(_chainId, _app, _signal), _value, _hop.accountProof, _hop.storageProof ); } function _authorizePause(address, bool) internal pure override notImplemented { } function _syncChainData( uint64 _chainId, bytes32 _kind, uint64 _blockId, bytes32 _chainData ) private returns (bytes32 signal_) { signal_ = signalForChainData(_chainId, _kind, _blockId); _sendSignal(address(this), signal_, _chainData); if (topBlockId[_chainId][_kind] < _blockId) { topBlockId[_chainId][_kind] = _blockId; } emit ChainDataSynced(_chainId, _blockId, _kind, _chainData, signal_); } function _sendSignal( address _app, bytes32 _signal, bytes32 _value ) private nonZeroAddr(_app) nonZeroValue(_signal) nonZeroValue(_value) returns (bytes32 slot_) { slot_ = getSignalSlot(uint64(block.chainid), _app, _signal); assembly { sstore(slot_, _value) } emit SignalSent(_app, _signal, slot_, _value); } function _cache(CacheAction memory _action) private returns (uint256 numCacheOps_) { // cache state root bool cacheStateRoot = _action.option == CacheOption.CACHE_BOTH || _action.option == CacheOption.CACHE_STATE_ROOT; if (cacheStateRoot && _action.isFullProof && !_action.isLastHop) { numCacheOps_ = 1; _syncChainData( _action.chainId, LibStrings.H_STATE_ROOT, _action.blockId, _action.rootHash ); } // cache signal root bool cacheSignalRoot = _action.option == CacheOption.CACHE_BOTH || _action.option == CacheOption.CACHE_SIGNAL_ROOT; if (cacheSignalRoot && (_action.isFullProof || !_action.isLastHop)) { numCacheOps_ += 1; _syncChainData( _action.chainId, LibStrings.H_SIGNAL_ROOT, _action.blockId, _action.signalRoot ); } } function _loadSignalValue( address _app, bytes32 _signal ) private view nonZeroAddr(_app) nonZeroValue(_signal) returns (bytes32 value_) { bytes32 slot = getSignalSlot(uint64(block.chainid), _app, _signal); assembly { value_ := sload(slot) } } function _verifySignalReceived( uint64 _chainId, address _app, bytes32 _signal, bytes calldata _proof, bool _prepareCaching ) private view nonZeroAddr(_app) nonZeroValue(_signal) returns (CacheAction[] memory actions) { HopProof[] memory hopProofs = abi.decode(_proof, (HopProof[])); if (hopProofs.length == 0) revert SS_EMPTY_PROOF(); uint64[] memory trace = new uint64[](hopProofs.length - 1); if (_prepareCaching) { actions = new CacheAction[](hopProofs.length); } uint64 chainId = _chainId; address app = _app; bytes32 signal = _signal; bytes32 value = _signal; address signalService = resolve(chainId, LibStrings.B_SIGNAL_SERVICE, false); if (signalService == address(this)) revert SS_INVALID_MID_HOP_CHAINID(); HopProof memory hop; bytes32 signalRoot; bool isFullProof; bool isLastHop; for (uint256 i; i < hopProofs.length; ++i) { hop = hopProofs[i]; for (uint256 j; j < i; ++j) { if (trace[j] == hop.chainId) revert SS_INVALID_HOPS_WITH_LOOP(); } signalRoot = _verifyHopProof(chainId, app, signal, value, hop, signalService); isLastHop = i == trace.length; if (isLastHop) { if (hop.chainId != block.chainid) revert SS_INVALID_LAST_HOP_CHAINID(); signalService = address(this); } else { trace[i] = hop.chainId; if (hop.chainId == 0 || hop.chainId == block.chainid) { revert SS_INVALID_MID_HOP_CHAINID(); } signalService = resolve(hop.chainId, LibStrings.B_SIGNAL_SERVICE, false); if (signalService == address(this)) revert SS_INVALID_MID_HOP_CHAINID(); } isFullProof = hop.accountProof.length != 0; if (_prepareCaching) { actions[i] = CacheAction( hop.rootHash, signalRoot, chainId, hop.blockId, isFullProof, isLastHop, hop.cacheOption ); } signal = signalForChainData( chainId, isFullProof ? LibStrings.H_STATE_ROOT : LibStrings.H_SIGNAL_ROOT, hop.blockId ); value = hop.rootHash; chainId = hop.chainId; app = signalService; } if (value == 0 || value != _loadSignalValue(address(this), signal)) { revert SS_SIGNAL_NOT_FOUND(); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "../common/LibStrings.sol"; /// @title LibSharedAddressCache /// @custom:security-contact [email protected] library LibSharedAddressCache { function getAddress( uint64 _chainId, bytes32 _name ) internal pure returns (bool found, address addr) { if (_chainId == 1) { if (_name == LibStrings.B_TAIKO_TOKEN) { return (true, 0x10dea67478c5F8C5E2D90e5E9B26dBe60c54d800); } if (_name == LibStrings.B_QUOTA_MANAGER) { return (true, 0x91f67118DD47d502B1f0C354D0611997B022f29E); } if (_name == LibStrings.B_BRIDGE) { return (true, 0xd60247c6848B7Ca29eDdF63AA924E53dB6Ddd8EC); } if (_name == LibStrings.B_BRIDGED_ERC20) { return (true, 0x79BC0Aada00fcF6E7AB514Bfeb093b5Fae3653e3); } if (_name == LibStrings.B_BRIDGED_ERC721) { return (true, 0xC3310905E2BC9Cfb198695B75EF3e5B69C6A1Bf7); } if (_name == LibStrings.B_BRIDGED_ERC1155) { return (true, 0x3c90963cFBa436400B0F9C46Aa9224cB379c2c40); } if (_name == LibStrings.B_ERC20_VAULT) { return (true, 0x996282cA11E5DEb6B5D122CC3B9A1FcAAD4415Ab); } if (_name == LibStrings.B_ERC721_VAULT) { return (true, 0x0b470dd3A0e1C41228856Fb319649E7c08f419Aa); } if (_name == LibStrings.B_ERC1155_VAULT) { return (true, 0xaf145913EA4a56BE22E120ED9C24589659881702); } if (_name == LibStrings.B_SIGNAL_SERVICE) { return (true, 0x9e0a24964e5397B566c1ed39258e21aB5E35C77C); } } else if (_chainId == 167_000) { if (_name == LibStrings.B_BRIDGE) { return (true, 0x1670000000000000000000000000000000000001); } if (_name == LibStrings.B_ERC20_VAULT) { return (true, 0x1670000000000000000000000000000000000002); } if (_name == LibStrings.B_ERC721_VAULT) { return (true, 0x1670000000000000000000000000000000000003); } if (_name == LibStrings.B_ERC1155_VAULT) { return (true, 0x1670000000000000000000000000000000000004); } if (_name == LibStrings.B_SIGNAL_SERVICE) { return (true, 0x1670000000000000000000000000000000000005); } } return (false, address(0)); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; import "./AddressResolver.sol"; import "../libs/LibNetwork.sol"; /// @title EssentialContract /// @custom:security-contact [email protected] abstract contract EssentialContract is UUPSUpgradeable, Ownable2StepUpgradeable, AddressResolver { uint8 private constant _FALSE = 1; uint8 private constant _TRUE = 2; /// @dev The slot in transient storage of the reentry lock. /// This is the result of keccak256("ownerUUPS.reentry_slot") plus 1. The addition aims to /// prevent hash collisions with slots defined in EIP-1967, where slots are derived by /// keccak256("something") - 1, and with slots in SignalService, calculated directly with /// keccak256("something"). bytes32 private constant _REENTRY_SLOT = 0xa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b; /// @dev Slot 1. uint8 private __reentry; uint8 private __paused; uint64 public lastUnpausedAt; uint256[49] private __gap; /// @notice Emitted when the contract is paused. /// @param account The account that paused the contract. event Paused(address account); /// @notice Emitted when the contract is unpaused. /// @param account The account that unpaused the contract. event Unpaused(address account); error INVALID_PAUSE_STATUS(); error FUNC_NOT_IMPLEMENTED(); error REENTRANT_CALL(); error ZERO_ADDRESS(); error ZERO_VALUE(); /// @dev Modifier that ensures the caller is the owner or resolved address of a given name. /// @param _name The name to check against. modifier onlyFromOwnerOrNamed(bytes32 _name) { if (msg.sender != owner() && msg.sender != resolve(_name, true)) revert RESOLVER_DENIED(); _; } modifier notImplemented() { revert FUNC_NOT_IMPLEMENTED(); _; } modifier nonReentrant() { if (_loadReentryLock() == _TRUE) revert REENTRANT_CALL(); _storeReentryLock(_TRUE); _; _storeReentryLock(_FALSE); } modifier whenPaused() { if (!paused()) revert INVALID_PAUSE_STATUS(); _; } modifier whenNotPaused() { if (paused()) revert INVALID_PAUSE_STATUS(); _; } modifier nonZeroAddr(address _addr) { if (_addr == address(0)) revert ZERO_ADDRESS(); _; } modifier nonZeroValue(bytes32 _value) { if (_value == 0) revert ZERO_VALUE(); _; } /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /// @notice Pauses the contract. function pause() public virtual { _pause(); // We call the authorize function here to avoid: // Warning (5740): Unreachable code. _authorizePause(msg.sender, true); } /// @notice Unpauses the contract. function unpause() public virtual { _unpause(); // We call the authorize function here to avoid: // Warning (5740): Unreachable code. _authorizePause(msg.sender, false); } function impl() public view returns (address) { return _getImplementation(); } /// @notice Returns true if the contract is paused, and false otherwise. /// @return true if paused, false otherwise. function paused() public view returns (bool) { return __paused == _TRUE; } function inNonReentrant() public view returns (bool) { return _loadReentryLock() == _TRUE; } /// @notice Initializes the contract. /// @param _owner The owner of this contract. msg.sender will be used if this value is zero. /// @param _addressManager The address of the {AddressManager} contract. function __Essential_init( address _owner, address _addressManager ) internal nonZeroAddr(_addressManager) { __Essential_init(_owner); __AddressResolver_init(_addressManager); } function __Essential_init(address _owner) internal virtual onlyInitializing { __Context_init(); _transferOwnership(_owner == address(0) ? msg.sender : _owner); __paused = _FALSE; } function _pause() internal whenNotPaused { __paused = _TRUE; emit Paused(msg.sender); } function _unpause() internal whenPaused { __paused = _FALSE; lastUnpausedAt = uint64(block.timestamp); emit Unpaused(msg.sender); } function _authorizeUpgrade(address) internal virtual override onlyOwner { } function _authorizePause(address, bool) internal virtual onlyOwner { } // Stores the reentry lock function _storeReentryLock(uint8 _reentry) internal virtual { if (LibNetwork.isDencunSupported(block.chainid)) { assembly { tstore(_REENTRY_SLOT, _reentry) } } else { __reentry = _reentry; } } // Loads the reentry lock function _loadReentryLock() internal view virtual returns (uint8 reentry_) { if (LibNetwork.isDencunSupported(block.chainid)) { assembly { reentry_ := tload(_REENTRY_SLOT) } } else { reentry_ = __reentry; } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title LibStrings /// @custom:security-contact [email protected] library LibStrings { bytes32 internal constant B_AUTOMATA_DCAP_ATTESTATION = bytes32("automata_dcap_attestation"); bytes32 internal constant B_BRIDGE = bytes32("bridge"); bytes32 internal constant B_BRIDGE_WATCHDOG = bytes32("bridge_watchdog"); bytes32 internal constant B_BRIDGED_ERC1155 = bytes32("bridged_erc1155"); bytes32 internal constant B_BRIDGED_ERC20 = bytes32("bridged_erc20"); bytes32 internal constant B_BRIDGED_ERC721 = bytes32("bridged_erc721"); bytes32 internal constant B_CHAIN_WATCHDOG = bytes32("chain_watchdog"); bytes32 internal constant B_ERC1155_VAULT = bytes32("erc1155_vault"); bytes32 internal constant B_ERC20_VAULT = bytes32("erc20_vault"); bytes32 internal constant B_ERC721_VAULT = bytes32("erc721_vault"); bytes32 internal constant B_PROVER_ASSIGNMENT = bytes32("PROVER_ASSIGNMENT"); bytes32 internal constant B_PROVER_SET = bytes32("prover_set"); bytes32 internal constant B_QUOTA_MANAGER = bytes32("quota_manager"); bytes32 internal constant B_SGX_WATCHDOG = bytes32("sgx_watchdog"); bytes32 internal constant B_SIGNAL_SERVICE = bytes32("signal_service"); bytes32 internal constant B_TAIKO = bytes32("taiko"); bytes32 internal constant B_TAIKO_TOKEN = bytes32("taiko_token"); bytes32 internal constant B_TIER_GUARDIAN = bytes32("tier_guardian"); bytes32 internal constant B_TIER_GUARDIAN_MINORITY = bytes32("tier_guardian_minority"); bytes32 internal constant B_TIER_ROUTER = bytes32("tier_router"); bytes32 internal constant B_TIER_SGX = bytes32("tier_sgx"); bytes32 internal constant B_TIER_SGX_ZKVM = bytes32("tier_sgx_zkvm"); bytes32 internal constant B_WITHDRAWER = bytes32("withdrawer"); bytes32 internal constant H_RETURN_LIVENESS_BOND = keccak256("RETURN_LIVENESS_BOND"); bytes32 internal constant H_SIGNAL_ROOT = keccak256("SIGNAL_ROOT"); bytes32 internal constant H_STATE_ROOT = keccak256("STATE_ROOT"); }
// SPDX-License-Identifier: MIT // _____ _ _ _ _ // |_ _|_ _(_) |_____ | | __ _| |__ ___ // | |/ _` | | / / _ \ | |__/ _` | '_ (_-< // |_|\__,_|_|_\_\___/ |____\__,_|_.__/__/ pragma solidity 0.8.24; import "../thirdparty/optimism/rlp/RLPReader.sol"; import "../thirdparty/optimism/rlp/RLPWriter.sol"; import "../thirdparty/optimism/trie/SecureMerkleTrie.sol"; /// @title LibTrieProof /// @custom:security-contact [email protected] library LibTrieProof { // The consensus format representing account is RLP encoded in the // following order: nonce, balance, storageHash, codeHash. uint256 private constant _ACCOUNT_FIELD_INDEX_STORAGE_HASH = 2; error LTP_INVALID_ACCOUNT_PROOF(); error LTP_INVALID_INCLUSION_PROOF(); /// @notice Verifies that the value of a slot in the storage of an account is value. /// /// @param _rootHash The merkle root of state tree or the account tree. If accountProof's length /// is zero, it is used as the account's storage root, otherwise it will be used as the state /// root. /// @param _addr The address of contract. /// @param _slot The slot in the contract. /// @param _value The value to be verified. /// @param _accountProof The account proof /// @param _storageProof The storage proof /// @return storageRoot_ The account's storage root function verifyMerkleProof( bytes32 _rootHash, address _addr, bytes32 _slot, bytes32 _value, bytes[] memory _accountProof, bytes[] memory _storageProof ) internal pure returns (bytes32 storageRoot_) { if (_accountProof.length != 0) { bytes memory rlpAccount = SecureMerkleTrie.get(abi.encodePacked(_addr), _accountProof, _rootHash); if (rlpAccount.length == 0) revert LTP_INVALID_ACCOUNT_PROOF(); RLPReader.RLPItem[] memory accountState = RLPReader.readList(rlpAccount); storageRoot_ = bytes32(RLPReader.readBytes(accountState[_ACCOUNT_FIELD_INDEX_STORAGE_HASH])); } else { storageRoot_ = _rootHash; } bool verified = SecureMerkleTrie.verifyInclusionProof( bytes.concat(_slot), RLPWriter.writeUint(uint256(_value)), _storageProof, storageRoot_ ); if (!verified) revert LTP_INVALID_INCLUSION_PROOF(); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title ISignalService /// @notice The SignalService contract serves as a secure cross-chain message /// passing system. It defines methods for sending and verifying signals with /// merkle proofs. The trust assumption is that the target chain has secure /// access to the merkle root (such as Taiko injects it in the anchor /// transaction). With this, verifying a signal is reduced to simply verifying /// a merkle proof. /// @custom:security-contact [email protected] interface ISignalService { enum CacheOption { CACHE_NOTHING, CACHE_SIGNAL_ROOT, CACHE_STATE_ROOT, CACHE_BOTH } struct HopProof { /// @notice This hop's destination chain ID. If there is a next hop, this ID is the next /// hop's source chain ID. uint64 chainId; /// @notice The ID of a source chain block whose state root has been synced to the hop's /// destination chain. /// Note that this block ID must be greater than or equal to the block ID where the signal /// was sent on the source chain. uint64 blockId; /// @notice The state root or signal root of the source chain at the above blockId. This /// value has been synced to the destination chain. /// @dev To get both the blockId and the rootHash, apps should subscribe to the /// ChainDataSynced event or query `topBlockId` first using the source chain's ID and /// LibStrings.H_STATE_ROOT to get the most recent block ID synced, then call /// `getSyncedChainData` to read the synchronized data. bytes32 rootHash; /// @notice Options to cache either the state roots or signal roots of middle-hops to the /// current chain. CacheOption cacheOption; /// @notice The signal service's account proof. If this value is empty, then `rootHash` will /// be used as the signal root, otherwise, `rootHash` will be used as the state root. bytes[] accountProof; /// @notice The signal service's storage proof. bytes[] storageProof; } /// @notice Emitted when a remote chain's state root or signal root is /// synced locally as a signal. /// @param chainId The remote chainId. /// @param blockId The chain data's corresponding blockId. /// @param kind A value to mark the data type. /// @param data The remote data. /// @param signal The signal for this chain data. event ChainDataSynced( uint64 indexed chainId, uint64 indexed blockId, bytes32 indexed kind, bytes32 data, bytes32 signal ); /// @notice Emitted when a signal is sent. /// @param app The address that initiated the signal. /// @param signal The signal (message) that was sent. /// @param slot The location in storage where this signal is stored. /// @param value The value of the signal. event SignalSent(address app, bytes32 signal, bytes32 slot, bytes32 value); /// @notice Emitted when an address is authorized or deauthorized. /// @param addr The address to be authorized or deauthorized. /// @param authorized True if authorized, false otherwise. event Authorized(address indexed addr, bool authorized); /// @notice Send a signal (message) by setting the storage slot to the same value as the signal /// itself. /// @param _signal The signal (message) to send. /// @return slot_ The location in storage where this signal is stored. function sendSignal(bytes32 _signal) external returns (bytes32 slot_); /// @notice Sync a data from a remote chain locally as a signal. The signal is calculated /// uniquely from chainId, kind, and data. /// @param _chainId The remote chainId. /// @param _kind A value to mark the data type. /// @param _blockId The chain data's corresponding blockId /// @param _chainData The remote data. /// @return signal_ The signal for this chain data. function syncChainData( uint64 _chainId, bytes32 _kind, uint64 _blockId, bytes32 _chainData ) external returns (bytes32 signal_); /// @notice Verifies if a signal has been received on the target chain. /// @param _chainId The identifier for the source chain from which the /// signal originated. /// @param _app The address that initiated the signal. /// @param _signal The signal (message) to send. /// @param _proof Merkle proof that the signal was persisted on the /// source chain. /// @return numCacheOps_ The number of newly cached items. function proveSignalReceived( uint64 _chainId, address _app, bytes32 _signal, bytes calldata _proof ) external returns (uint256 numCacheOps_); /// @notice Verifies if a signal has been received on the target chain. /// This is the "readonly" version of proveSignalReceived. /// @param _chainId The identifier for the source chain from which the /// signal originated. /// @param _app The address that initiated the signal. /// @param _signal The signal (message) to send. /// @param _proof Merkle proof that the signal was persisted on the /// source chain. function verifySignalReceived( uint64 _chainId, address _app, bytes32 _signal, bytes calldata _proof ) external view; /// @notice Verifies if a particular signal has already been sent. /// @param _app The address that initiated the signal. /// @param _signal The signal (message) that was sent. /// @return true if the signal has been sent, otherwise false. function isSignalSent(address _app, bytes32 _signal) external view returns (bool); /// @notice Checks if a chain data has been synced. /// @param _chainId The remote chainId. /// @param _kind A value to mark the data type. /// @param _blockId The chain data's corresponding blockId /// @param _chainData The remote data. /// @return true if the data has been synced, otherwise false. function isChainDataSynced( uint64 _chainId, bytes32 _kind, uint64 _blockId, bytes32 _chainData ) external view returns (bool); /// @notice Returns the given block's chain data. /// @param _chainId Identifier of the chainId. /// @param _kind A value to mark the data type. /// @param _blockId The chain data's corresponding block id. If this value is 0, use the top /// block id. /// @return blockId_ The actual block id. /// @return chainData_ The synced chain data. function getSyncedChainData( uint64 _chainId, bytes32 _kind, uint64 _blockId ) external view returns (uint64 blockId_, bytes32 chainData_); /// @notice Returns the data to be used for caching slot generation. /// @param _chainId Identifier of the chainId. /// @param _kind A value to mark the data type. /// @param _blockId The chain data's corresponding block id. If this value is 0, use the top /// block id. /// @return signal_ The signal used for caching slot creation. function signalForChainData( uint64 _chainId, bytes32 _kind, uint64 _blockId ) external pure returns (bytes32 signal_); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.0; import "../../interfaces/draft-IERC1822.sol"; import "../ERC1967/ERC1967Upgrade.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. * * _Available since v4.1._ */ abstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __self = address(this); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { require(address(this) != __self, "Function must be called through delegatecall"); require(_getImplementation() == __self, "Function must be called through active proxy"); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall"); _; } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual override notDelegated returns (bytes32) { return _IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeTo(address newImplementation) public virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data, true); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeTo} and {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal override onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol) pragma solidity ^0.8.0; import "./OwnableUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); function __Ownable2Step_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable2Step_init_unchained() internal onlyInitializing { } /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); _transferOwnership(sender); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "./IAddressManager.sol"; import "./IAddressResolver.sol"; /// @title AddressResolver /// @notice See the documentation in {IAddressResolver}. /// @custom:security-contact [email protected] abstract contract AddressResolver is IAddressResolver, Initializable { /// @notice Address of the AddressManager. address public addressManager; uint256[49] private __gap; error RESOLVER_DENIED(); error RESOLVER_INVALID_MANAGER(); error RESOLVER_UNEXPECTED_CHAINID(); error RESOLVER_ZERO_ADDR(uint64 chainId, bytes32 name); /// @dev Modifier that ensures the caller is the resolved address of a given /// name. /// @param _name The name to check against. modifier onlyFromNamed(bytes32 _name) { if (msg.sender != resolve(_name, true)) revert RESOLVER_DENIED(); _; } /// @dev Modifier that ensures the caller is a resolved address to either _name1 or _name2 /// name. /// @param _name1 The first name to check against. /// @param _name2 The second name to check against. modifier onlyFromNamedEither(bytes32 _name1, bytes32 _name2) { if (msg.sender != resolve(_name1, true) && msg.sender != resolve(_name2, true)) { revert RESOLVER_DENIED(); } _; } /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /// @inheritdoc IAddressResolver function resolve(bytes32 _name, bool _allowZeroAddress) public view virtual returns (address) { return _resolve(uint64(block.chainid), _name, _allowZeroAddress); } /// @inheritdoc IAddressResolver function resolve( uint64 _chainId, bytes32 _name, bool _allowZeroAddress ) public view virtual returns (address) { return _resolve(_chainId, _name, _allowZeroAddress); } /// @dev Initialization method for setting up AddressManager reference. /// @param _addressManager Address of the AddressManager. function __AddressResolver_init(address _addressManager) internal virtual onlyInitializing { if (block.chainid > type(uint64).max) { revert RESOLVER_UNEXPECTED_CHAINID(); } addressManager = _addressManager; } /// @dev Helper method to resolve name-to-address. /// @param _chainId The chainId of interest. /// @param _name Name whose address is to be resolved. /// @param _allowZeroAddress If set to true, does not throw if the resolved /// address is `address(0)`. /// @return addr_ Address associated with the given name on the specified /// chain. function _resolve( uint64 _chainId, bytes32 _name, bool _allowZeroAddress ) internal view returns (address addr_) { addr_ = _getAddress(_chainId, _name); if (!_allowZeroAddress && addr_ == address(0)) { revert RESOLVER_ZERO_ADDR(_chainId, _name); } } function _getAddress(uint64 _chainId, bytes32 _name) internal view virtual returns (address) { address _addressManager = addressManager; if (_addressManager == address(0)) revert RESOLVER_INVALID_MANAGER(); return IAddressManager(_addressManager).getAddress(_chainId, _name); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title LibNetwork library LibNetwork { uint256 internal constant MAINNET = 1; uint256 internal constant ROPSTEN = 2; uint256 internal constant RINKEBY = 4; uint256 internal constant GOERLI = 5; uint256 internal constant KOVAN = 42; uint256 internal constant HOLESKY = 17_000; uint256 internal constant SEPOLIA = 11_155_111; uint64 internal constant TAIKO_MAINNET = 167_000; uint64 internal constant TAIKO_HEKLA = 167_009; /// @dev Checks if the chain ID represents an Ethereum testnet. /// @param _chainId The chain ID. /// @return true if the chain ID represents an Ethereum testnet, false otherwise. function isEthereumTestnet(uint256 _chainId) internal pure returns (bool) { return _chainId == LibNetwork.ROPSTEN || _chainId == LibNetwork.RINKEBY || _chainId == LibNetwork.GOERLI || _chainId == LibNetwork.KOVAN || _chainId == LibNetwork.HOLESKY || _chainId == LibNetwork.SEPOLIA; } /// @dev Checks if the chain ID represents an Ethereum testnet or the Etheruem mainnet. /// @param _chainId The chain ID. /// @return true if the chain ID represents an Ethereum testnet or the Etheruem mainnet, false /// otherwise. function isEthereumMainnetOrTestnet(uint256 _chainId) internal pure returns (bool) { return _chainId == LibNetwork.MAINNET || isEthereumTestnet(_chainId); } /// @dev Checks if the chain ID represents the Taiko L2 mainnet. /// @param _chainId The chain ID. /// @return true if the chain ID represents the Taiko L2 mainnet. function isTaikoMainnet(uint256 _chainId) internal pure returns (bool) { return _chainId == TAIKO_MAINNET; } /// @dev Checks if the chain ID represents an internal Taiko devnet's base layer. /// @param _chainId The chain ID. /// @return true if the chain ID represents an internal Taiko devnet's base layer, false /// otherwise. function isTaikoDevnet(uint256 _chainId) internal pure returns (bool) { return _chainId >= 32_300 && _chainId <= 32_400; } /// @dev Checks if the chain supports Dencun hardfork. Note that this check doesn't need to be /// exhaustive. /// @param _chainId The chain ID. /// @return true if the chain supports Dencun hardfork, false otherwise. function isDencunSupported(uint256 _chainId) internal pure returns (bool) { return _chainId == LibNetwork.MAINNET || _chainId == LibNetwork.HOLESKY || _chainId == LibNetwork.SEPOLIA || isTaikoDevnet(_chainId); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @custom:attribution https://github.com/hamdiallam/Solidity-RLP /// @title RLPReader /// @notice RLPReader is a library for parsing RLP-encoded byte arrays into Solidity types. Adapted /// from Solidity-RLP (https://github.com/hamdiallam/Solidity-RLP) by Hamdi Allam with /// various tweaks to improve readability. (A shout-out to Optimism !) library RLPReader { /// @notice Custom pointer type to avoid confusion between pointers and uint256s. type MemoryPointer is uint256; /// @notice RLP item types. /// @custom:value DATA_ITEM Represents an RLP data item (NOT a list). /// @custom:value LIST_ITEM Represents an RLP list item. enum RLPItemType { DATA_ITEM, LIST_ITEM } /// @notice Struct representing an RLP item. /// @custom:field length Length of the RLP item. /// @custom:field ptr Pointer to the RLP item in memory. struct RLPItem { uint256 length; MemoryPointer ptr; } /// @notice Max list length that this library will accept. uint256 internal constant MAX_LIST_LENGTH = 32; /// @notice Converts bytes to a reference to memory position and length. /// @param _in Input bytes to convert. /// @return out_ Output memory reference. function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory out_) { // Empty arrays are not RLP items. require( _in.length > 0, "RLPReader: length of an RLP item must be greater than zero to be decodable" ); MemoryPointer ptr; assembly { ptr := add(_in, 32) } out_ = RLPItem({ length: _in.length, ptr: ptr }); } /// @notice Reads an RLP list value into a list of RLP items. /// @param _in RLP list value. /// @return out_ Decoded RLP list items. function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory out_) { (uint256 listOffset, uint256 listLength, RLPItemType itemType) = _decodeLength(_in); require( itemType == RLPItemType.LIST_ITEM, "RLPReader: decoded item type for list is not a list item" ); require( listOffset + listLength == _in.length, "RLPReader: list item has an invalid data remainder" ); // Solidity in-memory arrays can't be increased in size, but *can* be decreased in size by // writing to the length. Since we can't know the number of RLP items without looping over // the entire input, we'd have to loop twice to accurately size this array. It's easier to // simply set a reasonable maximum list length and decrease the size before we finish. out_ = new RLPItem[](MAX_LIST_LENGTH); uint256 itemCount = 0; uint256 offset = listOffset; while (offset < _in.length) { (uint256 itemOffset, uint256 itemLength,) = _decodeLength( RLPItem({ length: _in.length - offset, ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset) }) ); // We don't need to check itemCount < out.length explicitly because Solidity already // handles this check on our behalf, we'd just be wasting gas. out_[itemCount] = RLPItem({ length: itemLength + itemOffset, ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset) }); itemCount += 1; offset += itemOffset + itemLength; } // Decrease the array size to match the actual item count. assembly { mstore(out_, itemCount) } } /// @notice Reads an RLP list value into a list of RLP items. /// @param _in RLP list value. /// @return out_ Decoded RLP list items. function readList(bytes memory _in) internal pure returns (RLPItem[] memory out_) { out_ = readList(toRLPItem(_in)); } /// @notice Reads an RLP bytes value into bytes. /// @param _in RLP bytes value. /// @return out_ Decoded bytes. function readBytes(RLPItem memory _in) internal pure returns (bytes memory out_) { (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in); require( itemType == RLPItemType.DATA_ITEM, "RLPReader: decoded item type for bytes is not a data item" ); require( _in.length == itemOffset + itemLength, "RLPReader: bytes value contains an invalid remainder" ); out_ = _copy(_in.ptr, itemOffset, itemLength); } /// @notice Reads an RLP bytes value into bytes. /// @param _in RLP bytes value. /// @return out_ Decoded bytes. function readBytes(bytes memory _in) internal pure returns (bytes memory out_) { out_ = readBytes(toRLPItem(_in)); } /// @notice Reads the raw bytes of an RLP item. /// @param _in RLP item to read. /// @return out_ Raw RLP bytes. function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory out_) { out_ = _copy(_in.ptr, 0, _in.length); } /// @notice Decodes the length of an RLP item. /// @param _in RLP item to decode. /// @return offset_ Offset of the encoded data. /// @return length_ Length of the encoded data. /// @return type_ RLP item type (LIST_ITEM or DATA_ITEM). function _decodeLength(RLPItem memory _in) private pure returns (uint256 offset_, uint256 length_, RLPItemType type_) { // Short-circuit if there's nothing to decode, note that we perform this check when // the user creates an RLP item via toRLPItem, but it's always possible for them to bypass // that function and create an RLP item directly. So we need to check this anyway. require( _in.length > 0, "RLPReader: length of an RLP item must be greater than zero to be decodable" ); MemoryPointer ptr = _in.ptr; uint256 prefix; assembly { prefix := byte(0, mload(ptr)) } if (prefix <= 0x7f) { // Single byte. return (0, 1, RLPItemType.DATA_ITEM); } else if (prefix <= 0xb7) { // Short string. // slither-disable-next-line variable-scope uint256 strLen = prefix - 0x80; require( _in.length > strLen, "RLPReader: length of content must be greater than string length (short string)" ); bytes1 firstByteOfContent; assembly { firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff)) } require( strLen != 1 || firstByteOfContent >= 0x80, "RLPReader: invalid prefix, single byte < 0x80 are not prefixed (short string)" ); return (1, strLen, RLPItemType.DATA_ITEM); } else if (prefix <= 0xbf) { // Long string. uint256 lenOfStrLen = prefix - 0xb7; require( _in.length > lenOfStrLen, "RLPReader: length of content must be > than length of string length (long string)" ); bytes1 firstByteOfContent; assembly { firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff)) } require( firstByteOfContent != 0x00, "RLPReader: length of content must not have any leading zeros (long string)" ); uint256 strLen; assembly { strLen := shr(sub(256, mul(8, lenOfStrLen)), mload(add(ptr, 1))) } require( strLen > 55, "RLPReader: length of content must be greater than 55 bytes (long string)" ); require( _in.length > lenOfStrLen + strLen, "RLPReader: length of content must be greater than total length (long string)" ); return (1 + lenOfStrLen, strLen, RLPItemType.DATA_ITEM); } else if (prefix <= 0xf7) { // Short list. // slither-disable-next-line variable-scope uint256 listLen = prefix - 0xc0; require( _in.length > listLen, "RLPReader: length of content must be greater than list length (short list)" ); return (1, listLen, RLPItemType.LIST_ITEM); } else { // Long list. uint256 lenOfListLen = prefix - 0xf7; require( _in.length > lenOfListLen, "RLPReader: length of content must be > than length of list length (long list)" ); bytes1 firstByteOfContent; assembly { firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff)) } require( firstByteOfContent != 0x00, "RLPReader: length of content must not have any leading zeros (long list)" ); uint256 listLen; assembly { listLen := shr(sub(256, mul(8, lenOfListLen)), mload(add(ptr, 1))) } require( listLen > 55, "RLPReader: length of content must be greater than 55 bytes (long list)" ); require( _in.length > lenOfListLen + listLen, "RLPReader: length of content must be greater than total length (long list)" ); return (1 + lenOfListLen, listLen, RLPItemType.LIST_ITEM); } } /// @notice Copies the bytes from a memory location. /// @param _src Pointer to the location to read from. /// @param _offset Offset to start reading from. /// @param _length Number of bytes to read. /// @return out_ Copied bytes. function _copy( MemoryPointer _src, uint256 _offset, uint256 _length ) private pure returns (bytes memory out_) { out_ = new bytes(_length); if (_length == 0) { return out_; } // Mostly based on Solidity's copy_memory_to_memory: // solhint-disable max-line-length // https://github.com/ethereum/solidity/blob/34dd30d71b4da730488be72ff6af7083cf2a91f6/libsolidity/codegen/YulUtilFunctions.cpp#L102-L114 uint256 src = MemoryPointer.unwrap(_src) + _offset; assembly { let dest := add(out_, 32) let i := 0 for { } lt(i, _length) { i := add(i, 32) } { mstore(add(dest, i), mload(add(src, i))) } if gt(i, _length) { mstore(add(dest, _length), 0) } } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @custom:attribution https://github.com/bakaoh/solidity-rlp-encode /// @title RLPWriter /// @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's /// RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor /// modifications to improve legibility. (A shout-out to Optimism !) library RLPWriter { /// @notice RLP encodes a byte string. /// @param _in The byte string to encode. /// @return out_ The RLP encoded string in bytes. function writeBytes(bytes memory _in) internal pure returns (bytes memory out_) { if (_in.length == 1 && uint8(_in[0]) < 128) { out_ = _in; } else { out_ = abi.encodePacked(_writeLength(_in.length, 128), _in); } } /// @notice RLP encodes a uint. /// @param _in The uint256 to encode. /// @return out_ The RLP encoded uint256 in bytes. function writeUint(uint256 _in) internal pure returns (bytes memory out_) { out_ = writeBytes(_toBinary(_in)); } /// @notice Encode the first byte and then the `len` in binary form if `length` is more than 55. /// @param _len The length of the string or the payload. /// @param _offset 128 if item is string, 192 if item is list. /// @return out_ RLP encoded bytes. function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory out_) { if (_len < 56) { out_ = new bytes(1); out_[0] = bytes1(uint8(_len) + uint8(_offset)); } else { uint256 lenLen; uint256 i = 1; while (_len / i != 0) { lenLen++; i *= 256; } out_ = new bytes(lenLen + 1); out_[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55); for (i = 1; i <= lenLen; i++) { out_[i] = bytes1(uint8((_len / (256 ** (lenLen - i))) % 256)); } } } /// @notice Encode integer in big endian binary form with no leading zeroes. /// @param _x The integer to encode. /// @return out_ RLP encoded bytes. function _toBinary(uint256 _x) private pure returns (bytes memory out_) { bytes memory b = abi.encodePacked(_x); uint256 i = 0; for (; i < 32; i++) { if (b[i] != 0) { break; } } out_ = new bytes(32 - i); for (uint256 j = 0; j < out_.length; j++) { out_[j] = b[i++]; } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import { MerkleTrie } from "./MerkleTrie.sol"; /// @title SecureMerkleTrie /// @notice SecureMerkleTrie is a thin wrapper around the MerkleTrie library that hashes the input /// keys. Ethereum's state trie hashes input keys before storing them. library SecureMerkleTrie { /// @notice Verifies a proof that a given key/value pair is present in the Merkle trie. /// @param _key Key of the node to search for, as a hex string. /// @param _value Value of the node to search for, as a hex string. /// @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle /// trees, this proof is executed top-down and consists of a list of RLP-encoded /// nodes that make a path down to the target node. /// @param _root Known root of the Merkle trie. Used to verify that the included proof is /// correctly constructed. /// @return valid_ Whether or not the proof is valid. function verifyInclusionProof( bytes memory _key, bytes memory _value, bytes[] memory _proof, bytes32 _root ) internal pure returns (bool valid_) { bytes memory key = _getSecureKey(_key); valid_ = MerkleTrie.verifyInclusionProof(key, _value, _proof, _root); } /// @notice Retrieves the value associated with a given key. /// @param _key Key to search for, as hex bytes. /// @param _proof Merkle trie inclusion proof for the key. /// @param _root Known root of the Merkle trie. /// @return value_ Value of the key if it exists. function get( bytes memory _key, bytes[] memory _proof, bytes32 _root ) internal pure returns (bytes memory value_) { bytes memory key = _getSecureKey(_key); value_ = MerkleTrie.get(key, _proof, _root); } /// @notice Computes the hashed version of the input key. /// @param _key Key to hash. /// @return hash_ Hashed version of the key. function _getSecureKey(bytes memory _key) private pure returns (bytes memory hash_) { hash_ = abi.encodePacked(keccak256(_key)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeacon.sol"; import "../../interfaces/IERC1967.sol"; import "../../interfaces/draft-IERC1822.sol"; import "../../utils/Address.sol"; import "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ */ abstract contract ERC1967Upgrade is IERC1967 { // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { Address.functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( Address.isContract(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../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. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @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 Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 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 functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _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 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _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() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @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 { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title IAddressManager /// @notice Manages a mapping of (chainId, name) pairs to Ethereum addresses. /// @custom:security-contact [email protected] interface IAddressManager { /// @notice Gets the address mapped to a specific chainId-name pair. /// @dev Note that in production, this method shall be a pure function /// without any storage access. /// @param _chainId The chainId for which the address needs to be fetched. /// @param _name The name for which the address needs to be fetched. /// @return Address associated with the chainId-name pair. function getAddress(uint64 _chainId, bytes32 _name) external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title IAddressResolver /// @notice This contract acts as a bridge for name-to-address resolution. /// It delegates the resolution to the AddressManager. By separating the logic, /// we can maintain flexibility in address management without affecting the /// resolving process. /// @dev Note that the address manager should be changed using upgradability, there /// is no setAddressManager() function to guarantee atomicity across all /// contracts that are resolvers. /// @custom:security-contact [email protected] interface IAddressResolver { /// @notice Resolves a name to its address deployed on this chain. /// @param _name Name whose address is to be resolved. /// @param _allowZeroAddress If set to true, does not throw if the resolved /// address is `address(0)`. /// @return Address associated with the given name. function resolve(bytes32 _name, bool _allowZeroAddress) external view returns (address); /// @notice Resolves a name to its address deployed on a specified chain. /// @param _chainId The chainId of interest. /// @param _name Name whose address is to be resolved. /// @param _allowZeroAddress If set to true, does not throw if the resolved /// address is `address(0)`. /// @return Address associated with the given name on the specified /// chain. function resolve( uint64 _chainId, bytes32 _name, bool _allowZeroAddress ) external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import { Bytes } from "../Bytes.sol"; import { RLPReader } from "../rlp/RLPReader.sol"; /// @title MerkleTrie /// @notice MerkleTrie is a small library for verifying standard Ethereum Merkle-Patricia trie /// inclusion proofs. By default, this library assumes a hexary trie. One can change the /// trie radix constant to support other trie radixes. library MerkleTrie { /// @notice Struct representing a node in the trie. /// @custom:field encoded The RLP-encoded node. /// @custom:field decoded The RLP-decoded node. struct TrieNode { bytes encoded; RLPReader.RLPItem[] decoded; } /// @notice Determines the number of elements per branch node. uint256 internal constant TREE_RADIX = 16; /// @notice Branch nodes have TREE_RADIX elements and one value element. uint256 internal constant BRANCH_NODE_LENGTH = TREE_RADIX + 1; /// @notice Leaf nodes and extension nodes have two elements, a `path` and a `value`. uint256 internal constant LEAF_OR_EXTENSION_NODE_LENGTH = 2; /// @notice Prefix for even-nibbled extension node paths. uint8 internal constant PREFIX_EXTENSION_EVEN = 0; /// @notice Prefix for odd-nibbled extension node paths. uint8 internal constant PREFIX_EXTENSION_ODD = 1; /// @notice Prefix for even-nibbled leaf node paths. uint8 internal constant PREFIX_LEAF_EVEN = 2; /// @notice Prefix for odd-nibbled leaf node paths. uint8 internal constant PREFIX_LEAF_ODD = 3; /// @notice Verifies a proof that a given key/value pair is present in the trie. /// @param _key Key of the node to search for, as a hex string. /// @param _value Value of the node to search for, as a hex string. /// @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle /// trees, this proof is executed top-down and consists of a list of RLP-encoded /// nodes that make a path down to the target node. /// @param _root Known root of the Merkle trie. Used to verify that the included proof is /// correctly constructed. /// @return valid_ Whether or not the proof is valid. function verifyInclusionProof( bytes memory _key, bytes memory _value, bytes[] memory _proof, bytes32 _root ) internal pure returns (bool valid_) { valid_ = Bytes.equal(_value, get(_key, _proof, _root)); } /// @notice Retrieves the value associated with a given key. /// @param _key Key to search for, as hex bytes. /// @param _proof Merkle trie inclusion proof for the key. /// @param _root Known root of the Merkle trie. /// @return value_ Value of the key if it exists. function get( bytes memory _key, bytes[] memory _proof, bytes32 _root ) internal pure returns (bytes memory value_) { require(_key.length > 0, "MerkleTrie: empty key"); TrieNode[] memory proof = _parseProof(_proof); bytes memory key = Bytes.toNibbles(_key); bytes memory currentNodeID = abi.encodePacked(_root); uint256 currentKeyIndex = 0; // Proof is top-down, so we start at the first element (root). for (uint256 i = 0; i < proof.length; i++) { TrieNode memory currentNode = proof[i]; // Key index should never exceed total key length or we'll be out of bounds. require(currentKeyIndex <= key.length, "MerkleTrie: key index exceeds total key length"); if (currentKeyIndex == 0) { // First proof element is always the root node. require( Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID), "MerkleTrie: invalid root hash" ); } else if (currentNode.encoded.length >= 32) { // Nodes 32 bytes or larger are hashed inside branch nodes. require( Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID), "MerkleTrie: invalid large internal hash" ); } else { // Nodes smaller than 32 bytes aren't hashed. require( Bytes.equal(currentNode.encoded, currentNodeID), "MerkleTrie: invalid internal node hash" ); } if (currentNode.decoded.length == BRANCH_NODE_LENGTH) { if (currentKeyIndex == key.length) { // Value is the last element of the decoded list (for branch nodes). There's // some ambiguity in the Merkle trie specification because bytes(0) is a // valid value to place into the trie, but for branch nodes bytes(0) can exist // even when the value wasn't explicitly placed there. Geth treats a value of // bytes(0) as "key does not exist" and so we do the same. value_ = RLPReader.readBytes(currentNode.decoded[TREE_RADIX]); require( value_.length > 0, "MerkleTrie: value length must be greater than zero (branch)" ); // Extra proof elements are not allowed. require( i == proof.length - 1, "MerkleTrie: value node must be last node in proof (branch)" ); return value_; } else { // We're not at the end of the key yet. // Figure out what the next node ID should be and continue. uint8 branchKey = uint8(key[currentKeyIndex]); RLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey]; currentNodeID = _getNodeID(nextNode); currentKeyIndex += 1; } } else if (currentNode.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) { bytes memory path = _getNodePath(currentNode); uint8 prefix = uint8(path[0]); uint8 offset = 2 - (prefix % 2); bytes memory pathRemainder = Bytes.slice(path, offset); bytes memory keyRemainder = Bytes.slice(key, currentKeyIndex); uint256 sharedNibbleLength = _getSharedNibbleLength(pathRemainder, keyRemainder); // Whether this is a leaf node or an extension node, the path remainder MUST be a // prefix of the key remainder (or be equal to the key remainder) or the proof is // considered invalid. require( pathRemainder.length == sharedNibbleLength, "MerkleTrie: path remainder must share all nibbles with key" ); if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) { // Prefix of 2 or 3 means this is a leaf node. For the leaf node to be valid, // the key remainder must be exactly equal to the path remainder. We already // did the necessary byte comparison, so it's more efficient here to check that // the key remainder length equals the shared nibble length, which implies // equality with the path remainder (since we already did the same check with // the path remainder and the shared nibble length). require( keyRemainder.length == sharedNibbleLength, "MerkleTrie: key remainder must be identical to path remainder" ); // Our Merkle Trie is designed specifically for the purposes of the Ethereum // state trie. Empty values are not allowed in the state trie, so we can safely // say that if the value is empty, the key should not exist and the proof is // invalid. value_ = RLPReader.readBytes(currentNode.decoded[1]); require( value_.length > 0, "MerkleTrie: value length must be greater than zero (leaf)" ); // Extra proof elements are not allowed. require( i == proof.length - 1, "MerkleTrie: value node must be last node in proof (leaf)" ); return value_; } else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) { // Prefix of 0 or 1 means this is an extension node. We move onto the next node // in the proof and increment the key index by the length of the path remainder // which is equal to the shared nibble length. currentNodeID = _getNodeID(currentNode.decoded[1]); currentKeyIndex += sharedNibbleLength; } else { revert("MerkleTrie: received a node with an unknown prefix"); } } else { revert("MerkleTrie: received an unparseable node"); } } revert("MerkleTrie: ran out of proof elements"); } /// @notice Parses an array of proof elements into a new array that contains both the original /// encoded element and the RLP-decoded element. /// @param _proof Array of proof elements to parse. /// @return proof_ Proof parsed into easily accessible structs. function _parseProof(bytes[] memory _proof) private pure returns (TrieNode[] memory proof_) { uint256 length = _proof.length; proof_ = new TrieNode[](length); for (uint256 i = 0; i < length; ++i) { proof_[i] = TrieNode({ encoded: _proof[i], decoded: RLPReader.readList(_proof[i]) }); } } /// @notice Picks out the ID for a node. Node ID is referred to as the "hash" within the /// specification, but nodes < 32 bytes are not actually hashed. /// @param _node Node to pull an ID for. /// @return id_ ID for the node, depending on the size of its contents. function _getNodeID(RLPReader.RLPItem memory _node) private pure returns (bytes memory id_) { id_ = _node.length < 32 ? RLPReader.readRawBytes(_node) : RLPReader.readBytes(_node); } /// @notice Gets the path for a leaf or extension node. /// @param _node Node to get a path for. /// @return nibbles_ Node path, converted to an array of nibbles. function _getNodePath(TrieNode memory _node) private pure returns (bytes memory nibbles_) { nibbles_ = Bytes.toNibbles(RLPReader.readBytes(_node.decoded[0])); } /// @notice Utility; determines the number of nibbles shared between two nibble arrays. /// @param _a First nibble array. /// @param _b Second nibble array. /// @return shared_ Number of shared nibbles. function _getSharedNibbleLength( bytes memory _a, bytes memory _b ) private pure returns (uint256 shared_) { uint256 max = (_a.length < _b.length) ? _a.length : _b.length; for (; shared_ < max && _a[shared_] == _b[shared_];) { unchecked { ++shared_; } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.0; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. * * _Available since v4.8.3._ */ interface IERC1967 { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; 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; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title Bytes /// @notice Bytes is a library for manipulating byte arrays. library Bytes { /// @custom:attribution https://github.com/GNSPS/solidity-bytes-utils /// @notice Slices a byte array with a given starting index and length. Returns a new byte array /// as opposed to a pointer to the original array. Will throw if trying to slice more /// bytes than exist in the array. /// @param _bytes Byte array to slice. /// @param _start Starting index of the slice. /// @param _length Length of the slice. /// @return Slice of the input byte array. function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { unchecked { require(_length + 31 >= _length, "slice_overflow"); require(_start + _length >= _start, "slice_overflow"); require(_bytes.length >= _start + _length, "slice_outOfBounds"); } bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } /// @notice Slices a byte array with a given starting index up to the end of the original byte /// array. Returns a new array rather than a pointer to the original. /// @param _bytes Byte array to slice. /// @param _start Starting index of the slice. /// @return Slice of the input byte array. function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) { if (_start >= _bytes.length) { return bytes(""); } return slice(_bytes, _start, _bytes.length - _start); } /// @notice Converts a byte array into a nibble array by splitting each byte into two nibbles. /// Resulting nibble array will be exactly twice as long as the input byte array. /// @param _bytes Input byte array to convert. /// @return Resulting nibble array. function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) { bytes memory _nibbles; assembly { // Grab a free memory offset for the new array _nibbles := mload(0x40) // Load the length of the passed bytes array from memory let bytesLength := mload(_bytes) // Calculate the length of the new nibble array // This is the length of the input array times 2 let nibblesLength := shl(0x01, bytesLength) // Update the free memory pointer to allocate memory for the new array. // To do this, we add the length of the new array + 32 bytes for the array length // rounded up to the nearest 32 byte boundary to the current free memory pointer. mstore(0x40, add(_nibbles, and(not(0x1F), add(nibblesLength, 0x3F)))) // Store the length of the new array in memory mstore(_nibbles, nibblesLength) // Store the memory offset of the _bytes array's contents on the stack let bytesStart := add(_bytes, 0x20) // Store the memory offset of the nibbles array's contents on the stack let nibblesStart := add(_nibbles, 0x20) // Loop through each byte in the input array for { let i := 0x00 } lt(i, bytesLength) { i := add(i, 0x01) } { // Get the starting offset of the next 2 bytes in the nibbles array let offset := add(nibblesStart, shl(0x01, i)) // Load the byte at the current index within the `_bytes` array let b := byte(0x00, mload(add(bytesStart, i))) // Pull out the first nibble and store it in the new array mstore8(offset, shr(0x04, b)) // Pull out the second nibble and store it in the new array mstore8(add(offset, 0x01), and(b, 0x0F)) } } return _nibbles; } /// @notice Compares two byte arrays by comparing their keccak256 hashes. /// @param _bytes First byte array to compare. /// @param _other Second byte array to compare. /// @return true if the two byte arrays are equal, false otherwise. function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) { return keccak256(_bytes) == keccak256(_other); } }
{ "remappings": [ "@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/", "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/", "solady/=node_modules/solady/", "forge-std/=node_modules/forge-std/", "ds-test/=node_modules/ds-test/src/", "p256-verifier/=node_modules/p256-verifier/", "forge-safe/=node_modules/forge-safe/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"FUNC_NOT_IMPLEMENTED","type":"error"},{"inputs":[],"name":"INVALID_PAUSE_STATUS","type":"error"},{"inputs":[],"name":"LTP_INVALID_ACCOUNT_PROOF","type":"error"},{"inputs":[],"name":"LTP_INVALID_INCLUSION_PROOF","type":"error"},{"inputs":[],"name":"REENTRANT_CALL","type":"error"},{"inputs":[],"name":"RESOLVER_DENIED","type":"error"},{"inputs":[],"name":"RESOLVER_INVALID_MANAGER","type":"error"},{"inputs":[],"name":"RESOLVER_UNEXPECTED_CHAINID","type":"error"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"bytes32","name":"name","type":"bytes32"}],"name":"RESOLVER_ZERO_ADDR","type":"error"},{"inputs":[],"name":"SS_EMPTY_PROOF","type":"error"},{"inputs":[],"name":"SS_INVALID_HOPS_WITH_LOOP","type":"error"},{"inputs":[],"name":"SS_INVALID_LAST_HOP_CHAINID","type":"error"},{"inputs":[],"name":"SS_INVALID_MID_HOP_CHAINID","type":"error"},{"inputs":[],"name":"SS_INVALID_STATE","type":"error"},{"inputs":[],"name":"SS_SIGNAL_NOT_FOUND","type":"error"},{"inputs":[],"name":"SS_UNAUTHORIZED","type":"error"},{"inputs":[],"name":"ZERO_ADDRESS","type":"error"},{"inputs":[],"name":"ZERO_VALUE","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"bool","name":"authorized","type":"bool"}],"name":"Authorized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"blockId","type":"uint64"},{"indexed":true,"internalType":"bytes32","name":"kind","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"data","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"signal","type":"bytes32"}],"name":"ChainDataSynced","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"app","type":"address"},{"indexed":false,"internalType":"bytes32","name":"signal","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"slot","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"value","type":"bytes32"}],"name":"SignalSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"addressManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"},{"internalType":"bool","name":"_authorize","type":"bool"}],"name":"authorize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_chainId","type":"uint64"},{"internalType":"address","name":"_app","type":"address"},{"internalType":"bytes32","name":"_signal","type":"bytes32"}],"name":"getSignalSlot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint64","name":"_chainId","type":"uint64"},{"internalType":"bytes32","name":"_kind","type":"bytes32"},{"internalType":"uint64","name":"_blockId","type":"uint64"}],"name":"getSyncedChainData","outputs":[{"internalType":"uint64","name":"blockId_","type":"uint64"},{"internalType":"bytes32","name":"chainData_","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"impl","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inNonReentrant","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_addressManager","type":"address"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isAuthorized","outputs":[{"internalType":"bool","name":"authorized","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"_chainId","type":"uint64"},{"internalType":"bytes32","name":"_kind","type":"bytes32"},{"internalType":"uint64","name":"_blockId","type":"uint64"},{"internalType":"bytes32","name":"_chainData","type":"bytes32"}],"name":"isChainDataSynced","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_app","type":"address"},{"internalType":"bytes32","name":"_signal","type":"bytes32"}],"name":"isSignalSent","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastUnpausedAt","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":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"_chainId","type":"uint64"},{"internalType":"address","name":"_app","type":"address"},{"internalType":"bytes32","name":"_signal","type":"bytes32"},{"internalType":"bytes","name":"_proof","type":"bytes"}],"name":"proveSignalReceived","outputs":[{"internalType":"uint256","name":"numCacheOps_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_chainId","type":"uint64"},{"internalType":"bytes32","name":"_name","type":"bytes32"},{"internalType":"bool","name":"_allowZeroAddress","type":"bool"}],"name":"resolve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_name","type":"bytes32"},{"internalType":"bool","name":"_allowZeroAddress","type":"bool"}],"name":"resolve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_signal","type":"bytes32"}],"name":"sendSignal","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_chainId","type":"uint64"},{"internalType":"bytes32","name":"_kind","type":"bytes32"},{"internalType":"uint64","name":"_blockId","type":"uint64"}],"name":"signalForChainData","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint64","name":"_chainId","type":"uint64"},{"internalType":"bytes32","name":"_kind","type":"bytes32"},{"internalType":"uint64","name":"_blockId","type":"uint64"},{"internalType":"bytes32","name":"_chainData","type":"bytes32"}],"name":"syncChainData","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"bytes32","name":"kind","type":"bytes32"}],"name":"topBlockId","outputs":[{"internalType":"uint64","name":"blockId","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_chainId","type":"uint64"},{"internalType":"address","name":"_app","type":"address"},{"internalType":"bytes32","name":"_signal","type":"bytes32"},{"internalType":"bytes","name":"_proof","type":"bytes"}],"name":"verifySignalReceived","outputs":[],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040523060805234801562000014575f80fd5b506200001f6200002f565b620000296200002f565b620000ed565b5f54610100900460ff16156200009b5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff90811614620000eb575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6080516148dd620001225f395f8181610692015281816106db015281816107d30152818161081301526108d401526148dd5ff3fe6080604052600436106101c5575f3560e01c806379ba5097116100f2578063a86f9d9e11610092578063e30c397811610062578063e30c39781461052f578063f09a40161461054c578063f2fde38b1461056b578063fe9fbb801461058a575f80fd5b8063a86f9d9e1461048e578063ce9d0820146104ad578063dfc8ff1d146104cc578063e07baba61461050a575f80fd5b80638da5cb5b116100cd5780638da5cb5b14610414578063910af6ed1461043157806391f3f74b146104505780639b527cfa1461046f575f80fd5b806379ba5097146103d85780638456cb59146103ec5780638abf607714610400575f80fd5b80633eb6b8cf1161016857806352d1902d1161013857806352d1902d146103715780635c975abb1461038557806366ca2bc0146103a5578063715018a6146103c4575f80fd5b80633eb6b8cf146102fe5780633f4ba83a1461031d5780634f1ef286146103315780634f90a67414610344575f80fd5b8063355bcc3d116101a3578063355bcc3d146102325780633659cfe6146102895780633ab76e9f146102a85780633ced0e08146102df575f80fd5b80632d1fb389146101c95780633075db56146101ea57806332676bc614610213575b5f80fd5b3480156101d4575f80fd5b506101e86101e3366004613e4e565b6105b8565b005b3480156101f5575f80fd5b506101fe61065e565b60405190151581526020015b60405180910390f35b34801561021e575f80fd5b506101fe61022d366004613e81565b610672565b34801561023d575f80fd5b5061027161024c366004613ec1565b60fb60209081525f92835260408084209091529082529020546001600160401b031681565b6040516001600160401b03909116815260200161020a565b348015610294575f80fd5b506101e86102a3366004613edb565b610688565b3480156102b3575f80fd5b506097546102c7906001600160a01b031681565b6040516001600160a01b03909116815260200161020a565b3480156102ea575f80fd5b506101fe6102f9366004613ef6565b610758565b348015610309575f80fd5b506102c7610318366004613f37565b61079f565b348015610328575f80fd5b506101e86107b5565b6101e861033f366004614047565b6107c9565b34801561034f575f80fd5b5061036361035e366004613ef6565b610882565b60405190815260200161020a565b34801561037c575f80fd5b506103636108c8565b348015610390575f80fd5b506101fe60c954610100900460ff1660021490565b3480156103b0575f80fd5b506103636103bf366004614093565b610979565b3480156103cf575f80fd5b506101e8610985565b3480156103e3575f80fd5b506101e8610996565b3480156103f7575f80fd5b506101e8610a0d565b34801561040b575f80fd5b506102c7610a20565b34801561041f575f80fd5b506033546001600160a01b03166102c7565b34801561043c575f80fd5b5061036361044b3660046140aa565b610a2e565b34801561045b575f80fd5b5061036361046a36600461413e565b610afe565b34801561047a575f80fd5b5061036361048936600461417a565b610b69565b348015610499575f80fd5b506102c76104a83660046141aa565b610b95565b3480156104b8575f80fd5b506101e86104c73660046140aa565b610ba1565b3480156104d7575f80fd5b506104eb6104e636600461417a565b610bb7565b604080516001600160401b03909316835260208301919091520161020a565b348015610515575f80fd5b5060c954610271906201000090046001600160401b031681565b34801561053a575f80fd5b506065546001600160a01b03166102c7565b348015610557575f80fd5b506101e86105663660046141cb565b610c4b565b348015610576575f80fd5b506101e8610585366004613edb565b610d5a565b348015610595575f80fd5b506101fe6105a4366004613edb565b60fc6020525f908152604090205460ff1681565b6105c0610dcb565b6001600160a01b0382165f90815260fc602052604090205481151560ff909116151503610600576040516398f26f4560e01b815260040160405180910390fd5b6001600160a01b0382165f81815260fc6020908152604091829020805460ff191685151590811790915591519182527f4c0079b9bcd37cd5d29a13938effd97c881798cbc6bd52a3026a29d94b27d1bf910160405180910390a25050565b5f6002610669610e25565b60ff1614905090565b5f61067d8383610e64565b151590505b92915050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036106d95760405162461bcd60e51b81526004016106d090614202565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661070b610ec6565b6001600160a01b0316146107315760405162461bcd60e51b81526004016106d09061424e565b61073a81610ee1565b604080515f8082526020820190925261075591839190610ee9565b50565b5f8180820361077a5760405163ec73295960e01b815260040160405180910390fd5b5f610786878787610b69565b9050836107933083610e64565b14979650505050505050565b5f6107ab848484611053565b90505b9392505050565b6107bd6110a5565b6107c7335f611135565b565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036108115760405162461bcd60e51b81526004016106d090614202565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610843610ec6565b6001600160a01b0316146108695760405162461bcd60e51b81526004016106d09061424e565b61087282610ee1565b61087e82826001610ee9565b5050565b335f90815260fc602052604081205460ff166108b157604051631f67751f60e01b815260040160405180910390fd5b6108bd8585858561114e565b90505b949350505050565b5f306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146109675760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016106d0565b505f8051602061486183398151915290565b5f610682338384611230565b61098d610dcb565b6107c75f611309565b60655433906001600160a01b03168114610a045760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016106d0565b61075581611309565b610a15611322565b6107c7336001611135565b5f610a29610ec6565b905090565b5f610a4360c954610100900460ff1660021490565b15610a615760405163bae6e2a960e01b815260040160405180910390fd5b6002610a6b610e25565b60ff1603610a8c5760405163dfc60d8560e01b815260040160405180910390fd5b610a966002611393565b5f610aa6878787878760016113db565b90505f5b8151811015610ae957610ad5828281518110610ac857610ac861429a565b6020026020010151611897565b610adf90846142c2565b9250600101610aaa565b5050610af56001611393565b95945050505050565b6040516514d251d3905360d21b60208201526001600160c01b031960c085901b1660268201526bffffffffffffffffffffffff19606084901b16602e820152604281018290525f906062015b6040516020818303038152906040528051906020012090509392505050565b604080516001600160401b03808616602083015291810184905290821660608201525f90608001610b4a565b5f6107ae468484611053565b610baf85858585855f6113db565b505050505050565b5f80826001600160401b03165f03610bf3576001600160401b038086165f90815260fb6020908152604080832088845290915290205416610bf5565b825b91506001600160401b03821615610c43575f610c12868685610b69565b9050610c1e3082610e64565b91505f829003610c415760405163738afa0560e01b815260040160405180910390fd5b505b935093915050565b5f54610100900460ff1615808015610c6957505f54600160ff909116105b80610c825750303b158015610c8257505f5460ff166001145b610ce55760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016106d0565b5f805460ff191660011790558015610d06575f805461ff0019166101001790555b610d1083836119db565b8015610d55575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b610d62610dcb565b606580546001600160a01b0383166001600160a01b03199091168117909155610d936033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146107c75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106d0565b5f610e2f46611a15565b15610e5a57507fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c90565b5060c95460ff1690565b5f826001600160a01b038116610e8d5760405163538ba4f960e01b815260040160405180910390fd5b825f819003610eaf5760405163ec73295960e01b815260040160405180910390fd5b5f610ebb468787610afe565b549695505050505050565b5f80516020614861833981519152546001600160a01b031690565b610755610dcb565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615610f1c57610d5583611a42565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610f76575060408051601f3d908101601f19168201909252610f73918101906142d5565b60015b610fd95760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016106d0565b5f8051602061486183398151915281146110475760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016106d0565b50610d55838383611add565b5f61105e8484611b07565b90508115801561107557506001600160a01b038116155b156107ae57604051632b0d65db60e01b81526001600160401b0385166004820152602481018490526044016106d0565b6110b960c954610100900460ff1660021490565b6110d65760405163bae6e2a960e01b815260040160405180910390fd5b60c9805461010069ffffffffffffffffff001990911662010000426001600160401b031602171790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b604051630c2b8f8f60e11b815260040160405180910390fd5b5f61115a858585610b69565b9050611167308284611230565b506001600160401b038581165f90815260fb60209081526040808320888452909152902054818516911610156111d1576001600160401b038581165f90815260fb602090815260408083208884529091529020805467ffffffffffffffff19169185169190911790555b83836001600160401b0316866001600160401b03167fde247c825b1fb2d7ff9e0e771cba6f9e757ad04479fcdc135d88ae91fd50b37d8585604051611220929190918252602082015260400190565b60405180910390a4949350505050565b5f836001600160a01b0381166112595760405163538ba4f960e01b815260040160405180910390fd5b835f81900361127b5760405163ec73295960e01b815260040160405180910390fd5b835f81900361129d5760405163ec73295960e01b815260040160405180910390fd5b6112a8468888610afe565b858155604080516001600160a01b038a16815260208101899052908101829052606081018790529094507f0ad2d108660a211f47bf7fb43a0443cae181624995d3d42b88ee6879d200e9739060800160405180910390a15050509392505050565b606580546001600160a01b031916905561075581611b2c565b61133660c954610100900460ff1660021490565b156113545760405163bae6e2a960e01b815260040160405180910390fd5b60c9805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200161112b565b61139c46611a15565b156113c757807fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5d50565b60c9805460ff831660ff1990911617905550565b6060856001600160a01b0381166114055760405163538ba4f960e01b815260040160405180910390fd5b855f8190036114275760405163ec73295960e01b815260040160405180910390fd5b5f6114348688018861439b565b905080515f0361145757604051630b92daef60e21b815260040160405180910390fd5b5f6001825161146691906144d9565b6001600160401b0381111561147d5761147d613f70565b6040519080825280602002602001820160405280156114a6578160200160208202803683370190505b50905085156115395781516001600160401b038111156114c8576114c8613f70565b60405190808252806020026020018201604052801561153557816020015b6115226040805160e0810182525f80825260208201819052918101829052606081018290526080810182905260a081018290529060c082015290565b8152602001906001900390816114e65790505b5094505b8a8a8a805f61155a856d7369676e616c5f7365727669636560901b8361079f565b9050306001600160a01b0382160361158557604051637556223560e11b815260040160405180910390fd5b6115bd6040805160c0810182525f80825260208201819052918101829052906060820190815260200160608152602001606081525090565b5f805f805b8b5181101561184b578b81815181106115dd576115dd61429a565b602002602001015194505f5b8181101561164757855f01516001600160401b03168c82815181106116105761161061429a565b60200260200101516001600160401b03160361163f576040516348362c2760e11b815260040160405180910390fd5b6001016115e9565b506116568a8a8a8a898b611b7d565b93508a518114915081156116965784516001600160401b0316461461168e576040516338bf822760e21b815260040160405180910390fd5b309550611741565b845f01518b82815181106116ac576116ac61429a565b6001600160401b03928316602091820292909201015285511615806116da575084516001600160401b031646145b156116f857604051637556223560e11b815260040160405180910390fd5b8451611716906d7369676e616c5f7365727669636560901b5f61079f565b9550306001600160a01b0387160361174157604051637556223560e11b815260040160405180910390fd5b608085015151151592508f156117d5576040518060e00160405280866040015181526020018581526020018b6001600160401b0316815260200186602001516001600160401b0316815260200184151581526020018315158152602001866060015160038111156117b4576117b46144ec565b8152508f82815181106117c9576117c961429a565b60200260200101819052505b6118308a84611804577fc6cdc4f2acf13acb10f410085b821f7b7113b303e9a4799023f928317396aaf5611826565b7f73e6d340850343cc6f001515dc593377337c95a6ffe034fe1e844d4dab5da1695b8760200151610b69565b604086015186519b50969950975094955087946001016115c2565b50851580611862575061185e3088610e64565b8614155b156118805760405163738afa0560e01b815260040160405180910390fd5b505050505050505050505050509695505050505050565b5f8060038360c0015160038111156118b1576118b16144ec565b14806118d2575060028360c0015160038111156118d0576118d06144ec565b145b90508080156118e2575082608001515b80156118f057508260a00151155b15611932576001915061193083604001517f73e6d340850343cc6f001515dc593377337c95a6ffe034fe1e844d4dab5da1698560600151865f015161114e565b505b5f60038460c00151600381111561194b5761194b6144ec565b148061196c575060018460c00151600381111561196a5761196a6144ec565b145b9050808015611988575083608001518061198857508360a00151155b156119d4576119986001846142c2565b92506119d284604001517fc6cdc4f2acf13acb10f410085b821f7b7113b303e9a4799023f928317396aaf58660600151876020015161114e565b505b5050919050565b806001600160a01b038116611a035760405163538ba4f960e01b815260040160405180910390fd5b611a0c83611c1c565b610d5582611c7a565b5f6001821480611a26575061426882145b80611a33575062aa36a782145b80610682575061068282611cea565b6001600160a01b0381163b611aaf5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016106d0565b5f8051602061486183398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b611ae683611d01565b5f82511180611af25750805b15610d5557611b018383611d40565b50505050565b5f805f611b148585611d65565b91509150816108c057611b2785856120b6565b610af5565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f856001600160a01b038116611ba65760405163538ba4f960e01b815260040160405180910390fd5b855f819003611bc85760405163ec73295960e01b815260040160405180910390fd5b855f819003611bea5760405163ec73295960e01b815260040160405180910390fd5b611c0e866040015186611bfe8d8d8d610afe565b8a8a608001518b60a00151612158565b9a9950505050505050505050565b5f54610100900460ff16611c425760405162461bcd60e51b81526004016106d090614500565b611c4a612265565b611c686001600160a01b03821615611c625781611309565b33611309565b5060c9805461ff001916610100179055565b5f54610100900460ff16611ca05760405162461bcd60e51b81526004016106d090614500565b6001600160401b03461115611cc85760405163a12e8fa960e01b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b5f617e2c8210158015610682575050617e90101590565b611d0a81611a42565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606107ae83836040518060600160405280602781526020016148816027913961228b565b5f80836001600160401b0316600103611f91576a3a30b4b5b7afba37b5b2b760a91b8303611dac5750600190507310dea67478c5f8c5e2d90e5e9b26dbe60c54d8006120af565b6c38bab7ba30afb6b0b730b3b2b960991b8303611de25750600190507391f67118dd47d502b1f0c354d0611997b022f29e6120af565b6562726964676560d01b8303611e1157506001905073d60247c6848b7ca29eddf63aa924e53db6ddd8ec6120af565b6c0627269646765645f657263323609c1b8303611e475750600190507379bc0aada00fcf6e7ab514bfeb093b5fae3653e36120af565b6d627269646765645f65726337323160901b8303611e7e57506001905073c3310905e2bc9cfb198695b75ef3e5b69c6a1bf76120af565b6e627269646765645f6572633131353560881b8303611eb6575060019050733c90963cfba436400b0f9c46aa9224cb379c2c406120af565b6a195c98cc8c17dd985d5b1d60aa1b8303611eea57506001905073996282ca11e5deb6b5d122cc3b9a1fcaad4415ab6120af565b6b195c98cdcc8c57dd985d5b1d60a21b8303611f1f575060019050730b470dd3a0e1c41228856fb319649e7c08f419aa6120af565b6c195c98cc4c4d4d57dd985d5b1d609a1b8303611f5557506001905073af145913ea4a56be22e120ed9c245896598817026120af565b6d7369676e616c5f7365727669636560901b8303611f8c575060019050739e0a24964e5397b566c1ed39258e21ab5e35c77c6120af565b6120a9565b836001600160401b031662028c58036120a9576562726964676560d01b8303611fd35750600190507316700000000000000000000000000000000000016120af565b6a195c98cc8c17dd985d5b1d60aa1b83036120075750600190507316700000000000000000000000000000000000026120af565b6b195c98cdcc8c57dd985d5b1d60a21b830361203c5750600190507316700000000000000000000000000000000000036120af565b6c195c98cc4c4d4d57dd985d5b1d609a1b83036120725750600190507316700000000000000000000000000000000000046120af565b6d7369676e616c5f7365727669636560901b83036120a95750600190507316700000000000000000000000000000000000056120af565b505f9050805b9250929050565b6097545f906001600160a01b0316806120e257604051638ed88b2560e01b815260040160405180910390fd5b604051630a3dc4f360e21b81526001600160401b0385166004820152602481018490526001600160a01b038216906328f713cc90604401602060405180830381865afa158015612134573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108c0919061454b565b5f82515f14612200576040516bffffffffffffffffffffffff19606088901b1660208201525f9061219c90603401604051602081830303815290604052858a6122ff565b905080515f036121bf57604051630414cd5b60e31b815260040160405180910390fd5b5f6121c982612318565b90506121ee816002815181106121e1576121e161429a565b602002602001015161232b565b6121f790614566565b92505050612203565b50855b5f61223a8660405160200161221a91815260200190565b60408051601f198184030181529190526122338761244b565b858561245e565b90508061225a57604051638d9a4db360e01b815260040160405180910390fd5b509695505050505050565b5f54610100900460ff166107c75760405162461bcd60e51b81526004016106d090614500565b60605f80856001600160a01b0316856040516122a791906145ae565b5f60405180830381855af49150503d805f81146122df576040519150601f19603f3d011682016040523d82523d5f602084013e6122e4565b606091505b50915091506122f586838387612477565b9695505050505050565b60605f61230b856124ef565b9050610af5818585612521565b606061068261232683612d8e565b612ddf565b60605f805f61233985612ffc565b919450925090505f816001811115612353576123536144ec565b146123c65760405162461bcd60e51b815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d0000000000000060648201526084016106d0565b6123d082846142c2565b85511461243c5760405162461bcd60e51b815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527330b71034b73b30b634b2103932b6b0b4b73232b960611b60648201526084016106d0565b610af5856020015184846136a3565b606061068261245983613733565b613846565b5f80612469866124ef565b90506122f58186868661389e565b606083156124e55782515f036124de576001600160a01b0385163b6124de5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106d0565b50816108c0565b6108c083836138c4565b6060818051906020012060405160200161250b91815260200190565b6040516020818303038152906040529050919050565b60605f84511161256b5760405162461bcd60e51b81526020600482015260156024820152744d65726b6c65547269653a20656d707479206b657960581b60448201526064016106d0565b5f612575846138ee565b90505f612581866139d1565b90505f8460405160200161259791815260200190565b60405160208183030381529060405290505f805b8451811015612d37575f8582815181106125c7576125c761429a565b6020026020010151905084518311156126395760405162461bcd60e51b815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201526d0e8c2d840d6caf240d8cadccee8d60931b60648201526084016106d0565b825f036126d757805180516020918201206040516126869261266092910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b6126d25760405162461bcd60e51b815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f74206861736800000060448201526064016106d0565b6127cd565b80515160201161275d57805180516020918201206040516127019261266092910190815260200190565b6126d25760405162461bcd60e51b815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e6044820152660c2d840d0c2e6d60cb1b60648201526084016106d0565b8051845160208087019190912082519190920120146127cd5760405162461bcd60e51b815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f646044820152650ca40d0c2e6d60d31b60648201526084016106d0565b6127d9601060016142c2565b81602001515103612971578451830361290b5761280681602001516010815181106121e1576121e161429a565b96505f87511161287e5760405162461bcd60e51b815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e636829000000000060648201526084016106d0565b6001865161288c91906144d9565b82146129005760405162461bcd60e51b815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e63682900000000000060648201526084016106d0565b5050505050506107ae565b5f85848151811061291e5761291e61429a565b602001015160f81c60f81b60f81c90505f82602001518260ff16815181106129485761294861429a565b6020026020010151905061295b81613a32565b95506129686001866142c2565b94505050612d2e565b600281602001515103612cd5575f61298882613a56565b90505f815f8151811061299d5761299d61429a565b016020015160f81c90505f6129b36002836145dd565b6129be9060026145fe565b90505f6129ce848360ff16613a79565b90505f6129db8a89613a79565b90505f6129e88383613aae565b905080835114612a605760405162461bcd60e51b815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b657900000000000060648201526084016106d0565b60ff851660021480612a75575060ff85166003145b15612c155780825114612af05760405162461bcd60e51b815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e64657200000060648201526084016106d0565b612b0a87602001516001815181106121e1576121e161429a565b9c505f8d5111612b825760405162461bcd60e51b815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c656166290000000000000060648201526084016106d0565b60018c51612b9091906144d9565b8814612c045760405162461bcd60e51b815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c65616629000000000000000060648201526084016106d0565b5050505050505050505050506107ae565b60ff85161580612c28575060ff85166001145b15612c6757612c548760200151600181518110612c4757612c4761429a565b6020026020010151613a32565b9950612c60818a6142c2565b9850612cca565b60405162461bcd60e51b815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f64652077697468604482015271040c2dc40eadcd6dcdeeedc40e0e4caccd2f60731b60648201526084016106d0565b505050505050612d2e565b60405162461bcd60e51b815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e706172736561604482015267626c65206e6f646560c01b60648201526084016106d0565b506001016125ab565b5060405162461bcd60e51b815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c656044820152646d656e747360d81b60648201526084016106d0565b604080518082019091525f80825260208201525f825111612dc15760405162461bcd60e51b81526004016106d090614617565b50604080518082019091528151815260209182019181019190915290565b60605f805f612ded85612ffc565b919450925090506001816001811115612e0857612e086144ec565b14612e7b5760405162461bcd60e51b815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d000000000000000060648201526084016106d0565b8451612e8783856142c2565b14612eef5760405162461bcd60e51b815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e76616044820152713634b2103230ba30903932b6b0b4b73232b960711b60648201526084016106d0565b604080516020808252610420820190925290816020015b604080518082019091525f8082526020820152815260200190600190039081612f065790505093505f835b8651811015612ff0575f80612f756040518060400160405280858c5f0151612f5991906144d9565b8152602001858c60200151612f6e91906142c2565b9052612ffc565b509150915060405180604001604052808383612f9191906142c2565b8152602001848b60200151612fa691906142c2565b815250888581518110612fbb57612fbb61429a565b6020908102919091010152612fd16001856142c2565b9350612fdd81836142c2565b612fe790846142c2565b92505050612f31565b50845250919392505050565b5f805f80845f0151116130215760405162461bcd60e51b81526004016106d090614617565b602084015180515f1a607f8111613043575f60015f945094509450505061369c565b60b7811161319c575f6130576080836144d9565b905080875f0151116130d55760405162461bcd60e51b815260206004820152604e60248201525f8051602061484183398151915260448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201526d2873686f727420737472696e672960901b608482015260a4016106d0565b6001838101516001600160f81b03191690821415806131025750600160ff1b6001600160f81b0319821610155b61318a5760405162461bcd60e51b815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201526c73686f727420737472696e672960981b608482015260a4016106d0565b506001955093505f925061369c915050565b60bf81116133d5575f6131b060b7836144d9565b905080875f0151116132315760405162461bcd60e51b815260206004820152605160248201525f8051602061484183398151915260448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527067746820286c6f6e6720737472696e672960781b608482015260a4016106d0565b60018301516001600160f81b0319165f8190036132b65760405162461bcd60e51b815260206004820152604a60248201525f8051602061484183398151915260448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f6064820152696e6720737472696e672960b01b608482015260a4016106d0565b600184015160088302610100031c603781116133385760405162461bcd60e51b815260206004820152604860248201525f8051602061484183398151915260448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201526720737472696e672960c01b608482015260a4016106d0565b61334281846142c2565b8951116133b95760405162461bcd60e51b815260206004820152604c60248201525f8051602061484183398151915260448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201526b6c6f6e6720737472696e672960a01b608482015260a4016106d0565b6133c48360016142c2565b975095505f945061369c9350505050565b60f78111613474575f6133e960c0836144d9565b905080875f0151116134635760405162461bcd60e51b815260206004820152604a60248201525f8051602061484183398151915260448201527f742062652067726561746572207468616e206c697374206c656e677468202873606482015269686f7274206c6973742960b01b608482015260a4016106d0565b60019550935084925061369c915050565b5f61348060f7836144d9565b905080875f0151116134fd5760405162461bcd60e51b815260206004820152604d60248201525f8051602061484183398151915260448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201526c6820286c6f6e67206c6973742960981b608482015260a4016106d0565b60018301516001600160f81b0319165f8190036135805760405162461bcd60e51b815260206004820152604860248201525f8051602061484183398151915260448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f6064820152676e67206c6973742960c01b608482015260a4016106d0565b600184015160088302610100031c603781116136005760405162461bcd60e51b815260206004820152604660248201525f8051602061484183398151915260448201527f742062652067726561746572207468616e20353520627974657320286c6f6e67606482015265206c6973742960d01b608482015260a4016106d0565b61360a81846142c2565b89511161367f5760405162461bcd60e51b815260206004820152604a60248201525f8051602061484183398151915260448201527f742062652067726561746572207468616e20746f74616c206c656e67746820286064820152696c6f6e67206c6973742960b01b608482015260a4016106d0565b61368a8360016142c2565b975095506001945061369c9350505050565b9193909250565b6060816001600160401b038111156136bd576136bd613f70565b6040519080825280601f01601f1916602001820160405280156136e7576020820181803683370190505b50905081156107ae575f6136fb84866142c2565b9050602082015f5b8481101561371b578281015182820152602001613703565b84811115613729575f858301525b5050509392505050565b60605f8260405160200161374991815260200190565b60405160208183030381529060405290505f5b6020811015613794578181815181106137775761377761429a565b01602001516001600160f81b0319165f036137945760010161375c565b61379f8160206144d9565b6001600160401b038111156137b6576137b6613f70565b6040519080825280601f01601f1916602001820160405280156137e0576020820181803683370190505b5092505f5b83518110156119d25782826137f981614687565b93508151811061380b5761380b61429a565b602001015160f81c60f81b8482815181106138285761382861429a565b60200101906001600160f81b03191690815f1a9053506001016137e5565b60608151600114801561387257506080825f815181106138685761386861429a565b016020015160f81c105b1561387b575090565b61388782516080613b31565b8260405160200161250b92919061469f565b919050565b5f6108bd846138ae878686612521565b8051602091820120825192909101919091201490565b8151156138d45781518083602001fd5b8060405162461bcd60e51b81526004016106d091906146cd565b8051606090806001600160401b0381111561390b5761390b613f70565b60405190808252806020026020018201604052801561395057816020015b60408051808201909152606080825260208201528152602001906001900390816139295790505b5091505f5b818110156119d457604051806040016040528085838151811061397a5761397a61429a565b602002602001015181526020016139a986848151811061399c5761399c61429a565b6020026020010151612318565b8152508382815181106139be576139be61429a565b6020908102919091010152600101613955565b606080604051905082518060011b603f8101601f191683016040528083525060208401602083015f5b83811015613a27578060011b8201818401515f1a8060041c8253600f8116600183015350506001016139fa565b509295945050505050565b60606020825f015110613a4d57613a488261232b565b610682565b61068282613cd6565b6060610682613a7483602001515f815181106121e1576121e161429a565b6139d1565b606082518210613a97575060408051602081019091525f8152610682565b6107ae8383848651613aa991906144d9565b613cea565b5f808251845110613ac0578251613ac3565b83515b90505b8082108015613b1a5750828281518110613ae257613ae261429a565b602001015160f81c60f81b6001600160f81b031916848381518110613b0957613b0961429a565b01602001516001600160f81b031916145b15613b2a57816001019150613ac6565b5092915050565b60606038831015613b955760408051600180825281830190925290602082018180368337019050509050613b6582846146ff565b60f81b815f81518110613b7a57613b7a61429a565b60200101906001600160f81b03191690815f1a905350610682565b5f60015b613ba38186614718565b15613bc95781613bb281614687565b9250613bc290506101008261472b565b9050613b99565b613bd48260016142c2565b6001600160401b03811115613beb57613beb613f70565b6040519080825280601f01601f191660200182016040528015613c15576020820181803683370190505b509250613c2284836146ff565b613c2d9060376146ff565b60f81b835f81518110613c4257613c4261429a565b60200101906001600160f81b03191690815f1a905350600190505b818111613cce57610100613c7182846144d9565b613c7d90610100614822565b613c879087614718565b613c91919061482d565b60f81b838281518110613ca657613ca661429a565b60200101906001600160f81b03191690815f1a90535080613cc681614687565b915050613c5d565b505092915050565b606061068282602001515f845f01516136a3565b60608182601f011015613d305760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b60448201526064016106d0565b828284011015613d735760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b60448201526064016106d0565b81830184511015613dba5760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b60448201526064016106d0565b606082158015613dd85760405191505f825260208201604052613e22565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015613e11578051835260209283019201613df9565b5050858452601f01601f1916604052505b50949350505050565b6001600160a01b0381168114610755575f80fd5b80358015158114613899575f80fd5b5f8060408385031215613e5f575f80fd5b8235613e6a81613e2b565b9150613e7860208401613e3f565b90509250929050565b5f8060408385031215613e92575f80fd5b8235613e9d81613e2b565b946020939093013593505050565b80356001600160401b0381168114613899575f80fd5b5f8060408385031215613ed2575f80fd5b613e9d83613eab565b5f60208284031215613eeb575f80fd5b81356107ae81613e2b565b5f805f8060808587031215613f09575f80fd5b613f1285613eab565b935060208501359250613f2760408601613eab565b9396929550929360600135925050565b5f805f60608486031215613f49575f80fd5b613f5284613eab565b925060208401359150613f6760408501613e3f565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b60405160c081016001600160401b0381118282101715613fa657613fa6613f70565b60405290565b604051601f8201601f191681016001600160401b0381118282101715613fd457613fd4613f70565b604052919050565b5f82601f830112613feb575f80fd5b81356001600160401b0381111561400457614004613f70565b614017601f8201601f1916602001613fac565b81815284602083860101111561402b575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8060408385031215614058575f80fd5b823561406381613e2b565b915060208301356001600160401b0381111561407d575f80fd5b61408985828601613fdc565b9150509250929050565b5f602082840312156140a3575f80fd5b5035919050565b5f805f805f608086880312156140be575f80fd5b6140c786613eab565b945060208601356140d781613e2b565b93506040860135925060608601356001600160401b03808211156140f9575f80fd5b818801915088601f83011261410c575f80fd5b81358181111561411a575f80fd5b89602082850101111561412b575f80fd5b9699959850939650602001949392505050565b5f805f60608486031215614150575f80fd5b61415984613eab565b9250602084013561416981613e2b565b929592945050506040919091013590565b5f805f6060848603121561418c575f80fd5b61419584613eab565b925060208401359150613f6760408501613eab565b5f80604083850312156141bb575f80fd5b82359150613e7860208401613e3f565b5f80604083850312156141dc575f80fd5b82356141e781613e2b565b915060208301356141f781613e2b565b809150509250929050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b80820180821115610682576106826142ae565b5f602082840312156142e5575f80fd5b5051919050565b5f6001600160401b0382111561430457614304613f70565b5060051b60200190565b803560048110613899575f80fd5b5f82601f83011261432b575f80fd5b8135602061434061433b836142ec565b613fac565b82815260059290921b8401810191818101908684111561435e575f80fd5b8286015b8481101561225a5780356001600160401b0381111561437f575f80fd5b61438d8986838b0101613fdc565b845250918301918301614362565b5f60208083850312156143ac575f80fd5b82356001600160401b03808211156143c2575f80fd5b818501915085601f8301126143d5575f80fd5b81356143e361433b826142ec565b81815260059190911b83018401908481019088831115614401575f80fd5b8585015b838110156144cc5780358581111561441b575f80fd5b860160c0818c03601f19011215614430575f80fd5b614438613f84565b614443898301613eab565b81526040614452818401613eab565b8a830152606080840135828401526080915061446f82850161430e565b9083015260a08381013589811115614485575f80fd5b6144938f8d8388010161431c565b838501525060c08401359150888211156144ab575f80fd5b6144b98e8c8487010161431c565b9083015250845250918601918601614405565b5098975050505050505050565b81810381811115610682576106826142ae565b634e487b7160e01b5f52602160045260245ffd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b5f6020828403121561455b575f80fd5b81516107ae81613e2b565b80516020808301519190811015614586575f198160200360031b1b821691505b50919050565b5f5b838110156145a657818101518382015260200161458e565b50505f910152565b5f82516145bf81846020870161458c565b9190910192915050565b634e487b7160e01b5f52601260045260245ffd5b5f60ff8316806145ef576145ef6145c9565b8060ff84160691505092915050565b60ff8281168282160390811115610682576106826142ae565b6020808252604a908201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60408201527f206d7573742062652067726561746572207468616e207a65726f20746f206265606082015269206465636f6461626c6560b01b608082015260a00190565b5f60018201614698576146986142ae565b5060010190565b5f83516146b081846020880161458c565b8351908301906146c481836020880161458c565b01949350505050565b602081525f82518060208401526146eb81604085016020870161458c565b601f01601f19169190910160400192915050565b60ff8181168382160190811115610682576106826142ae565b5f82614726576147266145c9565b500490565b8082028115828204841417610682576106826142ae565b600181815b8085111561477c57815f1904821115614762576147626142ae565b8085161561476f57918102915b93841c9390800290614747565b509250929050565b5f8261479257506001610682565b8161479e57505f610682565b81600181146147b457600281146147be576147da565b6001915050610682565b60ff8411156147cf576147cf6142ae565b50506001821b610682565b5060208310610133831016604e8410600b84101617156147fd575081810a610682565b6148078383614742565b805f190482111561481a5761481a6142ae565b029392505050565b5f6107ae8383614784565b5f8261483b5761483b6145c9565b50069056fe524c505265616465723a206c656e677468206f6620636f6e74656e74206d7573360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122005726ab612e27c3dc5c690575cf42b98990053c2ec8929436ed696a02c35e78d64736f6c63430008180033
Deployed Bytecode
0x6080604052600436106101c5575f3560e01c806379ba5097116100f2578063a86f9d9e11610092578063e30c397811610062578063e30c39781461052f578063f09a40161461054c578063f2fde38b1461056b578063fe9fbb801461058a575f80fd5b8063a86f9d9e1461048e578063ce9d0820146104ad578063dfc8ff1d146104cc578063e07baba61461050a575f80fd5b80638da5cb5b116100cd5780638da5cb5b14610414578063910af6ed1461043157806391f3f74b146104505780639b527cfa1461046f575f80fd5b806379ba5097146103d85780638456cb59146103ec5780638abf607714610400575f80fd5b80633eb6b8cf1161016857806352d1902d1161013857806352d1902d146103715780635c975abb1461038557806366ca2bc0146103a5578063715018a6146103c4575f80fd5b80633eb6b8cf146102fe5780633f4ba83a1461031d5780634f1ef286146103315780634f90a67414610344575f80fd5b8063355bcc3d116101a3578063355bcc3d146102325780633659cfe6146102895780633ab76e9f146102a85780633ced0e08146102df575f80fd5b80632d1fb389146101c95780633075db56146101ea57806332676bc614610213575b5f80fd5b3480156101d4575f80fd5b506101e86101e3366004613e4e565b6105b8565b005b3480156101f5575f80fd5b506101fe61065e565b60405190151581526020015b60405180910390f35b34801561021e575f80fd5b506101fe61022d366004613e81565b610672565b34801561023d575f80fd5b5061027161024c366004613ec1565b60fb60209081525f92835260408084209091529082529020546001600160401b031681565b6040516001600160401b03909116815260200161020a565b348015610294575f80fd5b506101e86102a3366004613edb565b610688565b3480156102b3575f80fd5b506097546102c7906001600160a01b031681565b6040516001600160a01b03909116815260200161020a565b3480156102ea575f80fd5b506101fe6102f9366004613ef6565b610758565b348015610309575f80fd5b506102c7610318366004613f37565b61079f565b348015610328575f80fd5b506101e86107b5565b6101e861033f366004614047565b6107c9565b34801561034f575f80fd5b5061036361035e366004613ef6565b610882565b60405190815260200161020a565b34801561037c575f80fd5b506103636108c8565b348015610390575f80fd5b506101fe60c954610100900460ff1660021490565b3480156103b0575f80fd5b506103636103bf366004614093565b610979565b3480156103cf575f80fd5b506101e8610985565b3480156103e3575f80fd5b506101e8610996565b3480156103f7575f80fd5b506101e8610a0d565b34801561040b575f80fd5b506102c7610a20565b34801561041f575f80fd5b506033546001600160a01b03166102c7565b34801561043c575f80fd5b5061036361044b3660046140aa565b610a2e565b34801561045b575f80fd5b5061036361046a36600461413e565b610afe565b34801561047a575f80fd5b5061036361048936600461417a565b610b69565b348015610499575f80fd5b506102c76104a83660046141aa565b610b95565b3480156104b8575f80fd5b506101e86104c73660046140aa565b610ba1565b3480156104d7575f80fd5b506104eb6104e636600461417a565b610bb7565b604080516001600160401b03909316835260208301919091520161020a565b348015610515575f80fd5b5060c954610271906201000090046001600160401b031681565b34801561053a575f80fd5b506065546001600160a01b03166102c7565b348015610557575f80fd5b506101e86105663660046141cb565b610c4b565b348015610576575f80fd5b506101e8610585366004613edb565b610d5a565b348015610595575f80fd5b506101fe6105a4366004613edb565b60fc6020525f908152604090205460ff1681565b6105c0610dcb565b6001600160a01b0382165f90815260fc602052604090205481151560ff909116151503610600576040516398f26f4560e01b815260040160405180910390fd5b6001600160a01b0382165f81815260fc6020908152604091829020805460ff191685151590811790915591519182527f4c0079b9bcd37cd5d29a13938effd97c881798cbc6bd52a3026a29d94b27d1bf910160405180910390a25050565b5f6002610669610e25565b60ff1614905090565b5f61067d8383610e64565b151590505b92915050565b6001600160a01b037f000000000000000000000000df8642a1fbfc2014de27e8e87283d6f3eef315df1630036106d95760405162461bcd60e51b81526004016106d090614202565b60405180910390fd5b7f000000000000000000000000df8642a1fbfc2014de27e8e87283d6f3eef315df6001600160a01b031661070b610ec6565b6001600160a01b0316146107315760405162461bcd60e51b81526004016106d09061424e565b61073a81610ee1565b604080515f8082526020820190925261075591839190610ee9565b50565b5f8180820361077a5760405163ec73295960e01b815260040160405180910390fd5b5f610786878787610b69565b9050836107933083610e64565b14979650505050505050565b5f6107ab848484611053565b90505b9392505050565b6107bd6110a5565b6107c7335f611135565b565b6001600160a01b037f000000000000000000000000df8642a1fbfc2014de27e8e87283d6f3eef315df1630036108115760405162461bcd60e51b81526004016106d090614202565b7f000000000000000000000000df8642a1fbfc2014de27e8e87283d6f3eef315df6001600160a01b0316610843610ec6565b6001600160a01b0316146108695760405162461bcd60e51b81526004016106d09061424e565b61087282610ee1565b61087e82826001610ee9565b5050565b335f90815260fc602052604081205460ff166108b157604051631f67751f60e01b815260040160405180910390fd5b6108bd8585858561114e565b90505b949350505050565b5f306001600160a01b037f000000000000000000000000df8642a1fbfc2014de27e8e87283d6f3eef315df16146109675760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016106d0565b505f8051602061486183398151915290565b5f610682338384611230565b61098d610dcb565b6107c75f611309565b60655433906001600160a01b03168114610a045760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016106d0565b61075581611309565b610a15611322565b6107c7336001611135565b5f610a29610ec6565b905090565b5f610a4360c954610100900460ff1660021490565b15610a615760405163bae6e2a960e01b815260040160405180910390fd5b6002610a6b610e25565b60ff1603610a8c5760405163dfc60d8560e01b815260040160405180910390fd5b610a966002611393565b5f610aa6878787878760016113db565b90505f5b8151811015610ae957610ad5828281518110610ac857610ac861429a565b6020026020010151611897565b610adf90846142c2565b9250600101610aaa565b5050610af56001611393565b95945050505050565b6040516514d251d3905360d21b60208201526001600160c01b031960c085901b1660268201526bffffffffffffffffffffffff19606084901b16602e820152604281018290525f906062015b6040516020818303038152906040528051906020012090509392505050565b604080516001600160401b03808616602083015291810184905290821660608201525f90608001610b4a565b5f6107ae468484611053565b610baf85858585855f6113db565b505050505050565b5f80826001600160401b03165f03610bf3576001600160401b038086165f90815260fb6020908152604080832088845290915290205416610bf5565b825b91506001600160401b03821615610c43575f610c12868685610b69565b9050610c1e3082610e64565b91505f829003610c415760405163738afa0560e01b815260040160405180910390fd5b505b935093915050565b5f54610100900460ff1615808015610c6957505f54600160ff909116105b80610c825750303b158015610c8257505f5460ff166001145b610ce55760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016106d0565b5f805460ff191660011790558015610d06575f805461ff0019166101001790555b610d1083836119db565b8015610d55575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b610d62610dcb565b606580546001600160a01b0383166001600160a01b03199091168117909155610d936033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146107c75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106d0565b5f610e2f46611a15565b15610e5a57507fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c90565b5060c95460ff1690565b5f826001600160a01b038116610e8d5760405163538ba4f960e01b815260040160405180910390fd5b825f819003610eaf5760405163ec73295960e01b815260040160405180910390fd5b5f610ebb468787610afe565b549695505050505050565b5f80516020614861833981519152546001600160a01b031690565b610755610dcb565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615610f1c57610d5583611a42565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610f76575060408051601f3d908101601f19168201909252610f73918101906142d5565b60015b610fd95760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016106d0565b5f8051602061486183398151915281146110475760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016106d0565b50610d55838383611add565b5f61105e8484611b07565b90508115801561107557506001600160a01b038116155b156107ae57604051632b0d65db60e01b81526001600160401b0385166004820152602481018490526044016106d0565b6110b960c954610100900460ff1660021490565b6110d65760405163bae6e2a960e01b815260040160405180910390fd5b60c9805461010069ffffffffffffffffff001990911662010000426001600160401b031602171790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b604051630c2b8f8f60e11b815260040160405180910390fd5b5f61115a858585610b69565b9050611167308284611230565b506001600160401b038581165f90815260fb60209081526040808320888452909152902054818516911610156111d1576001600160401b038581165f90815260fb602090815260408083208884529091529020805467ffffffffffffffff19169185169190911790555b83836001600160401b0316866001600160401b03167fde247c825b1fb2d7ff9e0e771cba6f9e757ad04479fcdc135d88ae91fd50b37d8585604051611220929190918252602082015260400190565b60405180910390a4949350505050565b5f836001600160a01b0381166112595760405163538ba4f960e01b815260040160405180910390fd5b835f81900361127b5760405163ec73295960e01b815260040160405180910390fd5b835f81900361129d5760405163ec73295960e01b815260040160405180910390fd5b6112a8468888610afe565b858155604080516001600160a01b038a16815260208101899052908101829052606081018790529094507f0ad2d108660a211f47bf7fb43a0443cae181624995d3d42b88ee6879d200e9739060800160405180910390a15050509392505050565b606580546001600160a01b031916905561075581611b2c565b61133660c954610100900460ff1660021490565b156113545760405163bae6e2a960e01b815260040160405180910390fd5b60c9805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200161112b565b61139c46611a15565b156113c757807fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5d50565b60c9805460ff831660ff1990911617905550565b6060856001600160a01b0381166114055760405163538ba4f960e01b815260040160405180910390fd5b855f8190036114275760405163ec73295960e01b815260040160405180910390fd5b5f6114348688018861439b565b905080515f0361145757604051630b92daef60e21b815260040160405180910390fd5b5f6001825161146691906144d9565b6001600160401b0381111561147d5761147d613f70565b6040519080825280602002602001820160405280156114a6578160200160208202803683370190505b50905085156115395781516001600160401b038111156114c8576114c8613f70565b60405190808252806020026020018201604052801561153557816020015b6115226040805160e0810182525f80825260208201819052918101829052606081018290526080810182905260a081018290529060c082015290565b8152602001906001900390816114e65790505b5094505b8a8a8a805f61155a856d7369676e616c5f7365727669636560901b8361079f565b9050306001600160a01b0382160361158557604051637556223560e11b815260040160405180910390fd5b6115bd6040805160c0810182525f80825260208201819052918101829052906060820190815260200160608152602001606081525090565b5f805f805b8b5181101561184b578b81815181106115dd576115dd61429a565b602002602001015194505f5b8181101561164757855f01516001600160401b03168c82815181106116105761161061429a565b60200260200101516001600160401b03160361163f576040516348362c2760e11b815260040160405180910390fd5b6001016115e9565b506116568a8a8a8a898b611b7d565b93508a518114915081156116965784516001600160401b0316461461168e576040516338bf822760e21b815260040160405180910390fd5b309550611741565b845f01518b82815181106116ac576116ac61429a565b6001600160401b03928316602091820292909201015285511615806116da575084516001600160401b031646145b156116f857604051637556223560e11b815260040160405180910390fd5b8451611716906d7369676e616c5f7365727669636560901b5f61079f565b9550306001600160a01b0387160361174157604051637556223560e11b815260040160405180910390fd5b608085015151151592508f156117d5576040518060e00160405280866040015181526020018581526020018b6001600160401b0316815260200186602001516001600160401b0316815260200184151581526020018315158152602001866060015160038111156117b4576117b46144ec565b8152508f82815181106117c9576117c961429a565b60200260200101819052505b6118308a84611804577fc6cdc4f2acf13acb10f410085b821f7b7113b303e9a4799023f928317396aaf5611826565b7f73e6d340850343cc6f001515dc593377337c95a6ffe034fe1e844d4dab5da1695b8760200151610b69565b604086015186519b50969950975094955087946001016115c2565b50851580611862575061185e3088610e64565b8614155b156118805760405163738afa0560e01b815260040160405180910390fd5b505050505050505050505050509695505050505050565b5f8060038360c0015160038111156118b1576118b16144ec565b14806118d2575060028360c0015160038111156118d0576118d06144ec565b145b90508080156118e2575082608001515b80156118f057508260a00151155b15611932576001915061193083604001517f73e6d340850343cc6f001515dc593377337c95a6ffe034fe1e844d4dab5da1698560600151865f015161114e565b505b5f60038460c00151600381111561194b5761194b6144ec565b148061196c575060018460c00151600381111561196a5761196a6144ec565b145b9050808015611988575083608001518061198857508360a00151155b156119d4576119986001846142c2565b92506119d284604001517fc6cdc4f2acf13acb10f410085b821f7b7113b303e9a4799023f928317396aaf58660600151876020015161114e565b505b5050919050565b806001600160a01b038116611a035760405163538ba4f960e01b815260040160405180910390fd5b611a0c83611c1c565b610d5582611c7a565b5f6001821480611a26575061426882145b80611a33575062aa36a782145b80610682575061068282611cea565b6001600160a01b0381163b611aaf5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016106d0565b5f8051602061486183398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b611ae683611d01565b5f82511180611af25750805b15610d5557611b018383611d40565b50505050565b5f805f611b148585611d65565b91509150816108c057611b2785856120b6565b610af5565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f856001600160a01b038116611ba65760405163538ba4f960e01b815260040160405180910390fd5b855f819003611bc85760405163ec73295960e01b815260040160405180910390fd5b855f819003611bea5760405163ec73295960e01b815260040160405180910390fd5b611c0e866040015186611bfe8d8d8d610afe565b8a8a608001518b60a00151612158565b9a9950505050505050505050565b5f54610100900460ff16611c425760405162461bcd60e51b81526004016106d090614500565b611c4a612265565b611c686001600160a01b03821615611c625781611309565b33611309565b5060c9805461ff001916610100179055565b5f54610100900460ff16611ca05760405162461bcd60e51b81526004016106d090614500565b6001600160401b03461115611cc85760405163a12e8fa960e01b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b5f617e2c8210158015610682575050617e90101590565b611d0a81611a42565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606107ae83836040518060600160405280602781526020016148816027913961228b565b5f80836001600160401b0316600103611f91576a3a30b4b5b7afba37b5b2b760a91b8303611dac5750600190507310dea67478c5f8c5e2d90e5e9b26dbe60c54d8006120af565b6c38bab7ba30afb6b0b730b3b2b960991b8303611de25750600190507391f67118dd47d502b1f0c354d0611997b022f29e6120af565b6562726964676560d01b8303611e1157506001905073d60247c6848b7ca29eddf63aa924e53db6ddd8ec6120af565b6c0627269646765645f657263323609c1b8303611e475750600190507379bc0aada00fcf6e7ab514bfeb093b5fae3653e36120af565b6d627269646765645f65726337323160901b8303611e7e57506001905073c3310905e2bc9cfb198695b75ef3e5b69c6a1bf76120af565b6e627269646765645f6572633131353560881b8303611eb6575060019050733c90963cfba436400b0f9c46aa9224cb379c2c406120af565b6a195c98cc8c17dd985d5b1d60aa1b8303611eea57506001905073996282ca11e5deb6b5d122cc3b9a1fcaad4415ab6120af565b6b195c98cdcc8c57dd985d5b1d60a21b8303611f1f575060019050730b470dd3a0e1c41228856fb319649e7c08f419aa6120af565b6c195c98cc4c4d4d57dd985d5b1d609a1b8303611f5557506001905073af145913ea4a56be22e120ed9c245896598817026120af565b6d7369676e616c5f7365727669636560901b8303611f8c575060019050739e0a24964e5397b566c1ed39258e21ab5e35c77c6120af565b6120a9565b836001600160401b031662028c58036120a9576562726964676560d01b8303611fd35750600190507316700000000000000000000000000000000000016120af565b6a195c98cc8c17dd985d5b1d60aa1b83036120075750600190507316700000000000000000000000000000000000026120af565b6b195c98cdcc8c57dd985d5b1d60a21b830361203c5750600190507316700000000000000000000000000000000000036120af565b6c195c98cc4c4d4d57dd985d5b1d609a1b83036120725750600190507316700000000000000000000000000000000000046120af565b6d7369676e616c5f7365727669636560901b83036120a95750600190507316700000000000000000000000000000000000056120af565b505f9050805b9250929050565b6097545f906001600160a01b0316806120e257604051638ed88b2560e01b815260040160405180910390fd5b604051630a3dc4f360e21b81526001600160401b0385166004820152602481018490526001600160a01b038216906328f713cc90604401602060405180830381865afa158015612134573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108c0919061454b565b5f82515f14612200576040516bffffffffffffffffffffffff19606088901b1660208201525f9061219c90603401604051602081830303815290604052858a6122ff565b905080515f036121bf57604051630414cd5b60e31b815260040160405180910390fd5b5f6121c982612318565b90506121ee816002815181106121e1576121e161429a565b602002602001015161232b565b6121f790614566565b92505050612203565b50855b5f61223a8660405160200161221a91815260200190565b60408051601f198184030181529190526122338761244b565b858561245e565b90508061225a57604051638d9a4db360e01b815260040160405180910390fd5b509695505050505050565b5f54610100900460ff166107c75760405162461bcd60e51b81526004016106d090614500565b60605f80856001600160a01b0316856040516122a791906145ae565b5f60405180830381855af49150503d805f81146122df576040519150601f19603f3d011682016040523d82523d5f602084013e6122e4565b606091505b50915091506122f586838387612477565b9695505050505050565b60605f61230b856124ef565b9050610af5818585612521565b606061068261232683612d8e565b612ddf565b60605f805f61233985612ffc565b919450925090505f816001811115612353576123536144ec565b146123c65760405162461bcd60e51b815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d0000000000000060648201526084016106d0565b6123d082846142c2565b85511461243c5760405162461bcd60e51b815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527330b71034b73b30b634b2103932b6b0b4b73232b960611b60648201526084016106d0565b610af5856020015184846136a3565b606061068261245983613733565b613846565b5f80612469866124ef565b90506122f58186868661389e565b606083156124e55782515f036124de576001600160a01b0385163b6124de5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106d0565b50816108c0565b6108c083836138c4565b6060818051906020012060405160200161250b91815260200190565b6040516020818303038152906040529050919050565b60605f84511161256b5760405162461bcd60e51b81526020600482015260156024820152744d65726b6c65547269653a20656d707479206b657960581b60448201526064016106d0565b5f612575846138ee565b90505f612581866139d1565b90505f8460405160200161259791815260200190565b60405160208183030381529060405290505f805b8451811015612d37575f8582815181106125c7576125c761429a565b6020026020010151905084518311156126395760405162461bcd60e51b815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201526d0e8c2d840d6caf240d8cadccee8d60931b60648201526084016106d0565b825f036126d757805180516020918201206040516126869261266092910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b6126d25760405162461bcd60e51b815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f74206861736800000060448201526064016106d0565b6127cd565b80515160201161275d57805180516020918201206040516127019261266092910190815260200190565b6126d25760405162461bcd60e51b815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e6044820152660c2d840d0c2e6d60cb1b60648201526084016106d0565b8051845160208087019190912082519190920120146127cd5760405162461bcd60e51b815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f646044820152650ca40d0c2e6d60d31b60648201526084016106d0565b6127d9601060016142c2565b81602001515103612971578451830361290b5761280681602001516010815181106121e1576121e161429a565b96505f87511161287e5760405162461bcd60e51b815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e636829000000000060648201526084016106d0565b6001865161288c91906144d9565b82146129005760405162461bcd60e51b815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e63682900000000000060648201526084016106d0565b5050505050506107ae565b5f85848151811061291e5761291e61429a565b602001015160f81c60f81b60f81c90505f82602001518260ff16815181106129485761294861429a565b6020026020010151905061295b81613a32565b95506129686001866142c2565b94505050612d2e565b600281602001515103612cd5575f61298882613a56565b90505f815f8151811061299d5761299d61429a565b016020015160f81c90505f6129b36002836145dd565b6129be9060026145fe565b90505f6129ce848360ff16613a79565b90505f6129db8a89613a79565b90505f6129e88383613aae565b905080835114612a605760405162461bcd60e51b815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b657900000000000060648201526084016106d0565b60ff851660021480612a75575060ff85166003145b15612c155780825114612af05760405162461bcd60e51b815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e64657200000060648201526084016106d0565b612b0a87602001516001815181106121e1576121e161429a565b9c505f8d5111612b825760405162461bcd60e51b815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c656166290000000000000060648201526084016106d0565b60018c51612b9091906144d9565b8814612c045760405162461bcd60e51b815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c65616629000000000000000060648201526084016106d0565b5050505050505050505050506107ae565b60ff85161580612c28575060ff85166001145b15612c6757612c548760200151600181518110612c4757612c4761429a565b6020026020010151613a32565b9950612c60818a6142c2565b9850612cca565b60405162461bcd60e51b815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f64652077697468604482015271040c2dc40eadcd6dcdeeedc40e0e4caccd2f60731b60648201526084016106d0565b505050505050612d2e565b60405162461bcd60e51b815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e706172736561604482015267626c65206e6f646560c01b60648201526084016106d0565b506001016125ab565b5060405162461bcd60e51b815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c656044820152646d656e747360d81b60648201526084016106d0565b604080518082019091525f80825260208201525f825111612dc15760405162461bcd60e51b81526004016106d090614617565b50604080518082019091528151815260209182019181019190915290565b60605f805f612ded85612ffc565b919450925090506001816001811115612e0857612e086144ec565b14612e7b5760405162461bcd60e51b815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d000000000000000060648201526084016106d0565b8451612e8783856142c2565b14612eef5760405162461bcd60e51b815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e76616044820152713634b2103230ba30903932b6b0b4b73232b960711b60648201526084016106d0565b604080516020808252610420820190925290816020015b604080518082019091525f8082526020820152815260200190600190039081612f065790505093505f835b8651811015612ff0575f80612f756040518060400160405280858c5f0151612f5991906144d9565b8152602001858c60200151612f6e91906142c2565b9052612ffc565b509150915060405180604001604052808383612f9191906142c2565b8152602001848b60200151612fa691906142c2565b815250888581518110612fbb57612fbb61429a565b6020908102919091010152612fd16001856142c2565b9350612fdd81836142c2565b612fe790846142c2565b92505050612f31565b50845250919392505050565b5f805f80845f0151116130215760405162461bcd60e51b81526004016106d090614617565b602084015180515f1a607f8111613043575f60015f945094509450505061369c565b60b7811161319c575f6130576080836144d9565b905080875f0151116130d55760405162461bcd60e51b815260206004820152604e60248201525f8051602061484183398151915260448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201526d2873686f727420737472696e672960901b608482015260a4016106d0565b6001838101516001600160f81b03191690821415806131025750600160ff1b6001600160f81b0319821610155b61318a5760405162461bcd60e51b815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201526c73686f727420737472696e672960981b608482015260a4016106d0565b506001955093505f925061369c915050565b60bf81116133d5575f6131b060b7836144d9565b905080875f0151116132315760405162461bcd60e51b815260206004820152605160248201525f8051602061484183398151915260448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527067746820286c6f6e6720737472696e672960781b608482015260a4016106d0565b60018301516001600160f81b0319165f8190036132b65760405162461bcd60e51b815260206004820152604a60248201525f8051602061484183398151915260448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f6064820152696e6720737472696e672960b01b608482015260a4016106d0565b600184015160088302610100031c603781116133385760405162461bcd60e51b815260206004820152604860248201525f8051602061484183398151915260448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201526720737472696e672960c01b608482015260a4016106d0565b61334281846142c2565b8951116133b95760405162461bcd60e51b815260206004820152604c60248201525f8051602061484183398151915260448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201526b6c6f6e6720737472696e672960a01b608482015260a4016106d0565b6133c48360016142c2565b975095505f945061369c9350505050565b60f78111613474575f6133e960c0836144d9565b905080875f0151116134635760405162461bcd60e51b815260206004820152604a60248201525f8051602061484183398151915260448201527f742062652067726561746572207468616e206c697374206c656e677468202873606482015269686f7274206c6973742960b01b608482015260a4016106d0565b60019550935084925061369c915050565b5f61348060f7836144d9565b905080875f0151116134fd5760405162461bcd60e51b815260206004820152604d60248201525f8051602061484183398151915260448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201526c6820286c6f6e67206c6973742960981b608482015260a4016106d0565b60018301516001600160f81b0319165f8190036135805760405162461bcd60e51b815260206004820152604860248201525f8051602061484183398151915260448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f6064820152676e67206c6973742960c01b608482015260a4016106d0565b600184015160088302610100031c603781116136005760405162461bcd60e51b815260206004820152604660248201525f8051602061484183398151915260448201527f742062652067726561746572207468616e20353520627974657320286c6f6e67606482015265206c6973742960d01b608482015260a4016106d0565b61360a81846142c2565b89511161367f5760405162461bcd60e51b815260206004820152604a60248201525f8051602061484183398151915260448201527f742062652067726561746572207468616e20746f74616c206c656e67746820286064820152696c6f6e67206c6973742960b01b608482015260a4016106d0565b61368a8360016142c2565b975095506001945061369c9350505050565b9193909250565b6060816001600160401b038111156136bd576136bd613f70565b6040519080825280601f01601f1916602001820160405280156136e7576020820181803683370190505b50905081156107ae575f6136fb84866142c2565b9050602082015f5b8481101561371b578281015182820152602001613703565b84811115613729575f858301525b5050509392505050565b60605f8260405160200161374991815260200190565b60405160208183030381529060405290505f5b6020811015613794578181815181106137775761377761429a565b01602001516001600160f81b0319165f036137945760010161375c565b61379f8160206144d9565b6001600160401b038111156137b6576137b6613f70565b6040519080825280601f01601f1916602001820160405280156137e0576020820181803683370190505b5092505f5b83518110156119d25782826137f981614687565b93508151811061380b5761380b61429a565b602001015160f81c60f81b8482815181106138285761382861429a565b60200101906001600160f81b03191690815f1a9053506001016137e5565b60608151600114801561387257506080825f815181106138685761386861429a565b016020015160f81c105b1561387b575090565b61388782516080613b31565b8260405160200161250b92919061469f565b919050565b5f6108bd846138ae878686612521565b8051602091820120825192909101919091201490565b8151156138d45781518083602001fd5b8060405162461bcd60e51b81526004016106d091906146cd565b8051606090806001600160401b0381111561390b5761390b613f70565b60405190808252806020026020018201604052801561395057816020015b60408051808201909152606080825260208201528152602001906001900390816139295790505b5091505f5b818110156119d457604051806040016040528085838151811061397a5761397a61429a565b602002602001015181526020016139a986848151811061399c5761399c61429a565b6020026020010151612318565b8152508382815181106139be576139be61429a565b6020908102919091010152600101613955565b606080604051905082518060011b603f8101601f191683016040528083525060208401602083015f5b83811015613a27578060011b8201818401515f1a8060041c8253600f8116600183015350506001016139fa565b509295945050505050565b60606020825f015110613a4d57613a488261232b565b610682565b61068282613cd6565b6060610682613a7483602001515f815181106121e1576121e161429a565b6139d1565b606082518210613a97575060408051602081019091525f8152610682565b6107ae8383848651613aa991906144d9565b613cea565b5f808251845110613ac0578251613ac3565b83515b90505b8082108015613b1a5750828281518110613ae257613ae261429a565b602001015160f81c60f81b6001600160f81b031916848381518110613b0957613b0961429a565b01602001516001600160f81b031916145b15613b2a57816001019150613ac6565b5092915050565b60606038831015613b955760408051600180825281830190925290602082018180368337019050509050613b6582846146ff565b60f81b815f81518110613b7a57613b7a61429a565b60200101906001600160f81b03191690815f1a905350610682565b5f60015b613ba38186614718565b15613bc95781613bb281614687565b9250613bc290506101008261472b565b9050613b99565b613bd48260016142c2565b6001600160401b03811115613beb57613beb613f70565b6040519080825280601f01601f191660200182016040528015613c15576020820181803683370190505b509250613c2284836146ff565b613c2d9060376146ff565b60f81b835f81518110613c4257613c4261429a565b60200101906001600160f81b03191690815f1a905350600190505b818111613cce57610100613c7182846144d9565b613c7d90610100614822565b613c879087614718565b613c91919061482d565b60f81b838281518110613ca657613ca661429a565b60200101906001600160f81b03191690815f1a90535080613cc681614687565b915050613c5d565b505092915050565b606061068282602001515f845f01516136a3565b60608182601f011015613d305760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b60448201526064016106d0565b828284011015613d735760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b60448201526064016106d0565b81830184511015613dba5760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b60448201526064016106d0565b606082158015613dd85760405191505f825260208201604052613e22565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015613e11578051835260209283019201613df9565b5050858452601f01601f1916604052505b50949350505050565b6001600160a01b0381168114610755575f80fd5b80358015158114613899575f80fd5b5f8060408385031215613e5f575f80fd5b8235613e6a81613e2b565b9150613e7860208401613e3f565b90509250929050565b5f8060408385031215613e92575f80fd5b8235613e9d81613e2b565b946020939093013593505050565b80356001600160401b0381168114613899575f80fd5b5f8060408385031215613ed2575f80fd5b613e9d83613eab565b5f60208284031215613eeb575f80fd5b81356107ae81613e2b565b5f805f8060808587031215613f09575f80fd5b613f1285613eab565b935060208501359250613f2760408601613eab565b9396929550929360600135925050565b5f805f60608486031215613f49575f80fd5b613f5284613eab565b925060208401359150613f6760408501613e3f565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b60405160c081016001600160401b0381118282101715613fa657613fa6613f70565b60405290565b604051601f8201601f191681016001600160401b0381118282101715613fd457613fd4613f70565b604052919050565b5f82601f830112613feb575f80fd5b81356001600160401b0381111561400457614004613f70565b614017601f8201601f1916602001613fac565b81815284602083860101111561402b575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8060408385031215614058575f80fd5b823561406381613e2b565b915060208301356001600160401b0381111561407d575f80fd5b61408985828601613fdc565b9150509250929050565b5f602082840312156140a3575f80fd5b5035919050565b5f805f805f608086880312156140be575f80fd5b6140c786613eab565b945060208601356140d781613e2b565b93506040860135925060608601356001600160401b03808211156140f9575f80fd5b818801915088601f83011261410c575f80fd5b81358181111561411a575f80fd5b89602082850101111561412b575f80fd5b9699959850939650602001949392505050565b5f805f60608486031215614150575f80fd5b61415984613eab565b9250602084013561416981613e2b565b929592945050506040919091013590565b5f805f6060848603121561418c575f80fd5b61419584613eab565b925060208401359150613f6760408501613eab565b5f80604083850312156141bb575f80fd5b82359150613e7860208401613e3f565b5f80604083850312156141dc575f80fd5b82356141e781613e2b565b915060208301356141f781613e2b565b809150509250929050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b80820180821115610682576106826142ae565b5f602082840312156142e5575f80fd5b5051919050565b5f6001600160401b0382111561430457614304613f70565b5060051b60200190565b803560048110613899575f80fd5b5f82601f83011261432b575f80fd5b8135602061434061433b836142ec565b613fac565b82815260059290921b8401810191818101908684111561435e575f80fd5b8286015b8481101561225a5780356001600160401b0381111561437f575f80fd5b61438d8986838b0101613fdc565b845250918301918301614362565b5f60208083850312156143ac575f80fd5b82356001600160401b03808211156143c2575f80fd5b818501915085601f8301126143d5575f80fd5b81356143e361433b826142ec565b81815260059190911b83018401908481019088831115614401575f80fd5b8585015b838110156144cc5780358581111561441b575f80fd5b860160c0818c03601f19011215614430575f80fd5b614438613f84565b614443898301613eab565b81526040614452818401613eab565b8a830152606080840135828401526080915061446f82850161430e565b9083015260a08381013589811115614485575f80fd5b6144938f8d8388010161431c565b838501525060c08401359150888211156144ab575f80fd5b6144b98e8c8487010161431c565b9083015250845250918601918601614405565b5098975050505050505050565b81810381811115610682576106826142ae565b634e487b7160e01b5f52602160045260245ffd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b5f6020828403121561455b575f80fd5b81516107ae81613e2b565b80516020808301519190811015614586575f198160200360031b1b821691505b50919050565b5f5b838110156145a657818101518382015260200161458e565b50505f910152565b5f82516145bf81846020870161458c565b9190910192915050565b634e487b7160e01b5f52601260045260245ffd5b5f60ff8316806145ef576145ef6145c9565b8060ff84160691505092915050565b60ff8281168282160390811115610682576106826142ae565b6020808252604a908201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60408201527f206d7573742062652067726561746572207468616e207a65726f20746f206265606082015269206465636f6461626c6560b01b608082015260a00190565b5f60018201614698576146986142ae565b5060010190565b5f83516146b081846020880161458c565b8351908301906146c481836020880161458c565b01949350505050565b602081525f82518060208401526146eb81604085016020870161458c565b601f01601f19169190910160400192915050565b60ff8181168382160190811115610682576106826142ae565b5f82614726576147266145c9565b500490565b8082028115828204841417610682576106826142ae565b600181815b8085111561477c57815f1904821115614762576147626142ae565b8085161561476f57918102915b93841c9390800290614747565b509250929050565b5f8261479257506001610682565b8161479e57505f610682565b81600181146147b457600281146147be576147da565b6001915050610682565b60ff8411156147cf576147cf6142ae565b50506001821b610682565b5060208310610133831016604e8410600b84101617156147fd575081810a610682565b6148078383614742565b805f190482111561481a5761481a6142ae565b029392505050565b5f6107ae8383614784565b5f8261483b5761483b6145c9565b50069056fe524c505265616465723a206c656e677468206f6620636f6e74656e74206d7573360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122005726ab612e27c3dc5c690575cf42b98990053c2ec8929436ed696a02c35e78d64736f6c63430008180033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.