Source Code
Overview
CELO Balance
CELO Value
$0.00Multichain Info
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
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 "./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;
bytes32 public constant MESSAGE_TOPIC = 0xb8abfd5c33667c7440a4fc1153ae39a24833dbe44f7eb19cbe5cd5f2583e4940;
struct LogMessage {
uint16 dstChainId;
uint64 sequence;
address dstAddress;
bytes32 srcAddress;
bytes32 srcZkBridge;
bytes payload;
}
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);
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 = keccak256(abi.encode(srcChainId, logMessage.srcAddress, logMessage.sequence));
require(!isTransferCompleted(hash), "Message already executed.");
_setTransferCompleted(hash);
address srcAddress = _truncateAddress(logMessage.srcAddress);
IZKBridgeReceiver(logMessage.dstAddress).zkReceive(srcChainId, srcAddress, logMessage.sequence, logMessage.payload);
emit ExecutedMessage(srcAddress, srcChainId, logMessage.sequence, logMessage.dstAddress, logMessage.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 _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.8.3) (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.9._
*/
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.8.3) (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._
*
* @custom:oz-upgrades-unsafe-allow delegatecall
*/
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.8.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
* ====
*
* [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://diligence.consensys.net/posts/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.5.11/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.7.0) (utils/StorageSlot.sol)
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:
* ```
* 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`, and `uint256`._
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 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
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./State.sol";
import "./interfaces/IMptVerifier.sol";
import "./interfaces/IBlockUpdater.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;
}
}// 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 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 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;
}// 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: 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;
}
}// 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;
}
}
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":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"isTransferCompleted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"chainId","type":"uint16"},{"internalType":"address","name":"blockUpdater","type":"address"}],"name":"setBlockUpdater","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":"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
608060405234801561001057600080fd5b506121ee806100206000396000f3fe6080604052600436106101445760003560e01c8063813d31c9116100b6578063b1d995dd1161006f578063b1d995dd14610463578063bd51f42e1461048e578063d1dc83c2146104c4578063d294f093146104d9578063d60b347f146104ee578063fe2db7d014610527576101ab565b8063813d31c91461038d5780638da5cb5b146103ad5780639a8a0592146103cb5780639f0a22a6146103ee578063aa4efa5b14610403578063ae04d45d14610443576101ab565b80634f64ca19116101085780634f64ca19146102a457806365bb3ea7146102c457806366798c2c146102e45780636b83252a1461031e5780637cf5744f146103585780638129fc1c14610378576101ab565b80630d668087146101e1578063396f7b23146102055780633a552757146102375780633fe3da36146102595780633ff032071461028d576101ab565b366101ab5760405162461bcd60e51b815260206004820152602c60248201527f746865205a6b42726964676520636f6e747261637420646f6573206e6f74206160448201526b63636570742061737365747360a01b60648201526084015b60405180910390fd5b60405162461bcd60e51b815260206004820152600b60248201526a1d5b9cdd5c1c1bdc9d195960aa1b60448201526064016101a2565b3480156101ed57600080fd5b506004545b6040519081526020015b60405180910390f35b34801561021157600080fd5b506002546001600160a01b03165b6040516001600160a01b0390911681526020016101fc565b34801561024357600080fd5b50610257610252366004611adf565b610558565b005b34801561026557600080fd5b506101f27fb8abfd5c33667c7440a4fc1153ae39a24833dbe44f7eb19cbe5cd5f2583e494081565b34801561029957600080fd5b506101f26201518081565b3480156102b057600080fd5b506102576102bf366004611bcf565b610665565b3480156102d057600080fd5b506102576102df366004611c31565b610b5b565b3480156102f057600080fd5b5061021f6102ff366004611c5d565b61ffff166000908152600a60205260409020546001600160a01b031690565b34801561032a57600080fd5b5061021f610339366004611c5d565b61ffff166000908152600960205260409020546001600160a01b031690565b34801561036457600080fd5b50610257610373366004611c7a565b610bac565b34801561038457600080fd5b50610257610c15565b34801561039957600080fd5b506102576103a8366004611c7a565b610cda565b3480156103b957600080fd5b506001546001600160a01b031661021f565b3480156103d757600080fd5b5060005460405161ffff90911681526020016101fc565b3480156103fa57600080fd5b506003546101f2565b34801561040f57600080fd5b5061043361041e366004611cb3565b60009081526008602052604090205460ff1690565b60405190151581526020016101fc565b34801561044f57600080fd5b5061025761045e366004611cb3565b610d43565b610476610471366004611ccc565b610dd8565b6040516001600160401b0390911681526020016101fc565b34801561049a57600080fd5b506104766104a9366004611cb3565b6000908152600560205260409020546001600160401b031690565b3480156104d057600080fd5b50610257610ea7565b3480156104e557600080fd5b506102576110db565b3480156104fa57600080fd5b50610433610509366004611adf565b6001600160a01b031660009081526007602052604090205460ff1690565b34801561053357600080fd5b506101f2610542366004611c5d565b61ffff1660009081526006602052604090205490565b3361056b6001546001600160a01b031690565b6001600160a01b0316146105915760405162461bcd60e51b81526004016101a290611d2d565b6001600160a01b0381166105e75760405162461bcd60e51b815260206004820152601b60248201527f436865636b2070656e64696e67496d706c656d656e746174696f6e000000000060448201526064016101a2565b60006105fb6002546001600160a01b031690565b90506106068261114d565b61062161061260045490565b61061c9042611d78565b600355565b816001600160a01b0316816001600160a01b03167fe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d81560405160405180910390a35050565b61ffff8416600090815260096020908152604080832054600a909252909120546001600160a01b039182169116816106d85760405162461bcd60e51b8152602060048201526016602482015275135c1d15995c9a599a595c881a5cc81b9bdd081cd95d60521b60448201526064016101a2565b6001600160a01b03811661072e5760405162461bcd60e51b815260206004820152601860248201527f426c6f636b2055706461746572206973206e6f7420736574000000000000000060448201526064016101a2565b60405163057d916d60e11b81526000906001600160a01b03841690630afb22da9061075d908790600401611dec565b600060405180830381865afa15801561077a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107a29190810190611e44565b905080602001516001146107f85760405162461bcd60e51b815260206004820181905260248201527f536f7572636520436861696e205472616e73616374696f6e204661696c75726560448201526064016101a2565b8051604051636e1ac47560e11b81526001600160a01b0384169163dc3588ea9161082f918a91600401918252602082015260400190565b602060405180830381865afa15801561084c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108709190611edc565b6108bc5760405162461bcd60e51b815260206004820152601760248201527f426c6f636b20486561646572206973206e6f742073657400000000000000000060448201526064016101a2565b60006108cc82604001518761116f565b90506108e88861ffff1660009081526006602052604090205490565b81608001511461093a5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420736f75726365205a4b42726964676500000000000000000060448201526064016101a2565b600054815161ffff9081169116146109945760405162461bcd60e51b815260206004820152601960248201527f496e76616c69642064657374696e6174696f6e20636861696e0000000000000060448201526064016101a2565b600088826060015183602001516040516020016109d39392919061ffff93909316835260208301919091526001600160401b0316604082015260600190565b604051602081830303815290604052805190602001209050610a048160009081526008602052604090205460ff1690565b15610a515760405162461bcd60e51b815260206004820152601960248201527f4d65737361676520616c72656164792065786563757465642e0000000000000060448201526064016101a2565b610a70816000908152600860205260409020805460ff19166001179055565b6000610a7f83606001516113cb565b905082604001516001600160a01b0316632de9952a8b8386602001518760a001516040518563ffffffff1660e01b8152600401610abf9493929190611efe565b600060405180830381600087803b158015610ad957600080fd5b505af1158015610aed573d6000803e3d6000fd5b5050505082602001516001600160401b03168a61ffff16826001600160a01b03167f4a008ac830958ba6fe8a6e667e2ab53a530eb6cdf93e55b27fc42d7a54cf25b786604001518760a00151604051610b47929190611f45565b60405180910390a450505050505050505050565b33610b6e6001546001600160a01b031690565b6001600160a01b031614610b945760405162461bcd60e51b81526004016101a290611d2d565b61ffff91909116600090815260066020526040902055565b33610bbf6001546001600160a01b031690565b6001600160a01b031614610be55760405162461bcd60e51b81526004016101a290611d2d565b61ffff8216600090815260096020526040902080546001600160a01b0319166001600160a01b0383161790555050565b6000610c487f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b9050610c6c816001600160a01b031660009081526007602052604090205460ff1690565b15610caf5760405162461bcd60e51b8152602060048201526013602482015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b60448201526064016101a2565b610cd7816001600160a01b03166000908152600760205260409020805460ff19166001179055565b50565b33610ced6001546001600160a01b031690565b6001600160a01b031614610d135760405162461bcd60e51b81526004016101a290611d2d565b61ffff82166000908152600a6020526040902080546001600160a01b0319166001600160a01b0383161790555050565b33610d566001546001600160a01b031690565b6001600160a01b031614610d7c5760405162461bcd60e51b81526004016101a290611d2d565b62015180811015610dcf5760405162461bcd60e51b815260206004820152601b60248201527f496e636f7272656374206c6f636b54696d652073657474696e6773000000000060448201526064016101a2565b610cd781600455565b6000805461ffff1661ffff168461ffff1603610e365760405162461bcd60e51b815260206004820152601960248201527f43616e6e6f742073656e6420746f2073616d6520636861696e0000000000000060448201526064016101a2565b610e4c610e4660005461ffff1690565b3361141f565b9050806001600160401b03168461ffff16336001600160a01b03167fb8abfd5c33667c7440a4fc1153ae39a24833dbe44f7eb19cbe5cd5f2583e49408686604051610e98929190611f45565b60405180910390a49392505050565b33610eba6001546001600160a01b031690565b6001600160a01b031614610ee05760405162461bcd60e51b81526004016101a290611d2d565b6000610ef46002546001600160a01b031690565b6001600160a01b031603610f4a5760405162461bcd60e51b815260206004820152601b60248201527f436865636b2070656e64696e67496d706c656d656e746174696f6e000000000060448201526064016101a2565b600354421015610f8e5760405162461bcd60e51b815260206004820152600f60248201526e29ba34b636103637b1b5b2b21034b760891b60448201526064016101a2565b6000610fc17f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b90506000610fd76002546001600160a01b031690565b9050610fe3600061114d565b610fec816114c4565b60408051600481526024810182526020810180516001600160e01b031663204a7f0760e21b179052905160009182916001600160a01b0385169161102f91611f69565b600060405180830381855af49150503d806000811461106a576040519150601f19603f3d011682016040523d82523d6000602084013e61106f565b606091505b50915091508181906110945760405162461bcd60e51b81526004016101a29190611dec565b50826001600160a01b0316846001600160a01b03167f2e4cc16c100f0b55e2df82ab0b1a7e294aa9cbd01b48fbaf622683fbc0507a4960405160405180910390a350505050565b336110ee6001546001600160a01b031690565b6001600160a01b0316146111145760405162461bcd60e51b81526004016101a290611d2d565b6001546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015610cd7573d6000803e3d6000fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6040805160c0810182526000808252602080830182905282840182905260608084018390526080840183905260a08401528351808501855282815281018290528351808501909452855184528581019084015290916111d290611504565b611504565b9050821561123c576112396111cd61120c836111ef876002611d78565b815181106111ff576111ff611f85565b6020026020010151611619565b60408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b90505b600061125a6111cd61120c846001815181106111ff576111ff611f85565b905060006112818260008151811061127457611274611f85565b6020026020010151611690565b8060200190518101906112949190611f9b565b90507f475402a3cc99838bbf5b03eeac51c65db7cc241bb0814e6341a32a0da7c1b6c081016113c2576112e0836000815181106112d3576112d3611f85565b602002602001015161170d565b608085015281516112fe908390600190811061127457611274611f85565b8060200190518101906113119190611f9b565b6060850152815161132f908390600290811061127457611274611f85565b8060200190518101906113429190611fb4565b61ffff1684528151611361908390600390811061127457611274611f85565b8060200190518101906113749190611fd1565b6001600160401b03166020850152825161139b908490600290811061127457611274611f85565b8060200190518101906113ae9190611ffa565b60a08601526001600160a01b031660408501525b50505092915050565b60006001600160a01b031982161561141b5760405162461bcd60e51b8152602060048201526013602482015272696e76616c69642045564d206164647265737360681b60448201526064016101a2565b5090565b6040805161ffff841660208201526001600160a01b03831691810191909152600090819060600160405160208183030381529060405280519060200120905061147d816000908152600560205260409020546001600160401b031690565b91506114bd8161148e84600161204a565b600091825260056020526040909120805467ffffffffffffffff19166001600160401b03909216919091179055565b5092915050565b6114cd8161171e565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061150f826117cc565b61151857600080fd5b600061152383611807565b90506000816001600160401b0381111561153f5761153f611b0c565b60405190808252806020026020018201604052801561158457816020015b604080518082019091526000808252602082015281526020019060019003908161155d5790505b5090506000611596856020015161188c565b85602001516115a59190611d78565b90506000805b8481101561160e576115bc8361190e565b91506040518060400160405280838152602001848152508482815181106115e5576115e5611f85565b60209081029190910101526115fa8284611d78565b92508061160681612075565b9150506115ab565b509195945050505050565b6060600082600001516001600160401b0381111561163957611639611b0c565b6040519080825280601f01601f191660200182016040528015611663576020820181803683370190505b50905080516000036116755792915050565b60008160200190506114bd84602001518286600001516119b2565b805160609061169e57600080fd5b6000806116aa84611a35565b915091506000816001600160401b038111156116c8576116c8611b0c565b6040519080825280601f01601f1916602001820160405280156116f2576020820181803683370190505b509050602081016117048482856119b2565b50949350505050565b600061171882611a7c565b92915050565b6001600160a01b0381163b61178b5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016101a2565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b805160009081036117df57506000919050565b6020820151805160001a9060c08210156117fd575060009392505050565b5060019392505050565b8051600090810361181a57506000919050565b60008061182a846020015161188c565b84602001516118399190611d78565b90506000846000015185602001516118519190611d78565b90505b80821015611883576118658261190e565b61186f9083611d78565b91508261187b81612075565b935050611854565b50909392505050565b8051600090811a60808110156118a55750600092915050565b60b88110806118c0575060c081108015906118c0575060f881105b156118ce5750600192915050565b60c0811015611902576118e3600160b861208e565b6118f09060ff16826120b1565b6118fb906001611d78565b9392505050565b6118e3600160f861208e565b80516000908190811a608081101561192957600191506114bd565b60b881101561194f5761193d6080826120b1565b611948906001611d78565b91506114bd565b60c081101561197c5760b78103600185019450806020036101000a855104600182018101935050506114bd565b60f88110156119905761193d60c0826120b1565b60019390930151602084900360f7016101000a900490920160f5190192915050565b806000036119bf57505050565b602081106119f757825182526119d6602084611d78565b92506119e3602083611d78565b91506119f06020826120b1565b90506119bf565b8015611a305760006001611a0c8360206120b1565b611a18906101006121ac565b611a2291906120b1565b845184518216911916178352505b505050565b6000806000611a47846020015161188c565b90506000818560200151611a5b9190611d78565b90506000828660000151611a6f91906120b1565b9196919550909350505050565b805160009015801590611a9157508151602110155b611a9a57600080fd5b600080611aa684611a35565b815191935091506020821015611ac25760208290036101000a90045b949350505050565b6001600160a01b0381168114610cd757600080fd5b600060208284031215611af157600080fd5b81356118fb81611aca565b61ffff81168114610cd757600080fd5b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611b4a57611b4a611b0c565b604052919050565b60006001600160401b03821115611b6b57611b6b611b0c565b50601f01601f191660200190565b600082601f830112611b8a57600080fd5b8135611b9d611b9882611b52565b611b22565b818152846020838601011115611bb257600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215611be557600080fd5b8435611bf081611afc565b9350602085013592506040850135915060608501356001600160401b03811115611c1957600080fd5b611c2587828801611b79565b91505092959194509250565b60008060408385031215611c4457600080fd5b8235611c4f81611afc565b946020939093013593505050565b600060208284031215611c6f57600080fd5b81356118fb81611afc565b60008060408385031215611c8d57600080fd5b8235611c9881611afc565b91506020830135611ca881611aca565b809150509250929050565b600060208284031215611cc557600080fd5b5035919050565b600080600060608486031215611ce157600080fd5b8335611cec81611afc565b92506020840135611cfc81611aca565b915060408401356001600160401b03811115611d1757600080fd5b611d2386828701611b79565b9150509250925092565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052601160045260246000fd5b60008219821115611d8b57611d8b611d62565b500190565b60005b83811015611dab578181015183820152602001611d93565b83811115611dba576000848401525b50505050565b60008151808452611dd8816020860160208601611d90565b601f01601f19169290920160200192915050565b6020815260006118fb6020830184611dc0565b600082601f830112611e1057600080fd5b8151611e1e611b9882611b52565b818152846020838601011115611e3357600080fd5b611ac2826020830160208701611d90565b600060208284031215611e5657600080fd5b81516001600160401b0380821115611e6d57600080fd5b9083019060608286031215611e8157600080fd5b604051606081018181108382111715611e9c57611e9c611b0c565b80604052508251815260208301516020820152604083015182811115611ec157600080fd5b611ecd87828601611dff565b60408301525095945050505050565b600060208284031215611eee57600080fd5b815180151581146118fb57600080fd5b61ffff851681526001600160a01b03841660208201526001600160401b0383166040820152608060608201819052600090611f3b90830184611dc0565b9695505050505050565b6001600160a01b0383168152604060208201819052600090611ac290830184611dc0565b60008251611f7b818460208701611d90565b9190910192915050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611fad57600080fd5b5051919050565b600060208284031215611fc657600080fd5b81516118fb81611afc565b600060208284031215611fe357600080fd5b81516001600160401b03811681146118fb57600080fd5b6000806040838503121561200d57600080fd5b825161201881611aca565b60208401519092506001600160401b0381111561203457600080fd5b61204085828601611dff565b9150509250929050565b60006001600160401b0380831681851680830382111561206c5761206c611d62565b01949350505050565b60006001820161208757612087611d62565b5060010190565b600060ff821660ff8416808210156120a8576120a8611d62565b90039392505050565b6000828210156120c3576120c3611d62565b500390565b600181815b808511156121035781600019048211156120e9576120e9611d62565b808516156120f657918102915b93841c93908002906120cd565b509250929050565b60008261211a57506001611718565b8161212757506000611718565b816001811461213d576002811461214757612163565b6001915050611718565b60ff84111561215857612158611d62565b50506001821b611718565b5060208310610133831016604e8410600b8410161715612186575081810a611718565b61219083836120c8565b80600019048211156121a4576121a4611d62565b029392505050565b60006118fb838361210b56fea2646970667358221220aca67fd56b11b803902027b44648ec38f60bde397396a4a6fe265fc7399940bd64736f6c634300080e0033
Deployed Bytecode
0x6080604052600436106101445760003560e01c8063813d31c9116100b6578063b1d995dd1161006f578063b1d995dd14610463578063bd51f42e1461048e578063d1dc83c2146104c4578063d294f093146104d9578063d60b347f146104ee578063fe2db7d014610527576101ab565b8063813d31c91461038d5780638da5cb5b146103ad5780639a8a0592146103cb5780639f0a22a6146103ee578063aa4efa5b14610403578063ae04d45d14610443576101ab565b80634f64ca19116101085780634f64ca19146102a457806365bb3ea7146102c457806366798c2c146102e45780636b83252a1461031e5780637cf5744f146103585780638129fc1c14610378576101ab565b80630d668087146101e1578063396f7b23146102055780633a552757146102375780633fe3da36146102595780633ff032071461028d576101ab565b366101ab5760405162461bcd60e51b815260206004820152602c60248201527f746865205a6b42726964676520636f6e747261637420646f6573206e6f74206160448201526b63636570742061737365747360a01b60648201526084015b60405180910390fd5b60405162461bcd60e51b815260206004820152600b60248201526a1d5b9cdd5c1c1bdc9d195960aa1b60448201526064016101a2565b3480156101ed57600080fd5b506004545b6040519081526020015b60405180910390f35b34801561021157600080fd5b506002546001600160a01b03165b6040516001600160a01b0390911681526020016101fc565b34801561024357600080fd5b50610257610252366004611adf565b610558565b005b34801561026557600080fd5b506101f27fb8abfd5c33667c7440a4fc1153ae39a24833dbe44f7eb19cbe5cd5f2583e494081565b34801561029957600080fd5b506101f26201518081565b3480156102b057600080fd5b506102576102bf366004611bcf565b610665565b3480156102d057600080fd5b506102576102df366004611c31565b610b5b565b3480156102f057600080fd5b5061021f6102ff366004611c5d565b61ffff166000908152600a60205260409020546001600160a01b031690565b34801561032a57600080fd5b5061021f610339366004611c5d565b61ffff166000908152600960205260409020546001600160a01b031690565b34801561036457600080fd5b50610257610373366004611c7a565b610bac565b34801561038457600080fd5b50610257610c15565b34801561039957600080fd5b506102576103a8366004611c7a565b610cda565b3480156103b957600080fd5b506001546001600160a01b031661021f565b3480156103d757600080fd5b5060005460405161ffff90911681526020016101fc565b3480156103fa57600080fd5b506003546101f2565b34801561040f57600080fd5b5061043361041e366004611cb3565b60009081526008602052604090205460ff1690565b60405190151581526020016101fc565b34801561044f57600080fd5b5061025761045e366004611cb3565b610d43565b610476610471366004611ccc565b610dd8565b6040516001600160401b0390911681526020016101fc565b34801561049a57600080fd5b506104766104a9366004611cb3565b6000908152600560205260409020546001600160401b031690565b3480156104d057600080fd5b50610257610ea7565b3480156104e557600080fd5b506102576110db565b3480156104fa57600080fd5b50610433610509366004611adf565b6001600160a01b031660009081526007602052604090205460ff1690565b34801561053357600080fd5b506101f2610542366004611c5d565b61ffff1660009081526006602052604090205490565b3361056b6001546001600160a01b031690565b6001600160a01b0316146105915760405162461bcd60e51b81526004016101a290611d2d565b6001600160a01b0381166105e75760405162461bcd60e51b815260206004820152601b60248201527f436865636b2070656e64696e67496d706c656d656e746174696f6e000000000060448201526064016101a2565b60006105fb6002546001600160a01b031690565b90506106068261114d565b61062161061260045490565b61061c9042611d78565b600355565b816001600160a01b0316816001600160a01b03167fe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d81560405160405180910390a35050565b61ffff8416600090815260096020908152604080832054600a909252909120546001600160a01b039182169116816106d85760405162461bcd60e51b8152602060048201526016602482015275135c1d15995c9a599a595c881a5cc81b9bdd081cd95d60521b60448201526064016101a2565b6001600160a01b03811661072e5760405162461bcd60e51b815260206004820152601860248201527f426c6f636b2055706461746572206973206e6f7420736574000000000000000060448201526064016101a2565b60405163057d916d60e11b81526000906001600160a01b03841690630afb22da9061075d908790600401611dec565b600060405180830381865afa15801561077a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107a29190810190611e44565b905080602001516001146107f85760405162461bcd60e51b815260206004820181905260248201527f536f7572636520436861696e205472616e73616374696f6e204661696c75726560448201526064016101a2565b8051604051636e1ac47560e11b81526001600160a01b0384169163dc3588ea9161082f918a91600401918252602082015260400190565b602060405180830381865afa15801561084c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108709190611edc565b6108bc5760405162461bcd60e51b815260206004820152601760248201527f426c6f636b20486561646572206973206e6f742073657400000000000000000060448201526064016101a2565b60006108cc82604001518761116f565b90506108e88861ffff1660009081526006602052604090205490565b81608001511461093a5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420736f75726365205a4b42726964676500000000000000000060448201526064016101a2565b600054815161ffff9081169116146109945760405162461bcd60e51b815260206004820152601960248201527f496e76616c69642064657374696e6174696f6e20636861696e0000000000000060448201526064016101a2565b600088826060015183602001516040516020016109d39392919061ffff93909316835260208301919091526001600160401b0316604082015260600190565b604051602081830303815290604052805190602001209050610a048160009081526008602052604090205460ff1690565b15610a515760405162461bcd60e51b815260206004820152601960248201527f4d65737361676520616c72656164792065786563757465642e0000000000000060448201526064016101a2565b610a70816000908152600860205260409020805460ff19166001179055565b6000610a7f83606001516113cb565b905082604001516001600160a01b0316632de9952a8b8386602001518760a001516040518563ffffffff1660e01b8152600401610abf9493929190611efe565b600060405180830381600087803b158015610ad957600080fd5b505af1158015610aed573d6000803e3d6000fd5b5050505082602001516001600160401b03168a61ffff16826001600160a01b03167f4a008ac830958ba6fe8a6e667e2ab53a530eb6cdf93e55b27fc42d7a54cf25b786604001518760a00151604051610b47929190611f45565b60405180910390a450505050505050505050565b33610b6e6001546001600160a01b031690565b6001600160a01b031614610b945760405162461bcd60e51b81526004016101a290611d2d565b61ffff91909116600090815260066020526040902055565b33610bbf6001546001600160a01b031690565b6001600160a01b031614610be55760405162461bcd60e51b81526004016101a290611d2d565b61ffff8216600090815260096020526040902080546001600160a01b0319166001600160a01b0383161790555050565b6000610c487f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b9050610c6c816001600160a01b031660009081526007602052604090205460ff1690565b15610caf5760405162461bcd60e51b8152602060048201526013602482015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b60448201526064016101a2565b610cd7816001600160a01b03166000908152600760205260409020805460ff19166001179055565b50565b33610ced6001546001600160a01b031690565b6001600160a01b031614610d135760405162461bcd60e51b81526004016101a290611d2d565b61ffff82166000908152600a6020526040902080546001600160a01b0319166001600160a01b0383161790555050565b33610d566001546001600160a01b031690565b6001600160a01b031614610d7c5760405162461bcd60e51b81526004016101a290611d2d565b62015180811015610dcf5760405162461bcd60e51b815260206004820152601b60248201527f496e636f7272656374206c6f636b54696d652073657474696e6773000000000060448201526064016101a2565b610cd781600455565b6000805461ffff1661ffff168461ffff1603610e365760405162461bcd60e51b815260206004820152601960248201527f43616e6e6f742073656e6420746f2073616d6520636861696e0000000000000060448201526064016101a2565b610e4c610e4660005461ffff1690565b3361141f565b9050806001600160401b03168461ffff16336001600160a01b03167fb8abfd5c33667c7440a4fc1153ae39a24833dbe44f7eb19cbe5cd5f2583e49408686604051610e98929190611f45565b60405180910390a49392505050565b33610eba6001546001600160a01b031690565b6001600160a01b031614610ee05760405162461bcd60e51b81526004016101a290611d2d565b6000610ef46002546001600160a01b031690565b6001600160a01b031603610f4a5760405162461bcd60e51b815260206004820152601b60248201527f436865636b2070656e64696e67496d706c656d656e746174696f6e000000000060448201526064016101a2565b600354421015610f8e5760405162461bcd60e51b815260206004820152600f60248201526e29ba34b636103637b1b5b2b21034b760891b60448201526064016101a2565b6000610fc17f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b90506000610fd76002546001600160a01b031690565b9050610fe3600061114d565b610fec816114c4565b60408051600481526024810182526020810180516001600160e01b031663204a7f0760e21b179052905160009182916001600160a01b0385169161102f91611f69565b600060405180830381855af49150503d806000811461106a576040519150601f19603f3d011682016040523d82523d6000602084013e61106f565b606091505b50915091508181906110945760405162461bcd60e51b81526004016101a29190611dec565b50826001600160a01b0316846001600160a01b03167f2e4cc16c100f0b55e2df82ab0b1a7e294aa9cbd01b48fbaf622683fbc0507a4960405160405180910390a350505050565b336110ee6001546001600160a01b031690565b6001600160a01b0316146111145760405162461bcd60e51b81526004016101a290611d2d565b6001546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015610cd7573d6000803e3d6000fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6040805160c0810182526000808252602080830182905282840182905260608084018390526080840183905260a08401528351808501855282815281018290528351808501909452855184528581019084015290916111d290611504565b611504565b9050821561123c576112396111cd61120c836111ef876002611d78565b815181106111ff576111ff611f85565b6020026020010151611619565b60408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b90505b600061125a6111cd61120c846001815181106111ff576111ff611f85565b905060006112818260008151811061127457611274611f85565b6020026020010151611690565b8060200190518101906112949190611f9b565b90507f475402a3cc99838bbf5b03eeac51c65db7cc241bb0814e6341a32a0da7c1b6c081016113c2576112e0836000815181106112d3576112d3611f85565b602002602001015161170d565b608085015281516112fe908390600190811061127457611274611f85565b8060200190518101906113119190611f9b565b6060850152815161132f908390600290811061127457611274611f85565b8060200190518101906113429190611fb4565b61ffff1684528151611361908390600390811061127457611274611f85565b8060200190518101906113749190611fd1565b6001600160401b03166020850152825161139b908490600290811061127457611274611f85565b8060200190518101906113ae9190611ffa565b60a08601526001600160a01b031660408501525b50505092915050565b60006001600160a01b031982161561141b5760405162461bcd60e51b8152602060048201526013602482015272696e76616c69642045564d206164647265737360681b60448201526064016101a2565b5090565b6040805161ffff841660208201526001600160a01b03831691810191909152600090819060600160405160208183030381529060405280519060200120905061147d816000908152600560205260409020546001600160401b031690565b91506114bd8161148e84600161204a565b600091825260056020526040909120805467ffffffffffffffff19166001600160401b03909216919091179055565b5092915050565b6114cd8161171e565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061150f826117cc565b61151857600080fd5b600061152383611807565b90506000816001600160401b0381111561153f5761153f611b0c565b60405190808252806020026020018201604052801561158457816020015b604080518082019091526000808252602082015281526020019060019003908161155d5790505b5090506000611596856020015161188c565b85602001516115a59190611d78565b90506000805b8481101561160e576115bc8361190e565b91506040518060400160405280838152602001848152508482815181106115e5576115e5611f85565b60209081029190910101526115fa8284611d78565b92508061160681612075565b9150506115ab565b509195945050505050565b6060600082600001516001600160401b0381111561163957611639611b0c565b6040519080825280601f01601f191660200182016040528015611663576020820181803683370190505b50905080516000036116755792915050565b60008160200190506114bd84602001518286600001516119b2565b805160609061169e57600080fd5b6000806116aa84611a35565b915091506000816001600160401b038111156116c8576116c8611b0c565b6040519080825280601f01601f1916602001820160405280156116f2576020820181803683370190505b509050602081016117048482856119b2565b50949350505050565b600061171882611a7c565b92915050565b6001600160a01b0381163b61178b5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016101a2565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b805160009081036117df57506000919050565b6020820151805160001a9060c08210156117fd575060009392505050565b5060019392505050565b8051600090810361181a57506000919050565b60008061182a846020015161188c565b84602001516118399190611d78565b90506000846000015185602001516118519190611d78565b90505b80821015611883576118658261190e565b61186f9083611d78565b91508261187b81612075565b935050611854565b50909392505050565b8051600090811a60808110156118a55750600092915050565b60b88110806118c0575060c081108015906118c0575060f881105b156118ce5750600192915050565b60c0811015611902576118e3600160b861208e565b6118f09060ff16826120b1565b6118fb906001611d78565b9392505050565b6118e3600160f861208e565b80516000908190811a608081101561192957600191506114bd565b60b881101561194f5761193d6080826120b1565b611948906001611d78565b91506114bd565b60c081101561197c5760b78103600185019450806020036101000a855104600182018101935050506114bd565b60f88110156119905761193d60c0826120b1565b60019390930151602084900360f7016101000a900490920160f5190192915050565b806000036119bf57505050565b602081106119f757825182526119d6602084611d78565b92506119e3602083611d78565b91506119f06020826120b1565b90506119bf565b8015611a305760006001611a0c8360206120b1565b611a18906101006121ac565b611a2291906120b1565b845184518216911916178352505b505050565b6000806000611a47846020015161188c565b90506000818560200151611a5b9190611d78565b90506000828660000151611a6f91906120b1565b9196919550909350505050565b805160009015801590611a9157508151602110155b611a9a57600080fd5b600080611aa684611a35565b815191935091506020821015611ac25760208290036101000a90045b949350505050565b6001600160a01b0381168114610cd757600080fd5b600060208284031215611af157600080fd5b81356118fb81611aca565b61ffff81168114610cd757600080fd5b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611b4a57611b4a611b0c565b604052919050565b60006001600160401b03821115611b6b57611b6b611b0c565b50601f01601f191660200190565b600082601f830112611b8a57600080fd5b8135611b9d611b9882611b52565b611b22565b818152846020838601011115611bb257600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215611be557600080fd5b8435611bf081611afc565b9350602085013592506040850135915060608501356001600160401b03811115611c1957600080fd5b611c2587828801611b79565b91505092959194509250565b60008060408385031215611c4457600080fd5b8235611c4f81611afc565b946020939093013593505050565b600060208284031215611c6f57600080fd5b81356118fb81611afc565b60008060408385031215611c8d57600080fd5b8235611c9881611afc565b91506020830135611ca881611aca565b809150509250929050565b600060208284031215611cc557600080fd5b5035919050565b600080600060608486031215611ce157600080fd5b8335611cec81611afc565b92506020840135611cfc81611aca565b915060408401356001600160401b03811115611d1757600080fd5b611d2386828701611b79565b9150509250925092565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052601160045260246000fd5b60008219821115611d8b57611d8b611d62565b500190565b60005b83811015611dab578181015183820152602001611d93565b83811115611dba576000848401525b50505050565b60008151808452611dd8816020860160208601611d90565b601f01601f19169290920160200192915050565b6020815260006118fb6020830184611dc0565b600082601f830112611e1057600080fd5b8151611e1e611b9882611b52565b818152846020838601011115611e3357600080fd5b611ac2826020830160208701611d90565b600060208284031215611e5657600080fd5b81516001600160401b0380821115611e6d57600080fd5b9083019060608286031215611e8157600080fd5b604051606081018181108382111715611e9c57611e9c611b0c565b80604052508251815260208301516020820152604083015182811115611ec157600080fd5b611ecd87828601611dff565b60408301525095945050505050565b600060208284031215611eee57600080fd5b815180151581146118fb57600080fd5b61ffff851681526001600160a01b03841660208201526001600160401b0383166040820152608060608201819052600090611f3b90830184611dc0565b9695505050505050565b6001600160a01b0383168152604060208201819052600090611ac290830184611dc0565b60008251611f7b818460208701611d90565b9190910192915050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611fad57600080fd5b5051919050565b600060208284031215611fc657600080fd5b81516118fb81611afc565b600060208284031215611fe357600080fd5b81516001600160401b03811681146118fb57600080fd5b6000806040838503121561200d57600080fd5b825161201881611aca565b60208401519092506001600160401b0381111561203457600080fd5b61204085828601611dff565b9150509250929050565b60006001600160401b0380831681851680830382111561206c5761206c611d62565b01949350505050565b60006001820161208757612087611d62565b5060010190565b600060ff821660ff8416808210156120a8576120a8611d62565b90039392505050565b6000828210156120c3576120c3611d62565b500390565b600181815b808511156121035781600019048211156120e9576120e9611d62565b808516156120f657918102915b93841c93908002906120cd565b509250929050565b60008261211a57506001611718565b8161212757506000611718565b816001811461213d576002811461214757612163565b6001915050611718565b60ff84111561215857612158611d62565b50506001821b611718565b5060208310610133831016604e8410600b8410161715612186575081810a611718565b61219083836120c8565b80600019048211156121a4576121a4611d62565b029392505050565b60006118fb838361210b56fea2646970667358221220aca67fd56b11b803902027b44648ec38f60bde397396a4a6fe265fc7399940bd64736f6c634300080e0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.