Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60a06040 | 18987043 | 316 days ago | IN | 0 ETH | 0.06503254 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
WorldIDIdentityManagerImplV2
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import "./WorldIDIdentityManagerImplV1.sol"; /// @title WorldID Identity Manager Implementation Version 2 /// @author Worldcoin /// @notice An implementation of a batch-based identity manager for the WorldID protocol. /// @dev The manager is based on the principle of verifying externally-created Zero Knowledge Proofs /// to perform the deletions. /// @dev This is the implementation delegated to by a proxy. contract WorldIDIdentityManagerImplV2 is WorldIDIdentityManagerImplV1 { /////////////////////////////////////////////////////////////////////////////// /// A NOTE ON IMPLEMENTATION CONTRACTS /// /////////////////////////////////////////////////////////////////////////////// // This contract is designed explicitly to operate from behind a proxy contract. As a result, // there are a few important implementation considerations: // // - All updates made after deploying a given version of the implementation should inherit from // the latest version of the implementation. This contract inherits from its previous implementation // WorldIDIdentityManagerImplV1. This prevents storage clashes. // - All functions that are less access-restricted than `private` should be marked `virtual` in // order to enable the fixing of bugs in the existing interface. // - Any function that reads from or modifies state (i.e. is not marked `pure`) must be // annotated with the `onlyProxy` and `onlyInitialized` modifiers. This ensures that it can // only be called when it has access to the data in the proxy, otherwise results are likely to // be nonsensical. // - This contract deals with important data for the WorldID system. Ensure that all newly-added // functionality is carefully access controlled using `onlyOwner`, or a more granular access // mechanism. // - Do not assign any contract-level variables at the definition site unless they are // `constant`. // // Additionally, the following notes apply: // // - Initialisation and ownership management are not protected behind `onlyProxy` intentionally. // This ensures that the contract can safely be disposed of after it is no longer used. // - Carefully consider what data recovery options are presented as new functionality is added. // Care must be taken to ensure that a migration plan can exist for cases where upgrades // cannot recover from an issue or vulnerability. /////////////////////////////////////////////////////////////////////////////// /// !!!!! DATA: DO NOT REORDER !!!!! /// /////////////////////////////////////////////////////////////////////////////// // To ensure compatibility between upgrades, it is exceedingly important that no reordering of // these variables takes place. If reordering happens, a storage clash will occur (effectively a // memory safety error). /// @notice The table of verifiers for verifying batch identity deletions. VerifierLookupTable internal batchDeletionVerifiers; /// @notice Thrown when the WorldIDIdentityManagerImplV2 contract is initalized event WorldIDIdentityManagerImplV2Initialized(); /// @notice Thrown when the bytes calldata packedDeletionIndices array /// is not a multiple of 4 (to make up 32 bit indices) error InvalidDeletionIndices(); /// @notice Initializes the V2 implementation contract. /// @param _batchDeletionVerifiers The table of verifiers for verifying batch identity deletions. /// @dev Must be called exactly once /// @dev This is marked `reinitializer()` to allow for updated initialisation steps when working /// with upgrades based upon this contract. Be aware that there are only 256 (zero-indexed) /// initialisations allowed, so decide carefully when to use them. Many cases can safely be /// replaced by use of setters. /// @dev This function is explicitly not virtual as it does not make sense to override even when /// upgrading. Create a separate initializer function instead. /// /// /// @custom:reverts InvalidVerifierLUT if `_batchDeletionVerifiers` is set to the zero address function initializeV2(VerifierLookupTable _batchDeletionVerifiers) public reinitializer(2) { if (address(_batchDeletionVerifiers) == address(0)) { revert InvalidVerifierLUT(); } batchDeletionVerifiers = _batchDeletionVerifiers; emit WorldIDIdentityManagerImplV2Initialized(); } /////////////////////////////////////////////////////////////////// /// IDENTITY MANAGEMENT /// /////////////////////////////////////////////////////////////////// /// @notice Deletes identities from the WorldID system. /// @dev Can only be called by the identity operator. /// @dev Deletion is performed off-chain and verified on-chain via the `deletionProof`. /// This saves gas and time over deleting identities one at a time. /// /// @param deletionProof The proof that given the conditions (`preRoot` and `packedDeletionIndices`), /// deletion into the tree results in `postRoot`. Elements 0 and 1 are the `x` and `y` /// coordinates for `ar` respectively. Elements 2 and 3 are the `x` coordinate for `bs`, /// and elements 4 and 5 are the `y` coordinate for `bs`. Elements 6 and 7 are the `x` /// and `y` coordinates for `krs`. /// @param packedDeletionIndices The indices of the identities that were deleted from the tree. The batch size is inferred from the length of this //// array: batchSize = packedDeletionIndices / 4 /// @param preRoot The value for the root of the tree before the corresponding identity commitments have /// been deleted. Must be an element of the field `Kr`. /// @param postRoot The root obtained after deleting all of `identityCommitments` into the tree /// described by `preRoot`. Must be an element of the field `Kr`. /// /// @custom:reverts Unauthorized If the message sender is not authorised to add identities. /// @custom:reverts NotLatestRoot If the provided `preRoot` is not the latest root. /// @custom:reverts ProofValidationFailure If `deletionProof` cannot be verified using the /// provided inputs. /// @custom:reverts VerifierLookupTable.NoSuchVerifier If the batch sizes doesn't match a known /// verifier. /// @custom:reverts InvalidDeletionIndices if the length of `packedDeletionIndices` /// is not a multiple of 4 (8*4 = 32 bits per index) function deleteIdentities( uint256[8] calldata deletionProof, bytes calldata packedDeletionIndices, uint256 preRoot, uint256 postRoot ) public virtual onlyProxy onlyInitialized onlyIdentityOperator { if (packedDeletionIndices.length % 4 != 0) { revert InvalidDeletionIndices(); } uint32 batchSize = uint32(packedDeletionIndices.length / 4); if (preRoot != _latestRoot) { revert NotLatestRoot(preRoot, _latestRoot); } // Having validated the preconditions we can now check the proof itself. bytes32 inputHash = calculateIdentityDeletionInputHash(packedDeletionIndices, preRoot, postRoot, batchSize); // No matter what, the inputs can result in a hash that is not an element of the scalar // field in which we're operating. We reduce it into the field before handing it to the // verifier. All other elements that are passed as calldata are reduced in the circuit. uint256 reducedElement = uint256(inputHash) % SNARK_SCALAR_FIELD; // We need to look up the correct verifier before we can verify. ITreeVerifier deletionVerifier = batchDeletionVerifiers.getVerifierFor(batchSize); // With that, we can properly try and verify. try deletionVerifier.verifyProof(deletionProof, [reducedElement]) { // If it did verify, we need to update the contract's state. We set the currently valid // root to the root after the deletions. _latestRoot = postRoot; // We also need to add the previous root to the history, and set the timestamp at // which it was expired. rootHistory[preRoot] = uint128(block.timestamp); emit TreeChanged(preRoot, TreeChange.Deletion, postRoot); } catch Error(string memory errString) { /// This is not the revert we're looking for. revert(errString); } catch { // If we reach here we know it's the internal error, as the tree verifier only uses // `require`s otherwise, which will be re-thrown above. revert ProofValidationFailure(); } } /// @notice Gets the address for the lookup table of merkle tree verifiers used for batch identity /// deletions. /// @dev The deletion verifier supports batch deletions of size 10, 100 and 1000 members per batch. /// /// @return addr The address of the contract being used as the verifier lookup table. function getDeleteIdentitiesVerifierLookupTableAddress() public view virtual onlyProxy onlyInitialized returns (address) { return address(batchDeletionVerifiers); } /// @notice Sets the address for the lookup table of merkle tree verifiers used for identity /// deletions. /// @dev Only the owner of the contract can call this function. /// /// @param newTable The new verifier lookup table to be used for verifying identity /// deletions. /// @custom:reverts InvalidVerifierLUT if `newTable` is set to the zero address function setDeleteIdentitiesVerifierLookupTable(VerifierLookupTable newTable) public virtual onlyProxy onlyInitialized onlyOwner { if (address(newTable) == address(0)) { revert InvalidVerifierLUT(); } VerifierLookupTable oldTable = batchDeletionVerifiers; batchDeletionVerifiers = newTable; emit DependencyUpdated( Dependency.DeletionVerifierLookupTable, address(oldTable), address(newTable) ); } /////////////////////////////////////////////////////////////////////////////// /// UTILITY FUNCTIONS /// /////////////////////////////////////////////////////////////////////////////// /// @notice Calculates the input hash for the identity deletion verifier. /// @dev Implements the computation described below. /// /// @param packedDeletionIndices The indices of the identities that were deleted from the tree. /// @param preRoot The root value of the tree before these deletions were made. /// @param postRoot The root value of the tree after these deletions were made. /// @param batchSize The number of identities that were deleted in this batch /// /// @return hash The input hash calculated as described below. /// /// @dev the deletion indices are packed into bytes calldata where each deletion index is 32 bits /// wide. The indices are encoded using abi.encodePacked for testing. /// /// We keccak hash all input to save verification gas. Inputs for the hash are arranged as follows: /// /// packedDeletionIndices || PreRoot || PostRoot /// 32 bits * batchSize || 256 || 256 function calculateIdentityDeletionInputHash( bytes calldata packedDeletionIndices, uint256 preRoot, uint256 postRoot, uint32 batchSize ) public view virtual onlyProxy onlyInitialized returns (bytes32 hash) { assembly { let startOffset := mload(0x40) let indicesByteSize := mul(batchSize, 4) calldatacopy(startOffset, packedDeletionIndices.offset, indicesByteSize) let rootsOffset := add(startOffset, indicesByteSize) mstore(rootsOffset, preRoot) mstore(add(rootsOffset, 32), postRoot) hash := keccak256(startOffset, add(64, indicesByteSize)) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import {WorldIDImpl} from "./abstract/WorldIDImpl.sol"; import {IWorldID} from "./interfaces/IWorldID.sol"; import {ITreeVerifier} from "./interfaces/ITreeVerifier.sol"; import {ISemaphoreVerifier} from "src/interfaces/ISemaphoreVerifier.sol"; import {IBridge} from "./interfaces/IBridge.sol"; import {SemaphoreTreeDepthValidator} from "./utils/SemaphoreTreeDepthValidator.sol"; import {VerifierLookupTable} from "./data/VerifierLookupTable.sol"; /// @title WorldID Identity Manager Implementation Version 1 /// @author Worldcoin /// @notice An implementation of a batch-based identity manager for the WorldID protocol. /// @dev The manager is based on the principle of verifying externally-created Zero Knowledge Proofs /// to perform the insertions. /// @dev This is the implementation delegated to by a proxy. contract WorldIDIdentityManagerImplV1 is WorldIDImpl, IWorldID { /////////////////////////////////////////////////////////////////////////////// /// A NOTE ON IMPLEMENTATION CONTRACTS /// /////////////////////////////////////////////////////////////////////////////// // This contract is designed explicitly to operate from behind a proxy contract. As a result, // there are a few important implementation considerations: // // - All updates made after deploying a given version of the implementation should inherit from // the latest version of the implementation. This prevents storage clashes. // - All functions that are less access-restricted than `private` should be marked `virtual` in // order to enable the fixing of bugs in the existing interface. // - Any function that reads from or modifies state (i.e. is not marked `pure`) must be // annotated with the `onlyProxy` and `onlyInitialized` modifiers. This ensures that it can // only be called when it has access to the data in the proxy, otherwise results are likely to // be nonsensical. // - This contract deals with important data for the WorldID system. Ensure that all newly-added // functionality is carefully access controlled using `onlyOwner`, or a more granular access // mechanism. // - Do not assign any contract-level variables at the definition site unless they are // `constant`. // // Additionally, the following notes apply: // // - Initialisation and ownership management are not protected behind `onlyProxy` intentionally. // This ensures that the contract can safely be disposed of after it is no longer used. // - Carefully consider what data recovery options are presented as new functionality is added. // Care must be taken to ensure that a migration plan can exist for cases where upgrades // cannot recover from an issue or vulnerability. /////////////////////////////////////////////////////////////////////////////// /// !!!!! DATA: DO NOT REORDER !!!!! /// /////////////////////////////////////////////////////////////////////////////// // To ensure compatibility between upgrades, it is exceedingly important that no reordering of // these variables takes place. If reordering happens, a storage clash will occur (effectively a // memory safety error). /// @notice The address of the contract authorized to perform identity management operations. /// @dev The identity operator defaults to being the same as the owner. address internal _identityOperator; /// @notice The latest root of the identity merkle tree. uint256 internal _latestRoot; /// @notice A mapping from the value of the merkle tree root to the timestamp at which the root /// was superseded by a newer one. mapping(uint256 => uint128) internal rootHistory; /// @notice The amount of time an outdated root is considered as valid. /// @dev This prevents proofs getting invalidated in the mempool by another tx modifying the /// group. uint256 internal rootHistoryExpiry; /// @notice The `r` for the finite field `Fr` under which arithmetic is done on the proof input. /// @dev Used internally to ensure that the proof input is scaled to within the field `Fr`. uint256 internal constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617; uint256 internal constant SNARK_SCALAR_FIELD_MIN_ONE = 21888242871839275222246405745257275088548364400416034343698204186575808495616; /// @notice The table of verifiers for verifying batch identity insertions. VerifierLookupTable internal batchInsertionVerifiers; /// @notice The table of verifiers for verifying identity updates. /// @dev preserved for storage reasons, no longer used VerifierLookupTable internal identityUpdateVerifiers; /// @notice The verifier instance needed for operating within the semaphore protocol. ISemaphoreVerifier internal semaphoreVerifier; /// @notice The interface of the bridge contract from L1 to supported target chains. /// @dev preserved for storage reasons, no longer used IBridge internal _stateBridge; /// @notice Boolean flag to enable/disable the state bridge. bool internal _isStateBridgeEnabled; /// @notice The depth of the Semaphore merkle tree. uint8 internal treeDepth; /////////////////////////////////////////////////////////////////////////////// /// PUBLIC TYPES /// /////////////////////////////////////////////////////////////////////////////// /// @notice Provides information about a merkle tree root. /// /// @param root The value of the merkle tree root. /// @param supersededTimestamp The timestamp at which the root was inserted into the history. /// This may be 0 if the requested root is the current root (which has not yet been /// inserted into the history). /// @param isValid Whether or not the root is valid (has not expired). struct RootInfo { uint256 root; uint128 supersededTimestamp; bool isValid; } /// @notice Represents the kind of element that has not been provided in reduced form. /// @dev preserved for ABI backwards compatibility with V1, no longer used /// all elements come out reduced from the circuit enum UnreducedElementType { PreRoot, IdentityCommitment, PostRoot } /// @notice Represents the kind of change that is made to the root of the tree. enum TreeChange { Insertion, Deletion } /// @notice Represents the kinds of dependencies that can be updated. enum Dependency { StateBridge, InsertionVerifierLookupTable, DeletionVerifierLookupTable, SemaphoreVerifier } /////////////////////////////////////////////////////////////////////////////// /// CONSTANT FUNCTIONS /// /////////////////////////////////////////////////////////////////////////////// /// @notice A constant representing a root that doesn't exist. /// @dev Can be checked against when querying for root data. function NO_SUCH_ROOT() public pure returns (RootInfo memory rootInfo) { return RootInfo(0x0, 0x0, false); } /////////////////////////////////////////////////////////////////////////////// /// ERRORS /// /////////////////////////////////////////////////////////////////////////////// /// @notice Thrown when encountering an element that should be reduced as a member of `Fr` but /// is not. /// @dev `r` in this case is given by `SNARK_SCALAR_FIELD`. /// /// @param elementType The kind of element that was encountered unreduced. /// @param element The value of that element. /// @dev preserved for ABI backwards compatibility with V1, no longer used, /// all elements come out reduced from the circuit error UnreducedElement(UnreducedElementType elementType, uint256 element); /// @notice Thrown when trying to execute a privileged action without being the contract /// manager. /// /// @param user The user that attempted the action that they were not authorised for. error Unauthorized(address user); /// @notice Thrown when one or more of the identity commitments to be inserted is invalid. /// /// @param index The index in the array of identity commitments where the invalid commitment was /// found. /// @dev This error is no longer in use as we now verify the commitments off-chain within the circuit /// no need to check for reduced elements or invalid commitments. /// @dev preserved for ABI backwards compatibility with V1, no longer used, /// all elements are validated by the circuit error InvalidCommitment(uint256 index); /// @notice Thrown when the provided proof cannot be verified for the accompanying inputs. error ProofValidationFailure(); /// @notice Thrown when the provided root is not the very latest root. /// /// @param providedRoot The root that was provided as the `preRoot` for a transaction. /// @param latestRoot The actual latest root at the time of the transaction. error NotLatestRoot(uint256 providedRoot, uint256 latestRoot); /// @notice Thrown when attempting to enable the bridge when it is already enabled. /// @dev preserved for ABI backwards compatibility with V1, no longer used error StateBridgeAlreadyEnabled(); /// @notice Thrown when attempting to disable the bridge when it is already disabled. /// @dev preserved for ABI backwards compatibility with V1, no longer used error StateBridgeAlreadyDisabled(); /// @notice Thrown when attempting to set the state bridge address to the zero address. /// @dev preserved for ABI backwards compatibility with V1, no longer used error InvalidStateBridgeAddress(); /// @notice Thrown when Semaphore tree depth is not supported. /// /// @param depth Passed tree depth. error UnsupportedTreeDepth(uint8 depth); /// @notice Thrown when the inputs to `removeIdentities` do not match in /// length. /// @dev preserved for ABI backwards compatibility with V1, no longer used error MismatchedInputLengths(); /// @notice Thrown when a verifier is initialized to be the zero address error InvalidVerifier(); /// @notice Thrown when a verifier lookup table is initialized to be the zero address error InvalidVerifierLUT(); /////////////////////////////////////////////////////////////////////////////// /// EVENTS /// /////////////////////////////////////////////////////////////////////////////// /// @notice Emitted when the current root of the tree is updated. /// /// @param preRoot The value of the tree's root before the update. /// @param kind Either "insertion" or "update", the kind of alteration that was made to the /// tree. /// @param postRoot The value of the tree's root after the update. event TreeChanged(uint256 indexed preRoot, TreeChange indexed kind, uint256 indexed postRoot); /// @notice Emitted when a dependency's address is updated via an admin action. /// /// @param kind The kind of dependency that was updated. /// @param oldAddress The old address of that dependency. /// @param newAddress The new address of that dependency. event DependencyUpdated( Dependency indexed kind, address indexed oldAddress, address indexed newAddress ); /// @notice Emitted when the state bridge is enabled or disabled. /// /// @param isEnabled Set to `true` if the event comes from the state bridge being enabled, /// `false` otherwise. /// @dev preserved for ABI backwards compatibility with V1, no longer used event StateBridgeStateChange(bool indexed isEnabled); /// @notice Emitted when the root history expiry time is changed. /// /// @param oldExpiryTime The expiry time prior to the change. /// @param newExpiryTime The expiry time after the change. event RootHistoryExpirySet(uint256 indexed oldExpiryTime, uint256 indexed newExpiryTime); /// @notice Emitted when the identity operator is changed. /// /// @param oldOperator The address of the old identity operator. /// @param newOperator The address of the new identity operator. event IdentityOperatorChanged(address indexed oldOperator, address indexed newOperator); /// @notice Emitter when the WorldIDIdentityManagerImpl is initialized. /// @param _treeDepth The depth of the MerkeTree /// @param initialRoot The initial value for the `latestRoot` in the contract. When deploying /// this should be set to the root of the empty tree. event WorldIDIdentityManagerImplInitialized(uint8 _treeDepth, uint256 initialRoot); /////////////////////////////////////////////////////////////////////////////// /// INITIALIZATION /// /////////////////////////////////////////////////////////////////////////////// /// @notice Constructs the contract. constructor() { // When called in the constructor, this is called in the context of the implementation and // not the proxy. Calling this thereby ensures that the contract cannot be spuriously // initialized on its own. _disableInitializers(); } /// @notice Initializes the contract. /// @dev Must be called exactly once. /// @dev This is marked `reinitializer()` to allow for updated initialisation steps when working /// with upgrades based upon this contract. Be aware that there are only 256 (zero-indexed) /// initialisations allowed, so decide carefully when to use them. Many cases can safely be /// replaced by use of setters. /// @dev This function is explicitly not virtual as it does not make sense to override even when /// upgrading. Create a separate initializer function instead. /// /// @param _treeDepth The depth of the MerkeTree /// @param initialRoot The initial value for the `latestRoot` in the contract. When deploying /// this should be set to the root of the empty tree. /// @param _batchInsertionVerifiers The verifier lookup table for batch insertions. /// @param _batchUpdateVerifiers The verifier lookup table for batch updates. /// @param _semaphoreVerifier The verifier to use for semaphore protocol proofs. /// /// @custom:reverts string If called more than once at the same initialisation number. /// @custom:reverts UnsupportedTreeDepth If passed tree depth is not among defined values. /// @custom:reverts InvalidVerifierLUT if `_batchInsertionVerifiers` or `_batchUpdateVerifiers` is set to the zero address /// @custom:reverts InvalidVerifier if `_semaphoreVerifier` is set to the zero address function initialize( uint8 _treeDepth, uint256 initialRoot, VerifierLookupTable _batchInsertionVerifiers, VerifierLookupTable _batchUpdateVerifiers, ISemaphoreVerifier _semaphoreVerifier ) public reinitializer(1) { if (address(_batchInsertionVerifiers) == address(0)) { revert InvalidVerifierLUT(); } if (address(_batchUpdateVerifiers) == address(0)) { revert InvalidVerifierLUT(); } if (address(_semaphoreVerifier) == address(0)) { revert InvalidVerifier(); } // First, ensure that all of the parent contracts are initialised. __delegateInit(); if (!SemaphoreTreeDepthValidator.validate(_treeDepth)) { revert UnsupportedTreeDepth(_treeDepth); } // Now perform the init logic for this contract. treeDepth = _treeDepth; rootHistoryExpiry = 1 hours; _latestRoot = initialRoot; batchInsertionVerifiers = _batchInsertionVerifiers; identityUpdateVerifiers = _batchUpdateVerifiers; semaphoreVerifier = _semaphoreVerifier; _identityOperator = owner(); // Say that the contract is initialized. __setInitialized(); emit WorldIDIdentityManagerImplInitialized(_treeDepth, initialRoot); } /// @notice Responsible for initialising all of the supertypes of this contract. /// @dev Must be called exactly once. /// @dev When adding new superclasses, ensure that any initialization that they need to perform /// is accounted for here. /// /// @custom:reverts string If called more than once. function __delegateInit() internal virtual onlyInitializing { __WorldIDImpl_init(); } /////////////////////////////////////////////////////////////////////////////// /// IDENTITY MANAGEMENT /// /////////////////////////////////////////////////////////////////////////////// /// @notice Registers identities into the WorldID system. /// @dev Can only be called by the identity operator. /// @dev Registration is performed off-chain and verified on-chain via the `insertionProof`. /// This saves gas and time over inserting identities one at a time. /// /// @param insertionProof The proof that given the conditions (`preRoot`, `startIndex` and /// `identityCommitments`), insertion into the tree results in `postRoot`. Elements 0 and /// 1 are the `x` and `y` coordinates for `ar` respectively. Elements 2 and 3 are the `x` /// coordinate for `bs`, and elements 4 and 5 are the `y` coordinate for `bs`. Elements 6 /// and 7 are the `x` and `y` coordinates for `krs`. /// @param preRoot The value for the root of the tree before the `identityCommitments` have been //// inserted. Must be an element of the field `Kr`. (already in reduced form) /// @param startIndex The position in the tree at which the insertions were made. /// @param identityCommitments The identities that were inserted into the tree starting at /// `startIndex` and `preRoot` to give `postRoot`. All of the commitments must be /// elements of the field `Kr`. /// @param postRoot The root obtained after inserting all of `identityCommitments` into the tree /// described by `preRoot`. Must be an element of the field `Kr`. (alread in reduced form) /// /// @custom:reverts Unauthorized If the message sender is not authorised to add identities. /// @custom:reverts NotLatestRoot If the provided `preRoot` is not the latest root. /// @custom:reverts ProofValidationFailure If `insertionProof` cannot be verified using the /// provided inputs. /// @custom:reverts VerifierLookupTable.NoSuchVerifier If the batch sizes doesn't match a known /// verifier. function registerIdentities( uint256[8] calldata insertionProof, uint256 preRoot, uint32 startIndex, uint256[] calldata identityCommitments, uint256 postRoot ) public virtual onlyProxy onlyInitialized onlyIdentityOperator { if (preRoot != _latestRoot) { revert NotLatestRoot(preRoot, _latestRoot); } // Having validated the preconditions we can now check the proof itself. bytes32 inputHash = calculateIdentityRegistrationInputHash( startIndex, preRoot, postRoot, identityCommitments ); // No matter what, the inputs can result in a hash that is not an element of the scalar // field in which we're operating. We reduce it into the field before handing it to the // verifier. All other elements that are passed as calldata are reduced in the circuit. uint256 reducedElement = uint256(inputHash) % SNARK_SCALAR_FIELD; // We need to look up the correct verifier before we can verify. ITreeVerifier insertionVerifier = batchInsertionVerifiers.getVerifierFor(identityCommitments.length); // With that, we can properly try and verify. try insertionVerifier.verifyProof(insertionProof, [reducedElement]) { // If it did verify, we need to update the contract's state. We set the currently valid // root to the root after the insertions. _latestRoot = postRoot; // We also need to add the previous root to the history, and set the timestamp at // which it was expired. rootHistory[preRoot] = uint128(block.timestamp); emit TreeChanged(preRoot, TreeChange.Insertion, postRoot); } catch Error(string memory errString) { /// This is not the revert we're looking for. revert(errString); } catch { // If we reach here we know it's the internal error, as the tree verifier only uses // `require`s otherwise, which will be re-thrown above. revert ProofValidationFailure(); } } /////////////////////////////////////////////////////////////////////////////// /// UTILITY FUNCTIONS /// /////////////////////////////////////////////////////////////////////////////// /// @notice Calculates the input hash for the identity registration verifier. /// @dev Implements the computation described below. /// /// @param startIndex The index in the tree from which inserting started. /// @param preRoot The root value of the tree before these insertions were made. /// @param postRoot The root value of the tree after these insertions were made. /// @param identityCommitments The identities that were added to the tree to produce `postRoot`. /// /// @return hash The input hash calculated as described below. /// /// We keccak hash all input to save verification gas. Inputs are arranged as follows: /// /// StartIndex || PreRoot || PostRoot || IdComms[0] || IdComms[1] || ... || IdComms[batchSize-1] /// 32 || 256 || 256 || 256 || 256 || ... || 256 bits function calculateIdentityRegistrationInputHash( uint32 startIndex, uint256 preRoot, uint256 postRoot, uint256[] calldata identityCommitments ) public view virtual onlyProxy onlyInitialized returns (bytes32 hash) { bytes memory bytesToHash = abi.encodePacked(startIndex, preRoot, postRoot, identityCommitments); hash = keccak256(bytesToHash); } /// @notice Allows a caller to query the latest root. /// /// @return root The value of the latest tree root. function latestRoot() public view virtual onlyProxy onlyInitialized returns (uint256) { return _latestRoot; } /// @notice Allows a caller to query the root history for information about a given root. /// @dev Should be used sparingly as the query can be quite expensive. /// /// @param root The root for which you are querying information. /// @return rootInfo The information about `root`, or `NO_SUCH_ROOT` if `root` does not exist. /// Note that if the queried root is the current, the timestamp will be invalid as the /// root has not been superseded. function queryRoot(uint256 root) public view virtual onlyProxy onlyInitialized returns (RootInfo memory) { if (root == _latestRoot) { return RootInfo(_latestRoot, 0, true); } else { uint128 rootTimestamp = rootHistory[root]; if (rootTimestamp == 0) { return NO_SUCH_ROOT(); } bool isValid = !(block.timestamp - rootTimestamp > rootHistoryExpiry); return RootInfo(root, rootTimestamp, isValid); } } /// @notice Reverts if the provided root value is not valid. /// @dev A root is valid if it is either the latest root, or not the latest root but has not /// expired. /// /// @param root The root of the merkle tree to check for validity. /// /// @custom:reverts ExpiredRoot If the provided `root` has expired. /// @custom:reverts NonExistentRoot If the provided `root` does not exist in the history. function requireValidRoot(uint256 root) public view virtual onlyProxy onlyInitialized { // The latest root is always valid. if (root == _latestRoot) { return; } // Otherwise, we need to check things via the timestamp. uint128 rootTimestamp = rootHistory[root]; // A root does not exist if it has no associated timestamp. if (rootTimestamp == 0) { revert NonExistentRoot(); } // A root is no longer valid if it has expired. if (block.timestamp - rootTimestamp > rootHistoryExpiry) { revert ExpiredRoot(); } } /// @notice Gets the address for the lookup table of merkle tree verifiers used for identity /// registrations. /// /// @return addr The address of the contract being used as the verifier lookup table. function getRegisterIdentitiesVerifierLookupTableAddress() public view virtual onlyProxy onlyInitialized returns (address) { return address(batchInsertionVerifiers); } /// @notice Sets the address for the lookup table of merkle tree verifiers used for identity /// registrations. /// @dev Only the owner of the contract can call this function. /// /// @param newTable The new verifier lookup table to be used for verifying identity /// registrations. /// @custom:reverts InvalidVerifierLUT if `newTable` is set to the zero address function setRegisterIdentitiesVerifierLookupTable(VerifierLookupTable newTable) public virtual onlyProxy onlyInitialized onlyOwner { if (address(newTable) == address(0)) { revert InvalidVerifierLUT(); } VerifierLookupTable oldTable = batchInsertionVerifiers; batchInsertionVerifiers = newTable; emit DependencyUpdated( Dependency.InsertionVerifierLookupTable, address(oldTable), address(newTable) ); } /// @notice Gets the address of the verifier used for verification of semaphore proofs. /// /// @return addr The address of the contract being used as the verifier. function getSemaphoreVerifierAddress() public view virtual onlyProxy onlyInitialized returns (address) { return address(semaphoreVerifier); } /// @notice Sets the address for the semaphore verifier to be used for verification of /// semaphore proofs. /// @dev Only the owner of the contract can call this function. /// /// @param newVerifier The new verifier instance to be used for verifying semaphore proofs. /// @custom:reverts InvalidVerifier if `newVerifier` is set to the zero address function setSemaphoreVerifier(ISemaphoreVerifier newVerifier) public virtual onlyProxy onlyInitialized onlyOwner { if (address(newVerifier) == address(0)) { revert InvalidVerifier(); } ISemaphoreVerifier oldVerifier = semaphoreVerifier; semaphoreVerifier = newVerifier; emit DependencyUpdated( Dependency.SemaphoreVerifier, address(oldVerifier), address(newVerifier) ); } /// @notice Gets the current amount of time used to expire roots in the history. /// /// @return expiryTime The amount of time it takes for a root to expire. function getRootHistoryExpiry() public view virtual onlyProxy onlyInitialized returns (uint256) { return rootHistoryExpiry; } /// @notice Sets the time to wait before expiring a root from the root history. /// @dev Only the owner of the contract can call this function. /// /// @param newExpiryTime The new time to use to expire roots. function setRootHistoryExpiry(uint256 newExpiryTime) public virtual onlyProxy onlyInitialized onlyOwner { if (newExpiryTime == 0) { revert("Expiry time cannot be zero."); } uint256 oldExpiry = rootHistoryExpiry; rootHistoryExpiry = newExpiryTime; emit RootHistoryExpirySet(oldExpiry, newExpiryTime); } /// @notice Gets the Semaphore tree depth the contract was initialized with. /// /// @return initializedTreeDepth Tree depth. function getTreeDepth() public view virtual onlyProxy onlyInitialized returns (uint8) { return treeDepth; } /// @notice Gets the address that is authorised to perform identity operations on this identity /// manager instance. /// /// @return _ The address authorized to perform identity operations. function identityOperator() public view virtual onlyProxy onlyInitialized returns (address) { return _identityOperator; } /// @notice Sets the address that is authorised to perform identity operations on this identity /// manager instance. /// /// @param newIdentityOperator The address of the new identity operator. /// /// @return _ The address of the old identity operator. function setIdentityOperator(address newIdentityOperator) public virtual onlyProxy onlyInitialized onlyOwner returns (address) { address oldOperator = _identityOperator; _identityOperator = newIdentityOperator; emit IdentityOperatorChanged(oldOperator, newIdentityOperator); return oldOperator; } /////////////////////////////////////////////////////////////////////////////// /// SEMAPHORE PROOF VALIDATION LOGIC /// /////////////////////////////////////////////////////////////////////////////// /// @notice A verifier for the semaphore protocol. /// @dev Note that a double-signaling check is not included here, and should be carried by the /// caller. /// /// @param proof The zero-knowledge proof /// @param root The of the Merkle tree /// @param signalHash A keccak256 hash of the Semaphore signal /// @param nullifierHash The nullifier hash /// @param externalNullifierHash A keccak256 hash of the external nullifier /// /// @custom:reverts string If the zero-knowledge proof cannot be verified for the public inputs. function verifyProof( uint256 root, uint256 signalHash, uint256 nullifierHash, uint256 externalNullifierHash, uint256[8] calldata proof ) public view virtual onlyProxy onlyInitialized { // Check the preconditions on the inputs. requireValidRoot(root); // With that done we can now verify the proof. semaphoreVerifier.verifyProof( proof, [root, nullifierHash, signalHash, externalNullifierHash] ); } /////////////////////////////////////////////////////////////////////////////// /// SEMAPHORE PROOF VALIDATION LOGIC /// /////////////////////////////////////////////////////////////////////////////// /// @notice Ensures that the guarded operation can only be performed by the authorized identity /// operator contract. /// /// @custom:reverts Unauthorized If the caller is not the identity operator. modifier onlyIdentityOperator() { if (msg.sender != _identityOperator) { revert Unauthorized(msg.sender); } _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import {CheckInitialized} from "../utils/CheckInitialized.sol"; import {Ownable2StepUpgradeable} from "contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; import {UUPSUpgradeable} from "contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; /// @title WorldID Proxy Contract Implementation /// @author Worldcoin /// @notice A router component that can dispatch group numbers to the correct identity manager /// implementation. /// @dev This is base class for implementations delegated to by a proxy. abstract contract WorldIDImpl is Ownable2StepUpgradeable, UUPSUpgradeable, CheckInitialized { /////////////////////////////////////////////////////////////////////////////// /// A NOTE ON IMPLEMENTATION CONTRACTS /// /////////////////////////////////////////////////////////////////////////////// // This contract is designed explicitly to operate from behind a proxy contract. As a result, // there are a few important implementation considerations: // // - All updates made after deploying a given version of the implementation should inherit from // the latest version of the implementation. This prevents storage clashes. // - All functions that are less access-restricted than `private` should be marked `virtual` in // order to enable the fixing of bugs in the existing interface. // - Any function that reads from or modifies state (i.e. is not marked `pure`) must be // annotated with the `onlyProxy` and `onlyInitialized` modifiers. This ensures that it can // only be called when it has access to the data in the proxy, otherwise results are likely to // be nonsensical. // - This contract deals with important data for the WorldID system. Ensure that all newly-added // functionality is carefully access controlled using `onlyOwner`, or a more granular access // mechanism. // - Do not assign any contract-level variables at the definition site unless they are // `constant`. // // Additionally, the following notes apply: // // - Initialisation and ownership management are not protected behind `onlyProxy` intentionally. // This ensures that the contract can safely be disposed of after it is no longer used. // - Carefully consider what data recovery options are presented as new functionality is added. // Care must be taken to ensure that a migration plan can exist for cases where upgrades // cannot recover from an issue or vulnerability. /////////////////////////////////////////////////////////////////////////////// /// INITIALIZATION /// /////////////////////////////////////////////////////////////////////////////// /// @notice Performs the initialisation steps necessary for the base contracts of this contract. /// @dev Must be called during `initialize` before performing any additional steps. function __WorldIDImpl_init() internal virtual onlyInitializing { __Ownable_init(); __UUPSUpgradeable_init(); } /////////////////////////////////////////////////////////////////////////////// /// ERRORS /// /////////////////////////////////////////////////////////////////////////////// /// @notice Thrown when an attempt is made to renounce ownership. error CannotRenounceOwnership(); /////////////////////////////////////////////////////////////////////////////// /// AUTHENTICATION /// /////////////////////////////////////////////////////////////////////////////// /// @notice Is called when upgrading the contract to check whether it should be performed. /// /// @param newImplementation The address of the implementation being upgraded to. /// /// @custom:reverts string If the upgrade should not be performed. function _authorizeUpgrade(address newImplementation) internal virtual override onlyProxy onlyOwner { // No body needed as `onlyOwner` handles it. } /// @notice Ensures that ownership of WorldID implementations cannot be renounced. /// @dev This function is intentionally not `virtual` as we do not want it to be possible to /// renounce ownership for any WorldID implementation. /// @dev This function is marked as `onlyOwner` to maintain the access restriction from the base /// contract. function renounceOwnership() public view override onlyOwner { revert CannotRenounceOwnership(); } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import {IBaseWorldID} from "./IBaseWorldID.sol"; /// @title WorldID Interface /// @author Worldcoin /// @notice The interface to the proof verification for WorldID. interface IWorldID is IBaseWorldID { /// @notice Verifies a WorldID zero knowledge proof. /// @dev Note that a double-signaling check is not included here, and should be carried by the /// caller. /// @dev It is highly recommended that the implementation is restricted to `view` if possible. /// /// @param root The of the Merkle tree /// @param signalHash A keccak256 hash of the Semaphore signal /// @param nullifierHash The nullifier hash /// @param externalNullifierHash A keccak256 hash of the external nullifier /// @param proof The zero-knowledge proof /// /// @custom:reverts string If the `proof` is invalid. function verifyProof( uint256 root, uint256 signalHash, uint256 nullifierHash, uint256 externalNullifierHash, uint256[8] calldata proof ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; /// @title Tree Verifier Interface /// @author Worldcoin /// @notice An interface representing a merkle tree verifier. interface ITreeVerifier { /// @notice Verify an uncompressed Groth16 proof. /// @notice Reverts with InvalidProof if the proof is invalid or /// with PublicInputNotInField the public input is not reduced. /// @notice There is no return value. If the function does not revert, the /// proof was succesfully verified. /// @param proof the points (A, B, C) in EIP-197 format matching the output /// of compressProof. /// @param input the public input field elements in the scalar field Fr. /// Elements must be reduced. function verifyProof(uint256[8] calldata proof, uint256[1] calldata input) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; /// @title Tree Verifier Interface /// @author Worldcoin /// @notice An interface representing a merkle tree verifier. interface ISemaphoreVerifier { /// @notice Verify an uncompressed Groth16 proof. /// @notice Reverts with InvalidProof if the proof is invalid or /// with PublicInputNotInField the public input is not reduced. /// @notice There is no return value. If the function does not revert, the /// proof was succesfully verified. /// @param proof the points (A, B, C) in EIP-197 format matching the output /// of compressProof. /// @param input the public input field elements in the scalar field Fr. /// Elements must be reduced. function verifyProof(uint256[8] calldata proof, uint256[4] calldata input) external view; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; interface IBridge { /// @notice Sends the latest Semaphore root to Optimism. /// @dev Calls this method on the L1 Proxy contract to relay the latest root to all supported networks /// @param root The latest Semaphore root. function sendRootMultichain(uint256 root) external; /// @notice Sets the root history expiry for OpWorldID (on Optimism) and PolygonWorldID (on Polygon) /// @param expiryTime The new root history expiry for OpWorldID and PolygonWorldID /// @dev gated by onlyWorldIDIdentityManager modifier function setRootHistoryExpiry(uint256 expiryTime) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; /// @title Semaphore tree depth validator /// @author Worldcoin /// @notice library SemaphoreTreeDepthValidator { /// @notice Checks if the provided `treeDepth` is amoung supported depths. /// /// @param treeDepth The tree depth to validate. /// @return supportedDepth Returns `true` if `treeDepth` is between 16 and 32 - depths supported by the Semaphore function validate(uint8 treeDepth) internal pure returns (bool supportedDepth) { uint8 minDepth = 16; uint8 maxDepth = 32; return treeDepth >= minDepth && treeDepth <= maxDepth; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import {Ownable2Step} from "openzeppelin-contracts/access/Ownable2Step.sol"; import {ITreeVerifier} from "../interfaces/ITreeVerifier.sol"; /// @title Batch Lookup Table /// @author Worldcoin /// @notice A table that provides the correct tree verifier based on the provided batch size. /// @dev It should be used to query the correct verifier before using that verifier for verifying a /// tree modification proof. contract VerifierLookupTable is Ownable2Step { //////////////////////////////////////////////////////////////////////////////// /// DATA /// //////////////////////////////////////////////////////////////////////////////// /// The null address. address internal constant nullAddress = address(0x0); /// The null verifier. ITreeVerifier internal constant nullVerifier = ITreeVerifier(nullAddress); /// The lookup table for routing batches. /// /// As we expect to only have a few batch sizes per contract, a mapping is used due to its /// natively sparse storage. mapping(uint256 => ITreeVerifier) internal verifier_lut; //////////////////////////////////////////////////////////////////////////////// /// ERRORS /// //////////////////////////////////////////////////////////////////////////////// /// @notice Raised if a batch size is requested that the lookup table doesn't know about. error NoSuchVerifier(); /// @notice Raised if an attempt is made to add a verifier for a batch size that already exists. error VerifierExists(); /// @notice Thrown when an attempt is made to renounce ownership. error CannotRenounceOwnership(); //////////////////////////////////////////////////////////////////////////////// /// EVENTS /// //////////////////////////////////////////////////////////////////////////////// /// @notice Emitted when a verifier is added to the lookup table. /// /// @param batchSize The size of the batch that the verifier has been added for. /// @param verifierAddress The address of the verifier that was associated with `batchSize`. event VerifierAdded(uint256 indexed batchSize, address indexed verifierAddress); /// @notice Emitted when a verifier is updated in the lookup table. /// /// @param batchSize The size of the batch that the verifier has been updated for. /// @param oldVerifierAddress The address of the old verifier for `batchSize`. /// @param newVerifierAddress The address of the new verifier for `batchSize`. event VerifierUpdated( uint256 indexed batchSize, address indexed oldVerifierAddress, address indexed newVerifierAddress ); /// @notice Emitted when a verifier is disabled in the lookup table. /// /// @param batchSize The batch size that had its verifier disabled. event VerifierDisabled(uint256 indexed batchSize); //////////////////////////////////////////////////////////////////////////////// /// CONSTRUCTION /// //////////////////////////////////////////////////////////////////////////////// /// @notice Constructs a new batch lookup table. /// @dev It is initially constructed without any verifiers. constructor() Ownable2Step() {} //////////////////////////////////////////////////////////////////////////////// /// ACCESSORS /// //////////////////////////////////////////////////////////////////////////////// /// @notice Obtains the verifier for the provided `batchSize`. /// /// @param batchSize The batch size to get the associated verifier for. /// /// @return verifier The tree verifier for the provided `batchSize`. /// /// @custom:reverts NoSuchVerifier If there is no verifier associated with the `batchSize`. function getVerifierFor(uint256 batchSize) public view returns (ITreeVerifier verifier) { // Check the preconditions for querying the verifier. validateVerifier(batchSize); // With the preconditions checked, we can return the verifier. verifier = verifier_lut[batchSize]; } /// @notice Adds a verifier for the provided `batchSize`. /// /// @param batchSize The batch size to add the verifier for. /// @param verifier The verifier for a batch of size `batchSize`. /// /// @custom:reverts VerifierExists If `batchSize` already has an associated verifier. /// @custom:reverts string If the caller is not the owner. function addVerifier(uint256 batchSize, ITreeVerifier verifier) public onlyOwner { // Check that there is no entry for that batch size. if (verifier_lut[batchSize] != nullVerifier) { revert VerifierExists(); } // Add the verifier. updateVerifier(batchSize, verifier); emit VerifierAdded(batchSize, address(verifier)); } /// @notice Updates the verifier for the provided `batchSize`. /// /// @param batchSize The batch size to add the verifier for. /// @param verifier The verifier for a batch of size `batchSize`. /// /// @return oldVerifier The old verifier instance associated with this batch size. /// /// @custom:reverts string If the caller is not the owner. function updateVerifier(uint256 batchSize, ITreeVerifier verifier) public onlyOwner returns (ITreeVerifier oldVerifier) { oldVerifier = verifier_lut[batchSize]; verifier_lut[batchSize] = verifier; emit VerifierUpdated(batchSize, address(oldVerifier), address(verifier)); } /// @notice Disables the verifier for the provided batch size. /// /// @param batchSize The batch size to disable the verifier for. /// /// @return oldVerifier The old verifier associated with the batch size. /// /// @custom:reverts string If the caller is not the owner. function disableVerifier(uint256 batchSize) public onlyOwner returns (ITreeVerifier oldVerifier) { oldVerifier = updateVerifier(batchSize, ITreeVerifier(nullAddress)); emit VerifierDisabled(batchSize); } //////////////////////////////////////////////////////////////////////////////// /// INTERNAL FUNCTIONALITY /// //////////////////////////////////////////////////////////////////////////////// /// @notice Checks if the entry for the provided `batchSize` is a valid verifier. /// /// @param batchSize The batch size to check. /// /// @custom:reverts NoSuchVerifier If `batchSize` does not have an associated verifier. /// @custom:reverts BatchTooLarge If `batchSize` exceeds the maximum batch size. function validateVerifier(uint256 batchSize) internal view { if (verifier_lut[batchSize] == nullVerifier) { revert NoSuchVerifier(); } } //////////////////////////////////////////////////////////////////////////////// /// OWNERSHIP MANAGEMENT /// //////////////////////////////////////////////////////////////////////////////// /// @notice Ensures that ownership of the lookup table cannot be renounced. /// @dev This function is intentionally not `virtual` as we do not want it to be possible to /// renounce ownership for the lookup table. /// @dev This function is marked as `onlyOwner` to maintain the access restriction from the base /// contract. function renounceOwnership() public view override onlyOwner { revert CannotRenounceOwnership(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import {Initializable} from "contracts-upgradeable/proxy/utils/Initializable.sol"; /// @title Initialization Checker /// @author Worldcoin /// @notice A contract that represents the ability to initialize a proxy-based contract but also to /// check that said contract is initialized. contract CheckInitialized is Initializable { /// @notice Whether the initialization has been completed. /// @dev This relies on the fact that a default-init `bool` is `false` here. bool private _initialized; /// @notice Thrown when attempting to call a function while the implementation has not been /// initialized. error ImplementationNotInitialized(); /// @notice Sets the contract as initialized. function __setInitialized() internal onlyInitializing { _initialized = true; } /// @notice Asserts that the annotated function can only be called once the contract has been /// initialized. modifier onlyInitialized() { if (!_initialized) { revert ImplementationNotInitialized(); } _; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (access/Ownable2Step.sol) pragma solidity ^0.8.0; import "./OwnableUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable { function __Ownable2Step_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable2Step_init_unchained() internal onlyInitializing { } address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() external { address sender = _msgSender(); require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); _transferOwnership(sender); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.0; import "../../interfaces/draft-IERC1822Upgradeable.sol"; import "../ERC1967/ERC1967UpgradeUpgradeable.sol"; import "./Initializable.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. * * _Available since v4.1._ */ abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable { function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __self = address(this); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { require(address(this) != __self, "Function must be called through delegatecall"); require(_getImplementation() == __self, "Function must be called through active proxy"); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall"); _; } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual override notDelegated returns (bytes32) { return _IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeTo(address newImplementation) external virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data, true); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeTo} and {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal override onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.21; /// @title Base WorldID interface /// @author Worldcoin /// @notice The interface providing basic types across various WorldID contracts. interface IBaseWorldID { /////////////////////////////////////////////////////////////////////////////// /// ERRORS /// /////////////////////////////////////////////////////////////////////////////// /// @notice Thrown when attempting to validate a root that has expired. error ExpiredRoot(); /// @notice Thrown when attempting to validate a root that has yet to be added to the root /// history. error NonExistentRoot(); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (access/Ownable2Step.sol) pragma solidity ^0.8.0; import "./Ownable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); _transferOwnership(sender); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.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 IERC1822ProxiableUpgradeable { /** * @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.5.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeaconUpgradeable.sol"; import "../../interfaces/draft-IERC1822Upgradeable.sol"; import "../../utils/AddressUpgradeable.sol"; import "../../utils/StorageSlotUpgradeable.sol"; import "../utils/Initializable.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 ERC1967UpgradeUpgradeable is Initializable { function __ERC1967Upgrade_init() internal onlyInitializing { } function __ERC1967Upgrade_init_unchained() internal onlyInitializing { } // 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 Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlotUpgradeable.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) { _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 (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822ProxiableUpgradeable(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 Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlotUpgradeable.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"); StorageSlotUpgradeable.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 Emitted when the beacon is upgraded. */ event BeaconUpgraded(address indexed beacon); /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlotUpgradeable.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) { _functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data); } } /** * @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) private returns (bytes memory) { require(AddressUpgradeable.isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return AddressUpgradeable.verifyCallResult(success, returndata, "Address: low-level delegate call failed"); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// 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 AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [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 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 v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeaconUpgradeable { /** * @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.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 StorageSlotUpgradeable { 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 // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
{ "remappings": [ "ds-test/=lib/ds-test/src/", "@zk-kit/=lib/zk-kit/packages/", "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/", "contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "semaphore/=lib/semaphore/packages/contracts/contracts/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin/=lib/openzeppelin-contracts/contracts/", "solmate/=lib/solmate/src/", "zk-kit/=lib/zk-kit/" ], "optimizer": { "enabled": true, "runs": 200, "details": { "peephole": true, "inliner": true, "deduplicate": true, "cse": true, "yul": true } }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"CannotRenounceOwnership","type":"error"},{"inputs":[],"name":"ExpiredRoot","type":"error"},{"inputs":[],"name":"ImplementationNotInitialized","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidCommitment","type":"error"},{"inputs":[],"name":"InvalidDeletionIndices","type":"error"},{"inputs":[],"name":"InvalidStateBridgeAddress","type":"error"},{"inputs":[],"name":"InvalidVerifier","type":"error"},{"inputs":[],"name":"InvalidVerifierLUT","type":"error"},{"inputs":[],"name":"MismatchedInputLengths","type":"error"},{"inputs":[],"name":"NonExistentRoot","type":"error"},{"inputs":[{"internalType":"uint256","name":"providedRoot","type":"uint256"},{"internalType":"uint256","name":"latestRoot","type":"uint256"}],"name":"NotLatestRoot","type":"error"},{"inputs":[],"name":"ProofValidationFailure","type":"error"},{"inputs":[],"name":"StateBridgeAlreadyDisabled","type":"error"},{"inputs":[],"name":"StateBridgeAlreadyEnabled","type":"error"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"Unauthorized","type":"error"},{"inputs":[{"internalType":"enum WorldIDIdentityManagerImplV1.UnreducedElementType","name":"elementType","type":"uint8"},{"internalType":"uint256","name":"element","type":"uint256"}],"name":"UnreducedElement","type":"error"},{"inputs":[{"internalType":"uint8","name":"depth","type":"uint8"}],"name":"UnsupportedTreeDepth","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum WorldIDIdentityManagerImplV1.Dependency","name":"kind","type":"uint8"},{"indexed":true,"internalType":"address","name":"oldAddress","type":"address"},{"indexed":true,"internalType":"address","name":"newAddress","type":"address"}],"name":"DependencyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOperator","type":"address"},{"indexed":true,"internalType":"address","name":"newOperator","type":"address"}],"name":"IdentityOperatorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"oldExpiryTime","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"newExpiryTime","type":"uint256"}],"name":"RootHistoryExpirySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"isEnabled","type":"bool"}],"name":"StateBridgeStateChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"preRoot","type":"uint256"},{"indexed":true,"internalType":"enum WorldIDIdentityManagerImplV1.TreeChange","name":"kind","type":"uint8"},{"indexed":true,"internalType":"uint256","name":"postRoot","type":"uint256"}],"name":"TreeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"_treeDepth","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"initialRoot","type":"uint256"}],"name":"WorldIDIdentityManagerImplInitialized","type":"event"},{"anonymous":false,"inputs":[],"name":"WorldIDIdentityManagerImplV2Initialized","type":"event"},{"inputs":[],"name":"NO_SUCH_ROOT","outputs":[{"components":[{"internalType":"uint256","name":"root","type":"uint256"},{"internalType":"uint128","name":"supersededTimestamp","type":"uint128"},{"internalType":"bool","name":"isValid","type":"bool"}],"internalType":"struct WorldIDIdentityManagerImplV1.RootInfo","name":"rootInfo","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"packedDeletionIndices","type":"bytes"},{"internalType":"uint256","name":"preRoot","type":"uint256"},{"internalType":"uint256","name":"postRoot","type":"uint256"},{"internalType":"uint32","name":"batchSize","type":"uint32"}],"name":"calculateIdentityDeletionInputHash","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"startIndex","type":"uint32"},{"internalType":"uint256","name":"preRoot","type":"uint256"},{"internalType":"uint256","name":"postRoot","type":"uint256"},{"internalType":"uint256[]","name":"identityCommitments","type":"uint256[]"}],"name":"calculateIdentityRegistrationInputHash","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[8]","name":"deletionProof","type":"uint256[8]"},{"internalType":"bytes","name":"packedDeletionIndices","type":"bytes"},{"internalType":"uint256","name":"preRoot","type":"uint256"},{"internalType":"uint256","name":"postRoot","type":"uint256"}],"name":"deleteIdentities","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getDeleteIdentitiesVerifierLookupTableAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRegisterIdentitiesVerifierLookupTableAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRootHistoryExpiry","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSemaphoreVerifierAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTreeDepth","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"identityOperator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_treeDepth","type":"uint8"},{"internalType":"uint256","name":"initialRoot","type":"uint256"},{"internalType":"contract VerifierLookupTable","name":"_batchInsertionVerifiers","type":"address"},{"internalType":"contract VerifierLookupTable","name":"_batchUpdateVerifiers","type":"address"},{"internalType":"contract ISemaphoreVerifier","name":"_semaphoreVerifier","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract VerifierLookupTable","name":"_batchDeletionVerifiers","type":"address"}],"name":"initializeV2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"latestRoot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"root","type":"uint256"}],"name":"queryRoot","outputs":[{"components":[{"internalType":"uint256","name":"root","type":"uint256"},{"internalType":"uint128","name":"supersededTimestamp","type":"uint128"},{"internalType":"bool","name":"isValid","type":"bool"}],"internalType":"struct WorldIDIdentityManagerImplV1.RootInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[8]","name":"insertionProof","type":"uint256[8]"},{"internalType":"uint256","name":"preRoot","type":"uint256"},{"internalType":"uint32","name":"startIndex","type":"uint32"},{"internalType":"uint256[]","name":"identityCommitments","type":"uint256[]"},{"internalType":"uint256","name":"postRoot","type":"uint256"}],"name":"registerIdentities","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"root","type":"uint256"}],"name":"requireValidRoot","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract VerifierLookupTable","name":"newTable","type":"address"}],"name":"setDeleteIdentitiesVerifierLookupTable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newIdentityOperator","type":"address"}],"name":"setIdentityOperator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract VerifierLookupTable","name":"newTable","type":"address"}],"name":"setRegisterIdentitiesVerifierLookupTable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newExpiryTime","type":"uint256"}],"name":"setRootHistoryExpiry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISemaphoreVerifier","name":"newVerifier","type":"address"}],"name":"setSemaphoreVerifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"root","type":"uint256"},{"internalType":"uint256","name":"signalHash","type":"uint256"},{"internalType":"uint256","name":"nullifierHash","type":"uint256"},{"internalType":"uint256","name":"externalNullifierHash","type":"uint256"},{"internalType":"uint256[8]","name":"proof","type":"uint256[8]"}],"name":"verifyProof","outputs":[],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a0604052306080523480156200001557600080fd5b506200002062000026565b620000e8565b600054610100900460ff1615620000935760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff9081161015620000e6576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b60805161328e62000238600039600081816105ad015281816105f6015281816106fb0152818161073b01528181610b0001528181610b4001528181610c1e01528181610c5e01528181610d0a01528181610d4a01528181610e5401528181610e9401528181611119015281816111590152818161120b0152818161124b015281816113a1015281816113e10152818161146c015281816114ac0152818161152801528181611672015281816116b201528181611775015281816117b50152818161184c0152818161188c015281816119220152818161196201528181611a4201528181611a8201528181611b5e01528181611b9e01528181611cb501528181611cf501528181611d8001528181611dc00152818161206d015281816120ad015281816121430152818161218301528181612217015281816122570152818161243d015261247d015261328e6000f3fe6080604052600436106101cd5760003560e01c806379ba5097116100f7578063c70aa72711610095578063f134b6ca11610064578063f134b6ca14610539578063f2038f951461054e578063f2358e1d14610563578063f2fde38b1461058357600080fd5b8063c70aa727146104c6578063d7b0fef1146104e6578063e30c3978146104fb578063ea10fbbe1461051957600080fd5b80638e5cdd50116100d15780638e5cdd501461044a5780638fc22e9f14610471578063a7bba58214610486578063aa4a729e146104a657600080fd5b806379ba5097146103f75780638c76a9091461040c5780638da5cb5b1461042c57600080fd5b806338c870651161016f5780634f1ef2861161013e5780634f1ef2861461037657806352d1902d14610389578063561f204b1461039e578063715018a6146103e257600080fd5b806338c87065146102c75780633e8919b6146102e75780633f7c178d1461031457806343f974cb1461036157600080fd5b80632f059fca116101ab5780632f059fca1461023457806331e4e99214610254578063354ca120146102875780633659cfe6146102a757600080fd5b80630e3a12f3146101d25780632217b211146101f457806329b6eca914610214575b600080fd5b3480156101de57600080fd5b506101f26101ed366004612a3a565b6105a3565b005b34801561020057600080fd5b506101f261020f366004612ac9565b6106f1565b34801561022057600080fd5b506101f261022f366004612a3a565b6109f3565b34801561024057600080fd5b506101f261024f366004612a3a565b610af6565b34801561026057600080fd5b5061027461026f366004612b88565b610c12565b6040519081526020015b60405180910390f35b34801561029357600080fd5b506101f26102a2366004612bef565b610d00565b3480156102b357600080fd5b506101f26102c2366004612a3a565b610e4a565b3480156102d357600080fd5b506101f26102e2366004612c2e565b610f12565b3480156102f357600080fd5b506102fc61110d565b6040516001600160a01b03909116815260200161027e565b34801561032057600080fd5b5061033461032f366004612c9c565b6111e4565b60408051825181526020808401516001600160801b0316908201529181015115159082015260600161027e565b34801561036d57600080fd5b50610274611395565b6101f2610384366004612cf8565b611462565b34801561039557600080fd5b5061027461151b565b3480156103aa57600080fd5b506040805160608082018352600080835260208084018290529284018190528351918201845280825291810182905291820152610334565b3480156103ee57600080fd5b506101f26115ce565b34801561040357600080fd5b506101f26115ef565b34801561041857600080fd5b50610274610427366004612da4565b611666565b34801561043857600080fd5b506033546001600160a01b03166102fc565b34801561045657600080fd5b5061045f611769565b60405160ff909116815260200161027e565b34801561047d57600080fd5b506102fc611840565b34801561049257600080fd5b506102fc6104a1366004612a3a565b611916565b3480156104b257600080fd5b506101f26104c1366004612a3a565b611a38565b3480156104d257600080fd5b506101f26104e1366004612c9c565b611b54565b3480156104f257600080fd5b50610274611ca9565b34801561050757600080fd5b506065546001600160a01b03166102fc565b34801561052557600080fd5b506101f2610534366004612e0c565b611d76565b34801561054557600080fd5b506102fc612061565b34801561055a57600080fd5b506102fc612137565b34801561056f57600080fd5b506101f261057e366004612c9c565b61220d565b34801561058f57600080fd5b506101f261059e366004612a3a565b61234a565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036105f45760405162461bcd60e51b81526004016105eb90612e76565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166106266123bb565b6001600160a01b03161461064c5760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff1661066f57604051630103019560e11b815260040160405180910390fd5b6106776123d7565b6001600160a01b03811661069e5760405163baa3de5f60e01b815260040160405180910390fd5b61013380546001600160a01b038381166001600160a01b03198316811790935516908160035b6040517fd194b8423e9cb3c7cbebbbc3fe7f79dc2cbe0b40e03270d975abff491504c7b190600090a45050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036107395760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661076b6123bb565b6001600160a01b0316146107915760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff166107b457604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b031633146107e25760405163472511eb60e11b81523360048201526024016105eb565b61012e5485146108145761012e5460405163542fced960e11b81526105eb918791600401918252602082015260400190565b60006108238587848787611666565b905060006108517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183612f24565b61013154604051638a283fc360e01b8152600481018790529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa1580156108a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c59190612f38565b604080516020810182528481529051631b81f82960e01b81529192506001600160a01b03831691631b81f82991610901918d9190600401612f55565b600060405180830381600087803b15801561091b57600080fd5b505af192505050801561092c575060015b61098c57610938612f90565b806308c379a003610971575061094c612fab565b806109575750610973565b8060405162461bcd60e51b81526004016105eb9190613059565b505b604051631e716a8b60e01b815260040160405180910390fd5b61012e849055600088815261012f6020526040812080546001600160801b031916426001600160801b031617905584906040518a907f25f6d5cc356ee0b49cf708c13c68197947f5740a878a298765e4b18e4afdaf0490600090a45b505050505050505050565b600054600290610100900460ff16158015610a15575060005460ff8083169116105b610a315760405162461bcd60e51b81526004016105eb9061308c565b6000805461ffff191660ff8316176101001790556001600160a01b038216610a6c57604051634fdab25360e01b815260040160405180910390fd5b61013580546001600160a01b0319166001600160a01b0384161790556040517fe416bec7423c88399c6c76ff0386950a64e454d25b846ef46c397bf835c7df7a90600090a16000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610b3e5760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610b706123bb565b6001600160a01b031614610b965760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff16610bb957604051630103019560e11b815260040160405180910390fd5b610bc16123d7565b6001600160a01b038116610be857604051634fdab25360e01b815260040160405180910390fd5b61013180546001600160a01b038381166001600160a01b03198316811790935516908160016106c4565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610c5c5760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610c8e6123bb565b6001600160a01b031614610cb45760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff16610cd757604051630103019560e11b815260040160405180910390fd5b604051600483028088833781810195865260209095019390935250506040909101902092915050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610d485760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610d7a6123bb565b6001600160a01b031614610da05760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff16610dc357604051630103019560e11b815260040160405180910390fd5b610dcc8561220d565b610133546040805160808101825287815260208101869052808201879052606081018590529051632357251160e01b81526001600160a01b0390921691632357251191610e1e918591906004016130da565b60006040518083038186803b158015610e3657600080fd5b505afa1580156109e8573d6000803e3d6000fd5b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610e925760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610ec46123bb565b6001600160a01b031614610eea5760405162461bcd60e51b81526004016105eb90612ec2565b610ef381612433565b60408051600080825260208201909252610f0f918391906124db565b50565b600054600190610100900460ff16158015610f34575060005460ff8083169116105b610f505760405162461bcd60e51b81526004016105eb9061308c565b6000805461ffff191660ff8316176101001790556001600160a01b038416610f8b57604051634fdab25360e01b815260040160405180910390fd5b6001600160a01b038316610fb257604051634fdab25360e01b815260040160405180910390fd5b6001600160a01b038216610fd95760405163baa3de5f60e01b815260040160405180910390fd5b610fe161264b565b610fea8661267a565b61100c57604051630220cee360e61b815260ff871660048201526024016105eb565b610134805460ff60a81b1916600160a81b60ff891602179055610e106101305561012e85905561013180546001600160a01b03199081166001600160a01b0387811691909117909255610132805482168684161790556101338054821685841617905560335461012d80549190931691161790556110886126a1565b6040805160ff88168152602081018790527fd1bcc66c061c32a21f569d138c2dadef4a38a0636309881954af5f44010ec1d8910160405180910390a16000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050505050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036111575760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166111896123bb565b6001600160a01b0316146111af5760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff166111d257604051630103019560e11b815260040160405180910390fd5b50610135546001600160a01b03165b90565b60408051606081018252600080825260208201819052918101919091526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036112495760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661127b6123bb565b6001600160a01b0316146112a15760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff166112c457604051630103019560e11b815260040160405180910390fd5b61012e5482036112f35750506040805160608101825261012e5481526000602082015260019181019190915290565b600082815261012f60205260408120546001600160801b03169081900361134e5760408051606080820183526000808352602080840182905292840181905283519182018452808252918101829052918201525b9392505050565b610130546000906113686001600160801b0384164261310b565b604080516060810182528781526001600160801b039095166020860152911015908301525090505b919050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036113df5760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166114116123bb565b6001600160a01b0316146114375760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff1661145a57604051630103019560e11b815260040160405180910390fd5b506101305490565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036114aa5760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166114dc6123bb565b6001600160a01b0316146115025760405162461bcd60e51b81526004016105eb90612ec2565b61150b82612433565b611517828260016124db565b5050565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146115bb5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016105eb565b5060008051602061321283398151915290565b6115d66123d7565b6040516377aeb0ad60e01b815260040160405180910390fd5b60655433906001600160a01b0316811461165d5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016105eb565b610f0f816126d7565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036116b05760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166116e26123bb565b6001600160a01b0316146117085760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff1661172b57604051630103019560e11b815260040160405180910390fd5b6000868686868660405160200161174695949392919061312c565b60408051601f198184030181529190528051602090910120979650505050505050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036117b35760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166117e56123bb565b6001600160a01b03161461180b5760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff1661182e57604051630103019560e11b815260040160405180910390fd5b5061013454600160a81b900460ff1690565b60006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361188a5760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166118bc6123bb565b6001600160a01b0316146118e25760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff1661190557604051630103019560e11b815260040160405180910390fd5b50610131546001600160a01b031690565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036119605760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166119926123bb565b6001600160a01b0316146119b85760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff166119db57604051630103019560e11b815260040160405180910390fd5b6119e36123d7565b61012d80546001600160a01b038481166001600160a01b0319831681179093556040519116919082907f5a674c516c196404869e5f502b5634ce442416bb016dde54b5de4c812cc019e690600090a392915050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611a805760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611ab26123bb565b6001600160a01b031614611ad85760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff16611afb57604051630103019560e11b815260040160405180910390fd5b611b036123d7565b6001600160a01b038116611b2a57604051634fdab25360e01b815260040160405180910390fd5b61013580546001600160a01b038381166001600160a01b03198316811790935516908160026106c4565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611b9c5760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611bce6123bb565b6001600160a01b031614611bf45760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff16611c1757604051630103019560e11b815260040160405180910390fd5b611c1f6123d7565b80600003611c6f5760405162461bcd60e51b815260206004820152601b60248201527f4578706972792074696d652063616e6e6f74206265207a65726f2e000000000060448201526064016105eb565b610130805490829055604051829082907ff62a6f06fde00a303cd5939e6b53762854412c96a196cda26720cedd28af9e7090600090a35050565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611cf35760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611d256123bb565b6001600160a01b031614611d4b5760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff16611d6e57604051630103019560e11b815260040160405180910390fd5b5061012e5490565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611dbe5760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611df06123bb565b6001600160a01b031614611e165760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff16611e3957604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b03163314611e675760405163472511eb60e11b81523360048201526024016105eb565b611e72600484612f24565b15611e90576040516308f3ed5160e41b815260040160405180910390fd5b6000611e9d60048561317d565b905061012e548314611ed15761012e5460405163542fced960e11b81526105eb918591600401918252602082015260400190565b6000611ee08686868686610c12565b90506000611f0e7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183612f24565b61013554604051638a283fc360e01b815263ffffffff861660048201529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa158015611f63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f879190612f38565b604080516020810182528481529051631b81f82960e01b81529192506001600160a01b03831691631b81f82991611fc3918d9190600401612f55565b600060405180830381600087803b158015611fdd57600080fd5b505af1925050508015611fee575060015b611ffa57610938612f90565b61012e859055600086815261012f6020526040902080546001600160801b031916426001600160801b031617905584600160405188907f25f6d5cc356ee0b49cf708c13c68197947f5740a878a298765e4b18e4afdaf0490600090a4505050505050505050565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036120ab5760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166120dd6123bb565b6001600160a01b0316146121035760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff1661212657604051630103019560e11b815260040160405180910390fd5b5061012d546001600160a01b031690565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036121815760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166121b36123bb565b6001600160a01b0316146121d95760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff166121fc57604051630103019560e11b815260040160405180910390fd5b50610133546001600160a01b031690565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036122555760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166122876123bb565b6001600160a01b0316146122ad5760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff166122d057604051630103019560e11b815260040160405180910390fd5b61012e548114610f0f57600081815261012f60205260408120546001600160801b0316908190036123145760405163ddae3b7160e01b815260040160405180910390fd5b6101305461232b6001600160801b0383164261310b565b111561151757604051631d739acf60e11b815260040160405180910390fd5b6123526123d7565b606580546001600160a01b0383166001600160a01b031990911681179091556123836033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600080516020613212833981519152546001600160a01b031690565b6033546001600160a01b031633146124315760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105eb565b565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361247b5760405162461bcd60e51b81526004016105eb90612e76565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166124ad6123bb565b6001600160a01b0316146124d35760405162461bcd60e51b81526004016105eb90612ec2565b610f0f6123d7565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156125135761250e836126f0565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561256d575060408051601f3d908101601f1916820190925261256a91810190613191565b60015b6125d05760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016105eb565b600080516020613212833981519152811461263f5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016105eb565b5061250e83838361278c565b600054610100900460ff166126725760405162461bcd60e51b81526004016105eb906131aa565b6124316127b7565b60006010602060ff8416821180159061269957508060ff168460ff1611155b949350505050565b600054610100900460ff166126c85760405162461bcd60e51b81526004016105eb906131aa565b60fb805460ff19166001179055565b606580546001600160a01b0319169055610f0f816127ee565b6001600160a01b0381163b61275d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016105eb565b60008051602061321283398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61279583612840565b6000825111806127a25750805b1561250e576127b18383612880565b50505050565b600054610100900460ff166127de5760405162461bcd60e51b81526004016105eb906131aa565b6127e6612976565b6124316129a5565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b612849816126f0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6128e85760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016105eb565b600080846001600160a01b03168460405161290391906131f5565b600060405180830381855af49150503d806000811461293e576040519150601f19603f3d011682016040523d82523d6000602084013e612943565b606091505b509150915061296b8282604051806060016040528060278152602001613232602791396129cc565b925050505b92915050565b600054610100900460ff1661299d5760405162461bcd60e51b81526004016105eb906131aa565b6124316129e5565b600054610100900460ff166124315760405162461bcd60e51b81526004016105eb906131aa565b606083156129db575081611347565b6113478383612a15565b600054610100900460ff16612a0c5760405162461bcd60e51b81526004016105eb906131aa565b612431336126d7565b8151156109575781518083602001fd5b6001600160a01b0381168114610f0f57600080fd5b600060208284031215612a4c57600080fd5b813561134781612a25565b80610100810183101561297057600080fd5b803563ffffffff8116811461139057600080fd5b60008083601f840112612a8f57600080fd5b50813567ffffffffffffffff811115612aa757600080fd5b6020830191508360208260051b8501011115612ac257600080fd5b9250929050565b6000806000806000806101808789031215612ae357600080fd5b612aed8888612a57565b95506101008701359450612b046101208801612a69565b935061014087013567ffffffffffffffff811115612b2157600080fd5b612b2d89828a01612a7d565b979a969950949794969561016090950135949350505050565b60008083601f840112612b5857600080fd5b50813567ffffffffffffffff811115612b7057600080fd5b602083019150836020828501011115612ac257600080fd5b600080600080600060808688031215612ba057600080fd5b853567ffffffffffffffff811115612bb757600080fd5b612bc388828901612b46565b9096509450506020860135925060408601359150612be360608701612a69565b90509295509295909350565b60008060008060006101808688031215612c0857600080fd5b85359450602086013593506040860135925060608601359150612be38760808801612a57565b600080600080600060a08688031215612c4657600080fd5b853560ff81168114612c5757600080fd5b9450602086013593506040860135612c6e81612a25565b92506060860135612c7e81612a25565b91506080860135612c8e81612a25565b809150509295509295909350565b600060208284031215612cae57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f1916810167ffffffffffffffff81118282101715612cf157612cf1612cb5565b6040525050565b60008060408385031215612d0b57600080fd5b8235612d1681612a25565b915060208381013567ffffffffffffffff80821115612d3457600080fd5b818601915086601f830112612d4857600080fd5b813581811115612d5a57612d5a612cb5565b6040519150612d72601f8201601f1916850183612ccb565b8082528784828501011115612d8657600080fd5b80848401858401376000848284010152508093505050509250929050565b600080600080600060808688031215612dbc57600080fd5b612dc586612a69565b94506020860135935060408601359250606086013567ffffffffffffffff811115612def57600080fd5b612dfb88828901612a7d565b969995985093965092949392505050565b60008060008060006101608688031215612e2557600080fd5b612e2f8787612a57565b945061010086013567ffffffffffffffff811115612e4c57600080fd5b612e5888828901612b46565b96999098509596610120810135966101409091013595509350505050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b600052601260045260246000fd5b600082612f3357612f33612f0e565b500690565b600060208284031215612f4a57600080fd5b815161134781612a25565b61012081016101008085843782018360005b6001811015612f86578151835260209283019290910190600101612f67565b5050509392505050565b600060033d11156111e15760046000803e5060005160e01c90565b600060443d1015612fb95790565b6040516003193d81016004833e81513d67ffffffffffffffff8160248401118184111715612fe957505050505090565b82850191508151818111156130015750505050505090565b843d870101602082850101111561301b5750505050505090565b61302a60208286010187612ccb565b509095945050505050565b60005b83811015613050578181015183820152602001613038565b50506000910152565b6020815260008251806020840152613078816040850160208701613035565b601f01601f19169190910160400192915050565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b61018081016101008085843782018360005b6004811015612f865781518352602092830192909101906001016130ec565b8181038181111561297057634e487b7160e01b600052601160045260246000fd5b60e086901b6001600160e01b0319168152600481018590526024810184905260006001600160fb1b0383111561316157600080fd5b8260051b80856044850137919091016044019695505050505050565b60008261318c5761318c612f0e565b500490565b6000602082840312156131a357600080fd5b5051919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008251613207818460208701613035565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e2882e768fa852ec28bfac17f97929fd9bc23f261730adcec43156857cb6d9c464736f6c63430008150033
Deployed Bytecode
0x6080604052600436106101cd5760003560e01c806379ba5097116100f7578063c70aa72711610095578063f134b6ca11610064578063f134b6ca14610539578063f2038f951461054e578063f2358e1d14610563578063f2fde38b1461058357600080fd5b8063c70aa727146104c6578063d7b0fef1146104e6578063e30c3978146104fb578063ea10fbbe1461051957600080fd5b80638e5cdd50116100d15780638e5cdd501461044a5780638fc22e9f14610471578063a7bba58214610486578063aa4a729e146104a657600080fd5b806379ba5097146103f75780638c76a9091461040c5780638da5cb5b1461042c57600080fd5b806338c870651161016f5780634f1ef2861161013e5780634f1ef2861461037657806352d1902d14610389578063561f204b1461039e578063715018a6146103e257600080fd5b806338c87065146102c75780633e8919b6146102e75780633f7c178d1461031457806343f974cb1461036157600080fd5b80632f059fca116101ab5780632f059fca1461023457806331e4e99214610254578063354ca120146102875780633659cfe6146102a757600080fd5b80630e3a12f3146101d25780632217b211146101f457806329b6eca914610214575b600080fd5b3480156101de57600080fd5b506101f26101ed366004612a3a565b6105a3565b005b34801561020057600080fd5b506101f261020f366004612ac9565b6106f1565b34801561022057600080fd5b506101f261022f366004612a3a565b6109f3565b34801561024057600080fd5b506101f261024f366004612a3a565b610af6565b34801561026057600080fd5b5061027461026f366004612b88565b610c12565b6040519081526020015b60405180910390f35b34801561029357600080fd5b506101f26102a2366004612bef565b610d00565b3480156102b357600080fd5b506101f26102c2366004612a3a565b610e4a565b3480156102d357600080fd5b506101f26102e2366004612c2e565b610f12565b3480156102f357600080fd5b506102fc61110d565b6040516001600160a01b03909116815260200161027e565b34801561032057600080fd5b5061033461032f366004612c9c565b6111e4565b60408051825181526020808401516001600160801b0316908201529181015115159082015260600161027e565b34801561036d57600080fd5b50610274611395565b6101f2610384366004612cf8565b611462565b34801561039557600080fd5b5061027461151b565b3480156103aa57600080fd5b506040805160608082018352600080835260208084018290529284018190528351918201845280825291810182905291820152610334565b3480156103ee57600080fd5b506101f26115ce565b34801561040357600080fd5b506101f26115ef565b34801561041857600080fd5b50610274610427366004612da4565b611666565b34801561043857600080fd5b506033546001600160a01b03166102fc565b34801561045657600080fd5b5061045f611769565b60405160ff909116815260200161027e565b34801561047d57600080fd5b506102fc611840565b34801561049257600080fd5b506102fc6104a1366004612a3a565b611916565b3480156104b257600080fd5b506101f26104c1366004612a3a565b611a38565b3480156104d257600080fd5b506101f26104e1366004612c9c565b611b54565b3480156104f257600080fd5b50610274611ca9565b34801561050757600080fd5b506065546001600160a01b03166102fc565b34801561052557600080fd5b506101f2610534366004612e0c565b611d76565b34801561054557600080fd5b506102fc612061565b34801561055a57600080fd5b506102fc612137565b34801561056f57600080fd5b506101f261057e366004612c9c565b61220d565b34801561058f57600080fd5b506101f261059e366004612a3a565b61234a565b6001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd1630036105f45760405162461bcd60e51b81526004016105eb90612e76565b60405180910390fd5b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b03166106266123bb565b6001600160a01b03161461064c5760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff1661066f57604051630103019560e11b815260040160405180910390fd5b6106776123d7565b6001600160a01b03811661069e5760405163baa3de5f60e01b815260040160405180910390fd5b61013380546001600160a01b038381166001600160a01b03198316811790935516908160035b6040517fd194b8423e9cb3c7cbebbbc3fe7f79dc2cbe0b40e03270d975abff491504c7b190600090a45050565b6001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd1630036107395760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b031661076b6123bb565b6001600160a01b0316146107915760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff166107b457604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b031633146107e25760405163472511eb60e11b81523360048201526024016105eb565b61012e5485146108145761012e5460405163542fced960e11b81526105eb918791600401918252602082015260400190565b60006108238587848787611666565b905060006108517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183612f24565b61013154604051638a283fc360e01b8152600481018790529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa1580156108a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c59190612f38565b604080516020810182528481529051631b81f82960e01b81529192506001600160a01b03831691631b81f82991610901918d9190600401612f55565b600060405180830381600087803b15801561091b57600080fd5b505af192505050801561092c575060015b61098c57610938612f90565b806308c379a003610971575061094c612fab565b806109575750610973565b8060405162461bcd60e51b81526004016105eb9190613059565b505b604051631e716a8b60e01b815260040160405180910390fd5b61012e849055600088815261012f6020526040812080546001600160801b031916426001600160801b031617905584906040518a907f25f6d5cc356ee0b49cf708c13c68197947f5740a878a298765e4b18e4afdaf0490600090a45b505050505050505050565b600054600290610100900460ff16158015610a15575060005460ff8083169116105b610a315760405162461bcd60e51b81526004016105eb9061308c565b6000805461ffff191660ff8316176101001790556001600160a01b038216610a6c57604051634fdab25360e01b815260040160405180910390fd5b61013580546001600160a01b0319166001600160a01b0384161790556040517fe416bec7423c88399c6c76ff0386950a64e454d25b846ef46c397bf835c7df7a90600090a16000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd163003610b3e5760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b0316610b706123bb565b6001600160a01b031614610b965760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff16610bb957604051630103019560e11b815260040160405180910390fd5b610bc16123d7565b6001600160a01b038116610be857604051634fdab25360e01b815260040160405180910390fd5b61013180546001600160a01b038381166001600160a01b03198316811790935516908160016106c4565b60006001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd163003610c5c5760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b0316610c8e6123bb565b6001600160a01b031614610cb45760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff16610cd757604051630103019560e11b815260040160405180910390fd5b604051600483028088833781810195865260209095019390935250506040909101902092915050565b6001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd163003610d485760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b0316610d7a6123bb565b6001600160a01b031614610da05760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff16610dc357604051630103019560e11b815260040160405180910390fd5b610dcc8561220d565b610133546040805160808101825287815260208101869052808201879052606081018590529051632357251160e01b81526001600160a01b0390921691632357251191610e1e918591906004016130da565b60006040518083038186803b158015610e3657600080fd5b505afa1580156109e8573d6000803e3d6000fd5b6001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd163003610e925760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b0316610ec46123bb565b6001600160a01b031614610eea5760405162461bcd60e51b81526004016105eb90612ec2565b610ef381612433565b60408051600080825260208201909252610f0f918391906124db565b50565b600054600190610100900460ff16158015610f34575060005460ff8083169116105b610f505760405162461bcd60e51b81526004016105eb9061308c565b6000805461ffff191660ff8316176101001790556001600160a01b038416610f8b57604051634fdab25360e01b815260040160405180910390fd5b6001600160a01b038316610fb257604051634fdab25360e01b815260040160405180910390fd5b6001600160a01b038216610fd95760405163baa3de5f60e01b815260040160405180910390fd5b610fe161264b565b610fea8661267a565b61100c57604051630220cee360e61b815260ff871660048201526024016105eb565b610134805460ff60a81b1916600160a81b60ff891602179055610e106101305561012e85905561013180546001600160a01b03199081166001600160a01b0387811691909117909255610132805482168684161790556101338054821685841617905560335461012d80549190931691161790556110886126a1565b6040805160ff88168152602081018790527fd1bcc66c061c32a21f569d138c2dadef4a38a0636309881954af5f44010ec1d8910160405180910390a16000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050505050565b60006001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd1630036111575760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b03166111896123bb565b6001600160a01b0316146111af5760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff166111d257604051630103019560e11b815260040160405180910390fd5b50610135546001600160a01b03165b90565b60408051606081018252600080825260208201819052918101919091526001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd1630036112495760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b031661127b6123bb565b6001600160a01b0316146112a15760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff166112c457604051630103019560e11b815260040160405180910390fd5b61012e5482036112f35750506040805160608101825261012e5481526000602082015260019181019190915290565b600082815261012f60205260408120546001600160801b03169081900361134e5760408051606080820183526000808352602080840182905292840181905283519182018452808252918101829052918201525b9392505050565b610130546000906113686001600160801b0384164261310b565b604080516060810182528781526001600160801b039095166020860152911015908301525090505b919050565b60006001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd1630036113df5760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b03166114116123bb565b6001600160a01b0316146114375760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff1661145a57604051630103019560e11b815260040160405180910390fd5b506101305490565b6001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd1630036114aa5760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b03166114dc6123bb565b6001600160a01b0316146115025760405162461bcd60e51b81526004016105eb90612ec2565b61150b82612433565b611517828260016124db565b5050565b6000306001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd16146115bb5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016105eb565b5060008051602061321283398151915290565b6115d66123d7565b6040516377aeb0ad60e01b815260040160405180910390fd5b60655433906001600160a01b0316811461165d5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016105eb565b610f0f816126d7565b60006001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd1630036116b05760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b03166116e26123bb565b6001600160a01b0316146117085760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff1661172b57604051630103019560e11b815260040160405180910390fd5b6000868686868660405160200161174695949392919061312c565b60408051601f198184030181529190528051602090910120979650505050505050565b60006001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd1630036117b35760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b03166117e56123bb565b6001600160a01b03161461180b5760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff1661182e57604051630103019560e11b815260040160405180910390fd5b5061013454600160a81b900460ff1690565b60006001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd16300361188a5760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b03166118bc6123bb565b6001600160a01b0316146118e25760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff1661190557604051630103019560e11b815260040160405180910390fd5b50610131546001600160a01b031690565b60006001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd1630036119605760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b03166119926123bb565b6001600160a01b0316146119b85760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff166119db57604051630103019560e11b815260040160405180910390fd5b6119e36123d7565b61012d80546001600160a01b038481166001600160a01b0319831681179093556040519116919082907f5a674c516c196404869e5f502b5634ce442416bb016dde54b5de4c812cc019e690600090a392915050565b6001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd163003611a805760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b0316611ab26123bb565b6001600160a01b031614611ad85760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff16611afb57604051630103019560e11b815260040160405180910390fd5b611b036123d7565b6001600160a01b038116611b2a57604051634fdab25360e01b815260040160405180910390fd5b61013580546001600160a01b038381166001600160a01b03198316811790935516908160026106c4565b6001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd163003611b9c5760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b0316611bce6123bb565b6001600160a01b031614611bf45760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff16611c1757604051630103019560e11b815260040160405180910390fd5b611c1f6123d7565b80600003611c6f5760405162461bcd60e51b815260206004820152601b60248201527f4578706972792074696d652063616e6e6f74206265207a65726f2e000000000060448201526064016105eb565b610130805490829055604051829082907ff62a6f06fde00a303cd5939e6b53762854412c96a196cda26720cedd28af9e7090600090a35050565b60006001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd163003611cf35760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b0316611d256123bb565b6001600160a01b031614611d4b5760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff16611d6e57604051630103019560e11b815260040160405180910390fd5b5061012e5490565b6001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd163003611dbe5760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b0316611df06123bb565b6001600160a01b031614611e165760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff16611e3957604051630103019560e11b815260040160405180910390fd5b61012d546001600160a01b03163314611e675760405163472511eb60e11b81523360048201526024016105eb565b611e72600484612f24565b15611e90576040516308f3ed5160e41b815260040160405180910390fd5b6000611e9d60048561317d565b905061012e548314611ed15761012e5460405163542fced960e11b81526105eb918591600401918252602082015260400190565b6000611ee08686868686610c12565b90506000611f0e7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183612f24565b61013554604051638a283fc360e01b815263ffffffff861660048201529192506000916001600160a01b0390911690638a283fc390602401602060405180830381865afa158015611f63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f879190612f38565b604080516020810182528481529051631b81f82960e01b81529192506001600160a01b03831691631b81f82991611fc3918d9190600401612f55565b600060405180830381600087803b158015611fdd57600080fd5b505af1925050508015611fee575060015b611ffa57610938612f90565b61012e859055600086815261012f6020526040902080546001600160801b031916426001600160801b031617905584600160405188907f25f6d5cc356ee0b49cf708c13c68197947f5740a878a298765e4b18e4afdaf0490600090a4505050505050505050565b60006001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd1630036120ab5760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b03166120dd6123bb565b6001600160a01b0316146121035760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff1661212657604051630103019560e11b815260040160405180910390fd5b5061012d546001600160a01b031690565b60006001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd1630036121815760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b03166121b36123bb565b6001600160a01b0316146121d95760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff166121fc57604051630103019560e11b815260040160405180910390fd5b50610133546001600160a01b031690565b6001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd1630036122555760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b03166122876123bb565b6001600160a01b0316146122ad5760405162461bcd60e51b81526004016105eb90612ec2565b60fb5460ff166122d057604051630103019560e11b815260040160405180910390fd5b61012e548114610f0f57600081815261012f60205260408120546001600160801b0316908190036123145760405163ddae3b7160e01b815260040160405180910390fd5b6101305461232b6001600160801b0383164261310b565b111561151757604051631d739acf60e11b815260040160405180910390fd5b6123526123d7565b606580546001600160a01b0383166001600160a01b031990911681179091556123836033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600080516020613212833981519152546001600160a01b031690565b6033546001600160a01b031633146124315760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105eb565b565b6001600160a01b037f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd16300361247b5760405162461bcd60e51b81526004016105eb90612e76565b7f000000000000000000000000521e8fb3a32ea44237dc8b1e506dd78accfdf8bd6001600160a01b03166124ad6123bb565b6001600160a01b0316146124d35760405162461bcd60e51b81526004016105eb90612ec2565b610f0f6123d7565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156125135761250e836126f0565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561256d575060408051601f3d908101601f1916820190925261256a91810190613191565b60015b6125d05760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016105eb565b600080516020613212833981519152811461263f5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016105eb565b5061250e83838361278c565b600054610100900460ff166126725760405162461bcd60e51b81526004016105eb906131aa565b6124316127b7565b60006010602060ff8416821180159061269957508060ff168460ff1611155b949350505050565b600054610100900460ff166126c85760405162461bcd60e51b81526004016105eb906131aa565b60fb805460ff19166001179055565b606580546001600160a01b0319169055610f0f816127ee565b6001600160a01b0381163b61275d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016105eb565b60008051602061321283398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61279583612840565b6000825111806127a25750805b1561250e576127b18383612880565b50505050565b600054610100900460ff166127de5760405162461bcd60e51b81526004016105eb906131aa565b6127e6612976565b6124316129a5565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b612849816126f0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6128e85760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016105eb565b600080846001600160a01b03168460405161290391906131f5565b600060405180830381855af49150503d806000811461293e576040519150601f19603f3d011682016040523d82523d6000602084013e612943565b606091505b509150915061296b8282604051806060016040528060278152602001613232602791396129cc565b925050505b92915050565b600054610100900460ff1661299d5760405162461bcd60e51b81526004016105eb906131aa565b6124316129e5565b600054610100900460ff166124315760405162461bcd60e51b81526004016105eb906131aa565b606083156129db575081611347565b6113478383612a15565b600054610100900460ff16612a0c5760405162461bcd60e51b81526004016105eb906131aa565b612431336126d7565b8151156109575781518083602001fd5b6001600160a01b0381168114610f0f57600080fd5b600060208284031215612a4c57600080fd5b813561134781612a25565b80610100810183101561297057600080fd5b803563ffffffff8116811461139057600080fd5b60008083601f840112612a8f57600080fd5b50813567ffffffffffffffff811115612aa757600080fd5b6020830191508360208260051b8501011115612ac257600080fd5b9250929050565b6000806000806000806101808789031215612ae357600080fd5b612aed8888612a57565b95506101008701359450612b046101208801612a69565b935061014087013567ffffffffffffffff811115612b2157600080fd5b612b2d89828a01612a7d565b979a969950949794969561016090950135949350505050565b60008083601f840112612b5857600080fd5b50813567ffffffffffffffff811115612b7057600080fd5b602083019150836020828501011115612ac257600080fd5b600080600080600060808688031215612ba057600080fd5b853567ffffffffffffffff811115612bb757600080fd5b612bc388828901612b46565b9096509450506020860135925060408601359150612be360608701612a69565b90509295509295909350565b60008060008060006101808688031215612c0857600080fd5b85359450602086013593506040860135925060608601359150612be38760808801612a57565b600080600080600060a08688031215612c4657600080fd5b853560ff81168114612c5757600080fd5b9450602086013593506040860135612c6e81612a25565b92506060860135612c7e81612a25565b91506080860135612c8e81612a25565b809150509295509295909350565b600060208284031215612cae57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f1916810167ffffffffffffffff81118282101715612cf157612cf1612cb5565b6040525050565b60008060408385031215612d0b57600080fd5b8235612d1681612a25565b915060208381013567ffffffffffffffff80821115612d3457600080fd5b818601915086601f830112612d4857600080fd5b813581811115612d5a57612d5a612cb5565b6040519150612d72601f8201601f1916850183612ccb565b8082528784828501011115612d8657600080fd5b80848401858401376000848284010152508093505050509250929050565b600080600080600060808688031215612dbc57600080fd5b612dc586612a69565b94506020860135935060408601359250606086013567ffffffffffffffff811115612def57600080fd5b612dfb88828901612a7d565b969995985093965092949392505050565b60008060008060006101608688031215612e2557600080fd5b612e2f8787612a57565b945061010086013567ffffffffffffffff811115612e4c57600080fd5b612e5888828901612b46565b96999098509596610120810135966101409091013595509350505050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b600052601260045260246000fd5b600082612f3357612f33612f0e565b500690565b600060208284031215612f4a57600080fd5b815161134781612a25565b61012081016101008085843782018360005b6001811015612f86578151835260209283019290910190600101612f67565b5050509392505050565b600060033d11156111e15760046000803e5060005160e01c90565b600060443d1015612fb95790565b6040516003193d81016004833e81513d67ffffffffffffffff8160248401118184111715612fe957505050505090565b82850191508151818111156130015750505050505090565b843d870101602082850101111561301b5750505050505090565b61302a60208286010187612ccb565b509095945050505050565b60005b83811015613050578181015183820152602001613038565b50506000910152565b6020815260008251806020840152613078816040850160208701613035565b601f01601f19169190910160400192915050565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b61018081016101008085843782018360005b6004811015612f865781518352602092830192909101906001016130ec565b8181038181111561297057634e487b7160e01b600052601160045260246000fd5b60e086901b6001600160e01b0319168152600481018590526024810184905260006001600160fb1b0383111561316157600080fd5b8260051b80856044850137919091016044019695505050505050565b60008261318c5761318c612f0e565b500490565b6000602082840312156131a357600080fd5b5051919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008251613207818460208701613035565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e2882e768fa852ec28bfac17f97929fd9bc23f261730adcec43156857cb6d9c464736f6c63430008150033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.