Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
ZKBridge
Compiler Version
v0.8.14+commit.80d49f37
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./Governance.sol"; import "./libraries/external/RLPReader.sol"; import "./libraries/external/BytesLib.sol"; import "./interfaces/IZKBridgeEntrypoint.sol"; import "./interfaces/IZKBridgeReceiver.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol"; contract ZKBridge is Governance, IZKBridgeEntrypoint { using RLPReader for RLPReader.RLPItem; using RLPReader for bytes; using BytesLib for bytes; bytes32 public constant MESSAGE_TOPIC = 0xb8abfd5c33667c7440a4fc1153ae39a24833dbe44f7eb19cbe5cd5f2583e4940; struct LogMessage { uint16 dstChainId; uint64 sequence; address dstAddress; bytes32 srcAddress; bytes32 srcZkBridge; bytes payload; } struct Payload { uint16 srcChainId; uint16 dstChainId; address srcAddress; address dstAddress; uint64 sequence; bytes uaPayload; } modifier initializer() { address implementation = ERC1967Upgrade._getImplementation(); require(!isInitialized(implementation), "already initialized"); _setInitialized(implementation); _; } function initialize() initializer public virtual { // this function needs to be exposed for an upgrade to pass } function send(uint16 dstChainId, address dstAddress, bytes memory payload) external payable returns (uint64 sequence) { require(dstChainId != chainId(), "Cannot send to same chain"); sequence = _useSequence(chainId(), msg.sender); payload = abi.encodePacked(bytes32("ZKBridge v2 version"), chainId(), dstChainId, msg.sender, dstAddress, sequence, payload); if (isL2()) { l2MessageSend().sendMessage{value : l2MessageSend().getFee()}(chainId(), msg.sender, dstChainId, dstAddress, sequence, payload); } emit MessagePublished(msg.sender, dstChainId, sequence, dstAddress, payload); } function sendFromL2(uint16 srcChainId,uint16 dstChainId, address dstAddress, bytes memory payload) external returns (uint64 sequence) { require(msg.sender == l2MessageReceive(srcChainId), "caller is not the l2MessageReceive"); require(dstChainId != chainId(), "Cannot send to same chain"); sequence = _useSequence(chainId(), msg.sender); emit MessagePublished(msg.sender, dstChainId, sequence, dstAddress, payload); } function validateTransactionProof(uint16 srcChainId, bytes32 srcBlockHash, uint256 logIndex, bytes memory mptProof) external { IMptVerifier mptVerifier = mptVerifier(srcChainId); IBlockUpdater blockUpdater = blockUpdater(srcChainId); require(address(mptVerifier) != address(0), "MptVerifier is not set"); require(address(blockUpdater) != address(0), "Block Updater is not set"); IMptVerifier.Receipt memory receipt = mptVerifier.validateMPT(mptProof); require(receipt.state == 1, "Source Chain Transaction Failure"); require(blockUpdater.checkBlock(srcBlockHash, receipt.receiptHash), "Block Header is not set"); LogMessage memory logMessage = _parseLog(receipt.logs, logIndex); require(logMessage.srcZkBridge == zkBridgeContracts(srcChainId), "Invalid source ZKBridge"); require(logMessage.dstChainId == chainId(), "Invalid destination chain"); bytes32 hash; hash = keccak256(abi.encode(srcChainId, logMessage.srcAddress, logMessage.sequence)); require(!isTransferCompleted(hash), "Message already executed."); _setTransferCompleted(hash); emit ExecutedMessage(_truncateAddress(logMessage.srcAddress), srcChainId, logMessage.sequence, logMessage.dstAddress, logMessage.payload); (Payload memory p,bool isNewVersion) = _parsePayload(logMessage.payload); if (isNewVersion) { if (p.srcChainId != srcChainId) { require(p.dstChainId == chainId(), "Invalid destination chain"); hash = keccak256(abi.encode(p.srcChainId, p.srcAddress, p.sequence)); require(!isTransferCompleted(hash), "Message already executed."); _setTransferCompleted(hash); emit ExecutedMessage(p.srcAddress, p.srcChainId, p.sequence, p.dstAddress, p.uaPayload); } IZKBridgeReceiver(p.dstAddress).zkReceive(p.srcChainId, p.srcAddress, p.sequence, p.uaPayload); } else { IZKBridgeReceiver(logMessage.dstAddress).zkReceive(srcChainId, _truncateAddress(logMessage.srcAddress), logMessage.sequence, logMessage.payload); } } function validateTransactionFromL2(uint16 srcChainId, address srcAddress, address dstAddress, uint64 sequence, bytes calldata payload) external { require(msg.sender == l2MessageReceive(srcChainId), "caller is not the l2MessageReceive"); (Payload memory p,bool isNewVersion) = _parsePayload(payload); require(isNewVersion, "Unsupported version"); require(srcChainId == p.srcChainId, "Invalid srcChainId"); require(p.dstChainId == chainId(), "Invalid destination chain"); bytes32 hash = keccak256(abi.encode(srcChainId, srcAddress, sequence)); require(!isTransferCompleted(hash), "Message already executed."); _setTransferCompleted(hash); IZKBridgeReceiver(dstAddress).zkReceive(srcChainId, srcAddress, sequence, p.uaPayload); emit ExecutedMessage(srcAddress, srcChainId, sequence, dstAddress, payload); } function _useSequence(uint16 chainId, address emitter) internal returns (uint64 sequence) { bytes32 hash = keccak256(abi.encode(chainId, emitter)); sequence = nextSequence(hash); _setNextSequence(hash, sequence + 1); } function _parseLog(bytes memory logsByte, uint256 logIndex) internal pure returns (LogMessage memory logMessage) { RLPReader.RLPItem[] memory logs = logsByte.toRlpItem().toList(); if (logIndex != 0) { logs = logs[logIndex + 2].toRlpBytes().toRlpItem().toList(); } RLPReader.RLPItem[] memory topicItem = logs[1].toRlpBytes().toRlpItem().toList(); bytes32 topic = abi.decode(topicItem[0].toBytes(), (bytes32)); if (topic == MESSAGE_TOPIC) { logMessage.srcZkBridge = logs[0].toBytes32(); logMessage.srcAddress = abi.decode(topicItem[1].toBytes(), (bytes32)); logMessage.dstChainId = abi.decode(topicItem[2].toBytes(), (uint16)); logMessage.sequence = abi.decode(topicItem[3].toBytes(), (uint64)); (logMessage.dstAddress, logMessage.payload) = abi.decode(logs[2].toBytes(), (address, bytes)); } } function _parsePayload(bytes memory payload) internal pure returns (Payload memory txPayload, bool isNewVersion) { uint index = 0; bytes32 tag = payload.toBytes32(index); if (tag != bytes32("ZKBridge v2 version")) { return (txPayload, isNewVersion); } index += 32; txPayload.srcChainId = payload.toUint16(index); index += 2; txPayload.dstChainId = payload.toUint16(index); index += 2; txPayload.srcAddress = payload.toAddress(index); index += 20; txPayload.dstAddress = payload.toAddress(index); index += 20; txPayload.sequence = payload.toUint64(index); index += 8; txPayload.uaPayload = payload.slice(index, payload.length - index); isNewVersion = true; } function _truncateAddress(bytes32 b) internal pure returns (address) { require(bytes12(b) == 0, "invalid EVM address"); return address(uint160(uint256(b))); } fallback() external payable {revert("unsupported");} receive() external payable {revert("the ZkBridge contract does not accept assets");} }
// 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) (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 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) (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) (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 pragma solidity ^0.8.0; import "./State.sol"; import "./interfaces/IMptVerifier.sol"; import "./interfaces/IBlockUpdater.sol"; import "./interfaces/IL2MessageSend.sol"; contract Getters is State { function isInitialized(address impl) public view returns (bool) { return _state.initializedImplementations[impl]; } function chainId() public view returns (uint16) { return _state.provider.chainId; } function nextSequence(bytes32 hash) public view returns (uint64) { return _state.sequences[hash]; } function zkBridgeContracts(uint16 chainId) public view returns (bytes32){ return _state.zkBridgeImplementations[chainId]; } function isTransferCompleted(bytes32 hash) public view returns (bool) { return _state.completedTransfers[hash]; } function mptVerifier(uint16 chainId) public view returns (IMptVerifier) { return IMptVerifier(_state.mptVerifiers[chainId]); } function blockUpdater(uint16 chainId) public view returns (IBlockUpdater) { return IBlockUpdater(_state.blockUpdaters[chainId]); } function owner() public view returns (address) { return _state.owner; } function pendingImplementation() public view returns (address) { return _state.pendingImplementation; } function toUpdateTime() public view returns (uint256) { return _state.toUpdateTime; } function lockTime() public view returns (uint256) { return _state.lockTime; } function isL2() public view returns (bool) { return _state.isL2; } function l2MessageReceive(uint16 chainId) public view returns (address) { return _state.l2MessageReceives[chainId]; } function l2MessageSend() public view returns (IL2MessageSend) { return IL2MessageSend(_state.l2MessageSend); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./Setters.sol"; import "./Getters.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol"; abstract contract Governance is Setters, Getters, ERC1967Upgrade { event NewPendingImplementation(address indexed pendingImplementation, address indexed newImplementation); event ContractUpgraded(address indexed oldContract, address indexed newContract); modifier onlyOwner() { require(owner() == msg.sender, "Ownable: caller is not the owner"); _; } function registerChain(uint16 chainId, bytes32 bridgeContract) public onlyOwner { _setZKBridgeImplementation(chainId, bridgeContract); } function setMptVerifier(uint16 chainId, address mptVerifier) public onlyOwner { _setMptVerifier(chainId, mptVerifier); } function setBlockUpdater(uint16 chainId, address blockUpdater) public onlyOwner { _setBlockUpdater(chainId, blockUpdater); } function setLockTime(uint256 lockTime) public onlyOwner { require(lockTime >= MIN_LOCK_TIME, 'Incorrect lockTime settings'); _setLockTime(lockTime); } function setL2MessageReceive(uint16 chainId, address l2MessageReceive) public onlyOwner { _setL2MessageReceive(chainId, l2MessageReceive); } function setL2MessageSend(address l2MessageSend) public onlyOwner { _setL2MessageSend(l2MessageSend); } function setL2(bool isL2) public onlyOwner { _setL2(isL2); } function claimFees() external onlyOwner { payable(owner()).transfer(address(this).balance); } function submitContractUpgrade(address newImplementation) public onlyOwner { require(newImplementation != address(0), "Check pendingImplementation"); address currentPendingImplementation = pendingImplementation(); _setPendingImplementation(newImplementation); _setToUpdateTime(block.timestamp + lockTime()); emit NewPendingImplementation(currentPendingImplementation, newImplementation); } function confirmContractUpgrade() public onlyOwner { require(pendingImplementation() != address(0), "Check pendingImplementation"); require(block.timestamp >= toUpdateTime(), "Still locked in"); address currentImplementation = _getImplementation(); address newImplementation = pendingImplementation(); _setPendingImplementation(address(0)); _upgradeTo(newImplementation); // Call initialize function of the new implementation (bool success, bytes memory reason) = newImplementation.delegatecall(abi.encodeWithSignature("initialize()")); require(success, string(reason)); emit ContractUpgraded(currentImplementation, newImplementation); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IBlockUpdater { function checkBlock(bytes32 blockHash, bytes32 receiptsRoot) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IL2MessageSend { function sendMessage(uint16 _srcChainId, address _srcAddress, uint16 _dstChainId, address _dstAddress, uint64 _sequence, bytes calldata _payload) external payable; function getFee() external view returns (uint256 fee); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IMptVerifier { struct Receipt { bytes32 receiptHash; uint256 state; bytes logs; } function validateMPT(bytes memory proof) external view returns (Receipt memory receipt); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IZKBridgeEntrypoint { event MessagePublished(address indexed sender, uint16 indexed dstChainId, uint64 indexed sequence, address dstAddress, bytes payload); event ExecutedMessage(address indexed sender, uint16 indexed srcChainId, uint64 indexed sequence, address dstAddress, bytes payload); function send(uint16 dstChainId, address dstAddress, bytes memory payload) external payable returns (uint64 sequence); function validateTransactionProof(uint16 srcChainId, bytes32 srcBlockHash, uint256 logIndex, bytes memory mptProof) external; function sendFromL2(uint16 srcChainId, uint16 dstChainId, address dstAddress, bytes memory payload) external returns (uint64 sequence); function validateTransactionFromL2(uint16 srcChainId, address srcAddress, address dstAddress, uint64 sequence, bytes calldata payload) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IZKBridgeReceiver { // @notice ZKBridge endpoint will invoke this function to deliver the message on the destination // @param srcChainId - the source endpoint identifier // @param srcAddress - the source sending contract address from the source chain // @param sequence - the ordered message nonce // @param payload - the signed payload is the UA bytes has encoded to be sent function zkReceive(uint16 srcChainId, address srcAddress, uint64 sequence, bytes calldata payload) external; }
// SPDX-License-Identifier: Unlicense /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. */ pragma solidity >=0.8.0 <0.9.0; library BytesLib { function concat( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // Store the length of the first bytes array at the beginning of // the memory for tempBytes. let length := mload(_preBytes) mstore(tempBytes, length) // Maintain a memory counter for the current write location in the // temp bytes array by adding the 32 bytes for the array length to // the starting location. let mc := add(tempBytes, 0x20) // Stop copying when the memory counter reaches the length of the // first bytes array. let end := add(mc, length) for { // Initialize a copy counter to the start of the _preBytes data, // 32 bytes into its memory. let cc := add(_preBytes, 0x20) } lt(mc, end) { // Increase both counters by 32 bytes each iteration. mc := add(mc, 0x20) cc := add(cc, 0x20) } { // Write the _preBytes data into the tempBytes memory 32 bytes // at a time. mstore(mc, mload(cc)) } // Add the length of _postBytes to the current length of tempBytes // and store it as the new length in the first 32 bytes of the // tempBytes memory. length := mload(_postBytes) mstore(tempBytes, add(length, mload(tempBytes))) // Move the memory counter back from a multiple of 0x20 to the // actual end of the _preBytes data. mc := end // Stop copying when the memory counter reaches the new combined // length of the arrays. end := add(mc, length) for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). mstore(0x40, and( add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31) // Round down to the nearest 32 bytes. )) } return tempBytes; } function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal { assembly { // Read the first 32 bytes of _preBytes storage, which is the length // of the array. (We don't need to use the offset into the slot // because arrays use the entire slot.) let fslot := sload(_preBytes.slot) // Arrays of 31 bytes or less have an even value in their slot, // while longer arrays have an odd value. The actual length is // the slot divided by two for odd values, and the lowest order // byte divided by two for even values. // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) let newlength := add(slength, mlength) // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage switch add(lt(slength, 32), lt(newlength, 32)) case 2 { // Since the new array still fits in the slot, we just need to // update the contents of the slot. // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length sstore( _preBytes.slot, // all the modifications to the slot are inside this // next block add( // we can just add to the slot contents because the // bytes we want to change are the LSBs fslot, add( mul( div( // load the bytes from memory mload(add(_postBytes, 0x20)), // zero all bytes to the right exp(0x100, sub(32, mlength)) ), // and now shift left the number of bytes to // leave space for the length in the slot exp(0x100, sub(32, newlength)) ), // increase length by the double of the memory // bytes length mul(mlength, 2) ) ) ) } case 1 { // The stored value fits in the slot, but the combined value // will exceed it. // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // The contents of the _postBytes array start 32 bytes into // the structure. Our first read should obtain the `submod` // bytes that can fit into the unused space in the last word // of the stored array. To get this, we read 32 bytes starting // from `submod`, so the data we read overlaps with the array // contents by `submod` bytes. Masking the lowest-order // `submod` bytes allows us to add that value directly to the // stored value. let submod := sub(32, slength) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore( sc, add( and( fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 ), and(mload(mc), mask) ) ) for { mc := add(mc, 0x20) sc := add(sc, 1) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } default { // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) // Start copying to the last used word of the stored array. let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // Copy over the first `submod` bytes of the new data as in // case 1 above. let slengthmod := mod(slength, 32) let mlengthmod := mod(mlength, 32) let submod := sub(32, slengthmod) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore(sc, add(sload(sc), and(mload(mc), mask))) for { sc := add(sc, 1) mc := add(mc, 0x20) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } } } function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_length + 31 >= _length, "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; } function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { require(_bytes.length >= _start + 20, "toAddress_outOfBounds"); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) { require(_bytes.length >= _start + 1 , "toUint8_outOfBounds"); uint8 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x1), _start)) } return tempUint; } function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { require(_bytes.length >= _start + 2, "toUint16_outOfBounds"); uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) { require(_bytes.length >= _start + 4, "toUint32_outOfBounds"); uint32 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x4), _start)) } return tempUint; } function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) { require(_bytes.length >= _start + 8, "toUint64_outOfBounds"); uint64 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x8), _start)) } return tempUint; } function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) { require(_bytes.length >= _start + 12, "toUint96_outOfBounds"); uint96 tempUint; assembly { tempUint := mload(add(add(_bytes, 0xc), _start)) } return tempUint; } function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) { require(_bytes.length >= _start + 16, "toUint128_outOfBounds"); uint128 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x10), _start)) } return tempUint; } function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { require(_bytes.length >= _start + 32, "toBytes32_outOfBounds"); bytes32 tempBytes32; assembly { tempBytes32 := mload(add(add(_bytes, 0x20), _start)) } return tempBytes32; } function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let mc := add(_preBytes, 0x20) let end := add(mc, length) for { let cc := add(_postBytes, 0x20) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } } default { // unsuccess: success := 0 } } return success; } function equalStorage( bytes storage _preBytes, bytes memory _postBytes ) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Decode the length of the stored array like in concatStorage(). let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) for {} eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library RLPReader { uint8 constant STRING_SHORT_START = 0x80; uint8 constant STRING_LONG_START = 0xb8; uint8 constant LIST_SHORT_START = 0xc0; uint8 constant LIST_LONG_START = 0xf8; uint8 constant WORD_SIZE = 32; struct RLPItem { uint len; uint memPtr; } struct Iterator { RLPItem item; // Item that's being iterated over. uint nextPtr; // Position of the next item in the list. } /* * @dev Returns the next element in the iteration. Reverts if it has not next element. * @param self The iterator. * @return The next element in the iteration. */ function next(Iterator memory self) internal pure returns (RLPItem memory) { require(hasNext(self)); uint ptr = self.nextPtr; uint itemLength = _itemLength(ptr); self.nextPtr = ptr + itemLength; return RLPItem(itemLength, ptr); } /* * @dev Returns true if the iteration has more elements. * @param self The iterator. * @return true if the iteration has more elements. */ function hasNext(Iterator memory self) internal pure returns (bool) { RLPItem memory item = self.item; return self.nextPtr < item.memPtr + item.len; } /* * @param item RLP encoded bytes */ function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) { uint memPtr; assembly { memPtr := add(item, 0x20) } return RLPItem(item.length, memPtr); } /* * @dev Create an iterator. Reverts if item is not a list. * @param self The RLP item. * @return An 'Iterator' over the item. */ function iterator(RLPItem memory self) internal pure returns (Iterator memory) { require(isList(self)); uint ptr = self.memPtr + _payloadOffset(self.memPtr); return Iterator(self, ptr); } /* * @param the RLP item. */ function rlpLen(RLPItem memory item) internal pure returns (uint) { return item.len; } /* * @param the RLP item. * @return (memPtr, len) pair: location of the item's payload in memory. */ function payloadLocation(RLPItem memory item) internal pure returns (uint, uint) { uint offset = _payloadOffset(item.memPtr); uint memPtr = item.memPtr + offset; uint len = item.len - offset; // data length return (memPtr, len); } /* * @param the RLP item. */ function payloadLen(RLPItem memory item) internal pure returns (uint) { (, uint len) = payloadLocation(item); return len; } /* * @param the RLP item containing the encoded list. */ function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) { require(isList(item)); uint items = numItems(item); RLPItem[] memory result = new RLPItem[](items); uint memPtr = item.memPtr + _payloadOffset(item.memPtr); uint dataLen; for (uint i = 0; i < items; i++) { dataLen = _itemLength(memPtr); result[i] = RLPItem(dataLen, memPtr); memPtr = memPtr + dataLen; } return result; } // @return indicator whether encoded payload is a list. negate this function call for isData. function isList(RLPItem memory item) internal pure returns (bool) { if (item.len == 0) return false; uint8 byte0; uint memPtr = item.memPtr; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < LIST_SHORT_START) return false; return true; } /* * @dev A cheaper version of keccak256(toRlpBytes(item)) that avoids copying memory. * @return keccak256 hash of RLP encoded bytes. */ function rlpBytesKeccak256(RLPItem memory item) internal pure returns (bytes32) { uint256 ptr = item.memPtr; uint256 len = item.len; bytes32 result; assembly { result := keccak256(ptr, len) } return result; } /* * @dev A cheaper version of keccak256(toBytes(item)) that avoids copying memory. * @return keccak256 hash of the item payload. */ function payloadKeccak256(RLPItem memory item) internal pure returns (bytes32) { (uint memPtr, uint len) = payloadLocation(item); bytes32 result; assembly { result := keccak256(memPtr, len) } return result; } /** RLPItem conversions into data types **/ // @returns raw rlp encoding in bytes function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) { bytes memory result = new bytes(item.len); if (result.length == 0) return result; uint ptr; assembly { ptr := add(0x20, result) } copy(item.memPtr, ptr, item.len); return result; } // any non-zero byte except "0x80" is considered true function toBoolean(RLPItem memory item) internal pure returns (bool) { require(item.len == 1); uint result; uint memPtr = item.memPtr; assembly { result := byte(0, mload(memPtr)) } // SEE Github Issue #5. // Summary: Most commonly used RLP libraries (i.e Geth) will encode // "0" as "0x80" instead of as "0". We handle this edge case explicitly // here. if (result == 0 || result == STRING_SHORT_START) { return false; } else { return true; } } function toAddress(RLPItem memory item) internal pure returns (address) { // 1 byte for the length prefix require(item.len == 21); return address(uint160(toUint(item))); } function toUint(RLPItem memory item) internal pure returns (uint) { require(item.len > 0 && item.len <= 33); (uint memPtr, uint len) = payloadLocation(item); uint result; assembly { result := mload(memPtr) // shfit to the correct location if neccesary if lt(len, 32) { result := div(result, exp(256, sub(32, len))) } } return result; } // enforces 32 byte length function toUintStrict(RLPItem memory item) internal pure returns (uint) { // one byte prefix require(item.len == 33); uint result; uint memPtr = item.memPtr + 1; assembly { result := mload(memPtr) } return result; } function toBytes(RLPItem memory item) internal pure returns (bytes memory) { require(item.len > 0); (uint memPtr, uint len) = payloadLocation(item); bytes memory result = new bytes(len); uint destPtr; assembly { destPtr := add(0x20, result) } copy(memPtr, destPtr, len); return result; } /* * Private Helpers */ // @return number of payload items inside an encoded list. function numItems(RLPItem memory item) private pure returns (uint) { if (item.len == 0) return 0; uint count = 0; uint currPtr = item.memPtr + _payloadOffset(item.memPtr); uint endPtr = item.memPtr + item.len; while (currPtr < endPtr) { currPtr = currPtr + _itemLength(currPtr); // skip over an item count++; } return count; } // @return entire rlp item byte length function _itemLength(uint memPtr) private pure returns (uint) { uint itemLen; uint byte0; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < STRING_SHORT_START) itemLen = 1; else if (byte0 < STRING_LONG_START) itemLen = byte0 - STRING_SHORT_START + 1; else if (byte0 < LIST_SHORT_START) { assembly { let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is memPtr := add(memPtr, 1) // skip over the first byte /* 32 byte word size */ let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len itemLen := add(dataLen, add(byteLen, 1)) } } else if (byte0 < LIST_LONG_START) { itemLen = byte0 - LIST_SHORT_START + 1; } else { assembly { let byteLen := sub(byte0, 0xf7) memPtr := add(memPtr, 1) let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length itemLen := add(dataLen, add(byteLen, 1)) } } return itemLen; } // @return number of bytes until the data function _payloadOffset(uint memPtr) private pure returns (uint) { uint byte0; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < STRING_SHORT_START) return 0; else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) return 1; else if (byte0 < LIST_SHORT_START) // being explicit return byte0 - (STRING_LONG_START - 1) + 1; else return byte0 - (LIST_LONG_START - 1) + 1; } /* * @param src Pointer to source * @param dest Pointer to destination * @param len Amount of memory to copy from the source */ function copy(uint src, uint dest, uint len) private pure { if (len == 0) return; // copy as many word sizes as possible for (; len >= WORD_SIZE; len -= WORD_SIZE) { assembly { mstore(dest, mload(src)) } src += WORD_SIZE; dest += WORD_SIZE; } if (len > 0) { // left over bytes. Mask is used to remove unwanted bytes from the word uint mask = 256 ** (WORD_SIZE - len) - 1; assembly { let srcpart := and(mload(src), not(mask)) // zero out src let destpart := and(mload(dest), mask) // retrieve the bytes mstore(dest, or(destpart, srcpart)) } } } function toBytes32(RLPItem memory self) internal pure returns (bytes32 data) { return bytes32(toUint(self)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./State.sol"; contract Setters is State { function _setInitialized(address implementation) internal { _state.initializedImplementations[implementation] = true; } function _setChainId(uint16 chainId) internal { _state.provider.chainId = chainId; } function _setTransferCompleted(bytes32 hash) internal { _state.completedTransfers[hash] = true; } function _setZKBridgeImplementation(uint16 chainId, bytes32 bridgeContract) internal { _state.zkBridgeImplementations[chainId] = bridgeContract; } function _setOwner(address owner) internal { _state.owner = owner; } function _setNextSequence(bytes32 hash, uint64 sequence) internal { _state.sequences[hash] = sequence; } function _setMptVerifier(uint16 chainId,address mptVerifier) internal { _state.mptVerifiers[chainId] = mptVerifier; } function _setBlockUpdater(uint16 chainId,address blockUpdater) internal { _state.blockUpdaters[chainId] = blockUpdater; } function _setPendingImplementation(address pendingImplementation) internal { _state.pendingImplementation = pendingImplementation; } function _setToUpdateTime(uint256 toUpdateTime) internal { _state.toUpdateTime = toUpdateTime; } function _setLockTime(uint256 lockTime) internal { _state.lockTime = lockTime; } function _setL2MessageReceive(uint16 chainId,address l2MessageReceive) internal { _state.l2MessageReceives[chainId] = l2MessageReceive; } function _setL2MessageSend(address l2MessageSend) internal { _state.l2MessageSend = l2MessageSend; } function _setL2(bool isL2) internal { _state.isL2 = isL2; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Storage { struct Provider { uint16 chainId; } struct ZKBridgeState { Provider provider; // owner address owner; //upgrade pending contract address pendingImplementation; //Upgrade confirmation time uint256 toUpdateTime; //Upgrade lock time uint256 lockTime; // Sequence numbers per emitter mapping(bytes32 => uint64) sequences; // Mapping of zkBridge contracts on other chains mapping(uint16 => bytes32) zkBridgeImplementations; // Mapping of initialized implementations mapping(address => bool) initializedImplementations; // Mapping of consumed token transfers mapping(bytes32 => bool) completedTransfers; // Mapping of mpt verifiers mapping(uint16 => address) mptVerifiers; // Mapping of block updaters mapping(uint16 => address) blockUpdaters; address l2MessageSend; bool isL2; mapping(uint16 => address) l2MessageReceives; } } contract State { Storage.ZKBridgeState _state; uint256 public constant MIN_LOCK_TIME = 1 days; }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"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":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldContract","type":"address"},{"indexed":true,"internalType":"address","name":"newContract","type":"address"}],"name":"ContractUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint16","name":"srcChainId","type":"uint16"},{"indexed":true,"internalType":"uint64","name":"sequence","type":"uint64"},{"indexed":false,"internalType":"address","name":"dstAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"payload","type":"bytes"}],"name":"ExecutedMessage","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint16","name":"dstChainId","type":"uint16"},{"indexed":true,"internalType":"uint64","name":"sequence","type":"uint64"},{"indexed":false,"internalType":"address","name":"dstAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"payload","type":"bytes"}],"name":"MessagePublished","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingImplementation","type":"address"},{"indexed":true,"internalType":"address","name":"newImplementation","type":"address"}],"name":"NewPendingImplementation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"MESSAGE_TOPIC","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_LOCK_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId","type":"uint16"}],"name":"blockUpdater","outputs":[{"internalType":"contract IBlockUpdater","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainId","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"confirmContractUpgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"impl","type":"address"}],"name":"isInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isL2","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"isTransferCompleted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId","type":"uint16"}],"name":"l2MessageReceive","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"l2MessageSend","outputs":[{"internalType":"contract IL2MessageSend","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId","type":"uint16"}],"name":"mptVerifier","outputs":[{"internalType":"contract IMptVerifier","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"nextSequence","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":"pendingImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"bridgeContract","type":"bytes32"}],"name":"registerChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"dstChainId","type":"uint16"},{"internalType":"address","name":"dstAddress","type":"address"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"send","outputs":[{"internalType":"uint64","name":"sequence","type":"uint64"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"srcChainId","type":"uint16"},{"internalType":"uint16","name":"dstChainId","type":"uint16"},{"internalType":"address","name":"dstAddress","type":"address"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"sendFromL2","outputs":[{"internalType":"uint64","name":"sequence","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"address","name":"blockUpdater","type":"address"}],"name":"setBlockUpdater","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isL2","type":"bool"}],"name":"setL2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"address","name":"l2MessageReceive","type":"address"}],"name":"setL2MessageReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"l2MessageSend","type":"address"}],"name":"setL2MessageSend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"lockTime","type":"uint256"}],"name":"setLockTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"address","name":"mptVerifier","type":"address"}],"name":"setMptVerifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"submitContractUpgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"srcChainId","type":"uint16"},{"internalType":"address","name":"srcAddress","type":"address"},{"internalType":"address","name":"dstAddress","type":"address"},{"internalType":"uint64","name":"sequence","type":"uint64"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"validateTransactionFromL2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"srcChainId","type":"uint16"},{"internalType":"bytes32","name":"srcBlockHash","type":"bytes32"},{"internalType":"uint256","name":"logIndex","type":"uint256"},{"internalType":"bytes","name":"mptProof","type":"bytes"}],"name":"validateTransactionProof","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId","type":"uint16"}],"name":"zkBridgeContracts","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
608060405234801561001057600080fd5b506131d1806100206000396000f3fe6080604052600436106101dc5760003560e01c806376348f7111610102578063ae04d45d11610095578063d294f09311610064578063d294f09314610664578063d60b347f14610679578063d98465c3146106b2578063fe2db7d0146106d257610243565b8063ae04d45d146105e6578063b1d995dd14610606578063bd51f42e14610619578063d1dc83c21461064f57610243565b80638da5cb5b116100d15780638da5cb5b146105605780639a8a05921461057e5780639f0a22a6146105a1578063aa4efa5b146105b657610243565b806376348f71146104e05780637cf5744f1461050b5780638129fc1c1461052b578063813d31c91461054057610243565b80633ff032071161017a5780635af466aa116101495780635af466aa1461041457806365bb3ea71461044c57806366798c2c1461046c5780636b83252a146104a657610243565b80633ff032071461039d57806348a29593146103b45780634f64ca19146103d457806350520509146103f457610243565b806336ae03d8116101b657806336ae03d8146102f1578063396f7b231461032b5780633a552757146103495780633fe3da361461036957610243565b80630232c006146102795780630d668087146102b057806324ee48e9146102cf57610243565b366102435760405162461bcd60e51b815260206004820152602c60248201527f746865205a6b42726964676520636f6e747261637420646f6573206e6f74206160448201526b63636570742061737365747360a01b60648201526084015b60405180910390fd5b60405162461bcd60e51b815260206004820152600b60248201526a1d5b9cdd5c1c1bdc9d195960aa1b604482015260640161023a565b34801561028557600080fd5b50600b546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102bc57600080fd5b506004545b6040519081526020016102a7565b3480156102db57600080fd5b506102ef6102ea3660046127d5565b610703565b005b3480156102fd57600080fd5b5061029361030c366004612890565b61ffff166000908152600c60205260409020546001600160a01b031690565b34801561033757600080fd5b506002546001600160a01b0316610293565b34801561035557600080fd5b506102ef6103643660046128ad565b610995565b34801561037557600080fd5b506102c17fb8abfd5c33667c7440a4fc1153ae39a24833dbe44f7eb19cbe5cd5f2583e494081565b3480156103a957600080fd5b506102c16201518081565b3480156103c057600080fd5b506102ef6103cf3660046128ad565b610aa2565b3480156103e057600080fd5b506102ef6103ef36600461298d565b610afc565b34801561040057600080fd5b506102ef61040f3660046129fd565b611159565b34801561042057600080fd5b5061043461042f366004612a1a565b6111ac565b6040516001600160401b0390911681526020016102a7565b34801561045857600080fd5b506102ef610467366004612a76565b6112b2565b34801561047857600080fd5b50610293610487366004612890565b61ffff166000908152600a60205260409020546001600160a01b031690565b3480156104b257600080fd5b506102936104c1366004612890565b61ffff166000908152600960205260409020546001600160a01b031690565b3480156104ec57600080fd5b50600b54600160a01b900460ff165b60405190151581526020016102a7565b34801561051757600080fd5b506102ef610526366004612aa2565b611303565b34801561053757600080fd5b506102ef61136c565b34801561054c57600080fd5b506102ef61055b366004612aa2565b61142e565b34801561056c57600080fd5b506001546001600160a01b0316610293565b34801561058a57600080fd5b5060005460405161ffff90911681526020016102a7565b3480156105ad57600080fd5b506003546102c1565b3480156105c257600080fd5b506104fb6105d1366004612adb565b60009081526008602052604090205460ff1690565b3480156105f257600080fd5b506102ef610601366004612adb565b611497565b610434610614366004612af4565b61152c565b34801561062557600080fd5b50610434610634366004612adb565b6000908152600560205260409020546001600160401b031690565b34801561065b57600080fd5b506102ef61172d565b34801561067057600080fd5b506102ef611961565b34801561068557600080fd5b506104fb6106943660046128ad565b6001600160a01b031660009081526007602052604090205460ff1690565b3480156106be57600080fd5b506102ef6106cd366004612aa2565b6119d3565b3480156106de57600080fd5b506102c16106ed366004612890565b61ffff1660009081526006602052604090205490565b61ffff86166000908152600c60205260409020546001600160a01b0316331461073e5760405162461bcd60e51b815260040161023a90612b55565b60008061078084848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a3c92505050565b91509150806107c75760405162461bcd60e51b81526020600482015260136024820152722ab739bab83837b93a32b2103b32b939b4b7b760691b604482015260640161023a565b815161ffff8981169116146108135760405162461bcd60e51b8152602060048201526012602482015271125b9d985b1a59081cdc98d0da185a5b925960721b604482015260640161023a565b60005461ffff1661ffff16826020015161ffff16146108445760405162461bcd60e51b815260040161023a90612b97565b6040805161ffff8a1660208201526001600160a01b038916918101919091526001600160401b03861660608201526000906080016040516020818303038152906040528051906020012090506108a98160009081526008602052604090205460ff1690565b156108c65760405162461bcd60e51b815260040161023a90612bce565b6108cf81611b82565b60a08301516040516316f4ca9560e11b81526001600160a01b03891691632de9952a91610904918d918d918c91600401612c61565b600060405180830381600087803b15801561091e57600080fd5b505af1158015610932573d6000803e3d6000fd5b50505050856001600160401b03168961ffff16896001600160a01b03167f4a008ac830958ba6fe8a6e667e2ab53a530eb6cdf93e55b27fc42d7a54cf25b78a898960405161098293929190612ca8565b60405180910390a4505050505050505050565b336109a86001546001600160a01b031690565b6001600160a01b0316146109ce5760405162461bcd60e51b815260040161023a90612ce8565b6001600160a01b038116610a245760405162461bcd60e51b815260206004820152601b60248201527f436865636b2070656e64696e67496d706c656d656e746174696f6e0000000000604482015260640161023a565b6000610a386002546001600160a01b031690565b9050610a4382611b9d565b610a5e610a4f60045490565b610a599042612d33565b600355565b816001600160a01b0316816001600160a01b03167fe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d81560405160405180910390a35050565b33610ab56001546001600160a01b031690565b6001600160a01b031614610adb5760405162461bcd60e51b815260040161023a90612ce8565b600b80546001600160a01b0319166001600160a01b03831617905550565b50565b61ffff8416600090815260096020908152604080832054600a909252909120546001600160a01b03918216911681610b6f5760405162461bcd60e51b8152602060048201526016602482015275135c1d15995c9a599a595c881a5cc81b9bdd081cd95d60521b604482015260640161023a565b6001600160a01b038116610bc55760405162461bcd60e51b815260206004820152601860248201527f426c6f636b2055706461746572206973206e6f74207365740000000000000000604482015260640161023a565b60405163057d916d60e11b81526000906001600160a01b03841690630afb22da90610bf4908790600401612d4b565b600060405180830381865afa158015610c11573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c399190810190612da3565b90508060200151600114610c8f5760405162461bcd60e51b815260206004820181905260248201527f536f7572636520436861696e205472616e73616374696f6e204661696c757265604482015260640161023a565b8051604051636e1ac47560e11b81526001600160a01b0384169163dc3588ea91610cc6918a91600401918252602082015260400190565b602060405180830381865afa158015610ce3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d079190612e3b565b610d535760405162461bcd60e51b815260206004820152601760248201527f426c6f636b20486561646572206973206e6f7420736574000000000000000000604482015260640161023a565b6000610d63826040015187611bbf565b9050610d7f8861ffff1660009081526006602052604090205490565b816080015114610dd15760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420736f75726365205a4b427269646765000000000000000000604482015260640161023a565b600054815161ffff908116911614610dfb5760405162461bcd60e51b815260040161023a90612b97565b60008882606001518360200151604051602001610e3a9392919061ffff93909316835260208301919091526001600160401b0316604082015260600190565b604051602081830303815290604052805190602001209050610e6b8160009081526008602052604090205460ff1690565b15610e885760405162461bcd60e51b815260040161023a90612bce565b610e9181611b82565b81602001516001600160401b03168961ffff16610eb18460600151611e1b565b6001600160a01b03167f4a008ac830958ba6fe8a6e667e2ab53a530eb6cdf93e55b27fc42d7a54cf25b785604001518660a00151604051610ef3929190612e58565b60405180910390a4600080610f0b8460a00151611a3c565b9150915080156110cf578a61ffff16826000015161ffff16146110535760005461ffff1661ffff16826020015161ffff1614610f595760405162461bcd60e51b815260040161023a90612b97565b8151604080840151608080860151835161ffff90951660208601526001600160a01b03909216928401929092526001600160401b0316606083015201604051602081830303815290604052805190602001209250610fc68360009081526008602052604090205460ff1690565b15610fe35760405162461bcd60e51b815260040161023a90612bce565b610fec83611b82565b81608001516001600160401b0316826000015161ffff1683604001516001600160a01b03167f4a008ac830958ba6fe8a6e667e2ab53a530eb6cdf93e55b27fc42d7a54cf25b785606001518660a0015160405161104a929190612e58565b60405180910390a45b60608201518251604080850151608086015160a087015192516316f4ca9560e11b81526001600160a01b0390951694632de9952a946110989490939291600401612c61565b600060405180830381600087803b1580156110b257600080fd5b505af11580156110c6573d6000803e3d6000fd5b5050505061114c565b83604001516001600160a01b0316632de9952a8c6110f08760600151611e1b565b87602001518860a001516040518563ffffffff1660e01b81526004016111199493929190612c61565b600060405180830381600087803b15801561113357600080fd5b505af1158015611147573d6000803e3d6000fd5b505050505b5050505050505050505050565b3361116c6001546001600160a01b031690565b6001600160a01b0316146111925760405162461bcd60e51b815260040161023a90612ce8565b600b805460ff60a01b1916600160a01b8315150217905550565b61ffff84166000908152600c60205260408120546001600160a01b031633146111e75760405162461bcd60e51b815260040161023a90612b55565b60005461ffff1661ffff168461ffff16036112405760405162461bcd60e51b815260206004820152601960248201527821b0b73737ba1039b2b732103a379039b0b6b29031b430b4b760391b604482015260640161023a565b61125661125060005461ffff1690565b33611e6f565b9050806001600160401b03168461ffff16336001600160a01b03167fb8abfd5c33667c7440a4fc1153ae39a24833dbe44f7eb19cbe5cd5f2583e494086866040516112a2929190612e58565b60405180910390a4949350505050565b336112c56001546001600160a01b031690565b6001600160a01b0316146112eb5760405162461bcd60e51b815260040161023a90612ce8565b61ffff91909116600090815260066020526040902055565b336113166001546001600160a01b031690565b6001600160a01b03161461133c5760405162461bcd60e51b815260040161023a90612ce8565b61ffff8216600090815260096020526040902080546001600160a01b0319166001600160a01b0383161790555050565b600061139f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b90506113c3816001600160a01b031660009081526007602052604090205460ff1690565b156114065760405162461bcd60e51b8152602060048201526013602482015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015260640161023a565b610af9816001600160a01b03166000908152600760205260409020805460ff19166001179055565b336114416001546001600160a01b031690565b6001600160a01b0316146114675760405162461bcd60e51b815260040161023a90612ce8565b61ffff82166000908152600a6020526040902080546001600160a01b0319166001600160a01b0383161790555050565b336114aa6001546001600160a01b031690565b6001600160a01b0316146114d05760405162461bcd60e51b815260040161023a90612ce8565b620151808110156115235760405162461bcd60e51b815260206004820152601b60248201527f496e636f7272656374206c6f636b54696d652073657474696e67730000000000604482015260640161023a565b610af981600455565b6000805461ffff1661ffff168461ffff16036115865760405162461bcd60e51b815260206004820152601960248201527821b0b73737ba1039b2b732103a379039b0b6b29031b430b4b760391b604482015260640161023a565b61159661125060005461ffff1690565b9050722d25a13934b233b2903b19103b32b939b4b7b760691b6115bc60005461ffff1690565b85338685876040516020016115d79796959493929190612e7c565b60405160208183030381529060405291506115fc600b5460ff600160a01b9091041690565b156116d457600b546001600160a01b031663ccbf1a2c816001600160a01b031663ced72f876040518163ffffffff1660e01b8152600401602060405180830381865afa158015611650573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116749190612efe565b60005461ffff1633888887896040518863ffffffff1660e01b81526004016116a196959493929190612f17565b6000604051808303818588803b1580156116ba57600080fd5b505af11580156116ce573d6000803e3d6000fd5b50505050505b806001600160401b03168461ffff16336001600160a01b03167fb8abfd5c33667c7440a4fc1153ae39a24833dbe44f7eb19cbe5cd5f2583e4940868660405161171e929190612e58565b60405180910390a49392505050565b336117406001546001600160a01b031690565b6001600160a01b0316146117665760405162461bcd60e51b815260040161023a90612ce8565b600061177a6002546001600160a01b031690565b6001600160a01b0316036117d05760405162461bcd60e51b815260206004820152601b60248201527f436865636b2070656e64696e67496d706c656d656e746174696f6e0000000000604482015260640161023a565b6003544210156118145760405162461bcd60e51b815260206004820152600f60248201526e29ba34b636103637b1b5b2b21034b760891b604482015260640161023a565b60006118477f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b9050600061185d6002546001600160a01b031690565b90506118696000611b9d565b61187281611f14565b60408051600481526024810182526020810180516001600160e01b031663204a7f0760e21b179052905160009182916001600160a01b038516916118b591612f71565b600060405180830381855af49150503d80600081146118f0576040519150601f19603f3d011682016040523d82523d6000602084013e6118f5565b606091505b509150915081819061191a5760405162461bcd60e51b815260040161023a9190612d4b565b50826001600160a01b0316846001600160a01b03167f2e4cc16c100f0b55e2df82ab0b1a7e294aa9cbd01b48fbaf622683fbc0507a4960405160405180910390a350505050565b336119746001546001600160a01b031690565b6001600160a01b03161461199a5760405162461bcd60e51b815260040161023a90612ce8565b6001546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015610af9573d6000803e3d6000fd5b336119e66001546001600160a01b031690565b6001600160a01b031614611a0c5760405162461bcd60e51b815260040161023a90612ce8565b61ffff82166000908152600c6020526040902080546001600160a01b0319166001600160a01b0383161790555050565b6040805160c08101825260008082526020820181905291810182905260608082018390526080820183905260a0820152908080611a798582611f54565b9050722d25a13934b233b2903b19103b32b939b4b7b760691b8114611a9f575050915091565b611aaa602083612d33565b9150611ab68583611fb8565b61ffff168452611ac7600283612d33565b9150611ad38583611fb8565b61ffff166020850152611ae7600283612d33565b9150611af38583612015565b6001600160a01b03166040850152611b0c601483612d33565b9150611b188583612015565b6001600160a01b03166060850152611b31601483612d33565b9150611b3d858361207a565b6001600160401b03166080850152611b56600883612d33565b9150611b7182838751611b699190612f8d565b8791906120d7565b60a085015250919360019350915050565b6000908152600860205260409020805460ff19166001179055565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6040805160c0810182526000808252602080830182905282840182905260608084018390526080840183905260a0840152835180850185528281528101829052835180850190945285518452858101908401529091611c22906121e4565b6121e4565b90508215611c8c57611c89611c1d611c5c83611c3f876002612d33565b81518110611c4f57611c4f612fa4565b60200260200101516122f9565b60408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b90505b6000611caa611c1d611c5c84600181518110611c4f57611c4f612fa4565b90506000611cd182600081518110611cc457611cc4612fa4565b6020026020010151612370565b806020019051810190611ce49190612efe565b90507f475402a3cc99838bbf5b03eeac51c65db7cc241bb0814e6341a32a0da7c1b6c08101611e1257611d3083600081518110611d2357611d23612fa4565b60200260200101516123e4565b60808501528151611d4e9083906001908110611cc457611cc4612fa4565b806020019051810190611d619190612efe565b60608501528151611d7f9083906002908110611cc457611cc4612fa4565b806020019051810190611d929190612fba565b61ffff1684528151611db19083906003908110611cc457611cc4612fa4565b806020019051810190611dc49190612fd7565b6001600160401b031660208501528251611deb9084906002908110611cc457611cc4612fa4565b806020019051810190611dfe9190612ff4565b60a08601526001600160a01b031660408501525b50505092915050565b60006001600160a01b0319821615611e6b5760405162461bcd60e51b8152602060048201526013602482015272696e76616c69642045564d206164647265737360681b604482015260640161023a565b5090565b6040805161ffff841660208201526001600160a01b038316918101919091526000908190606001604051602081830303815290604052805190602001209050611ecd816000908152600560205260409020546001600160401b031690565b9150611f0d81611ede846001613044565b600091825260056020526040909120805467ffffffffffffffff19166001600160401b03909216919091179055565b5092915050565b611f1d816123ef565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6000611f61826020612d33565b83511015611fa95760405162461bcd60e51b8152602060048201526015602482015274746f427974657333325f6f75744f66426f756e647360581b604482015260640161023a565b50818101602001515b92915050565b6000611fc5826002612d33565b8351101561200c5760405162461bcd60e51b8152602060048201526014602482015273746f55696e7431365f6f75744f66426f756e647360601b604482015260640161023a565b50016002015190565b6000612022826014612d33565b8351101561206a5760405162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b604482015260640161023a565b500160200151600160601b900490565b6000612087826008612d33565b835110156120ce5760405162461bcd60e51b8152602060048201526014602482015273746f55696e7436345f6f75744f66426f756e647360601b604482015260640161023a565b50016008015190565b6060816120e581601f612d33565b10156121245760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b604482015260640161023a565b61212e8284612d33565b845110156121725760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b604482015260640161023a565b60608215801561219157604051915060008252602082016040526121db565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156121ca5780518352602092830192016121b2565b5050858452601f01601f1916604052505b50949350505050565b60606121ef8261249d565b6121f857600080fd5b6000612203836124d8565b90506000816001600160401b0381111561221f5761221f6128ca565b60405190808252806020026020018201604052801561226457816020015b604080518082019091526000808252602082015281526020019060019003908161223d5790505b5090506000612276856020015161255d565b85602001516122859190612d33565b90506000805b848110156122ee5761229c836125df565b91506040518060400160405280838152602001848152508482815181106122c5576122c5612fa4565b60209081029190910101526122da8284612d33565b9250806122e68161306f565b91505061228b565b509195945050505050565b6060600082600001516001600160401b03811115612319576123196128ca565b6040519080825280601f01601f191660200182016040528015612343576020820181803683370190505b50905080516000036123555792915050565b6000816020019050611f0d8460200151828660000151612683565b805160609061237e57600080fd5b60008061238a84612706565b915091506000816001600160401b038111156123a8576123a86128ca565b6040519080825280601f01601f1916602001820160405280156123d2576020820181803683370190505b509050602081016121db848285612683565b6000611fb28261274d565b6001600160a01b0381163b61245c5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161023a565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b805160009081036124b057506000919050565b6020820151805160001a9060c08210156124ce575060009392505050565b5060019392505050565b805160009081036124eb57506000919050565b6000806124fb846020015161255d565b846020015161250a9190612d33565b90506000846000015185602001516125229190612d33565b90505b8082101561255457612536826125df565b6125409083612d33565b91508261254c8161306f565b935050612525565b50909392505050565b8051600090811a60808110156125765750600092915050565b60b8811080612591575060c08110801590612591575060f881105b1561259f5750600192915050565b60c08110156125d3576125b4600160b8613088565b6125c19060ff1682612f8d565b6125cc906001612d33565b9392505050565b6125b4600160f8613088565b80516000908190811a60808110156125fa5760019150611f0d565b60b88110156126205761260e608082612f8d565b612619906001612d33565b9150611f0d565b60c081101561264d5760b78103600185019450806020036101000a85510460018201810193505050611f0d565b60f88110156126615761260e60c082612f8d565b60019390930151602084900360f7016101000a900490920160f5190192915050565b8060000361269057505050565b602081106126c857825182526126a7602084612d33565b92506126b4602083612d33565b91506126c1602082612f8d565b9050612690565b801561270157600060016126dd836020612f8d565b6126e99061010061318f565b6126f39190612f8d565b845184518216911916178352505b505050565b6000806000612718846020015161255d565b9050600081856020015161272c9190612d33565b905060008286600001516127409190612f8d565b9196919550909350505050565b80516000901580159061276257508151602110155b61276b57600080fd5b60008061277784612706565b8151919350915060208210156127935760208290036101000a90045b949350505050565b61ffff81168114610af957600080fd5b6001600160a01b0381168114610af957600080fd5b6001600160401b0381168114610af957600080fd5b60008060008060008060a087890312156127ee57600080fd5b86356127f98161279b565b95506020870135612809816127ab565b94506040870135612819816127ab565b93506060870135612829816127c0565b925060808701356001600160401b038082111561284557600080fd5b818901915089601f83011261285957600080fd5b81358181111561286857600080fd5b8a602082850101111561287a57600080fd5b6020830194508093505050509295509295509295565b6000602082840312156128a257600080fd5b81356125cc8161279b565b6000602082840312156128bf57600080fd5b81356125cc816127ab565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715612908576129086128ca565b604052919050565b60006001600160401b03821115612929576129296128ca565b50601f01601f191660200190565b600082601f83011261294857600080fd5b813561295b61295682612910565b6128e0565b81815284602083860101111561297057600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080608085870312156129a357600080fd5b84356129ae8161279b565b9350602085013592506040850135915060608501356001600160401b038111156129d757600080fd5b6129e387828801612937565b91505092959194509250565b8015158114610af957600080fd5b600060208284031215612a0f57600080fd5b81356125cc816129ef565b60008060008060808587031215612a3057600080fd5b8435612a3b8161279b565b93506020850135612a4b8161279b565b92506040850135612a5b816127ab565b915060608501356001600160401b038111156129d757600080fd5b60008060408385031215612a8957600080fd5b8235612a948161279b565b946020939093013593505050565b60008060408385031215612ab557600080fd5b8235612ac08161279b565b91506020830135612ad0816127ab565b809150509250929050565b600060208284031215612aed57600080fd5b5035919050565b600080600060608486031215612b0957600080fd5b8335612b148161279b565b92506020840135612b24816127ab565b915060408401356001600160401b03811115612b3f57600080fd5b612b4b86828701612937565b9150509250925092565b60208082526022908201527f63616c6c6572206973206e6f7420746865206c324d6573736167655265636569604082015261766560f01b606082015260800190565b60208082526019908201527f496e76616c69642064657374696e6174696f6e20636861696e00000000000000604082015260600190565b60208082526019908201527f4d65737361676520616c72656164792065786563757465642e00000000000000604082015260600190565b60005b83811015612c20578181015183820152602001612c08565b83811115612c2f576000848401525b50505050565b60008151808452612c4d816020860160208601612c05565b601f01601f19169290920160200192915050565b61ffff851681526001600160a01b03841660208201526001600160401b0383166040820152608060608201819052600090612c9e90830184612c35565b9695505050505050565b6001600160a01b03841681526040602082018190528101829052818360608301376000818301606090810191909152601f909201601f1916010192915050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052601160045260246000fd5b60008219821115612d4657612d46612d1d565b500190565b6020815260006125cc6020830184612c35565b600082601f830112612d6f57600080fd5b8151612d7d61295682612910565b818152846020838601011115612d9257600080fd5b612793826020830160208701612c05565b600060208284031215612db557600080fd5b81516001600160401b0380821115612dcc57600080fd5b9083019060608286031215612de057600080fd5b604051606081018181108382111715612dfb57612dfb6128ca565b80604052508251815260208301516020820152604083015182811115612e2057600080fd5b612e2c87828601612d5e565b60408301525095945050505050565b600060208284031215612e4d57600080fd5b81516125cc816129ef565b6001600160a01b038316815260406020820181905260009061279390830184612c35565b878152600061ffff60f01b808960f01b166020840152808860f01b166022840152506bffffffffffffffffffffffff19808760601b166024840152808660601b166038840152506001600160401b0360c01b8460c01b16604c8301528251612eeb816054850160208701612c05565b9190910160540198975050505050505050565b600060208284031215612f1057600080fd5b5051919050565b61ffff87811682526001600160a01b0387811660208401529086166040830152841660608201526001600160401b038316608082015260c060a08201819052600090612f6590830184612c35565b98975050505050505050565b60008251612f83818460208701612c05565b9190910192915050565b600082821015612f9f57612f9f612d1d565b500390565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612fcc57600080fd5b81516125cc8161279b565b600060208284031215612fe957600080fd5b81516125cc816127c0565b6000806040838503121561300757600080fd5b8251613012816127ab565b60208401519092506001600160401b0381111561302e57600080fd5b61303a85828601612d5e565b9150509250929050565b60006001600160401b0380831681851680830382111561306657613066612d1d565b01949350505050565b60006001820161308157613081612d1d565b5060010190565b600060ff821660ff8416808210156130a2576130a2612d1d565b90039392505050565b600181815b808511156130e65781600019048211156130cc576130cc612d1d565b808516156130d957918102915b93841c93908002906130b0565b509250929050565b6000826130fd57506001611fb2565b8161310a57506000611fb2565b8160018114613120576002811461312a57613146565b6001915050611fb2565b60ff84111561313b5761313b612d1d565b50506001821b611fb2565b5060208310610133831016604e8410600b8410161715613169575081810a611fb2565b61317383836130ab565b806000190482111561318757613187612d1d565b029392505050565b60006125cc83836130ee56fea2646970667358221220aa0c3d00c085950339cd9e06fad3fb30056749ebb9092a0e564a806f20e3f6f864736f6c634300080e0033
Deployed Bytecode
0x6080604052600436106101dc5760003560e01c806376348f7111610102578063ae04d45d11610095578063d294f09311610064578063d294f09314610664578063d60b347f14610679578063d98465c3146106b2578063fe2db7d0146106d257610243565b8063ae04d45d146105e6578063b1d995dd14610606578063bd51f42e14610619578063d1dc83c21461064f57610243565b80638da5cb5b116100d15780638da5cb5b146105605780639a8a05921461057e5780639f0a22a6146105a1578063aa4efa5b146105b657610243565b806376348f71146104e05780637cf5744f1461050b5780638129fc1c1461052b578063813d31c91461054057610243565b80633ff032071161017a5780635af466aa116101495780635af466aa1461041457806365bb3ea71461044c57806366798c2c1461046c5780636b83252a146104a657610243565b80633ff032071461039d57806348a29593146103b45780634f64ca19146103d457806350520509146103f457610243565b806336ae03d8116101b657806336ae03d8146102f1578063396f7b231461032b5780633a552757146103495780633fe3da361461036957610243565b80630232c006146102795780630d668087146102b057806324ee48e9146102cf57610243565b366102435760405162461bcd60e51b815260206004820152602c60248201527f746865205a6b42726964676520636f6e747261637420646f6573206e6f74206160448201526b63636570742061737365747360a01b60648201526084015b60405180910390fd5b60405162461bcd60e51b815260206004820152600b60248201526a1d5b9cdd5c1c1bdc9d195960aa1b604482015260640161023a565b34801561028557600080fd5b50600b546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102bc57600080fd5b506004545b6040519081526020016102a7565b3480156102db57600080fd5b506102ef6102ea3660046127d5565b610703565b005b3480156102fd57600080fd5b5061029361030c366004612890565b61ffff166000908152600c60205260409020546001600160a01b031690565b34801561033757600080fd5b506002546001600160a01b0316610293565b34801561035557600080fd5b506102ef6103643660046128ad565b610995565b34801561037557600080fd5b506102c17fb8abfd5c33667c7440a4fc1153ae39a24833dbe44f7eb19cbe5cd5f2583e494081565b3480156103a957600080fd5b506102c16201518081565b3480156103c057600080fd5b506102ef6103cf3660046128ad565b610aa2565b3480156103e057600080fd5b506102ef6103ef36600461298d565b610afc565b34801561040057600080fd5b506102ef61040f3660046129fd565b611159565b34801561042057600080fd5b5061043461042f366004612a1a565b6111ac565b6040516001600160401b0390911681526020016102a7565b34801561045857600080fd5b506102ef610467366004612a76565b6112b2565b34801561047857600080fd5b50610293610487366004612890565b61ffff166000908152600a60205260409020546001600160a01b031690565b3480156104b257600080fd5b506102936104c1366004612890565b61ffff166000908152600960205260409020546001600160a01b031690565b3480156104ec57600080fd5b50600b54600160a01b900460ff165b60405190151581526020016102a7565b34801561051757600080fd5b506102ef610526366004612aa2565b611303565b34801561053757600080fd5b506102ef61136c565b34801561054c57600080fd5b506102ef61055b366004612aa2565b61142e565b34801561056c57600080fd5b506001546001600160a01b0316610293565b34801561058a57600080fd5b5060005460405161ffff90911681526020016102a7565b3480156105ad57600080fd5b506003546102c1565b3480156105c257600080fd5b506104fb6105d1366004612adb565b60009081526008602052604090205460ff1690565b3480156105f257600080fd5b506102ef610601366004612adb565b611497565b610434610614366004612af4565b61152c565b34801561062557600080fd5b50610434610634366004612adb565b6000908152600560205260409020546001600160401b031690565b34801561065b57600080fd5b506102ef61172d565b34801561067057600080fd5b506102ef611961565b34801561068557600080fd5b506104fb6106943660046128ad565b6001600160a01b031660009081526007602052604090205460ff1690565b3480156106be57600080fd5b506102ef6106cd366004612aa2565b6119d3565b3480156106de57600080fd5b506102c16106ed366004612890565b61ffff1660009081526006602052604090205490565b61ffff86166000908152600c60205260409020546001600160a01b0316331461073e5760405162461bcd60e51b815260040161023a90612b55565b60008061078084848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a3c92505050565b91509150806107c75760405162461bcd60e51b81526020600482015260136024820152722ab739bab83837b93a32b2103b32b939b4b7b760691b604482015260640161023a565b815161ffff8981169116146108135760405162461bcd60e51b8152602060048201526012602482015271125b9d985b1a59081cdc98d0da185a5b925960721b604482015260640161023a565b60005461ffff1661ffff16826020015161ffff16146108445760405162461bcd60e51b815260040161023a90612b97565b6040805161ffff8a1660208201526001600160a01b038916918101919091526001600160401b03861660608201526000906080016040516020818303038152906040528051906020012090506108a98160009081526008602052604090205460ff1690565b156108c65760405162461bcd60e51b815260040161023a90612bce565b6108cf81611b82565b60a08301516040516316f4ca9560e11b81526001600160a01b03891691632de9952a91610904918d918d918c91600401612c61565b600060405180830381600087803b15801561091e57600080fd5b505af1158015610932573d6000803e3d6000fd5b50505050856001600160401b03168961ffff16896001600160a01b03167f4a008ac830958ba6fe8a6e667e2ab53a530eb6cdf93e55b27fc42d7a54cf25b78a898960405161098293929190612ca8565b60405180910390a4505050505050505050565b336109a86001546001600160a01b031690565b6001600160a01b0316146109ce5760405162461bcd60e51b815260040161023a90612ce8565b6001600160a01b038116610a245760405162461bcd60e51b815260206004820152601b60248201527f436865636b2070656e64696e67496d706c656d656e746174696f6e0000000000604482015260640161023a565b6000610a386002546001600160a01b031690565b9050610a4382611b9d565b610a5e610a4f60045490565b610a599042612d33565b600355565b816001600160a01b0316816001600160a01b03167fe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d81560405160405180910390a35050565b33610ab56001546001600160a01b031690565b6001600160a01b031614610adb5760405162461bcd60e51b815260040161023a90612ce8565b600b80546001600160a01b0319166001600160a01b03831617905550565b50565b61ffff8416600090815260096020908152604080832054600a909252909120546001600160a01b03918216911681610b6f5760405162461bcd60e51b8152602060048201526016602482015275135c1d15995c9a599a595c881a5cc81b9bdd081cd95d60521b604482015260640161023a565b6001600160a01b038116610bc55760405162461bcd60e51b815260206004820152601860248201527f426c6f636b2055706461746572206973206e6f74207365740000000000000000604482015260640161023a565b60405163057d916d60e11b81526000906001600160a01b03841690630afb22da90610bf4908790600401612d4b565b600060405180830381865afa158015610c11573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c399190810190612da3565b90508060200151600114610c8f5760405162461bcd60e51b815260206004820181905260248201527f536f7572636520436861696e205472616e73616374696f6e204661696c757265604482015260640161023a565b8051604051636e1ac47560e11b81526001600160a01b0384169163dc3588ea91610cc6918a91600401918252602082015260400190565b602060405180830381865afa158015610ce3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d079190612e3b565b610d535760405162461bcd60e51b815260206004820152601760248201527f426c6f636b20486561646572206973206e6f7420736574000000000000000000604482015260640161023a565b6000610d63826040015187611bbf565b9050610d7f8861ffff1660009081526006602052604090205490565b816080015114610dd15760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420736f75726365205a4b427269646765000000000000000000604482015260640161023a565b600054815161ffff908116911614610dfb5760405162461bcd60e51b815260040161023a90612b97565b60008882606001518360200151604051602001610e3a9392919061ffff93909316835260208301919091526001600160401b0316604082015260600190565b604051602081830303815290604052805190602001209050610e6b8160009081526008602052604090205460ff1690565b15610e885760405162461bcd60e51b815260040161023a90612bce565b610e9181611b82565b81602001516001600160401b03168961ffff16610eb18460600151611e1b565b6001600160a01b03167f4a008ac830958ba6fe8a6e667e2ab53a530eb6cdf93e55b27fc42d7a54cf25b785604001518660a00151604051610ef3929190612e58565b60405180910390a4600080610f0b8460a00151611a3c565b9150915080156110cf578a61ffff16826000015161ffff16146110535760005461ffff1661ffff16826020015161ffff1614610f595760405162461bcd60e51b815260040161023a90612b97565b8151604080840151608080860151835161ffff90951660208601526001600160a01b03909216928401929092526001600160401b0316606083015201604051602081830303815290604052805190602001209250610fc68360009081526008602052604090205460ff1690565b15610fe35760405162461bcd60e51b815260040161023a90612bce565b610fec83611b82565b81608001516001600160401b0316826000015161ffff1683604001516001600160a01b03167f4a008ac830958ba6fe8a6e667e2ab53a530eb6cdf93e55b27fc42d7a54cf25b785606001518660a0015160405161104a929190612e58565b60405180910390a45b60608201518251604080850151608086015160a087015192516316f4ca9560e11b81526001600160a01b0390951694632de9952a946110989490939291600401612c61565b600060405180830381600087803b1580156110b257600080fd5b505af11580156110c6573d6000803e3d6000fd5b5050505061114c565b83604001516001600160a01b0316632de9952a8c6110f08760600151611e1b565b87602001518860a001516040518563ffffffff1660e01b81526004016111199493929190612c61565b600060405180830381600087803b15801561113357600080fd5b505af1158015611147573d6000803e3d6000fd5b505050505b5050505050505050505050565b3361116c6001546001600160a01b031690565b6001600160a01b0316146111925760405162461bcd60e51b815260040161023a90612ce8565b600b805460ff60a01b1916600160a01b8315150217905550565b61ffff84166000908152600c60205260408120546001600160a01b031633146111e75760405162461bcd60e51b815260040161023a90612b55565b60005461ffff1661ffff168461ffff16036112405760405162461bcd60e51b815260206004820152601960248201527821b0b73737ba1039b2b732103a379039b0b6b29031b430b4b760391b604482015260640161023a565b61125661125060005461ffff1690565b33611e6f565b9050806001600160401b03168461ffff16336001600160a01b03167fb8abfd5c33667c7440a4fc1153ae39a24833dbe44f7eb19cbe5cd5f2583e494086866040516112a2929190612e58565b60405180910390a4949350505050565b336112c56001546001600160a01b031690565b6001600160a01b0316146112eb5760405162461bcd60e51b815260040161023a90612ce8565b61ffff91909116600090815260066020526040902055565b336113166001546001600160a01b031690565b6001600160a01b03161461133c5760405162461bcd60e51b815260040161023a90612ce8565b61ffff8216600090815260096020526040902080546001600160a01b0319166001600160a01b0383161790555050565b600061139f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b90506113c3816001600160a01b031660009081526007602052604090205460ff1690565b156114065760405162461bcd60e51b8152602060048201526013602482015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015260640161023a565b610af9816001600160a01b03166000908152600760205260409020805460ff19166001179055565b336114416001546001600160a01b031690565b6001600160a01b0316146114675760405162461bcd60e51b815260040161023a90612ce8565b61ffff82166000908152600a6020526040902080546001600160a01b0319166001600160a01b0383161790555050565b336114aa6001546001600160a01b031690565b6001600160a01b0316146114d05760405162461bcd60e51b815260040161023a90612ce8565b620151808110156115235760405162461bcd60e51b815260206004820152601b60248201527f496e636f7272656374206c6f636b54696d652073657474696e67730000000000604482015260640161023a565b610af981600455565b6000805461ffff1661ffff168461ffff16036115865760405162461bcd60e51b815260206004820152601960248201527821b0b73737ba1039b2b732103a379039b0b6b29031b430b4b760391b604482015260640161023a565b61159661125060005461ffff1690565b9050722d25a13934b233b2903b19103b32b939b4b7b760691b6115bc60005461ffff1690565b85338685876040516020016115d79796959493929190612e7c565b60405160208183030381529060405291506115fc600b5460ff600160a01b9091041690565b156116d457600b546001600160a01b031663ccbf1a2c816001600160a01b031663ced72f876040518163ffffffff1660e01b8152600401602060405180830381865afa158015611650573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116749190612efe565b60005461ffff1633888887896040518863ffffffff1660e01b81526004016116a196959493929190612f17565b6000604051808303818588803b1580156116ba57600080fd5b505af11580156116ce573d6000803e3d6000fd5b50505050505b806001600160401b03168461ffff16336001600160a01b03167fb8abfd5c33667c7440a4fc1153ae39a24833dbe44f7eb19cbe5cd5f2583e4940868660405161171e929190612e58565b60405180910390a49392505050565b336117406001546001600160a01b031690565b6001600160a01b0316146117665760405162461bcd60e51b815260040161023a90612ce8565b600061177a6002546001600160a01b031690565b6001600160a01b0316036117d05760405162461bcd60e51b815260206004820152601b60248201527f436865636b2070656e64696e67496d706c656d656e746174696f6e0000000000604482015260640161023a565b6003544210156118145760405162461bcd60e51b815260206004820152600f60248201526e29ba34b636103637b1b5b2b21034b760891b604482015260640161023a565b60006118477f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b9050600061185d6002546001600160a01b031690565b90506118696000611b9d565b61187281611f14565b60408051600481526024810182526020810180516001600160e01b031663204a7f0760e21b179052905160009182916001600160a01b038516916118b591612f71565b600060405180830381855af49150503d80600081146118f0576040519150601f19603f3d011682016040523d82523d6000602084013e6118f5565b606091505b509150915081819061191a5760405162461bcd60e51b815260040161023a9190612d4b565b50826001600160a01b0316846001600160a01b03167f2e4cc16c100f0b55e2df82ab0b1a7e294aa9cbd01b48fbaf622683fbc0507a4960405160405180910390a350505050565b336119746001546001600160a01b031690565b6001600160a01b03161461199a5760405162461bcd60e51b815260040161023a90612ce8565b6001546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015610af9573d6000803e3d6000fd5b336119e66001546001600160a01b031690565b6001600160a01b031614611a0c5760405162461bcd60e51b815260040161023a90612ce8565b61ffff82166000908152600c6020526040902080546001600160a01b0319166001600160a01b0383161790555050565b6040805160c08101825260008082526020820181905291810182905260608082018390526080820183905260a0820152908080611a798582611f54565b9050722d25a13934b233b2903b19103b32b939b4b7b760691b8114611a9f575050915091565b611aaa602083612d33565b9150611ab68583611fb8565b61ffff168452611ac7600283612d33565b9150611ad38583611fb8565b61ffff166020850152611ae7600283612d33565b9150611af38583612015565b6001600160a01b03166040850152611b0c601483612d33565b9150611b188583612015565b6001600160a01b03166060850152611b31601483612d33565b9150611b3d858361207a565b6001600160401b03166080850152611b56600883612d33565b9150611b7182838751611b699190612f8d565b8791906120d7565b60a085015250919360019350915050565b6000908152600860205260409020805460ff19166001179055565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6040805160c0810182526000808252602080830182905282840182905260608084018390526080840183905260a0840152835180850185528281528101829052835180850190945285518452858101908401529091611c22906121e4565b6121e4565b90508215611c8c57611c89611c1d611c5c83611c3f876002612d33565b81518110611c4f57611c4f612fa4565b60200260200101516122f9565b60408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b90505b6000611caa611c1d611c5c84600181518110611c4f57611c4f612fa4565b90506000611cd182600081518110611cc457611cc4612fa4565b6020026020010151612370565b806020019051810190611ce49190612efe565b90507f475402a3cc99838bbf5b03eeac51c65db7cc241bb0814e6341a32a0da7c1b6c08101611e1257611d3083600081518110611d2357611d23612fa4565b60200260200101516123e4565b60808501528151611d4e9083906001908110611cc457611cc4612fa4565b806020019051810190611d619190612efe565b60608501528151611d7f9083906002908110611cc457611cc4612fa4565b806020019051810190611d929190612fba565b61ffff1684528151611db19083906003908110611cc457611cc4612fa4565b806020019051810190611dc49190612fd7565b6001600160401b031660208501528251611deb9084906002908110611cc457611cc4612fa4565b806020019051810190611dfe9190612ff4565b60a08601526001600160a01b031660408501525b50505092915050565b60006001600160a01b0319821615611e6b5760405162461bcd60e51b8152602060048201526013602482015272696e76616c69642045564d206164647265737360681b604482015260640161023a565b5090565b6040805161ffff841660208201526001600160a01b038316918101919091526000908190606001604051602081830303815290604052805190602001209050611ecd816000908152600560205260409020546001600160401b031690565b9150611f0d81611ede846001613044565b600091825260056020526040909120805467ffffffffffffffff19166001600160401b03909216919091179055565b5092915050565b611f1d816123ef565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6000611f61826020612d33565b83511015611fa95760405162461bcd60e51b8152602060048201526015602482015274746f427974657333325f6f75744f66426f756e647360581b604482015260640161023a565b50818101602001515b92915050565b6000611fc5826002612d33565b8351101561200c5760405162461bcd60e51b8152602060048201526014602482015273746f55696e7431365f6f75744f66426f756e647360601b604482015260640161023a565b50016002015190565b6000612022826014612d33565b8351101561206a5760405162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b604482015260640161023a565b500160200151600160601b900490565b6000612087826008612d33565b835110156120ce5760405162461bcd60e51b8152602060048201526014602482015273746f55696e7436345f6f75744f66426f756e647360601b604482015260640161023a565b50016008015190565b6060816120e581601f612d33565b10156121245760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b604482015260640161023a565b61212e8284612d33565b845110156121725760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b604482015260640161023a565b60608215801561219157604051915060008252602082016040526121db565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156121ca5780518352602092830192016121b2565b5050858452601f01601f1916604052505b50949350505050565b60606121ef8261249d565b6121f857600080fd5b6000612203836124d8565b90506000816001600160401b0381111561221f5761221f6128ca565b60405190808252806020026020018201604052801561226457816020015b604080518082019091526000808252602082015281526020019060019003908161223d5790505b5090506000612276856020015161255d565b85602001516122859190612d33565b90506000805b848110156122ee5761229c836125df565b91506040518060400160405280838152602001848152508482815181106122c5576122c5612fa4565b60209081029190910101526122da8284612d33565b9250806122e68161306f565b91505061228b565b509195945050505050565b6060600082600001516001600160401b03811115612319576123196128ca565b6040519080825280601f01601f191660200182016040528015612343576020820181803683370190505b50905080516000036123555792915050565b6000816020019050611f0d8460200151828660000151612683565b805160609061237e57600080fd5b60008061238a84612706565b915091506000816001600160401b038111156123a8576123a86128ca565b6040519080825280601f01601f1916602001820160405280156123d2576020820181803683370190505b509050602081016121db848285612683565b6000611fb28261274d565b6001600160a01b0381163b61245c5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161023a565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b805160009081036124b057506000919050565b6020820151805160001a9060c08210156124ce575060009392505050565b5060019392505050565b805160009081036124eb57506000919050565b6000806124fb846020015161255d565b846020015161250a9190612d33565b90506000846000015185602001516125229190612d33565b90505b8082101561255457612536826125df565b6125409083612d33565b91508261254c8161306f565b935050612525565b50909392505050565b8051600090811a60808110156125765750600092915050565b60b8811080612591575060c08110801590612591575060f881105b1561259f5750600192915050565b60c08110156125d3576125b4600160b8613088565b6125c19060ff1682612f8d565b6125cc906001612d33565b9392505050565b6125b4600160f8613088565b80516000908190811a60808110156125fa5760019150611f0d565b60b88110156126205761260e608082612f8d565b612619906001612d33565b9150611f0d565b60c081101561264d5760b78103600185019450806020036101000a85510460018201810193505050611f0d565b60f88110156126615761260e60c082612f8d565b60019390930151602084900360f7016101000a900490920160f5190192915050565b8060000361269057505050565b602081106126c857825182526126a7602084612d33565b92506126b4602083612d33565b91506126c1602082612f8d565b9050612690565b801561270157600060016126dd836020612f8d565b6126e99061010061318f565b6126f39190612f8d565b845184518216911916178352505b505050565b6000806000612718846020015161255d565b9050600081856020015161272c9190612d33565b905060008286600001516127409190612f8d565b9196919550909350505050565b80516000901580159061276257508151602110155b61276b57600080fd5b60008061277784612706565b8151919350915060208210156127935760208290036101000a90045b949350505050565b61ffff81168114610af957600080fd5b6001600160a01b0381168114610af957600080fd5b6001600160401b0381168114610af957600080fd5b60008060008060008060a087890312156127ee57600080fd5b86356127f98161279b565b95506020870135612809816127ab565b94506040870135612819816127ab565b93506060870135612829816127c0565b925060808701356001600160401b038082111561284557600080fd5b818901915089601f83011261285957600080fd5b81358181111561286857600080fd5b8a602082850101111561287a57600080fd5b6020830194508093505050509295509295509295565b6000602082840312156128a257600080fd5b81356125cc8161279b565b6000602082840312156128bf57600080fd5b81356125cc816127ab565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715612908576129086128ca565b604052919050565b60006001600160401b03821115612929576129296128ca565b50601f01601f191660200190565b600082601f83011261294857600080fd5b813561295b61295682612910565b6128e0565b81815284602083860101111561297057600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080608085870312156129a357600080fd5b84356129ae8161279b565b9350602085013592506040850135915060608501356001600160401b038111156129d757600080fd5b6129e387828801612937565b91505092959194509250565b8015158114610af957600080fd5b600060208284031215612a0f57600080fd5b81356125cc816129ef565b60008060008060808587031215612a3057600080fd5b8435612a3b8161279b565b93506020850135612a4b8161279b565b92506040850135612a5b816127ab565b915060608501356001600160401b038111156129d757600080fd5b60008060408385031215612a8957600080fd5b8235612a948161279b565b946020939093013593505050565b60008060408385031215612ab557600080fd5b8235612ac08161279b565b91506020830135612ad0816127ab565b809150509250929050565b600060208284031215612aed57600080fd5b5035919050565b600080600060608486031215612b0957600080fd5b8335612b148161279b565b92506020840135612b24816127ab565b915060408401356001600160401b03811115612b3f57600080fd5b612b4b86828701612937565b9150509250925092565b60208082526022908201527f63616c6c6572206973206e6f7420746865206c324d6573736167655265636569604082015261766560f01b606082015260800190565b60208082526019908201527f496e76616c69642064657374696e6174696f6e20636861696e00000000000000604082015260600190565b60208082526019908201527f4d65737361676520616c72656164792065786563757465642e00000000000000604082015260600190565b60005b83811015612c20578181015183820152602001612c08565b83811115612c2f576000848401525b50505050565b60008151808452612c4d816020860160208601612c05565b601f01601f19169290920160200192915050565b61ffff851681526001600160a01b03841660208201526001600160401b0383166040820152608060608201819052600090612c9e90830184612c35565b9695505050505050565b6001600160a01b03841681526040602082018190528101829052818360608301376000818301606090810191909152601f909201601f1916010192915050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052601160045260246000fd5b60008219821115612d4657612d46612d1d565b500190565b6020815260006125cc6020830184612c35565b600082601f830112612d6f57600080fd5b8151612d7d61295682612910565b818152846020838601011115612d9257600080fd5b612793826020830160208701612c05565b600060208284031215612db557600080fd5b81516001600160401b0380821115612dcc57600080fd5b9083019060608286031215612de057600080fd5b604051606081018181108382111715612dfb57612dfb6128ca565b80604052508251815260208301516020820152604083015182811115612e2057600080fd5b612e2c87828601612d5e565b60408301525095945050505050565b600060208284031215612e4d57600080fd5b81516125cc816129ef565b6001600160a01b038316815260406020820181905260009061279390830184612c35565b878152600061ffff60f01b808960f01b166020840152808860f01b166022840152506bffffffffffffffffffffffff19808760601b166024840152808660601b166038840152506001600160401b0360c01b8460c01b16604c8301528251612eeb816054850160208701612c05565b9190910160540198975050505050505050565b600060208284031215612f1057600080fd5b5051919050565b61ffff87811682526001600160a01b0387811660208401529086166040830152841660608201526001600160401b038316608082015260c060a08201819052600090612f6590830184612c35565b98975050505050505050565b60008251612f83818460208701612c05565b9190910192915050565b600082821015612f9f57612f9f612d1d565b500390565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612fcc57600080fd5b81516125cc8161279b565b600060208284031215612fe957600080fd5b81516125cc816127c0565b6000806040838503121561300757600080fd5b8251613012816127ab565b60208401519092506001600160401b0381111561302e57600080fd5b61303a85828601612d5e565b9150509250929050565b60006001600160401b0380831681851680830382111561306657613066612d1d565b01949350505050565b60006001820161308157613081612d1d565b5060010190565b600060ff821660ff8416808210156130a2576130a2612d1d565b90039392505050565b600181815b808511156130e65781600019048211156130cc576130cc612d1d565b808516156130d957918102915b93841c93908002906130b0565b509250929050565b6000826130fd57506001611fb2565b8161310a57506000611fb2565b8160018114613120576002811461312a57613146565b6001915050611fb2565b60ff84111561313b5761313b612d1d565b50506001821b611fb2565b5060208310610133831016604e8410600b8410161715613169575081810a611fb2565b61317383836130ab565b806000190482111561318757613187612d1d565b029392505050565b60006125cc83836130ee56fea2646970667358221220aa0c3d00c085950339cd9e06fad3fb30056749ebb9092a0e564a806f20e3f6f864736f6c634300080e0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.