Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
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:
AxiomV2Core
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 100000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; import { AccessControlUpgradeable } from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import { AxiomAccess } from "../libraries/access/AxiomAccess.sol"; import { IAxiomV2Core } from "../interfaces/core/IAxiomV2Core.sol"; import { MerkleTree } from "../libraries/MerkleTree.sol"; import { MerkleMountainRange } from "../libraries/MerkleMountainRange.sol"; import { PaddedMerkleMountainRange } from "../libraries/PaddedMerkleMountainRange.sol"; import { Hash } from "../libraries/Hash.sol"; import { BLOCK_BATCH_DEPTH, BLOCK_BATCH_SIZE, HISTORICAL_BLOCK_BATCH_SIZE, HISTORICAL_NUM_ROOTS, getAuxMmrPeak, getBoundaryBlockData } from "../libraries/configuration/AxiomV2Configuration.sol"; /// @title AxiomV2Core /// @notice Core Axiom smart contract that verifies the validity of historical block hashes using SNARKs. /// @dev For use in a UUPS upgradeable contract. contract AxiomV2Core is IAxiomV2Core, AxiomAccess, UUPSUpgradeable { using { MerkleTree.merkleRoot } for bytes32[HISTORICAL_NUM_ROOTS]; using PaddedMerkleMountainRange for PaddedMerkleMountainRange.PMMR; using MerkleMountainRange for MerkleMountainRange.MMR; /// @dev The verifier address for block header hash chains of up to 1024 block headers. address public verifierAddress; /// @dev The verifier address for historic block header hash chains. address public historicalVerifierAddress; /// @dev `historicalRoots[startBlockNumber]` is 0 unless `startBlockNumber % 1024 = 0` /// `historicalRoots(startBlockNumber) = 0` if block `startBlockNumber` is not verified /// `historicalRoots(startBlockNumber) = keccak256(prevHash || root || numFinal)` where || is concatenation /// - `prevHash` is the parent hash of block `startBlockNumber` /// - `root` is the Keccak Merkle root of hash(i) for i in [0, 1024), where /// hash(i) is the blockhash of block `startBlockNumber + i` if i < numFinal, /// hash(i) = bytes32(0x0) if i >= numFinal /// - `0 < numFinal <= 1024` is the number of verified consecutive roots in [startBlockNumber, startBlockNumber + numFinal) mapping(uint32 => bytes32) public historicalRoots; /// @dev `blockhashPmmr` is the current PMMR commitment to historic block hashes /// A commitment to each `blockhashPmmr` stored in the state is guaranteed to have been stored in `pmmrSnapshots` PaddedMerkleMountainRange.PMMR public blockhashPmmr; /// @dev Snapshots of commitments to `blockhashPmmr` as computed by `PaddedMerkleMountainRange.commit` /// `pmmrSnapshots[pmmrSize]` is a commitment to block hashes for blocks `[0, pmmrSize)` mapping(uint32 => bytes32) public pmmrSnapshots; /// @custom:oz-upgrades-unsafe-allow constructor /// @notice Prevents the implementation contract from being initialized outside of the upgradeable proxy. constructor() { _disableInitializers(); } /// @notice Initializes the contract and the parent contracts once. /// @param _verifierAddress The address of the SNARK verifier contract for `updateRecent` and `updateOld` /// @param _historicalVerifierAddress The address of the SNARK verifier contract for `updateHistorical` /// @param timelock The address of the timelock contract. /// @param guardian The address of the guardian contract. /// @param unfreeze The address of the unfreeze contract. /// @param prover The address of the prover contract. function initialize( address _verifierAddress, address _historicalVerifierAddress, address timelock, address guardian, address unfreeze, address prover ) public initializer { if (_verifierAddress == address(0)) { revert VerifierAddressIsZero(); } if (_historicalVerifierAddress == address(0)) { revert HistoricalVerifierAddressIsZero(); } if (timelock == address(0)) { revert TimelockAddressIsZero(); } if (guardian == address(0)) { revert GuardianAddressIsZero(); } if (unfreeze == address(0)) { revert UnfreezeAddressIsZero(); } if (prover == address(0)) { revert ProverAddressIsZero(); } __UUPSUpgradeable_init(); __AxiomAccess_init_unchained(); verifierAddress = _verifierAddress; historicalVerifierAddress = _historicalVerifierAddress; emit UpgradeSnarkVerifier(_verifierAddress); emit UpgradeHistoricalSnarkVerifier(_historicalVerifierAddress); _grantRole(DEFAULT_ADMIN_ROLE, timelock); _grantRole(TIMELOCK_ROLE, timelock); _grantRole(PROVER_ROLE, prover); _grantRole(GUARDIAN_ROLE, guardian); _grantRole(UNFREEZE_ROLE, unfreeze); } function updateRecent(bytes calldata proofData) external onlyProver onlyNotFrozen { (bytes32 prevHash, bytes32 endHash, uint32 startBlockNumber, uint32 endBlockNumber, bytes32 root) = getBoundaryBlockData(proofData); // See `getBoundaryBlockData` comments for initial `proofData` formatting uint32 numFinal = endBlockNumber - startBlockNumber + 1; if (numFinal > BLOCK_BATCH_SIZE) { revert IncorrectNumberOfBlocks(); } if (startBlockNumber % BLOCK_BATCH_SIZE != 0) { revert StartingBlockNotValid(); } if (endBlockNumber >= block.number) { revert NotRecentEndBlock(); } if (block.number - endBlockNumber > 256) { revert NotRecentEndBlock(); } if (blockhash(endBlockNumber) != endHash) { revert BlockHashIncorrect(); } if (!_verifyRaw(proofData)) { revert SNARKVerificationFailed(); } PaddedMerkleMountainRange.PMMR memory pmmr = blockhashPmmr.clone(); if (root == bytes32(0)) { // We have a Merkle mountain range of max depth 10 (so length 11 total) ordered in **decreasing** order of peak size, so: // `root` (above) is the peak for depth 10 // `roots` below are the peaks for depths 9..0 where `roots[i]` is for depth `9 - i` // 384 + 32 * 7 + 32 * 2 * i .. 384 + 32 * 7 + 32 * 2 * (i + 1): `roots[i]` (32 bytes) as two uint128 cast to uint256, same as blockHash // Note that the decreasing ordering is *different* than the convention in library MerkleMountainRange // compute Merkle root of completed Merkle mountain range with 0s for unconfirmed blockhashes for (uint256 round; round < BLOCK_BATCH_DEPTH;) { bytes32 peak = getAuxMmrPeak(proofData, BLOCK_BATCH_DEPTH - 1 - round); if (peak != 0) { root = Hash.keccak(peak, root); } else { root = Hash.keccak(root, MerkleTree.getEmptyHash(round)); } unchecked { ++round; } } } // The `blockhashPmmr` commits to block hashes in the range `[0, pmmrSize)`, and the proof // establishes a Keccak chain of blocks in the range `[startBlockNumber, endBlockNumber]`, // so we can extend `blockhashPmmr` so long as `size` lies in `[startBlockNumber, endBlockNumber]`. if (pmmr.size >= startBlockNumber && pmmr.size <= endBlockNumber) { // updating PMMR with the latest padded leaf uint256 peaksChanged = pmmr.updatePaddedLeaf(BLOCK_BATCH_SIZE, root, numFinal); blockhashPmmr.persistFrom(pmmr, peaksChanged); bytes32 blockhashPmmrKeccak = pmmr.commit(); pmmrSnapshots[endBlockNumber + 1] = blockhashPmmrKeccak; emit PaddedMerkleMountainRangeUpdated(blockhashPmmrKeccak, pmmr.size); } historicalRoots[startBlockNumber] = keccak256(abi.encodePacked(prevHash, root, numFinal)); emit HistoricalRootUpdated(startBlockNumber, prevHash, root, numFinal); } function updateOld(bytes32 nextRoot, uint32 nextNumFinal, bytes calldata proofData) external onlyProver onlyNotFrozen { (bytes32 prevHash, bytes32 endHash, uint32 startBlockNumber, uint32 endBlockNumber, bytes32 root) = getBoundaryBlockData(proofData); if (startBlockNumber % BLOCK_BATCH_SIZE != 0) { revert StartingBlockNotValid(); } if (endBlockNumber - startBlockNumber != BLOCK_BATCH_SIZE - 1) { revert IncorrectNumberOfBlocks(); } if (historicalRoots[endBlockNumber + 1] != keccak256(abi.encodePacked(endHash, nextRoot, nextNumFinal))) { revert BlockHashIncorrect(); } if (!_verifyRaw(proofData)) { revert SNARKVerificationFailed(); } historicalRoots[startBlockNumber] = keccak256(abi.encodePacked(prevHash, root, BLOCK_BATCH_SIZE)); emit HistoricalRootUpdated(startBlockNumber, prevHash, root, BLOCK_BATCH_SIZE); } /// @dev endHashProofs is length HISTORICAL_NUM_ROOTS - 1 because the last endHash is provided in proofData function updateHistorical( bytes32 nextRoot, uint32 nextNumFinal, bytes32[HISTORICAL_NUM_ROOTS] calldata roots, bytes32[BLOCK_BATCH_DEPTH + 1][HISTORICAL_NUM_ROOTS - 1] calldata endHashProofs, bytes calldata proofData ) external onlyProver onlyNotFrozen { (bytes32 _prevHash, bytes32 _endHash, uint32 startBlockNumber, uint32 endBlockNumber, bytes32 aggregateRoot) = getBoundaryBlockData(proofData); if (startBlockNumber % BLOCK_BATCH_SIZE != 0) { revert StartingBlockNotValid(); } if (endBlockNumber - startBlockNumber != HISTORICAL_BLOCK_BATCH_SIZE - 1) { revert IncorrectNumberOfBlocks(); } if (historicalRoots[endBlockNumber + 1] != keccak256(abi.encodePacked(_endHash, nextRoot, nextNumFinal))) { revert BlockHashIncorrect(); } if (roots.merkleRoot() != aggregateRoot) { revert MerkleProofFailed(); } if (!_verifyHistoricalRaw(proofData)) { revert SNARKVerificationFailed(); } for (uint256 i; i < HISTORICAL_NUM_ROOTS;) { if (i != HISTORICAL_NUM_ROOTS - 1) { bytes32 proofCheck = endHashProofs[i][BLOCK_BATCH_DEPTH]; for (uint256 j; j < BLOCK_BATCH_DEPTH;) { proofCheck = Hash.keccak(endHashProofs[i][BLOCK_BATCH_DEPTH - 1 - j], proofCheck); unchecked { ++j; } } if (proofCheck != roots[i]) { revert MerkleProofFailed(); } } bytes32 prevHash = i == 0 ? _prevHash : endHashProofs[i - 1][BLOCK_BATCH_DEPTH]; uint32 start = uint32(startBlockNumber + i * BLOCK_BATCH_SIZE); historicalRoots[start] = keccak256(abi.encodePacked(prevHash, roots[i], BLOCK_BATCH_SIZE)); emit HistoricalRootUpdated(start, prevHash, roots[i], BLOCK_BATCH_SIZE); unchecked { ++i; } } } function appendHistoricalPMMR( uint32 startBlockNumber, bytes32[] calldata roots, bytes32[] calldata prevHashes, uint32 lastNumFinal ) external onlyNotFrozen { PaddedMerkleMountainRange.PMMR memory pmmr = blockhashPmmr.clone(); // to compute total change if ( roots.length == 0 // must append non-empty list || roots.length != prevHashes.length // roots and prevHashes must be same length || startBlockNumber != pmmr.size - (pmmr.size % BLOCK_BATCH_SIZE) // startBlockNumber must be the size of completed leaves in PMMR ) { revert IncorrectNumberOfBlocks(); } // To append complete leaves to the PMMR, first remove any non-empty padded leaf pmmr.updatePaddedLeaf(BLOCK_BATCH_SIZE, bytes32(0x0), 0); // check all complete leaves bytes32 commitment; for (uint256 i; i < roots.length - 1;) { commitment = keccak256(abi.encodePacked(prevHashes[i], roots[i], BLOCK_BATCH_SIZE)); if (historicalRoots[startBlockNumber] != commitment) { revert AxiomBlockVerificationFailed(); } startBlockNumber += BLOCK_BATCH_SIZE; unchecked { ++i; } } // append all complete leaves uint256 peaksChanged = pmmr.appendCompleteLeaves(BLOCK_BATCH_SIZE, roots[:roots.length - 1]); // check the last, possibly incomplete leaf commitment = keccak256(abi.encodePacked(prevHashes[roots.length - 1], roots[roots.length - 1], lastNumFinal)); if (historicalRoots[startBlockNumber] != commitment) { revert AxiomBlockVerificationFailed(); } // append the last, possibly incomplete leaf uint256 leafPeaksChanged = pmmr.updatePaddedLeaf(BLOCK_BATCH_SIZE, roots[roots.length - 1], lastNumFinal); if (leafPeaksChanged > peaksChanged) { peaksChanged = leafPeaksChanged; } bytes32 blockhashPmmrKeccak = pmmr.commit(); pmmrSnapshots[pmmr.size] = blockhashPmmrKeccak; blockhashPmmr.persistFrom(pmmr, peaksChanged); emit PaddedMerkleMountainRangeUpdated(blockhashPmmrKeccak, pmmr.size); } /// @notice Updates the address of the SNARK verifier contract, governed by a 'timelock'. /// To avoid timelock bypass by metamorphic contracts, users should verify that /// the contract deployed at `_verifierAddress` does not contain any `SELFDESTRUCT` /// or `DELEGATECALL` opcodes. function upgradeSnarkVerifier(address _verifierAddress) external onlyRole(TIMELOCK_ROLE) { if (_verifierAddress == address(0)) { revert VerifierAddressIsZero(); } verifierAddress = _verifierAddress; emit UpgradeSnarkVerifier(_verifierAddress); } /// @notice Updates the address of the historical SNARK verifier contract, governed by a 'timelock'. /// To avoid timelock bypass by metamorphic contracts, users should verify that /// the contract deployed at `_historicalVerifierAddress` does not contain any `SELFDESTRUCT` /// or `DELEGATECALL` opcodes. /// @dev We expect this should never need to be called since the historical verifier is only used for the initial batch import of historical block hashes. function upgradeHistoricalSnarkVerifier(address _historicalVerifierAddress) external onlyRole(TIMELOCK_ROLE) { if (_historicalVerifierAddress == address(0)) { revert HistoricalVerifierAddressIsZero(); } historicalVerifierAddress = _historicalVerifierAddress; emit UpgradeHistoricalSnarkVerifier(_historicalVerifierAddress); } function blockhashPmmrLeaf() external view returns (bytes32) { return blockhashPmmr.paddedLeaf; } function blockhashPmmrPeaks() external view returns (MerkleMountainRange.MMR memory) { return blockhashPmmr.completeLeaves.clone(); } function blockhashPmmrSize() external view returns (uint32 pmmrSize) { return blockhashPmmr.size; } function fullBlockhashPmmr() external view returns (PaddedMerkleMountainRange.PMMR memory) { return blockhashPmmr.clone(); } function isRecentBlockHashValid(uint32 blockNumber, bytes32 claimedBlockHash) public view returns (bool) { bytes32 blockHash = blockhash(blockNumber); if (blockHash == 0x0) { revert BlockHashIncorrect(); } // Must supply block hash of one of 256 most recent blocks return (blockHash == claimedBlockHash); } function isBlockHashValid(BlockHashWitness calldata witness) public view returns (bool) { if (witness.claimedBlockHash == 0x0) { revert BlockHashIncorrect(); } // Claimed block hash cannot be 0 uint32 side = witness.blockNumber % BLOCK_BATCH_SIZE; uint32 startBlockNumber = witness.blockNumber - side; bytes32 merkleRoot = historicalRoots[startBlockNumber]; if (merkleRoot == 0) { revert MerkleProofFailed(); } // Merkle root must be stored already // compute Merkle root of blockhash bytes32 root = witness.claimedBlockHash; for (uint256 i; i < BLOCK_BATCH_DEPTH;) { // depth = BLOCK_BATCH_DEPTH - i // if i-th bit = 1, proof is on the left, else, proof is on the right if ((side >> i) & 1 == 0) { root = Hash.keccak(root, witness.merkleProof[i]); } else { root = Hash.keccak(witness.merkleProof[i], root); } unchecked { ++i; } } return merkleRoot == keccak256(abi.encodePacked(witness.prevHash, root, witness.numFinal)); } /// @dev Verify the SNARK proof for `updateRecent` and `updateOld` methods. /// @param input The SNARK proof data. /// @return success Whether the SNARK proof is valid. function _verifyRaw(bytes calldata input) private returns (bool) { (bool success,) = verifierAddress.call(input); return success; } /// @dev Verify the SNARK proof for `updateHistorical`. /// @param input The SNARK proof data. /// @return success Whether the SNARK proof is valid. function _verifyHistoricalRaw(bytes calldata input) private returns (bool) { (bool success,) = historicalVerifierAddress.call(input); return success; } /// @inheritdoc AccessControlUpgradeable function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControlUpgradeable) returns (bool) { return interfaceId == type(IAxiomV2Core).interfaceId || super.supportsInterface(interfaceId); } /// @inheritdoc UUPSUpgradeable function _authorizeUpgrade(address) internal override onlyRole(TIMELOCK_ROLE) { } /** * @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[40] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControlUpgradeable.sol"; import "../utils/ContextUpgradeable.sol"; import "../utils/StringsUpgradeable.sol"; import "../utils/introspection/ERC165Upgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable { function __AccessControl_init() internal onlyInitializing { } function __AccessControl_init_unchained() internal onlyInitializing { } struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `_msgSender()` is missing `role`. * Overriding this function changes the behavior of the {onlyRole} modifier. * * Format of the revert message is described in {_checkRole}. * * _Available since v4.6._ */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", StringsUpgradeable.toHexString(account), " is missing role ", StringsUpgradeable.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * May emit a {RoleGranted} event. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } /** * @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.19; import { AccessControlUpgradeable } from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; /// @title AxiomAccess /// @notice Abstract contract controlling permissions of Axiom contracts /// @dev For use in a UUPS upgradeable contract. abstract contract AxiomAccess is Initializable, AccessControlUpgradeable { bool public frozen; /// @notice Storage slot for the address with the permission of a 'timelock'. bytes32 public constant TIMELOCK_ROLE = keccak256("TIMELOCK_ROLE"); /// @notice Storage slot for the addresses with the permission of a 'guardian'. bytes32 public constant GUARDIAN_ROLE = keccak256("GUARDIAN_ROLE"); /// @notice Storage slot for the addresses with the permission of a 'unfreezer'. bytes32 public constant UNFREEZE_ROLE = keccak256("UNFREEZE_ROLE"); /// @notice Storage slot for the addresses with the permission of a 'prover'. bytes32 public constant PROVER_ROLE = keccak256("PROVER_ROLE"); /// @notice Storage slot for the addresses with the permission of different Axiom versions. bytes32 public constant AXIOM_ROLE = keccak256("AXIOM_ROLE"); /// @notice Emitted when the `freezeAll` is called event FreezeAll(); /// @notice Emitted when the `unfreezeAll` is called event UnfreezeAll(); /// @notice Error when trying to call contract while it is frozen error ContractIsFrozen(); /// @notice Error when trying to call contract from address without 'prover' role error NotProverRole(); /// @notice Error when trying to call contract from address without Axiom role error NotAxiomRole(); /** * @dev Modifier to make a function callable only by the 'prover' role. * As an initial safety mechanism, the 'update_' functions are only callable by the 'prover' role. * Granting the prover role to `address(0)` will enable this role for everyone. */ modifier onlyProver() { _checkProver(); _; } /// @notice Checks that the contract is not frozen. modifier onlyNotFrozen() { _checkNotFrozen(); _; } /// @dev Factor out prover check to reduce contract size. function _checkProver() internal view { if (!(hasRole(PROVER_ROLE, address(0)) || hasRole(PROVER_ROLE, _msgSender()))) { revert NotProverRole(); } } /// @dev Factor out freeze check to reduce contract size. function _checkNotFrozen() internal view { if (frozen) { revert ContractIsFrozen(); } } /// @notice Initializes the contract in the unfrozen state function __AxiomAccess_init() internal onlyInitializing { __AxiomAccess_init_unchained(); } /// @notice Initializes the contract in the unfrozen state function __AxiomAccess_init_unchained() internal onlyInitializing { frozen = false; } /// @notice Set the contract state to frozen, which will disable a set of security-sensitive functions. /// Intended only for use in reaction to an unforeseen vulnerability in ZK circuits or smart contracts. function freezeAll() external onlyRole(GUARDIAN_ROLE) { frozen = true; emit FreezeAll(); } /// @notice Set the contract state to unfrozen, which re-enables a set of security-sensitive functions. /// Intended for use after any vulnerability or potential vulnerability leading to a freeze is fixed. function unfreezeAll() external onlyRole(UNFREEZE_ROLE) { frozen = false; emit UnfreezeAll(); } /** * @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[40] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IAxiomV2Verifier } from "./IAxiomV2Verifier.sol"; import { IAxiomV2Update } from "./IAxiomV2Update.sol"; import { IAxiomV2State } from "./IAxiomV2State.sol"; import { IAxiomV2Events } from "./IAxiomV2Events.sol"; /// @title The interface for the core Axiom V2 contract /// @notice The Axiom V2 contract stores a continually updated cache of all historical block hashes /// @dev The interface is broken up into many smaller pieces interface IAxiomV2Core is IAxiomV2Events, IAxiomV2State, IAxiomV2Update, IAxiomV2Verifier { }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { HISTORICAL_NUM_ROOTS } from "./configuration/AxiomV2Configuration.sol"; import { Hash } from "./Hash.sol"; /// @title Merkle Tree /// @notice Helper functions for computing Merkle roots of Merkle trees library MerkleTree { /// @dev Error returned if the empty hash depth is not in range [0, 10) error InvalidEmptyHashDepth(); /// @notice Compute the Merkle root of a Merkle tree with HISTORICAL_NUM_ROOTS leaves /// @param leaves The HISTORICAL_NUM_ROOTS leaves of the Merkle tree function merkleRoot(bytes32[HISTORICAL_NUM_ROOTS] memory leaves) internal pure returns (bytes32) { // we create a new array to avoid mutating `leaves`, which is passed by reference // unnecessary if calldata `leaves` is passed in since it is automatically copied to memory bytes32[] memory hashes = new bytes32[](HISTORICAL_NUM_ROOTS / 2); for (uint256 i; i < HISTORICAL_NUM_ROOTS / 2;) { hashes[i] = Hash.keccak(leaves[i << 1], leaves[(i << 1) | 1]); unchecked { ++i; } } uint256 len = HISTORICAL_NUM_ROOTS / 4; while (len != 0) { for (uint256 i; i < len;) { hashes[i] = Hash.keccak(hashes[i << 1], hashes[(i << 1) | 1]); unchecked { ++i; } } len >>= 1; } return hashes[0]; } /// @notice Compute the Merkle root of a Merkle tree with 2^depth leaves all equal to bytes32(0x0) /// @param depth The depth of the Merkle tree, 0 <= depth < BLOCK_BATCH_DEPTH. function getEmptyHash(uint256 depth) internal pure returns (bytes32) { // emptyHashes[idx] is the Merkle root of a tree of depth idx with 0's as leaves if (depth == 0) { return bytes32(0x0000000000000000000000000000000000000000000000000000000000000000); } if (depth == 1) { return bytes32(0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5); } if (depth == 2) { return bytes32(0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30); } if (depth == 3) { return bytes32(0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85); } if (depth == 4) { return bytes32(0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344); } if (depth == 5) { return bytes32(0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d); } if (depth == 6) { return bytes32(0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968); } if (depth == 7) { return bytes32(0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83); } if (depth == 8) { return bytes32(0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af); } if (depth == 9) { return bytes32(0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0); } revert InvalidEmptyHashDepth(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { MerkleTree } from "./MerkleTree.sol"; import { Hash } from "./Hash.sol"; uint256 constant MAX_MMR_PEAKS = 32; /// @title Merkle Mountain Range /// @author Axiom /// @notice Library for Merkle Mountain Range data structure library MerkleMountainRange { /// @notice A Merkle mountain range is a data structure for efficiently storing a commitment to a variable length list of bytes32 values. /// @param peaks The peaks of the MMR as a fixed-length array of length 32. /// `peaks` is ordered in *increasing* size of peaks: `peaks[i]` is the Merkle root of a tree of size `2 ** i` corresponding to the `i`th bit of `len` (see @dev for details) /// @param peaksLength The actual number of peaks in the MMR /// @dev peaks stores `peaksLength := bit_length(len)` Merkle roots, with /// `peaks[i] = root(list[((len >> i) << i) - 2^i : ((len >> i) << i)])` if 2^i & len != 0, otherwise 0 /// where root(single element) = single element, and `list` is the underlying list for the MMR /// Warning: Only use the check `peaks[i] == 0` to determine if `peaks[i]` is undefined if the original list is guaranteed to not contain 0 /// (e.g., if the original list is already of hashes) /// Default initialization is to `len = 0`, `peaksLength = 0`, and all `peaks[i] = 0` struct MMR { bytes32[MAX_MMR_PEAKS] peaks; uint256 peaksLength; } /// @dev Create an MMR from a variable length array /// @param peaks The variable length array /// @return out The MMR in memory function fromPeaks(bytes32[] memory peaks) internal pure returns (MMR memory out) { return fromPeaks(peaks, 0, peaks.length); } /// @notice Create an MMR from a slice of variable length array /// @dev Only reads the peaks up to `peaksLength` /// @param peaks The variable length array /// @param start The start index of the subarray /// @param length The length of the subarray /// @return out The MMR in memory function fromPeaks(bytes32[] memory peaks, uint256 start, uint256 length) internal pure returns (MMR memory out) { out.peaksLength = length; for (uint256 idx; idx < length;) { unchecked { out.peaks[idx] = peaks[start + idx]; ++idx; } } } /// @notice Copies the MMR to memory /// @dev Only reads the peaks up to `peaksLength` /// @param self The MMR /// @return out The MMR in memory function clone(MMR storage self) internal view returns (MMR memory out) { out.peaksLength = self.peaksLength; uint256 outPeaksLength = out.peaksLength; for (uint256 i; i < outPeaksLength;) { out.peaks[i] = self.peaks[i]; unchecked { ++i; } } } /// @notice Copies MMR from memory to storage /// @dev Only changes peaks up to `peaksChanged` to limit SSTOREs /// @param self The MMR in storage /// @param peaksChanged Only copy newMMR.peaks[0 : peaksChanged] function persistFrom(MMR storage self, MMR memory newMMR, uint256 peaksChanged) internal { self.peaksLength = newMMR.peaksLength; for (uint256 i; i < peaksChanged;) { self.peaks[i] = newMMR.peaks[i]; unchecked { ++i; } } } /// @notice Compute the keccak of the concatenated peaks /// @param self The MMR /// @return keccak of the concatenated peaks function commit(MMR memory self) internal pure returns (bytes32) { bytes32[] memory peaks = new bytes32[](self.peaksLength); uint256 peaksLength = self.peaksLength; for (uint256 i; i < peaksLength;) { peaks[i] = self.peaks[i]; unchecked { ++i; } } return keccak256(abi.encodePacked(peaks)); } /// @notice Append a new element to the underlying list of the MMR /// @param self The MMR /// @param leaf The new element to append /// @return peaksChanged self.peaks[0 : peaksChanged] have been changed function appendLeaf(MMR memory self, bytes32 leaf) internal pure returns (uint256 peaksChanged) { unchecked { bytes32 newPeak = leaf; uint256 i; uint256 peaksLength = self.peaksLength; for (; i < peaksLength && self.peaks[i] != bytes32(0);) { newPeak = Hash.keccak(self.peaks[i], newPeak); delete self.peaks[i]; ++i; } self.peaks[i] = newPeak; if (i >= peaksLength) { self.peaksLength = i + 1; } peaksChanged = i + 1; } } /// @notice Append a sequence of new elements to the underlying list of the MMR, in order /// @dev Optimized compared to looping over `appendLeaf` /// @param self The MMR /// @param leaves The new elements to append /// @return peaksChanged self.peaks[0 : peaksChanged] have been changed /// @dev Warning: To save gas, this method overwrites values of `leaves` with intermediate computations. /// The input values of `leaves` should be considered invalidated after calling this method. function appendLeaves(MMR memory self, bytes32[] memory leaves) internal pure returns (uint256 peaksChanged) { // keeps track of running length of `leaves` uint256 toAdd = leaves.length; uint256 shift; uint256 i; bytes32 left; bytes32 right; uint256 nextAdd; uint256 bound; while (toAdd != 0) { // shift records whether there is an existing peak in the range we should hash with shift = (self.peaks[i] == bytes32(0)) ? 0 : 1; // if shift, add peaks[i] to beginning of leaves // then hash all leaves unchecked { nextAdd = (toAdd + shift) >> 1; } bound = (nextAdd << 1); for (uint256 j; j < bound;) { if (shift == 1) { if (j == 0) { left = self.peaks[i]; } else { unchecked { left = leaves[j - 1]; } } right = leaves[j]; } else { left = leaves[j]; unchecked { right = leaves[j + 1]; } } leaves[j >> 1] = Hash.keccak(left, right); unchecked { j = j + 2; } } // if toAdd + shift is odd, the last element is new self.peaks[i], otherwise 0 if (toAdd & 1 != shift) { unchecked { // toAdd is non-zero in this branch self.peaks[i] = leaves[toAdd - 1]; } } else if (shift == 1) { // if shift == 0 then self.peaks[i] is already 0 self.peaks[i] = 0; } toAdd = nextAdd; unchecked { ++i; } } if (i > self.peaksLength) { self.peaksLength = i; } peaksChanged = i; } /** * @notice Compute the `completeLeaves` of an existing MMR when converted to a padded MMR with depth `paddingDepth`. * @param self The MMR. * @param paddingDepth The depth of the padded Merkle tree. * @return out The `completeLeaves` of the padded Merkle mountain range corresponding to the MMR. */ function getCompleteLeaves(MMR memory self, uint256 paddingDepth) internal pure returns (MMR memory out) { unchecked { // if self.peaksLength < paddingDepth, then out.peaksLength = 0 if (self.peaksLength >= paddingDepth) { out.peaksLength = self.peaksLength - paddingDepth; } for (uint256 i = paddingDepth; i < self.peaksLength;) { out.peaks[i - paddingDepth] = self.peaks[i]; ++i; } } } /** * @notice Hash an existing MMR to a Merkle root of a 0-padded Merkle tree with depth `paddingDepth`. * @param self The MMR. * @param paddingDepth The depth of the padded Merkle tree. * @return root The Merkle root of the padded MMR. */ function getZeroPaddedMerkleRoot(MMR memory self, uint256 paddingDepth) internal pure returns (bytes32) { bytes32 root; bool started; for (uint256 peakIdx; peakIdx < paddingDepth;) { if (!started && self.peaks[peakIdx] != bytes32(0)) { root = MerkleTree.getEmptyHash(peakIdx); started = true; } if (started) { root = self.peaks[peakIdx] != bytes32(0) ? Hash.keccak(self.peaks[peakIdx], root) : Hash.keccak(root, MerkleTree.getEmptyHash(peakIdx)); } unchecked { ++peakIdx; } } return root; } /** * @dev Extend an existing MMR to a Merkle root of a padded list of length `paddingSize` using complement peaks. * @param self The MMR. * @param paddingDepth The depth of the padded Merkle tree. * @param mmrComplement Entries which contain peaks of a complementary MMR, where `mmrComplement[idx]` is either `bytes32(0x0)` or the * Merkle root of a tree of depth `idx`. Only the relevant indices are accessed. * @dev As an example, if `mmr` has peaks of depth 9 8 6 3, then `mmrComplement` has peaks of depth 3 4 5 7 * In this example, the peaks of `mmr` are Merkle roots of the first 2^9 leaves, then the next 2^8 leaves, and so on. * The peaks of `mmrComplement` are Merkle roots of the first 2^3 leaves after `mmr`, then the next 2^4 leaves, and so on. * @return root The Merkle root of the completion of `mmr`. */ function getComplementMerkleRoot(MMR memory self, uint256 paddingDepth, bytes32[] memory mmrComplement) internal pure returns (bytes32) { bytes32 root; bool started; for (uint256 peakIdx; peakIdx < paddingDepth;) { if (!started && self.peaks[peakIdx] != bytes32(0)) { root = mmrComplement[peakIdx]; started = true; } if (started) { root = self.peaks[peakIdx] != bytes32(0) ? Hash.keccak(self.peaks[peakIdx], root) : Hash.keccak(root, mmrComplement[peakIdx]); } unchecked { ++peakIdx; } } return root; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { MerkleMountainRange } from "./MerkleMountainRange.sol"; /// @title Padded Merkle Mountain Range /// @author Axiom /// @notice Library for Merkle Mountain Range data structure library PaddedMerkleMountainRange { using MerkleMountainRange for MerkleMountainRange.MMR; /// @dev Error returned if the leaf is too big error PmmrLeafIsTooBig(); /// @dev Error returned if the leaf is not empty error PmmrLeafIsNotEmpty(); /** * @notice A Padded Merkle mountain range is a data structure for efficiently storing a commitment * to a variable length list of hash values batched by a specific size. For a fixed `paddingSize` * which must be a power of two, a PMMR consists of a standard MMR of Merkle roots of batches of * `paddingSize` hashes and a `paddedLeaf`, which is a Merkle root of the 0-padded last partial batch of * hashes, where the number of hashes lies in `[0, paddingSize)`. * We define `paddedLeaf = bytes32(0x0)` if the last partial batch of hashes is empty. * @param completeLeaves The MMR of the complete leaves of the PMMR * @param paddedLeaf The Merkle root of the 0-padded last partial batch of hashes * @param size The number of hashes this PMMR is a commitment to. */ struct PMMR { MerkleMountainRange.MMR completeLeaves; bytes32 paddedLeaf; uint32 size; } /** * @notice Copies the PMMR from storage to memory * @param self The PMMR in storage * @return out The PMMR in memory */ function clone(PMMR storage self) internal view returns (PMMR memory out) { out.completeLeaves = self.completeLeaves.clone(); out.paddedLeaf = self.paddedLeaf; out.size = self.size; } /** * @notice Copies PMMR from memory to storage * @param self The PMMR in storage * @param sourcePMMR The PMMR in memory * @param peaksChanged Only copy newMMR.peaks[0 : peaksChanged] */ function persistFrom(PMMR storage self, PMMR memory sourcePMMR, uint256 peaksChanged) internal { self.completeLeaves.persistFrom(sourcePMMR.completeLeaves, peaksChanged); self.paddedLeaf = sourcePMMR.paddedLeaf; self.size = sourcePMMR.size; } /** * @notice Compute a commitment to the PMMR, defined by * keccak(paddedLeaf || completeLeaves.peaks[0] || ... || completeLeaves.peaks[completeLeaves.peaksLength - 1]) * @param self The PMMR * @return keccak the hash of the concatenation */ function commit(PMMR memory self) internal pure returns (bytes32) { bytes32[] memory peaks = new bytes32[](self.completeLeaves.peaksLength); for (uint256 i; i < self.completeLeaves.peaksLength;) { peaks[i] = self.completeLeaves.peaks[i]; unchecked { ++i; } } return keccak256(abi.encodePacked(self.paddedLeaf, peaks)); } /** * @notice Updates the first peak representing the padded batch leaf * @dev Warning: This method can overflow if `self.size + leafSize` exceeds `2**32 - 1`. * This cannot happen for realistic values of block numbers, which is not an issue * in our application. * @param self The PMMR * @param paddingSize The size of the padded batch * @param leaf The padded leaf update * @param leafSize The size of the padded leaf, defined as the number of non-zero hashes it contains * @return completePeaksChanged amount of peaks that have been changed */ function updatePaddedLeaf(PMMR memory self, uint32 paddingSize, bytes32 leaf, uint32 leafSize) internal pure returns (uint256 completePeaksChanged) { if (leafSize > paddingSize) { revert PmmrLeafIsTooBig(); } unchecked { self.size = self.size - self.size % paddingSize + leafSize; } // just updating the padded leaf that is always at index 0 if (leafSize < paddingSize) { self.paddedLeaf = leaf; return 0; } // If leaf is complete delete self.paddedLeaf; completePeaksChanged = self.completeLeaves.appendLeaf(leaf); } /** * @notice Append a sequence of complete leaves to the underlying list of the PMMR * @dev The padded leaf should be empty to be able to append complete leaves * @param self The PMMR * @param paddingSize The size of the padded batch * @param leaves The new elements to append * @return completePeaksChanged amount of peaks that have been changed * @dev Warning: To save gas, this method overwrites values of `leaves` with intermediate computations. * The input values of `leaves` should be considered invalidated after calling this method. */ function appendCompleteLeaves(PMMR memory self, uint32 paddingSize, bytes32[] memory leaves) internal pure returns (uint256 completePeaksChanged) { if (self.paddedLeaf != bytes32(0)) { revert PmmrLeafIsNotEmpty(); } self.size += uint32(leaves.length) * paddingSize; completePeaksChanged = self.completeLeaves.appendLeaves(leaves); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Hash /// @notice Gas-optimized library for computing packed Keccak hashes library Hash { /// @notice Compute the Keccak hash of the packed values `keccak(a || b)` /// Gas-optimized equivalent of `keccak256(abi.encodePacked(a, b))` function keccak(bytes32 a, bytes32 b) internal pure returns (bytes32 hash) { assembly { mstore(0x00, a) mstore(0x20, b) hash := keccak256(0x00, 0x40) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // Constants and free functions to be inlined into by AxiomV2Core and AxiomV2Query /* * Constants for AxiomV2Core */ // AxiomV2Core caches blockhashes in batches, stored as Merkle roots of binary Merkle trees uint32 constant BLOCK_BATCH_SIZE = 1024; uint32 constant BLOCK_BATCH_DEPTH = 10; // constants for batch import of historical block hashes // historical uploads a bigger batch of block hashes, stored as Merkle roots of binary Merkle trees uint32 constant HISTORICAL_BLOCK_BATCH_SIZE = 131_072; // 2 ** 17 uint32 constant HISTORICAL_BLOCK_BATCH_DEPTH = 17; // we will consider the historical Merkle tree of blocks as a Merkle tree of the block batch roots uint32 constant HISTORICAL_NUM_ROOTS = 128; // HISTORICAL_BATCH_SIZE / BLOCK_BATCH_SIZE // The first 4 * 3 * 32 bytes of proof calldata are reserved for two BN254 G1 points for a pairing check // It will then be followed by (7 + BLOCK_BATCH_DEPTH * 2) * 32 bytes of public inputs/outputs uint32 constant PUBLIC_BYTES_START_IDX = 384; // 4 * 3 * 32 uint32 constant AUX_PEAKS_START_IDX = 608; // PUBLIC_BYTES_START_IDX + 7 * 32 /// @notice Read public instances from the ZK proof /// @param proofData the entire ZK proof /// @return prevHash the hash of the previous block /// @return endHash the hash of the last block in the batch /// @return startBlockNumber the block number of the first block in the batch /// @return endBlockNumber the block number of the last block in the batch /// @return root the Merkle root of the 0-padded batch of blocks /// @dev proofData stores bytes32 and uint256 values in hi-lo format as two uint128 values because the BN254 scalar field is 254 bits /// @dev The first 12 * 32 bytes of proofData are reserved for ZK proof verification data // Extract public instances from proof // The public instances are laid out in the proof calldata as follows: // First 4 * 3 * 32 = 384 bytes are reserved for proof verification data used with the pairing precompile // 384..384 + 32 * 2: prevHash (32 bytes) as two uint128 cast to uint256, because zk proof uses 254 bit field and cannot fit uint256 into a single element // 384 + 32 * 2..384 + 32 * 4: endHash (32 bytes) as two uint128 cast to uint256 // 384 + 32 * 4..384 + 32 * 5: startBlockNumber (uint32: 4 bytes) and endBlockNumber (uint32: 4 bytes) are concatenated as `startBlockNumber . endBlockNumber` (8 bytes) and then cast to uint256 // 384 + 32 * 5..384 + 32 * 7: root (32 bytes) as two uint128 cast to uint256, this is the highest peak of the MMR if endBlockNumber - startBlockNumber == 1023, otherwise 0 function getBoundaryBlockData(bytes calldata proofData) pure returns (bytes32 prevHash, bytes32 endHash, uint32 startBlockNumber, uint32 endBlockNumber, bytes32 root) { prevHash = bytes32(uint256(bytes32(proofData[PUBLIC_BYTES_START_IDX:416])) << 128 | uint256(bytes32(proofData[416:448]))); endHash = bytes32(uint256(bytes32(proofData[448:480])) << 128 | uint256(bytes32(proofData[480:512]))); startBlockNumber = uint32(bytes4(proofData[536:540])); endBlockNumber = uint32(bytes4(proofData[540:544])); root = bytes32(uint256(bytes32(proofData[544:576])) << 128 | uint256(bytes32(proofData[576:AUX_PEAKS_START_IDX]))); } // We have a Merkle mountain range of max depth BLOCK_BATCH_DEPTH (so length BLOCK_BATCH_DEPTH + 1 total) ordered in **decreasing** order of peak size, so: // `root` from `getBoundaryBlockData` is the peak for depth BLOCK_BATCH_DEPTH // `getAuxMmrPeak(proofData, i)` is the peaks for depth BLOCK_BATCH_DEPTH - 1 - i // 384 + 32 * 7 + 32 * 2 * i .. 384 + 32 * 7 + 32 * 2 * (i + 1): (32 bytes) as two uint128 cast to uint256, same as blockHash // Note that the decreasing ordering is *different* than the convention in library MerkleMountainRange function getAuxMmrPeak(bytes calldata proofData, uint256 i) pure returns (bytes32) { return bytes32( uint256(bytes32(proofData[AUX_PEAKS_START_IDX + i * 64:AUX_PEAKS_START_IDX + i * 64 + 32])) << 128 | uint256(bytes32(proofData[AUX_PEAKS_START_IDX + i * 64 + 32:AUX_PEAKS_START_IDX + (i + 1) * 64])) ); } /* * Constants for AxiomV2Query */ /// @dev Chain IDs for Ethereum mainnet and testnets uint64 constant MAINNET_CHAIN_ID = 1; uint64 constant GOERLI_CHAIN_ID = 5; uint64 constant SEPOLIA_CHAIN_ID = 11_155_111; uint64 constant HOLESKY_CHAIN_ID = 17_000; /// @dev Constant recording the fact that this is Axiom V2 uint8 constant VERSION = 2; /// @dev Largest deposit allowed at one time uint256 constant MAX_DEPOSIT_SIZE = 100 ether; /// @dev Conservative upper bound for `proofVerificationGas`. Real values should be lower. uint32 constant MAX_PROOF_VERIFICATION_GAS = 600_000; /// @dev Conservative upper bound for `axiomQueryFee`. Real values should be lower. uint256 constant MAX_AXIOM_QUERY_FEE = 0.05 ether;
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControlUpgradeable { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// 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 (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/MathUpgradeable.sol"; /** * @dev String operations. */ library StringsUpgradeable { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = MathUpgradeable.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, MathUpgradeable.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } /** * @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.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.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.8.3) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeaconUpgradeable.sol"; import "../../interfaces/IERC1967Upgradeable.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, IERC1967Upgradeable { 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 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 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 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 pragma solidity ^0.8.0; interface IAxiomV2Verifier { /// @notice Witness data needed to verify a block against the verified blocks cached by AxiomV2Core /// @param blockNumber The block number to verify /// @param claimedBlockHash The claimed blockhash of block `blockNumber` /// @param prevHash The parent hash of the first block in the batch containing block `blockNumber` /// @param numFinal The number of consecutive blocks verified in this batch /// @param merkleProof The Merkle inclusion proof of `claimedBlockHash` to the root of the batch struct BlockHashWitness { uint32 blockNumber; bytes32 claimedBlockHash; bytes32 prevHash; uint32 numFinal; bytes32[] merkleProof; } /// @notice Verify the blockhash of block blockNumber equals claimedBlockHash. Assumes that blockNumber is within the last 256 most recent blocks. /// @param blockNumber The block number to verify /// @param claimedBlockHash The claimed blockhash of block blockNumber function isRecentBlockHashValid(uint32 blockNumber, bytes32 claimedBlockHash) external view returns (bool); /// @notice Verify the blockhash of block witness.blockNumber equals witness.claimedBlockHash by checking against Axiom's cache of #historicalRoots. /// @dev For block numbers within the last 256, use #isRecentBlockHashValid instead. /// @param witness The block hash to verify and the Merkle proof to verify it /// witness.blockNumber is the block number to verify /// witness.claimedBlockHash is the claimed blockhash of block witness.blockNumber /// witness.prevHash is the prevHash stored in #historicalRoots(witness.blockNumber - witness.blockNumber % 1024) /// witness.numFinal is the numFinal stored in #historicalRoots(witness.blockNumber - witness.blockNumber % 1024) /// witness.merkleProof is the Merkle inclusion proof of witness.claimedBlockHash to the root stored in #historicalRoots(witness.blockNumber - witness.blockNumber % 1024) /// witness.merkleProof[i] is the sibling of the Merkle node at depth 10 - i, for i = 0, ..., 10 function isBlockHashValid(BlockHashWitness calldata witness) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IAxiomV2Update { /// @notice Verify and store a batch of consecutive blocks, where the latest block in the batch is within the last 256 most recent blocks. /// @param proofData The raw bytes of a zero knowledge proof to be verified by the contract. /// proofData contains public inputs/outputs of /// (bytes32 prevHash, bytes32 endHash, uint32 startBlockNumber, uint32 endBlockNumber, bytes32[11] mmr) /// where the proof verifies the blockhashes of blocks [startBlockNumber, endBlockNumber], endBlockNumber - startBlockNumber <= 1023 /// - startBlockNumber must be a multiple of 1024 /// - prevHash is the parent hash of block `startBlockNumber`, /// - endHash is the blockhash of block `endBlockNumber`, /// - mmr is the keccak Merkle mountain range of the blockhashes of blocks [startBlockNumber, endBlockNumber], ordered from depth 10 to depth 0 function updateRecent(bytes calldata proofData) external; /// @notice Verify and store a batch of 1024 consecutive blocks, /// where the latest block in the batch is verified against the blockhash cache in #historicalRoots /// @dev The contract checks that #historicalRoots(endBlockNumber + 1) == keccak256(endHash || nextRoot || nextNumFinal) /// where endBlockNumber, endHash are derived from proofData. /// nextRoot and nextNumFinal should be obtained by reading event logs. For old blocks nextNumFinal is _usually_ 1024. /// @param proofData The raw bytes of a zero knowledge proof to be verified by the contract. Has same format as in #updateRecent except /// endBlockNumber = startBlockNumber + 1023, so the block batch size is exactly 1024 /// mmr contains the keccak Merkle root of the full Merkle tree of depth 10, followed by zeros /// @param nextRoot The Merkle root stored in #historicalRoots(endBlockNumber + 1) /// @param nextNumFinal The numFinal stored in #historicalRoots(endBlockNumber + 1) function updateOld(bytes32 nextRoot, uint32 nextNumFinal, bytes calldata proofData) external; /// @notice Verify and store a batch of 2^17 = 128 * 1024 consecutive blocks, /// where the latest block in the batch is verified against the blockhash cache in #historicalRoots /// @dev Has the same effect as calling #updateOld 128 times on consecutive batches of 1024 blocks each. /// But uses a different SNARK to verify the proof of all 2^17 blocks at once. /// endHashProofs is used to get the intermediate parent hashes of these 1024 block batches /// @param proofData The raw bytes of a zero knowledge proof to be verified by the contract. Has similar format as in #updateRecent except /// we require endBlockNumber = startBlockNumber + 2^17 - 1, so the block batch size is exactly 2^17. /// proofData contains public inputs/outputs of: /// (bytes32 prevHash, bytes32 endHash, uint32 startBlockNumber, uint32 endBlockNumber, bytes32[18] mmr) /// - startBlockNumber must be a multiple of 1024 /// - we require that endBlockNumber - startBlockNumber = 2^17 - 1 /// - prevHash is the parent hash of block `startBlockNumber`, /// - endHash is the blockhash of block `endBlockNumber`, /// - mmr[0] is the keccak Merkle root of the blockhashes of blocks [startBlockNumber, startBlockNumber + 2^17), the other entries in mmr are zeros /// @param nextRoot The Merkle root stored in #historicalRoots(endBlockNumber + 1) /// @param nextNumFinal The numFinal stored in #historicalRoots(endBlockNumber + 1) /// @param roots roots[i] is the Merkle root of the blockhashes of blocks [startBlockNumber + i * 1024, startBlockNumber + (i + 1) * 1024) for i = 0, ..., 127 /// @param endHashProofs endHashProofs[i] is the Merkle inclusion proof of the blockhash of block `startBlockNumber + (i + 1) * 1024 - 1` in roots[i], for i = 0, ..., 126 /// endHashProofs[i][10] is the blockhash of block `startBlockNumber + (i + 1) * 1024 - 1` /// endHashProofs[i][j] is the sibling of the Merkle node at depth j, for j = 0, ..., 9 function updateHistorical( bytes32 nextRoot, uint32 nextNumFinal, bytes32[128] calldata roots, bytes32[11][127] calldata endHashProofs, bytes calldata proofData ) external; /// @notice Extend `blockhashPmmr` with commitments to block hashes in `historicalRoots` /// @dev The blocks to append must be cached in entries of `historicalRoots` corresponding to `startBlockNumber` /// values which are consecutive multiples of 1024. All but the last entry in `historicalRoots` must have `numFinal = 1024`. /// `startBlockNumber` must equal `blockhashPmmr.size - (blockhashPmmr.size % 1024)`, but we make it an input for faster reverts /// @param startBlockNumber The block number of the first block to append /// @param roots roots[i] is the Merkle root of the blockhashes of blocks [startBlockNumber + i * 1024, startBlockNumber + (i + 1) * 1024) for i = 0, ..., roots.length - 2 /// roots[roots.length - 1] is the 0-padded Merkle root of the blockhashes of blocks [startBlockNumber + (roots.length - 1) * 1024, startBlockNumber + (roots.length - 1) * 1024 + lastNumFinal) /// @param prevHashes prevHashes[i] is the parent hash of block `startBlockNumber + i * 1024`, for i = 0, ..., roots.length - 1. prevHashes and roots must have the same length. /// @param lastNumFinal The `numFinal` value for the final group of block hashes committed to in `roots`. function appendHistoricalPMMR( uint32 startBlockNumber, bytes32[] calldata roots, bytes32[] calldata prevHashes, uint32 lastNumFinal ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { PaddedMerkleMountainRange } from "../../libraries/PaddedMerkleMountainRange.sol"; import { MerkleMountainRange } from "../../libraries/MerkleMountainRange.sol"; interface IAxiomV2State { /// @notice Returns the hash of a batch of consecutive blocks previously verified by the contract /// @param startBlockNumber The block number of the first block in the batch /// @dev The reads here will match the emitted #UpdateEvent /// @return historicalRoots(startBlockNumber) is 0 unless (startBlockNumber % 1024 == 0) /// historicalRoots(startBlockNumber) = 0 if block `startBlockNumber` is not verified /// historicalRoots(startBlockNumber) = keccak256(prevHash || root || numFinal) where || is concatenation /// - prevHash is the parent hash of block `startBlockNumber` /// - root is the keccak Merkle root of hash(i) for i in [0, 1024), where /// hash(i) is the blockhash of block `startBlockNumber + i` if i < numFinal, /// hash(i) = bytes32(0x0) if i >= numFinal /// - 0 < numFinal <= 1024 is the number of verified consecutive roots in [startBlockNumber, startBlockNumber + numFinal) function historicalRoots(uint32 startBlockNumber) external view returns (bytes32); /// @notice Get the number of consecutive blocks from genesis currently committed to in `blockhashPmmr` /// The padded Merkle mountain range `blockhashPmmr` commits to the block hashes of blocks /// `[0, pmmrSize)` /// @return pmmrSize indicates that the blockhashPmmr commits to blockhashes of blocks `[0, pmmrSize)` function blockhashPmmrSize() external view returns (uint32 pmmrSize); /// @notice Get the `paddedLeaf` of the padded Merkle mountain range `blockhashPmmr` /// @return paddedLeaf the `paddedLeaf` corresponding to `blockhashPmmr` function blockhashPmmrLeaf() external view returns (bytes32); /// @notice Returns the PMMR commitment to the blockhashes of blocks `[0, pmmrSize)`, if it exists, `bytes32(0x0)` otherwise /// @param pmmrSize The number of blocks committed to in the PMMR /// @return pmmrHash The hash of the PMMR, as computed by `PaddedMerkleMountainRange.commit` function pmmrSnapshots(uint32 pmmrSize) external view returns (bytes32); /// @notice Returns the Merkle mountain range of peaks in `blockhashPmmr /// @return mmr The Merkle mountain range. function blockhashPmmrPeaks() external view returns (MerkleMountainRange.MMR memory); /// @notice Get the full current `blockhashPmmr` /// @return blockhashPmmr The current PMMR commitment to historic block hashes function fullBlockhashPmmr() external view returns (PaddedMerkleMountainRange.PMMR memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IAxiomV2Events { /// @notice Error returned when the SNARK verification fails error SNARKVerificationFailed(); /// @notice Error returned when block header verification fails error AxiomBlockVerificationFailed(); /// @notice Error returned when the length of block header chain verified in a proof is inconsistent /// with other data. error IncorrectNumberOfBlocks(); /// @notice Error returned when the first block hash in a chain is not consistent with other dat. error StartingBlockNotValid(); /// @notice Error returned when the last block hash in a chain is not in the window of 256 recent block hashes. error NotRecentEndBlock(); /// @notice Error returned when the last block hash in a chain is not consistent with other data. error BlockHashIncorrect(); /// @notice Error returned when a Merkle proof verification fails. error MerkleProofFailed(); /// @dev Error returned if the prover address is 0. error VerifierAddressIsZero(); /// @dev Error returned if the prover address is 0. error HistoricalVerifierAddressIsZero(); /// @dev Error returned if the timelock address is 0. error TimelockAddressIsZero(); /// @dev Error returned if the guardian address is 0. error GuardianAddressIsZero(); /// @dev Error returned if the unfreeze address is 0. error UnfreezeAddressIsZero(); /// @dev Error returned if the prover address is 0. error ProverAddressIsZero(); /// @notice Emitted when a new batch of consecutive blocks is trustlessly verified and cached in the contract storage `historicalRoots` /// @param startBlockNumber The block number of the first block in the batch /// @param prevHash The parent hash of block `startBlockNumber` /// @param root The Merkle root of hash(i) for i in [0, 1024), where hash(i) is the blockhash of block `startBlockNumber + i` if i < numFinal, /// Otherwise hash(i) = bytes32(0x0) if i >= numFinal /// @param numFinal The number of consecutive blocks in this batch, i.e., [startBlockNumber, startBlockNumber + numFinal) blocks are verified event HistoricalRootUpdated(uint32 indexed startBlockNumber, bytes32 prevHash, bytes32 root, uint32 numFinal); /// @notice Emitted when the size of `blockhashPmmr` changes. /// @param commitment Commitment to `blockhashPmmr` as computed by `PaddedMerkleMountainRange.commit` /// @param pmmrSize The `blockhashPmmr` now commits to block hashes `[0, endBlockNumber)` event PaddedMerkleMountainRangeUpdated(bytes32 indexed commitment, uint32 pmmrSize); /// @notice Emitted when the SNARK verifierAddress changes /// @param newAddress The new address of the SNARK verifier contract event UpgradeSnarkVerifier(address newAddress); /// @notice Emitted when the SNARK historicalVerifierAddress changes /// @param newAddress The new address of the SNARK historical verifier contract event UpgradeHistoricalSnarkVerifier(address newAddress); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library MathUpgradeable { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// 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 (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.8.3) (interfaces/IERC1967.sol) pragma solidity ^0.8.0; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. * * _Available since v4.9._ */ interface IERC1967Upgradeable { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.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 } } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@solmate-utils/=lib/solmate/src/utils/", "@create3-factory/=lib/create3-factory/src/", "create3-factory/=lib/create3-factory/", "nitro-contracts/=lib/nitro-contracts/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "solmate/=lib/solmate/src/", "weird-erc20/=lib/solmate/lib/weird-erc20/src/" ], "optimizer": { "enabled": true, "runs": 100000, "details": { "constantOptimizer": false, "yul": false } }, "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
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AxiomBlockVerificationFailed","type":"error"},{"inputs":[],"name":"BlockHashIncorrect","type":"error"},{"inputs":[],"name":"ContractIsFrozen","type":"error"},{"inputs":[],"name":"GuardianAddressIsZero","type":"error"},{"inputs":[],"name":"HistoricalVerifierAddressIsZero","type":"error"},{"inputs":[],"name":"IncorrectNumberOfBlocks","type":"error"},{"inputs":[],"name":"InvalidEmptyHashDepth","type":"error"},{"inputs":[],"name":"MerkleProofFailed","type":"error"},{"inputs":[],"name":"NotAxiomRole","type":"error"},{"inputs":[],"name":"NotProverRole","type":"error"},{"inputs":[],"name":"NotRecentEndBlock","type":"error"},{"inputs":[],"name":"PmmrLeafIsNotEmpty","type":"error"},{"inputs":[],"name":"PmmrLeafIsTooBig","type":"error"},{"inputs":[],"name":"ProverAddressIsZero","type":"error"},{"inputs":[],"name":"SNARKVerificationFailed","type":"error"},{"inputs":[],"name":"StartingBlockNotValid","type":"error"},{"inputs":[],"name":"TimelockAddressIsZero","type":"error"},{"inputs":[],"name":"UnfreezeAddressIsZero","type":"error"},{"inputs":[],"name":"VerifierAddressIsZero","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":[],"name":"FreezeAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"startBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"prevHash","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"root","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"numFinal","type":"uint32"}],"name":"HistoricalRootUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"commitment","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"pmmrSize","type":"uint32"}],"name":"PaddedMerkleMountainRangeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[],"name":"UnfreezeAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAddress","type":"address"}],"name":"UpgradeHistoricalSnarkVerifier","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAddress","type":"address"}],"name":"UpgradeSnarkVerifier","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"AXIOM_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GUARDIAN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROVER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIMELOCK_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNFREEZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"startBlockNumber","type":"uint32"},{"internalType":"bytes32[]","name":"roots","type":"bytes32[]"},{"internalType":"bytes32[]","name":"prevHashes","type":"bytes32[]"},{"internalType":"uint32","name":"lastNumFinal","type":"uint32"}],"name":"appendHistoricalPMMR","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"blockhashPmmr","outputs":[{"components":[{"internalType":"bytes32[32]","name":"peaks","type":"bytes32[32]"},{"internalType":"uint256","name":"peaksLength","type":"uint256"}],"internalType":"struct MerkleMountainRange.MMR","name":"completeLeaves","type":"tuple"},{"internalType":"bytes32","name":"paddedLeaf","type":"bytes32"},{"internalType":"uint32","name":"size","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blockhashPmmrLeaf","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blockhashPmmrPeaks","outputs":[{"components":[{"internalType":"bytes32[32]","name":"peaks","type":"bytes32[32]"},{"internalType":"uint256","name":"peaksLength","type":"uint256"}],"internalType":"struct MerkleMountainRange.MMR","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blockhashPmmrSize","outputs":[{"internalType":"uint32","name":"pmmrSize","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"freezeAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"frozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fullBlockhashPmmr","outputs":[{"components":[{"components":[{"internalType":"bytes32[32]","name":"peaks","type":"bytes32[32]"},{"internalType":"uint256","name":"peaksLength","type":"uint256"}],"internalType":"struct MerkleMountainRange.MMR","name":"completeLeaves","type":"tuple"},{"internalType":"bytes32","name":"paddedLeaf","type":"bytes32"},{"internalType":"uint32","name":"size","type":"uint32"}],"internalType":"struct PaddedMerkleMountainRange.PMMR","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"historicalRoots","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"historicalVerifierAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_verifierAddress","type":"address"},{"internalType":"address","name":"_historicalVerifierAddress","type":"address"},{"internalType":"address","name":"timelock","type":"address"},{"internalType":"address","name":"guardian","type":"address"},{"internalType":"address","name":"unfreeze","type":"address"},{"internalType":"address","name":"prover","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"claimedBlockHash","type":"bytes32"},{"internalType":"bytes32","name":"prevHash","type":"bytes32"},{"internalType":"uint32","name":"numFinal","type":"uint32"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"internalType":"struct IAxiomV2Verifier.BlockHashWitness","name":"witness","type":"tuple"}],"name":"isBlockHashValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"claimedBlockHash","type":"bytes32"}],"name":"isRecentBlockHashValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"pmmrSnapshots","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unfreezeAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"nextRoot","type":"bytes32"},{"internalType":"uint32","name":"nextNumFinal","type":"uint32"},{"internalType":"bytes32[128]","name":"roots","type":"bytes32[128]"},{"internalType":"bytes32[11][127]","name":"endHashProofs","type":"bytes32[11][127]"},{"internalType":"bytes","name":"proofData","type":"bytes"}],"name":"updateHistorical","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"nextRoot","type":"bytes32"},{"internalType":"uint32","name":"nextNumFinal","type":"uint32"},{"internalType":"bytes","name":"proofData","type":"bytes"}],"name":"updateOld","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"proofData","type":"bytes"}],"name":"updateRecent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_historicalVerifierAddress","type":"address"}],"name":"upgradeHistoricalSnarkVerifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_verifierAddress","type":"address"}],"name":"upgradeSnarkVerifier","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":[],"name":"verifierAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a0604052306080523480156200001557600080fd5b506200002062000026565b62000164565b600054610100900460ff161562000074576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200006b90620000ec565b60405180910390fd5b60005460ff9081161015620000ea57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff9081179091556040517f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249891620000e19162000154565b60405180910390a15b565b602080825281016200014e81602781527f496e697469616c697a61626c653a20636f6e747261637420697320696e69746960208201527f616c697a696e6700000000000000000000000000000000000000000000000000604082015260600190565b92915050565b60ff82168152602081016200014e565b608051614d656200019c60003960008181610ea401528181610efe01528181610ffd01528181611057015261115e0152614d656000f3fe60806040526004361061024f5760003560e01c80637225fb2111610138578063c608b5e8116100b0578063dc9a4ef61161007f578063ee5ead6011610064578063ee5ead6014610726578063f288a2e214610746578063fe9ccb601461077a57600080fd5b8063dc9a4ef6146106d2578063dd3c91781461070657600080fd5b8063c608b5e814610630578063c6ca475314610664578063cc2a9a5b14610692578063d547741f146106b257600080fd5b8063a217fddf11610107578063adfc424c116100ec578063adfc424c146105ca578063b16fc75d146105ec578063c1f7cae21461061057600080fd5b8063a217fddf14610595578063ac59e61c146105aa57600080fd5b80637225fb21146104ed578063853ead4a1461050d57806391d148541461052d57806399464c891461058057600080fd5b806336568abe116101cb57806352d1902d1161019a578063596ef8a71161017f578063596ef8a7146104865780635ed36613146104aa57806366c5c4a0146104d857600080fd5b806352d1902d1461045b57806357b835f21461047057600080fd5b806336568abe146103e65780633659cfe6146104065780634f1ef286146104265780635144eeec1461043957600080fd5b806318bdffbb1161022257806324ea54f41161020757806324ea54f41461035e5780632b7d2bad146103925780632f2ff15d146103c657600080fd5b806318bdffbb146102e6578063248a9ca31461032157600080fd5b806301ef3afa1461025457806301ffc9a714610276578063054f7d9c146102ac57806311b63d01146102c6575b600080fd5b34801561026057600080fd5b5061027461026f366004613b72565b6107a8565b005b34801561028257600080fd5b50610296610291366004613bf4565b610b8a565b6040516102a39190613c1f565b60405180910390f35b3480156102b857600080fd5b506097546102969060ff1681565b3480156102d257600080fd5b506102746102e1366004613c55565b610bc5565b3480156102f257600080fd5b50610124546103149073ffffffffffffffffffffffffffffffffffffffff1681565b6040516102a39190613cea565b34801561032d57600080fd5b5061035161033c366004613cf8565b60009081526065602052604090206001015490565b6040516102a39190613d1f565b34801561036a57600080fd5b506103517f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504181565b34801561039e57600080fd5b506103517f542178611b653a605b79640db9b52a7afa591d6ace75cd36686e0ee264f4f57281565b3480156103d257600080fd5b506102746103e1366004613d41565b610dfd565b3480156103f257600080fd5b50610274610401366004613d41565b610e27565b34801561041257600080fd5b50610274610421366004613d7e565b610e8d565b610274610434366004613eef565b610fe6565b34801561044557600080fd5b5061044e61112c565b6040516102a39190613ff1565b34801561046757600080fd5b50610351611144565b34801561047c57600080fd5b5061014854610351565b34801561049257600080fd5b506101495463ffffffff166040516102a39190614000565b3480156104b657600080fd5b506103516104c536600461400e565b61014a6020526000908152604090205481565b3480156104e457600080fd5b506102746111da565b3480156104f957600080fd5b50610274610508366004614059565b611258565b34801561051957600080fd5b50610274610528366004613d7e565b6116ae565b34801561053957600080fd5b50610296610548366004613d41565b600091825260656020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561058c57600080fd5b506102746117a2565b3480156105a157600080fd5b50610351600081565b3480156105b657600080fd5b506102746105c5366004613d7e565b611823565b3480156105d657600080fd5b506105df61190b565b6040516102a391906140f2565b3480156105f857600080fd5b5061060161191e565b6040516102a393929190614101565b34801561061c57600080fd5b5061029661062b36600461412c565b611978565b34801561063c57600080fd5b506103517ff4e710c64967f31ba1090db2a7dd9e704155d00947ce853da47446cb68ee65da81565b34801561067057600080fd5b5061035161067f36600461400e565b6101266020526000908152604090205481565b34801561069e57600080fd5b506102746106ad36600461415f565b6119c4565b3480156106be57600080fd5b506102746106cd366004613d41565b611e5a565b3480156106de57600080fd5b506103517f60044782a422109ac08a415e44260ad5d3bad63d96ebe1fac0363399642ee3f281565b34801561071257600080fd5b50610296610721366004614204565b611e7f565b34801561073257600080fd5b5061027461074136600461428a565b612039565b34801561075257600080fd5b506103517ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f0581565b34801561078657600080fd5b50610125546103149073ffffffffffffffffffffffffffffffffffffffff1681565b6107b06123e4565b6107b86124a2565b60008060008060006107ca87876124df565b94509450945094509450600083836107e2919061434e565b6107ed90600161436e565b905061040063ffffffff82161115610831576040517f28e21b9700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61083d610400856143bd565b63ffffffff161561087a576040517f5eb1350600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b438363ffffffff16106108b9576040517faef3422900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101006108cc63ffffffff8516436143db565b1115610904576040517faef3422900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b848363ffffffff164014610944576040517fa46ad57500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61094e88886125dc565b610984576040517f1355d9a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061099161012761265b565b905082610a145760005b600a811015610a125760006109cd8b8b846109b86001600a61434e565b63ffffffff166109c891906143db565b61268c565b905080156109ea5760008181526020869052604090209450610a09565b610a06856109f78461274c565b60009182526020526040902090565b94505b5060010161099b565b505b8463ffffffff16816040015163ffffffff1610158015610a4457508363ffffffff16816040015163ffffffff1611155b15610ae3576000610a59826104008686612937565b9050610a6861012783836129ff565b6000610a7383612a55565b90508061014a6000610a8689600161436e565b63ffffffff1663ffffffff16815260200190815260200160002081905550807fa913f532bb19d8d4e81c3b0b5e83e90b57152693da6f0c1b53110241d9db68398460400151604051610ad89190614000565b60405180910390a250505b868383604051602001610af893929190614409565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012063ffffffff891660008181526101269093529290912055907f71c7303b6eab390db8d0d18c6c3aae2906f6f881861bbc6ee21a858a7af3f4c390610b77908a9087908790614440565b60405180910390a2505050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082161580610bbf5750610bbf82612b27565b92915050565b610bcd6123e4565b610bd56124a2565b6000806000806000610be787876124df565b9450945094509450945061040083610bff91906143bd565b63ffffffff1615610c3c576040517f5eb1350600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c49600161040061434e565b63ffffffff16610c59848461434e565b63ffffffff1614610c96576040517f28e21b9700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b838989604051602001610cab93929190614409565b604051602081830303815290604052805190602001206101266000846001610cd3919061436e565b63ffffffff1663ffffffff1681526020019081526020016000205414610d25576040517fa46ad57500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2f87876125dc565b610d65576040517f1355d9a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8481610400604051602001610d7c93929190614409565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012063ffffffff871660008181526101269093529290912055907f71c7303b6eab390db8d0d18c6c3aae2906f6f881861bbc6ee21a858a7af3f4c390610b77908890859061040090614440565b600082815260656020526040902060010154610e1881612bbe565b610e228383612bc8565b505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610e7f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e76906144c5565b60405180910390fd5b610e898282612cbc565b5050565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163003610efc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e769061452f565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610f717f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610fbe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7690614599565b610fc781612d77565b60408051600080825260208201909252610fe391839190612da1565b50565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163003611055576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e769061452f565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166110ca7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614611117576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7690614599565b61112082612d77565b610e8982826001612da1565b611134613aba565b61113f61012761265b565b905090565b60003073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146111b5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7690614603565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b7ff4e710c64967f31ba1090db2a7dd9e704155d00947ce853da47446cb68ee65da61120481612bbe565b609780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517fe6fdbf73945dd61794a752b9181ea29f77170a7b1ffd37e0a7ff9d2c6f7258b990600090a150565b6112606123e4565b6112686124a2565b600080600080600061127a87876124df565b945094509450945094506104008361129291906143bd565b63ffffffff16156112cf576040517f5eb1350600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112dd60016202000061434e565b63ffffffff166112ed848461434e565b63ffffffff161461132a576040517f28e21b9700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b838b8b60405160200161133f93929190614409565b604051602081830303815290604052805190602001206101266000846001611367919061436e565b63ffffffff1663ffffffff16815260200190815260200160002054146113b9576040517fa46ad57500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806113ec8a6080806020026040519081016040528092919082608060200280828437600092019190915250612ef4915050565b14611423576040517ff4c360f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61142d87876130a3565b611463576040517f1355d9a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b60808110156116a05761147b6001608061434e565b63ffffffff16811461156d5760008982607f811061149b5761149b614613565b6101600201600a6020020135905060005b600a81101561151b576115118b84607f81106114ca576114ca614613565b6101600201826114dc6001600a61434e565b63ffffffff166114ec91906143db565b600b81106114fc576114fc614613565b60200201358360009182526020526040902090565b91506001016114ac565b508a826080811061152e5761152e614613565b6020020135811461156b576040517ff4c360f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b600081156115a257896115816001846143db565b607f811061159157611591614613565b6101600201600a60200201356115a4565b865b905060006115b461040084614642565b6115c49063ffffffff8816614661565b9050818c84608081106115d9576115d9614613565b60200201356104006040516020016115f393929190614409565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012063ffffffff8416600081815261012690945291909220919091557f71c7303b6eab390db8d0d18c6c3aae2906f6f881861bbc6ee21a858a7af3f4c3838e866080811061167757611677614613565b602002013561040060405161168e93929190614440565b60405180910390a25050600101611466565b505050505050505050505050565b7ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f056116d881612bbe565b73ffffffffffffffffffffffffffffffffffffffff8216611725576040517f3815ff6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61012480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556040517f0f7ba11d4e9d02c6ec9175a0134522c2f112de7cfdb2cea3f888e7eeae24c9dd90611796908490613cea565b60405180910390a15050565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a50416117cc81612bbe565b609780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f61340a1b154d5d21d259a74bf95379201799b9d12cc6509bb46cb56dc281df5590600090a150565b7ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f0561184d81612bbe565b73ffffffffffffffffffffffffffffffffffffffff821661189a576040517ffe98f3bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61012580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556040517f1431075dc15e519b4b9b0b93ea4f7f3e2a34fde5e39f552bb899b7ea4bda134190611796908490613cea565b611913613ae1565b61113f6101276130d5565b6040805161044081018083526101279283918391820190839060209082845b81548152602001906001019080831161193d575050509183525050602091820154910152602182015460229092015490919063ffffffff1683565b600063ffffffff8316408082036119bb576040517fa46ad57500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b90911492915050565b600054610100900460ff16158080156119e45750600054600160ff909116105b806119fe5750303b1580156119fe575060005460ff166001145b611a34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e76906146ce565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611a9257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b73ffffffffffffffffffffffffffffffffffffffff8716611adf576040517f3815ff6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8616611b2c576040517ffe98f3bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8516611b79576040517fd5ae8cf700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8416611bc6576040517f40c2354200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316611c13576040517f6d92bcf300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216611c60576040517ffbc5fc2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c6861312f565b611c70613170565b610124805473ffffffffffffffffffffffffffffffffffffffff808a167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556101258054928916929091169190911790556040517f0f7ba11d4e9d02c6ec9175a0134522c2f112de7cfdb2cea3f888e7eeae24c9dd90611cf7908990613cea565b60405180910390a17f1431075dc15e519b4b9b0b93ea4f7f3e2a34fde5e39f552bb899b7ea4bda134186604051611d2e9190613cea565b60405180910390a1611d41600086612bc8565b611d6b7ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f0586612bc8565b611d957f60044782a422109ac08a415e44260ad5d3bad63d96ebe1fac0363399642ee3f283612bc8565b611dbf7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504185612bc8565b611de97ff4e710c64967f31ba1090db2a7dd9e704155d00947ce853da47446cb68ee65da84612bc8565b8015611e5157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690556040517f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890611e48906001906146f2565b60405180910390a15b50505050505050565b600082815260656020526040902060010154611e7581612bbe565b610e228383612cbc565b600060208201358103611ebe576040517fa46ad57500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610400611ed0602085018561400e565b611eda91906143bd565b9050600081611eec602086018661400e565b611ef6919061434e565b63ffffffff811660009081526101266020526040812054919250819003611f49576040517ff4c360f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602085013560005b600a811015611fed57600163ffffffff8616821c16600003611fab57611fa482611f7e60808a018a614700565b84818110611f8e57611f8e614613565b9050602002013560009182526020526040902090565b9150611fe5565b611fe2611fbb6080890189614700565b83818110611fcb57611fcb614613565b905060200201358360009182526020526040902090565b91505b600101611f51565b506040860135816120046080890160608a0161400e565b60405160200161201693929190614409565b604051602081830303815290604052805190602001208214945050505050919050565b6120416124a2565b600061204e61012761265b565b905084158061205d5750848314155b806120945750610400816040015161207591906143bd565b8160400151612084919061434e565b63ffffffff168763ffffffff1614155b156120cb576040517f28e21b9700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120da81610400600080612937565b506000805b6120ea6001886143db565b8110156121d45785858281811061210357612103614613565b9050602002013588888381811061211c5761211c614613565b9050602002013561040060405160200161213893929190614409565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012063ffffffff8c16600090815261012690935291205490925082146121be576040517f612489a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6121ca6104008a61436e565b98506001016120df565b50600061223361040089838a6121eb6001826143db565b926121f89392919061477b565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508894939250506131db9050565b9050858561224260018a6143db565b81811061225157612251614613565b6020029190910135905088886122686001826143db565b81811061227757612277614613565b905060200201358560405160200161229193929190614409565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012063ffffffff8c1660009081526101269093529120549092508214612317576040517f612489a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061234d6104008a8a61232c6001826143db565b81811061233b5761233b614613565b88939260209091020135905088612937565b90508181111561235b578091505b600061236685612a55565b60408087015163ffffffff908116600090815261014a6020529190912082905590915061239b9061012790879086906129ff16565b807fa913f532bb19d8d4e81c3b0b5e83e90b57152693da6f0c1b53110241d9db683986604001516040516123cf9190614000565b60405180910390a25050505050505050505050565b600080527f16d6d09ad43c2e13327e8e85b0f16a19ef2e63b72c391bfd77d21c5d499021856020527fdf4fae2a9d03ddefae2c9e431bd1ae49d400972b66abd41187abff73623b3c4b5460ff168061246a57503360009081527f16d6d09ad43c2e13327e8e85b0f16a19ef2e63b72c391bfd77d21c5d49902185602052604090205460ff165b6124a0576040517f6692e47700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60975460ff16156124a0576040517f379dfc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808080806124f56101c06101a0888a6147ae565b6124fe916147de565b60806125106101a06101808a8c6147ae565b612519916147de565b901b17945061252e6102006101e0888a6147ae565b612537916147de565b60806125496101e06101c08a8c6147ae565b612552916147de565b901b17935061256761021c610218888a6147ae565b61257091614827565b60e01c925061258561022061021c888a6147ae565b61258e91614827565b60e01c91506125a3610260610240888a6147ae565b6125ac916147de565b60806125be6102406102208a8c6147ae565b6125c7916147de565b60001c901b1760001b90509295509295909350565b61012454604051600091829173ffffffffffffffffffffffffffffffffffffffff9091169061260e9086908690614898565b6000604051808303816000865af19150503d806000811461264b576040519150601f19603f3d011682016040523d82523d6000602084013e612650565b606091505b509095945050505050565b612663613aba565b61266c826130d5565b81526021820154602082015260229091015463ffffffff16604082015290565b6000838361269b846040614642565b6126a790610260614661565b6126b2906020614661565b906126be856001614661565b6126c9906040614642565b6126d590610260614661565b926126e2939291906147ae565b6126eb916147de565b608085856126fa866040614642565b61270690610260614661565b90612712876040614642565b61271e90610260614661565b612729906020614661565b92612736939291906147ae565b61273f916147de565b901b1790505b9392505050565b60008160000361275e57506000919050565b8160010361278d57507fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5919050565b816002036127bc57507fb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30919050565b816003036127eb57507f21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85919050565b8160040361281a57507fe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344919050565b8160050361284957507f0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d919050565b8160060361287857507f887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968919050565b816007036128a757507fffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83919050565b816008036128d657507f9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af919050565b8160090361290557507fcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0919050565b6040517f90fa88a700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008363ffffffff168263ffffffff16111561297f576040517f6f4617f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818463ffffffff16866040015163ffffffff168161299f5761299f61438e565b0686604001510301856040019063ffffffff16908163ffffffff16815250508363ffffffff168263ffffffff1610156129e157506020840182905260006129f7565b6000602086015284516129f49084613253565b90505b949350505050565b8151612a0d9084908361331d565b506020810151602183015560400151602290910180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff909216919091179055565b60008082600001516020015167ffffffffffffffff811115612a7957612a79613d9f565b604051908082528060200260200182016040528015612aa2578160200160208202803683370190505b50905060005b835160200151811015612af3578351518160208110612ac957612ac9614613565b6020020151828281518110612ae057612ae0614613565b6020908102919091010152600101612aa8565b50602080840151604051612b09928491016148e7565b60405160208183030381529060405280519060200120915050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b000000000000000000000000000000000000000000000000000000001480610bbf57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610bbf565b610fe3813361336f565b600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610e8957600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055612c5e3390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1615610e8957600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b7ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f05610e8981612bbe565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612dd457610e2283613429565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612e59575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252612e569181019061490e565b60015b612e8f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7690614989565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612ee8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e76906149f3565b50610e228383836134dd565b600080612f0360026080614a03565b63ffffffff1667ffffffffffffffff811115612f2157612f21613d9f565b604051908082528060200260200182016040528015612f4a578160200160208202803683370190505b50905060005b612f5c60026080614a03565b63ffffffff16811015612fd757612fb284600183901b60808110612f8257612f82614613565b602002015185600184811b1760808110612f9e57612f9e614613565b602002015160009182526020526040902090565b828281518110612fc457612fc4614613565b6020908102919091010152600101612f50565b506000612fe660046080614a03565b63ffffffff1690505b801561307f5760005b818110156130765761305183600183901b8151811061301957613019614613565b602002602001015184600184901b6001178151811061303a5761303a614613565b602002602001015160009182526020526040902090565b83828151811061306357613063614613565b6020908102919091010152600101612ff8565b5060011c612fef565b8160008151811061309257613092614613565b602002602001015192505050919050565b61012554604051600091829173ffffffffffffffffffffffffffffffffffffffff9091169061260e9086908690614898565b6130dd613ae1565b60208083015490820181905260005b818110156131285783816020811061310657613106614613565b01548351826020811061311b5761311b614613565b60200201526001016130ec565b5050919050565b600054610100900460ff166124a0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7690614a7b565b600054610100900460ff166131b1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7690614a7b565b609780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b60208301516000901561321a576040517f27e3c14100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8282516132279190614a8b565b84604001818151613238919061436e565b63ffffffff90811690915285516129f7925090849061350216565b6020820151600090829082905b808210801561328857508551600090836020811061328057613280614613565b602002015114155b156132e65785516132b99083602081106132a4576132a4614613565b60200201518460009182526020526040902090565b865190935082602081106132cf576132cf614613565b602002016000801916815250816001019150613260565b8551839083602081106132fb576132fb614613565b6020020152808210613311576001820160208701525b50600101949350505050565b6020808301519084015560005b81811015613369578251816020811061334557613345614613565b602002015184600001826020811061335f5761335f614613565b015560010161332a565b50505050565b600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610e89576133af816136fa565b6133ba836020613719565b6040516020016133cb929190614af4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a0000000000000000000000000000000000000000000000000000000008252610e7691600401614ba8565b73ffffffffffffffffffffffffffffffffffffffff81163b613477576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7690614c13565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6134e68361392c565b6000825111806134f35750805b15610e22576133698383613979565b80516000908180808080805b86156136d8578951600090866020811061352a5761352a614613565b60200201511461353b57600161353e565b60005b60ff1695505050848401600181901c907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1660005b8181101561365e57866001036135eb57806000036135aa578a51866020811061359e5761359e614613565b602002015194506135ca565b8960018203815181106135bf576135bf614613565b602002602001015194505b8981815181106135dc576135dc614613565b60200260200101519350613627565b8981815181106135fd576135fd614613565b6020026020010151945089816001018151811061361c5761361c614613565b602002602001015193505b60008581526020859052604090208a600183901c8151811061364b5761364b614613565b6020908102919091010152600201613573565b508587600116146136a65788600188038151811061367e5761367e614613565b60200260200101518a60000151866020811061369c5761369c614613565b60200201526136ca565b856001036136ca57895160009086602081106136c4576136c4614613565b60200201525b81965084600101945061350e565b89602001518511156136ec5760208a018590525b509298975050505050505050565b6060610bbf73ffffffffffffffffffffffffffffffffffffffff831660145b60606000613728836002614642565b613733906002614661565b67ffffffffffffffff81111561374b5761374b613d9f565b6040519080825280601f01601f191660200182016040528015613775576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106137ac576137ac614613565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061380f5761380f614613565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061384b846002614642565b613856906001614661565b90505b60018111156138f3577f303132333435363738396162636465660000000000000000000000000000000085600f166010811061389757613897614613565b1a60f81b8282815181106138ad576138ad614613565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c936138ec81614c23565b9050613859565b508315612745576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7690614c58565b61393581613429565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606073ffffffffffffffffffffffffffffffffffffffff83163b6139c9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7690614cec565b6000808473ffffffffffffffffffffffffffffffffffffffff16846040516139f19190614cfc565b600060405180830381855af49150503d8060008114613a2c576040519150601f19603f3d011682016040523d82523d6000602084013e613a31565b606091505b5091509150613a598282604051806060016040528060278152602001614d0960279139613a62565b95945050505050565b60608315613a71575081612745565b6127458383815115613a865781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e769190614ba8565b6040518060600160405280613acd613ae1565b815260006020820181905260409091015290565b6040518060400160405280613af4613b01565b8152602001600081525090565b6040518061040001604052806020906020820280368337509192915050565b60008083601f840112613b3557613b35600080fd5b50813567ffffffffffffffff811115613b5057613b50600080fd5b602083019150836001820283011115613b6b57613b6b600080fd5b9250929050565b60008060208385031215613b8857613b88600080fd5b823567ffffffffffffffff811115613ba257613ba2600080fd5b613bae85828601613b20565b92509250509250929050565b7fffffffff0000000000000000000000000000000000000000000000000000000081165b8114610fe357600080fd5b8035610bbf81613bba565b600060208284031215613c0957613c09600080fd5b60006129f78484613be9565b8015155b82525050565b60208101610bbf8284613c15565b80613bde565b8035610bbf81613c2d565b63ffffffff8116613bde565b8035610bbf81613c3e565b60008060008060608587031215613c6e57613c6e600080fd5b6000613c7a8787613c33565b9450506020613c8b87828801613c4a565b935050604085013567ffffffffffffffff811115613cab57613cab600080fd5b613cb787828801613b20565b95989497509550505050565b600073ffffffffffffffffffffffffffffffffffffffff8216610bbf565b613c1981613cc3565b60208101610bbf8284613ce1565b600060208284031215613d0d57613d0d600080fd5b60006129f78484613c33565b80613c19565b60208101610bbf8284613d19565b613bde81613cc3565b8035610bbf81613d2d565b60008060408385031215613d5757613d57600080fd5b6000613d638585613c33565b9250506020613d7485828601613d36565b9150509250929050565b600060208284031215613d9357613d93600080fd5b60006129f78484613d36565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116810181811067ffffffffffffffff82111715613e1257613e12613d9f565b6040525050565b6000613e2460405190565b9050613e308282613dce565b919050565b600067ffffffffffffffff821115613e4f57613e4f613d9f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011660200192915050565b82818337506000910152565b6000613e9d613e9884613e35565b613e19565b905082815260208101848484011115613eb857613eb8600080fd5b613ec3848285613e7e565b509392505050565b600082601f830112613edf57613edf600080fd5b81356129f7848260208601613e8a565b60008060408385031215613f0557613f05600080fd5b6000613f118585613d36565b925050602083013567ffffffffffffffff811115613f3157613f31600080fd5b613d7485828601613ecb565b6000613f498383613d19565b505060200190565b6020818060005b83811015613f7d578151613f6c8782613f3d565b965060208301925050600101613f58565b505050505050565b8051610420830190613f978482613f51565b506020820151613369610400850182613d19565b63ffffffff8116613c19565b8051610460830190613fc98482613f85565b506020820151613fdd610420850182613d19565b506040820151613369610440850182613fab565b6104608101610bbf8284613fb7565b60208101610bbf8284613fab565b60006020828403121561402357614023600080fd5b60006129f78484613c4a565b806110008101831015610bbf57610bbf600080fd5b8061aea08101831015610bbf57610bbf600080fd5b60008060008060008061bf00878903121561407657614076600080fd5b60006140828989613c33565b965050602061409389828a01613c4a565b95505060406140a489828a0161402f565b9450506110406140b689828a01614044565b93505061bee087013567ffffffffffffffff8111156140d7576140d7600080fd5b6140e389828a01613b20565b92509250509295509295509295565b6104208101610bbf8284613f85565b61046081016141108286613f85565b61411e610420830185613d19565b6129f7610440830184613fab565b6000806040838503121561414257614142600080fd5b600061414e8585613c4a565b9250506020613d7485828601613c33565b60008060008060008060c0878903121561417b5761417b600080fd5b60006141878989613d36565b965050602061419889828a01613d36565b95505060406141a989828a01613d36565b94505060606141ba89828a01613d36565b93505060806141cb89828a01613d36565b92505060a06141dc89828a01613d36565b9150509295509295509295565b600060a082840312156141fe576141fe600080fd5b50919050565b60006020828403121561421957614219600080fd5b813567ffffffffffffffff81111561423357614233600080fd5b6129f7848285016141e9565b60008083601f84011261425457614254600080fd5b50813567ffffffffffffffff81111561426f5761426f600080fd5b602083019150836020820283011115613b6b57613b6b600080fd5b600080600080600080608087890312156142a6576142a6600080fd5b60006142b28989613c4a565b965050602087013567ffffffffffffffff8111156142d2576142d2600080fd5b6142de89828a0161423f565b9550955050604087013567ffffffffffffffff81111561430057614300600080fd5b61430c89828a0161423f565b935093505060606141dc89828a01613c4a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff918216919081169082820390811115610bbf57610bbf61431f565b63ffffffff918216919081169082820190811115610bbf57610bbf61431f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b63ffffffff91821691166000826143d6576143d661438e565b500690565b81810381811115610bbf57610bbf61431f565b6000610bbf8260e01b90565b613c1963ffffffff82166143ee565b60006144158286613d19565b6020820191506144258285613d19565b60208201915061443582846143fa565b506004019392505050565b6060810161444e8286613d19565b61445b6020830185613d19565b6129f76040830184613fab565b602f81526000602082017f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636581527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015291505b5060400190565b60208082528101610bbf81614468565b602c81526000602082017f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682081527f64656c656761746563616c6c0000000000000000000000000000000000000000602082015291506144be565b60208082528101610bbf816144d5565b602c81526000602082017f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682081527f6163746976652070726f78790000000000000000000000000000000000000000602082015291506144be565b60208082528101610bbf8161453f565b603881526000602082017f555550535570677261646561626c653a206d757374206e6f742062652063616c81527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000602082015291506144be565b60208082528101610bbf816145a9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b81810280821583820485141761465a5761465a61431f565b5092915050565b80820180821115610bbf57610bbf61431f565b602e81526000602082017f496e697469616c697a61626c653a20636f6e747261637420697320616c72656181527f647920696e697469616c697a6564000000000000000000000000000000000000602082015291506144be565b60208082528101610bbf81614674565b600060ff8216610bbf565b613c19816146de565b60208101610bbf82846146e9565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe13685900301811261473957614739600080fd5b80840192508235915067ffffffffffffffff82111561475a5761475a600080fd5b6020928301928202360383131561477357614773600080fd5b509250929050565b6000808585111561478e5761478e600080fd5b8386111561479e5761479e600080fd5b5050602083020193919092039150565b600080858511156147c1576147c1600080fd5b838611156147d1576147d1600080fd5b5050820193919092039150565b80358282602082101561481f5761481a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff836020036008021b90565b831692505b505092915050565b80357fffffffff00000000000000000000000000000000000000000000000000000000168282600482101561481f5761481a7fffffffff00000000000000000000000000000000000000000000000000000000836004036008021b90565b6000614892838584613e7e565b50500190565b60006129f7828486614885565b60006148af825190565b602083018060005b838110156148dc5781516148cb8882613f3d565b9750602083019250506001016148b7565b509495945050505050565b60006148f38285613d19565b6020820191506129f782846148a5565b8051610bbf81613c2d565b60006020828403121561492357614923600080fd5b60006129f78484614903565b602e81526000602082017f45524331393637557067726164653a206e657720696d706c656d656e7461746981527f6f6e206973206e6f742055555053000000000000000000000000000000000000602082015291506144be565b60208082528101610bbf8161492f565b602981526000602082017f45524331393637557067726164653a20756e737570706f727465642070726f7881527f6961626c65555549440000000000000000000000000000000000000000000000602082015291506144be565b60208082528101610bbf81614999565b63ffffffff9182169116600082614a1c57614a1c61438e565b500490565b602b81526000602082017f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206981527f6e697469616c697a696e67000000000000000000000000000000000000000000602082015291506144be565b60208082528101610bbf81614a21565b63ffffffff91821691908116908282029081169081811461465a5761465a61431f565b60005b83811015614ac9578181015183820152602001614ab1565b50506000910152565b6000614adc825190565b614aea818560208601614aae565b9290920192915050565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526017016000614b268285614ad2565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000815260110191506129f78284614ad2565b6000614b62825190565b808452602084019350614b79818560208601614aae565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920192915050565b602080825281016127458184614b58565b602d81526000602082017f455243313936373a206e657720696d706c656d656e746174696f6e206973206e81527f6f74206120636f6e747261637400000000000000000000000000000000000000602082015291506144be565b60208082528101610bbf81614bb9565b600081614c3257614c3261431f565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60208082528181019081527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604083015260608201610bbf565b602681526000602082017f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f81527f6e74726163740000000000000000000000000000000000000000000000000000602082015291506144be565b60208082528101610bbf81614c92565b60006127458284614ad256fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220095926f4570421c8947520e9537c293362b1b06553dbcf9dba2e8b4def32455364736f6c63430008130033
Deployed Bytecode
0x60806040526004361061024f5760003560e01c80637225fb2111610138578063c608b5e8116100b0578063dc9a4ef61161007f578063ee5ead6011610064578063ee5ead6014610726578063f288a2e214610746578063fe9ccb601461077a57600080fd5b8063dc9a4ef6146106d2578063dd3c91781461070657600080fd5b8063c608b5e814610630578063c6ca475314610664578063cc2a9a5b14610692578063d547741f146106b257600080fd5b8063a217fddf11610107578063adfc424c116100ec578063adfc424c146105ca578063b16fc75d146105ec578063c1f7cae21461061057600080fd5b8063a217fddf14610595578063ac59e61c146105aa57600080fd5b80637225fb21146104ed578063853ead4a1461050d57806391d148541461052d57806399464c891461058057600080fd5b806336568abe116101cb57806352d1902d1161019a578063596ef8a71161017f578063596ef8a7146104865780635ed36613146104aa57806366c5c4a0146104d857600080fd5b806352d1902d1461045b57806357b835f21461047057600080fd5b806336568abe146103e65780633659cfe6146104065780634f1ef286146104265780635144eeec1461043957600080fd5b806318bdffbb1161022257806324ea54f41161020757806324ea54f41461035e5780632b7d2bad146103925780632f2ff15d146103c657600080fd5b806318bdffbb146102e6578063248a9ca31461032157600080fd5b806301ef3afa1461025457806301ffc9a714610276578063054f7d9c146102ac57806311b63d01146102c6575b600080fd5b34801561026057600080fd5b5061027461026f366004613b72565b6107a8565b005b34801561028257600080fd5b50610296610291366004613bf4565b610b8a565b6040516102a39190613c1f565b60405180910390f35b3480156102b857600080fd5b506097546102969060ff1681565b3480156102d257600080fd5b506102746102e1366004613c55565b610bc5565b3480156102f257600080fd5b50610124546103149073ffffffffffffffffffffffffffffffffffffffff1681565b6040516102a39190613cea565b34801561032d57600080fd5b5061035161033c366004613cf8565b60009081526065602052604090206001015490565b6040516102a39190613d1f565b34801561036a57600080fd5b506103517f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504181565b34801561039e57600080fd5b506103517f542178611b653a605b79640db9b52a7afa591d6ace75cd36686e0ee264f4f57281565b3480156103d257600080fd5b506102746103e1366004613d41565b610dfd565b3480156103f257600080fd5b50610274610401366004613d41565b610e27565b34801561041257600080fd5b50610274610421366004613d7e565b610e8d565b610274610434366004613eef565b610fe6565b34801561044557600080fd5b5061044e61112c565b6040516102a39190613ff1565b34801561046757600080fd5b50610351611144565b34801561047c57600080fd5b5061014854610351565b34801561049257600080fd5b506101495463ffffffff166040516102a39190614000565b3480156104b657600080fd5b506103516104c536600461400e565b61014a6020526000908152604090205481565b3480156104e457600080fd5b506102746111da565b3480156104f957600080fd5b50610274610508366004614059565b611258565b34801561051957600080fd5b50610274610528366004613d7e565b6116ae565b34801561053957600080fd5b50610296610548366004613d41565b600091825260656020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561058c57600080fd5b506102746117a2565b3480156105a157600080fd5b50610351600081565b3480156105b657600080fd5b506102746105c5366004613d7e565b611823565b3480156105d657600080fd5b506105df61190b565b6040516102a391906140f2565b3480156105f857600080fd5b5061060161191e565b6040516102a393929190614101565b34801561061c57600080fd5b5061029661062b36600461412c565b611978565b34801561063c57600080fd5b506103517ff4e710c64967f31ba1090db2a7dd9e704155d00947ce853da47446cb68ee65da81565b34801561067057600080fd5b5061035161067f36600461400e565b6101266020526000908152604090205481565b34801561069e57600080fd5b506102746106ad36600461415f565b6119c4565b3480156106be57600080fd5b506102746106cd366004613d41565b611e5a565b3480156106de57600080fd5b506103517f60044782a422109ac08a415e44260ad5d3bad63d96ebe1fac0363399642ee3f281565b34801561071257600080fd5b50610296610721366004614204565b611e7f565b34801561073257600080fd5b5061027461074136600461428a565b612039565b34801561075257600080fd5b506103517ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f0581565b34801561078657600080fd5b50610125546103149073ffffffffffffffffffffffffffffffffffffffff1681565b6107b06123e4565b6107b86124a2565b60008060008060006107ca87876124df565b94509450945094509450600083836107e2919061434e565b6107ed90600161436e565b905061040063ffffffff82161115610831576040517f28e21b9700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61083d610400856143bd565b63ffffffff161561087a576040517f5eb1350600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b438363ffffffff16106108b9576040517faef3422900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101006108cc63ffffffff8516436143db565b1115610904576040517faef3422900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b848363ffffffff164014610944576040517fa46ad57500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61094e88886125dc565b610984576040517f1355d9a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061099161012761265b565b905082610a145760005b600a811015610a125760006109cd8b8b846109b86001600a61434e565b63ffffffff166109c891906143db565b61268c565b905080156109ea5760008181526020869052604090209450610a09565b610a06856109f78461274c565b60009182526020526040902090565b94505b5060010161099b565b505b8463ffffffff16816040015163ffffffff1610158015610a4457508363ffffffff16816040015163ffffffff1611155b15610ae3576000610a59826104008686612937565b9050610a6861012783836129ff565b6000610a7383612a55565b90508061014a6000610a8689600161436e565b63ffffffff1663ffffffff16815260200190815260200160002081905550807fa913f532bb19d8d4e81c3b0b5e83e90b57152693da6f0c1b53110241d9db68398460400151604051610ad89190614000565b60405180910390a250505b868383604051602001610af893929190614409565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012063ffffffff891660008181526101269093529290912055907f71c7303b6eab390db8d0d18c6c3aae2906f6f881861bbc6ee21a858a7af3f4c390610b77908a9087908790614440565b60405180910390a2505050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082161580610bbf5750610bbf82612b27565b92915050565b610bcd6123e4565b610bd56124a2565b6000806000806000610be787876124df565b9450945094509450945061040083610bff91906143bd565b63ffffffff1615610c3c576040517f5eb1350600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c49600161040061434e565b63ffffffff16610c59848461434e565b63ffffffff1614610c96576040517f28e21b9700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b838989604051602001610cab93929190614409565b604051602081830303815290604052805190602001206101266000846001610cd3919061436e565b63ffffffff1663ffffffff1681526020019081526020016000205414610d25576040517fa46ad57500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2f87876125dc565b610d65576040517f1355d9a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8481610400604051602001610d7c93929190614409565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012063ffffffff871660008181526101269093529290912055907f71c7303b6eab390db8d0d18c6c3aae2906f6f881861bbc6ee21a858a7af3f4c390610b77908890859061040090614440565b600082815260656020526040902060010154610e1881612bbe565b610e228383612bc8565b505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610e7f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e76906144c5565b60405180910390fd5b610e898282612cbc565b5050565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000007844b7a3adb2dae5476a2263fdd8897ef5afa3a7163003610efc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e769061452f565b7f0000000000000000000000007844b7a3adb2dae5476a2263fdd8897ef5afa3a773ffffffffffffffffffffffffffffffffffffffff16610f717f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610fbe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7690614599565b610fc781612d77565b60408051600080825260208201909252610fe391839190612da1565b50565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000007844b7a3adb2dae5476a2263fdd8897ef5afa3a7163003611055576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e769061452f565b7f0000000000000000000000007844b7a3adb2dae5476a2263fdd8897ef5afa3a773ffffffffffffffffffffffffffffffffffffffff166110ca7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614611117576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7690614599565b61112082612d77565b610e8982826001612da1565b611134613aba565b61113f61012761265b565b905090565b60003073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000007844b7a3adb2dae5476a2263fdd8897ef5afa3a716146111b5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7690614603565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b7ff4e710c64967f31ba1090db2a7dd9e704155d00947ce853da47446cb68ee65da61120481612bbe565b609780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517fe6fdbf73945dd61794a752b9181ea29f77170a7b1ffd37e0a7ff9d2c6f7258b990600090a150565b6112606123e4565b6112686124a2565b600080600080600061127a87876124df565b945094509450945094506104008361129291906143bd565b63ffffffff16156112cf576040517f5eb1350600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112dd60016202000061434e565b63ffffffff166112ed848461434e565b63ffffffff161461132a576040517f28e21b9700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b838b8b60405160200161133f93929190614409565b604051602081830303815290604052805190602001206101266000846001611367919061436e565b63ffffffff1663ffffffff16815260200190815260200160002054146113b9576040517fa46ad57500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806113ec8a6080806020026040519081016040528092919082608060200280828437600092019190915250612ef4915050565b14611423576040517ff4c360f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61142d87876130a3565b611463576040517f1355d9a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b60808110156116a05761147b6001608061434e565b63ffffffff16811461156d5760008982607f811061149b5761149b614613565b6101600201600a6020020135905060005b600a81101561151b576115118b84607f81106114ca576114ca614613565b6101600201826114dc6001600a61434e565b63ffffffff166114ec91906143db565b600b81106114fc576114fc614613565b60200201358360009182526020526040902090565b91506001016114ac565b508a826080811061152e5761152e614613565b6020020135811461156b576040517ff4c360f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b600081156115a257896115816001846143db565b607f811061159157611591614613565b6101600201600a60200201356115a4565b865b905060006115b461040084614642565b6115c49063ffffffff8816614661565b9050818c84608081106115d9576115d9614613565b60200201356104006040516020016115f393929190614409565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012063ffffffff8416600081815261012690945291909220919091557f71c7303b6eab390db8d0d18c6c3aae2906f6f881861bbc6ee21a858a7af3f4c3838e866080811061167757611677614613565b602002013561040060405161168e93929190614440565b60405180910390a25050600101611466565b505050505050505050505050565b7ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f056116d881612bbe565b73ffffffffffffffffffffffffffffffffffffffff8216611725576040517f3815ff6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61012480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556040517f0f7ba11d4e9d02c6ec9175a0134522c2f112de7cfdb2cea3f888e7eeae24c9dd90611796908490613cea565b60405180910390a15050565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a50416117cc81612bbe565b609780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f61340a1b154d5d21d259a74bf95379201799b9d12cc6509bb46cb56dc281df5590600090a150565b7ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f0561184d81612bbe565b73ffffffffffffffffffffffffffffffffffffffff821661189a576040517ffe98f3bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61012580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556040517f1431075dc15e519b4b9b0b93ea4f7f3e2a34fde5e39f552bb899b7ea4bda134190611796908490613cea565b611913613ae1565b61113f6101276130d5565b6040805161044081018083526101279283918391820190839060209082845b81548152602001906001019080831161193d575050509183525050602091820154910152602182015460229092015490919063ffffffff1683565b600063ffffffff8316408082036119bb576040517fa46ad57500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b90911492915050565b600054610100900460ff16158080156119e45750600054600160ff909116105b806119fe5750303b1580156119fe575060005460ff166001145b611a34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e76906146ce565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611a9257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b73ffffffffffffffffffffffffffffffffffffffff8716611adf576040517f3815ff6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8616611b2c576040517ffe98f3bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8516611b79576040517fd5ae8cf700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8416611bc6576040517f40c2354200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316611c13576040517f6d92bcf300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216611c60576040517ffbc5fc2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c6861312f565b611c70613170565b610124805473ffffffffffffffffffffffffffffffffffffffff808a167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556101258054928916929091169190911790556040517f0f7ba11d4e9d02c6ec9175a0134522c2f112de7cfdb2cea3f888e7eeae24c9dd90611cf7908990613cea565b60405180910390a17f1431075dc15e519b4b9b0b93ea4f7f3e2a34fde5e39f552bb899b7ea4bda134186604051611d2e9190613cea565b60405180910390a1611d41600086612bc8565b611d6b7ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f0586612bc8565b611d957f60044782a422109ac08a415e44260ad5d3bad63d96ebe1fac0363399642ee3f283612bc8565b611dbf7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504185612bc8565b611de97ff4e710c64967f31ba1090db2a7dd9e704155d00947ce853da47446cb68ee65da84612bc8565b8015611e5157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690556040517f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890611e48906001906146f2565b60405180910390a15b50505050505050565b600082815260656020526040902060010154611e7581612bbe565b610e228383612cbc565b600060208201358103611ebe576040517fa46ad57500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610400611ed0602085018561400e565b611eda91906143bd565b9050600081611eec602086018661400e565b611ef6919061434e565b63ffffffff811660009081526101266020526040812054919250819003611f49576040517ff4c360f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602085013560005b600a811015611fed57600163ffffffff8616821c16600003611fab57611fa482611f7e60808a018a614700565b84818110611f8e57611f8e614613565b9050602002013560009182526020526040902090565b9150611fe5565b611fe2611fbb6080890189614700565b83818110611fcb57611fcb614613565b905060200201358360009182526020526040902090565b91505b600101611f51565b506040860135816120046080890160608a0161400e565b60405160200161201693929190614409565b604051602081830303815290604052805190602001208214945050505050919050565b6120416124a2565b600061204e61012761265b565b905084158061205d5750848314155b806120945750610400816040015161207591906143bd565b8160400151612084919061434e565b63ffffffff168763ffffffff1614155b156120cb576040517f28e21b9700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120da81610400600080612937565b506000805b6120ea6001886143db565b8110156121d45785858281811061210357612103614613565b9050602002013588888381811061211c5761211c614613565b9050602002013561040060405160200161213893929190614409565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012063ffffffff8c16600090815261012690935291205490925082146121be576040517f612489a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6121ca6104008a61436e565b98506001016120df565b50600061223361040089838a6121eb6001826143db565b926121f89392919061477b565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508894939250506131db9050565b9050858561224260018a6143db565b81811061225157612251614613565b6020029190910135905088886122686001826143db565b81811061227757612277614613565b905060200201358560405160200161229193929190614409565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012063ffffffff8c1660009081526101269093529120549092508214612317576040517f612489a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061234d6104008a8a61232c6001826143db565b81811061233b5761233b614613565b88939260209091020135905088612937565b90508181111561235b578091505b600061236685612a55565b60408087015163ffffffff908116600090815261014a6020529190912082905590915061239b9061012790879086906129ff16565b807fa913f532bb19d8d4e81c3b0b5e83e90b57152693da6f0c1b53110241d9db683986604001516040516123cf9190614000565b60405180910390a25050505050505050505050565b600080527f16d6d09ad43c2e13327e8e85b0f16a19ef2e63b72c391bfd77d21c5d499021856020527fdf4fae2a9d03ddefae2c9e431bd1ae49d400972b66abd41187abff73623b3c4b5460ff168061246a57503360009081527f16d6d09ad43c2e13327e8e85b0f16a19ef2e63b72c391bfd77d21c5d49902185602052604090205460ff165b6124a0576040517f6692e47700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60975460ff16156124a0576040517f379dfc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808080806124f56101c06101a0888a6147ae565b6124fe916147de565b60806125106101a06101808a8c6147ae565b612519916147de565b901b17945061252e6102006101e0888a6147ae565b612537916147de565b60806125496101e06101c08a8c6147ae565b612552916147de565b901b17935061256761021c610218888a6147ae565b61257091614827565b60e01c925061258561022061021c888a6147ae565b61258e91614827565b60e01c91506125a3610260610240888a6147ae565b6125ac916147de565b60806125be6102406102208a8c6147ae565b6125c7916147de565b60001c901b1760001b90509295509295909350565b61012454604051600091829173ffffffffffffffffffffffffffffffffffffffff9091169061260e9086908690614898565b6000604051808303816000865af19150503d806000811461264b576040519150601f19603f3d011682016040523d82523d6000602084013e612650565b606091505b509095945050505050565b612663613aba565b61266c826130d5565b81526021820154602082015260229091015463ffffffff16604082015290565b6000838361269b846040614642565b6126a790610260614661565b6126b2906020614661565b906126be856001614661565b6126c9906040614642565b6126d590610260614661565b926126e2939291906147ae565b6126eb916147de565b608085856126fa866040614642565b61270690610260614661565b90612712876040614642565b61271e90610260614661565b612729906020614661565b92612736939291906147ae565b61273f916147de565b901b1790505b9392505050565b60008160000361275e57506000919050565b8160010361278d57507fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5919050565b816002036127bc57507fb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30919050565b816003036127eb57507f21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85919050565b8160040361281a57507fe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344919050565b8160050361284957507f0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d919050565b8160060361287857507f887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968919050565b816007036128a757507fffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83919050565b816008036128d657507f9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af919050565b8160090361290557507fcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0919050565b6040517f90fa88a700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008363ffffffff168263ffffffff16111561297f576040517f6f4617f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818463ffffffff16866040015163ffffffff168161299f5761299f61438e565b0686604001510301856040019063ffffffff16908163ffffffff16815250508363ffffffff168263ffffffff1610156129e157506020840182905260006129f7565b6000602086015284516129f49084613253565b90505b949350505050565b8151612a0d9084908361331d565b506020810151602183015560400151602290910180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff909216919091179055565b60008082600001516020015167ffffffffffffffff811115612a7957612a79613d9f565b604051908082528060200260200182016040528015612aa2578160200160208202803683370190505b50905060005b835160200151811015612af3578351518160208110612ac957612ac9614613565b6020020151828281518110612ae057612ae0614613565b6020908102919091010152600101612aa8565b50602080840151604051612b09928491016148e7565b60405160208183030381529060405280519060200120915050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b000000000000000000000000000000000000000000000000000000001480610bbf57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610bbf565b610fe3813361336f565b600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610e8957600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055612c5e3390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1615610e8957600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b7ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f05610e8981612bbe565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612dd457610e2283613429565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612e59575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252612e569181019061490e565b60015b612e8f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7690614989565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612ee8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e76906149f3565b50610e228383836134dd565b600080612f0360026080614a03565b63ffffffff1667ffffffffffffffff811115612f2157612f21613d9f565b604051908082528060200260200182016040528015612f4a578160200160208202803683370190505b50905060005b612f5c60026080614a03565b63ffffffff16811015612fd757612fb284600183901b60808110612f8257612f82614613565b602002015185600184811b1760808110612f9e57612f9e614613565b602002015160009182526020526040902090565b828281518110612fc457612fc4614613565b6020908102919091010152600101612f50565b506000612fe660046080614a03565b63ffffffff1690505b801561307f5760005b818110156130765761305183600183901b8151811061301957613019614613565b602002602001015184600184901b6001178151811061303a5761303a614613565b602002602001015160009182526020526040902090565b83828151811061306357613063614613565b6020908102919091010152600101612ff8565b5060011c612fef565b8160008151811061309257613092614613565b602002602001015192505050919050565b61012554604051600091829173ffffffffffffffffffffffffffffffffffffffff9091169061260e9086908690614898565b6130dd613ae1565b60208083015490820181905260005b818110156131285783816020811061310657613106614613565b01548351826020811061311b5761311b614613565b60200201526001016130ec565b5050919050565b600054610100900460ff166124a0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7690614a7b565b600054610100900460ff166131b1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7690614a7b565b609780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b60208301516000901561321a576040517f27e3c14100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8282516132279190614a8b565b84604001818151613238919061436e565b63ffffffff90811690915285516129f7925090849061350216565b6020820151600090829082905b808210801561328857508551600090836020811061328057613280614613565b602002015114155b156132e65785516132b99083602081106132a4576132a4614613565b60200201518460009182526020526040902090565b865190935082602081106132cf576132cf614613565b602002016000801916815250816001019150613260565b8551839083602081106132fb576132fb614613565b6020020152808210613311576001820160208701525b50600101949350505050565b6020808301519084015560005b81811015613369578251816020811061334557613345614613565b602002015184600001826020811061335f5761335f614613565b015560010161332a565b50505050565b600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610e89576133af816136fa565b6133ba836020613719565b6040516020016133cb929190614af4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a0000000000000000000000000000000000000000000000000000000008252610e7691600401614ba8565b73ffffffffffffffffffffffffffffffffffffffff81163b613477576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7690614c13565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6134e68361392c565b6000825111806134f35750805b15610e22576133698383613979565b80516000908180808080805b86156136d8578951600090866020811061352a5761352a614613565b60200201511461353b57600161353e565b60005b60ff1695505050848401600181901c907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1660005b8181101561365e57866001036135eb57806000036135aa578a51866020811061359e5761359e614613565b602002015194506135ca565b8960018203815181106135bf576135bf614613565b602002602001015194505b8981815181106135dc576135dc614613565b60200260200101519350613627565b8981815181106135fd576135fd614613565b6020026020010151945089816001018151811061361c5761361c614613565b602002602001015193505b60008581526020859052604090208a600183901c8151811061364b5761364b614613565b6020908102919091010152600201613573565b508587600116146136a65788600188038151811061367e5761367e614613565b60200260200101518a60000151866020811061369c5761369c614613565b60200201526136ca565b856001036136ca57895160009086602081106136c4576136c4614613565b60200201525b81965084600101945061350e565b89602001518511156136ec5760208a018590525b509298975050505050505050565b6060610bbf73ffffffffffffffffffffffffffffffffffffffff831660145b60606000613728836002614642565b613733906002614661565b67ffffffffffffffff81111561374b5761374b613d9f565b6040519080825280601f01601f191660200182016040528015613775576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106137ac576137ac614613565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061380f5761380f614613565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061384b846002614642565b613856906001614661565b90505b60018111156138f3577f303132333435363738396162636465660000000000000000000000000000000085600f166010811061389757613897614613565b1a60f81b8282815181106138ad576138ad614613565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c936138ec81614c23565b9050613859565b508315612745576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7690614c58565b61393581613429565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606073ffffffffffffffffffffffffffffffffffffffff83163b6139c9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7690614cec565b6000808473ffffffffffffffffffffffffffffffffffffffff16846040516139f19190614cfc565b600060405180830381855af49150503d8060008114613a2c576040519150601f19603f3d011682016040523d82523d6000602084013e613a31565b606091505b5091509150613a598282604051806060016040528060278152602001614d0960279139613a62565b95945050505050565b60608315613a71575081612745565b6127458383815115613a865781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e769190614ba8565b6040518060600160405280613acd613ae1565b815260006020820181905260409091015290565b6040518060400160405280613af4613b01565b8152602001600081525090565b6040518061040001604052806020906020820280368337509192915050565b60008083601f840112613b3557613b35600080fd5b50813567ffffffffffffffff811115613b5057613b50600080fd5b602083019150836001820283011115613b6b57613b6b600080fd5b9250929050565b60008060208385031215613b8857613b88600080fd5b823567ffffffffffffffff811115613ba257613ba2600080fd5b613bae85828601613b20565b92509250509250929050565b7fffffffff0000000000000000000000000000000000000000000000000000000081165b8114610fe357600080fd5b8035610bbf81613bba565b600060208284031215613c0957613c09600080fd5b60006129f78484613be9565b8015155b82525050565b60208101610bbf8284613c15565b80613bde565b8035610bbf81613c2d565b63ffffffff8116613bde565b8035610bbf81613c3e565b60008060008060608587031215613c6e57613c6e600080fd5b6000613c7a8787613c33565b9450506020613c8b87828801613c4a565b935050604085013567ffffffffffffffff811115613cab57613cab600080fd5b613cb787828801613b20565b95989497509550505050565b600073ffffffffffffffffffffffffffffffffffffffff8216610bbf565b613c1981613cc3565b60208101610bbf8284613ce1565b600060208284031215613d0d57613d0d600080fd5b60006129f78484613c33565b80613c19565b60208101610bbf8284613d19565b613bde81613cc3565b8035610bbf81613d2d565b60008060408385031215613d5757613d57600080fd5b6000613d638585613c33565b9250506020613d7485828601613d36565b9150509250929050565b600060208284031215613d9357613d93600080fd5b60006129f78484613d36565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116810181811067ffffffffffffffff82111715613e1257613e12613d9f565b6040525050565b6000613e2460405190565b9050613e308282613dce565b919050565b600067ffffffffffffffff821115613e4f57613e4f613d9f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011660200192915050565b82818337506000910152565b6000613e9d613e9884613e35565b613e19565b905082815260208101848484011115613eb857613eb8600080fd5b613ec3848285613e7e565b509392505050565b600082601f830112613edf57613edf600080fd5b81356129f7848260208601613e8a565b60008060408385031215613f0557613f05600080fd5b6000613f118585613d36565b925050602083013567ffffffffffffffff811115613f3157613f31600080fd5b613d7485828601613ecb565b6000613f498383613d19565b505060200190565b6020818060005b83811015613f7d578151613f6c8782613f3d565b965060208301925050600101613f58565b505050505050565b8051610420830190613f978482613f51565b506020820151613369610400850182613d19565b63ffffffff8116613c19565b8051610460830190613fc98482613f85565b506020820151613fdd610420850182613d19565b506040820151613369610440850182613fab565b6104608101610bbf8284613fb7565b60208101610bbf8284613fab565b60006020828403121561402357614023600080fd5b60006129f78484613c4a565b806110008101831015610bbf57610bbf600080fd5b8061aea08101831015610bbf57610bbf600080fd5b60008060008060008061bf00878903121561407657614076600080fd5b60006140828989613c33565b965050602061409389828a01613c4a565b95505060406140a489828a0161402f565b9450506110406140b689828a01614044565b93505061bee087013567ffffffffffffffff8111156140d7576140d7600080fd5b6140e389828a01613b20565b92509250509295509295509295565b6104208101610bbf8284613f85565b61046081016141108286613f85565b61411e610420830185613d19565b6129f7610440830184613fab565b6000806040838503121561414257614142600080fd5b600061414e8585613c4a565b9250506020613d7485828601613c33565b60008060008060008060c0878903121561417b5761417b600080fd5b60006141878989613d36565b965050602061419889828a01613d36565b95505060406141a989828a01613d36565b94505060606141ba89828a01613d36565b93505060806141cb89828a01613d36565b92505060a06141dc89828a01613d36565b9150509295509295509295565b600060a082840312156141fe576141fe600080fd5b50919050565b60006020828403121561421957614219600080fd5b813567ffffffffffffffff81111561423357614233600080fd5b6129f7848285016141e9565b60008083601f84011261425457614254600080fd5b50813567ffffffffffffffff81111561426f5761426f600080fd5b602083019150836020820283011115613b6b57613b6b600080fd5b600080600080600080608087890312156142a6576142a6600080fd5b60006142b28989613c4a565b965050602087013567ffffffffffffffff8111156142d2576142d2600080fd5b6142de89828a0161423f565b9550955050604087013567ffffffffffffffff81111561430057614300600080fd5b61430c89828a0161423f565b935093505060606141dc89828a01613c4a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff918216919081169082820390811115610bbf57610bbf61431f565b63ffffffff918216919081169082820190811115610bbf57610bbf61431f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b63ffffffff91821691166000826143d6576143d661438e565b500690565b81810381811115610bbf57610bbf61431f565b6000610bbf8260e01b90565b613c1963ffffffff82166143ee565b60006144158286613d19565b6020820191506144258285613d19565b60208201915061443582846143fa565b506004019392505050565b6060810161444e8286613d19565b61445b6020830185613d19565b6129f76040830184613fab565b602f81526000602082017f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636581527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015291505b5060400190565b60208082528101610bbf81614468565b602c81526000602082017f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682081527f64656c656761746563616c6c0000000000000000000000000000000000000000602082015291506144be565b60208082528101610bbf816144d5565b602c81526000602082017f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682081527f6163746976652070726f78790000000000000000000000000000000000000000602082015291506144be565b60208082528101610bbf8161453f565b603881526000602082017f555550535570677261646561626c653a206d757374206e6f742062652063616c81527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000602082015291506144be565b60208082528101610bbf816145a9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b81810280821583820485141761465a5761465a61431f565b5092915050565b80820180821115610bbf57610bbf61431f565b602e81526000602082017f496e697469616c697a61626c653a20636f6e747261637420697320616c72656181527f647920696e697469616c697a6564000000000000000000000000000000000000602082015291506144be565b60208082528101610bbf81614674565b600060ff8216610bbf565b613c19816146de565b60208101610bbf82846146e9565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe13685900301811261473957614739600080fd5b80840192508235915067ffffffffffffffff82111561475a5761475a600080fd5b6020928301928202360383131561477357614773600080fd5b509250929050565b6000808585111561478e5761478e600080fd5b8386111561479e5761479e600080fd5b5050602083020193919092039150565b600080858511156147c1576147c1600080fd5b838611156147d1576147d1600080fd5b5050820193919092039150565b80358282602082101561481f5761481a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff836020036008021b90565b831692505b505092915050565b80357fffffffff00000000000000000000000000000000000000000000000000000000168282600482101561481f5761481a7fffffffff00000000000000000000000000000000000000000000000000000000836004036008021b90565b6000614892838584613e7e565b50500190565b60006129f7828486614885565b60006148af825190565b602083018060005b838110156148dc5781516148cb8882613f3d565b9750602083019250506001016148b7565b509495945050505050565b60006148f38285613d19565b6020820191506129f782846148a5565b8051610bbf81613c2d565b60006020828403121561492357614923600080fd5b60006129f78484614903565b602e81526000602082017f45524331393637557067726164653a206e657720696d706c656d656e7461746981527f6f6e206973206e6f742055555053000000000000000000000000000000000000602082015291506144be565b60208082528101610bbf8161492f565b602981526000602082017f45524331393637557067726164653a20756e737570706f727465642070726f7881527f6961626c65555549440000000000000000000000000000000000000000000000602082015291506144be565b60208082528101610bbf81614999565b63ffffffff9182169116600082614a1c57614a1c61438e565b500490565b602b81526000602082017f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206981527f6e697469616c697a696e67000000000000000000000000000000000000000000602082015291506144be565b60208082528101610bbf81614a21565b63ffffffff91821691908116908282029081169081811461465a5761465a61431f565b60005b83811015614ac9578181015183820152602001614ab1565b50506000910152565b6000614adc825190565b614aea818560208601614aae565b9290920192915050565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526017016000614b268285614ad2565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000815260110191506129f78284614ad2565b6000614b62825190565b808452602084019350614b79818560208601614aae565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920192915050565b602080825281016127458184614b58565b602d81526000602082017f455243313936373a206e657720696d706c656d656e746174696f6e206973206e81527f6f74206120636f6e747261637400000000000000000000000000000000000000602082015291506144be565b60208082528101610bbf81614bb9565b600081614c3257614c3261431f565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60208082528181019081527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604083015260608201610bbf565b602681526000602082017f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f81527f6e74726163740000000000000000000000000000000000000000000000000000602082015291506144be565b60208082528101610bbf81614c92565b60006127458284614ad256fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220095926f4570421c8947520e9537c293362b1b06553dbcf9dba2e8b4def32455364736f6c63430008130033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.