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:
AxiomV1
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
default 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 {AxiomV1Core} from "./AxiomV1Core.sol"; import {AxiomV1Access} from "./AxiomV1Access.sol"; import {IAxiomV1} from "./interfaces/IAxiomV1.sol"; /// @title Axiom V1 /// @author Axiom /// @notice Core Axiom smart contract that verifies the validity of historical block hashes using SNARKs. contract AxiomV1 is AxiomV1Core, UUPSUpgradeable { /// @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. function initialize( address _verifierAddress, address _historicalVerifierAddress, address timelock, address guardian ) public initializer { require(timelock != address(0)); // AxiomV1: timelock cannot be the zero address __UUPSUpgradeable_init(); // prover is initialized to the contract deployer __AxiomV1Core_init(_verifierAddress, _historicalVerifierAddress, guardian, msg.sender); _grantRole(DEFAULT_ADMIN_ROLE, timelock); _grantRole(TIMELOCK_ROLE, timelock); } function _authorizeUpgrade(address) internal override onlyRole(TIMELOCK_ROLE) {} function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControlUpgradeable) returns (bool) { return interfaceId == type(IAxiomV1).interfaceId || super.supportsInterface(interfaceId); } }
// 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 {AxiomV1Access} from "./AxiomV1Access.sol"; import {IAxiomV1} from "./interfaces/IAxiomV1.sol"; import {MerkleTree} from "./libraries/MerkleTree.sol"; import {MerkleMountainRange} from "./libraries/MerkleMountainRange.sol"; import "./libraries/configuration/AxiomV1Configuration.sol"; /// @title Axiom V1 Core /// @notice Core Axiom smart contract that verifies the validity of historical block hashes using SNARKs. /// @dev For use in a UUPS upgradeable contract. contract AxiomV1Core is IAxiomV1, AxiomV1Access { using {MerkleTree.merkleRoot} for bytes32[HISTORICAL_NUM_ROOTS]; using MerkleMountainRange for MerkleMountainRange.MMR; address public verifierAddress; address public historicalVerifierAddress; mapping(uint32 => bytes32) public historicalRoots; MerkleMountainRange.MMR public historicalMMR; bytes32[MMR_RING_BUFFER_SIZE] public mmrRingBuffer; error SNARKVerificationFailed(); error AxiomBlockVerificationFailed(); error UpdatingIncorrectNumberOfBlocks(); error StartingBlockNotMultipleOfBatchSize(); error NotRecentEndBlock(); error BlockHashIncorrect(); error MerkleProofFailed(); /// @notice Initializes the contract and the parent contracts. function __AxiomV1Core_init( address _verifierAddress, address _historicalVerifierAddress, address guardian, address prover ) internal onlyInitializing { __AxiomV1Access_init(); __AxiomV1Core_init_unchained(_verifierAddress, _historicalVerifierAddress, guardian, prover); } /// @notice Initializes the contract without calling parent contract initializers. function __AxiomV1Core_init_unchained( address _verifierAddress, address _historicalVerifierAddress, address guardian, address prover ) internal onlyInitializing { require(_verifierAddress != address(0)); // AxiomV1Core: _verifierAddress cannot be the zero address require(_historicalVerifierAddress != address(0)); // AxiomV1Core: _historicalVerifierAddress cannot be the zero address" require(guardian != address(0)); // AxiomV1Core: guardian cannot be the zero address require(prover != address(0)); // AxiomV1Core: prover cannot be the zero address _grantRole(PROVER_ROLE, prover); _grantRole(GUARDIAN_ROLE, guardian); verifierAddress = _verifierAddress; historicalVerifierAddress = _historicalVerifierAddress; emit UpgradeSnarkVerifier(_verifierAddress); emit UpgradeHistoricalSnarkVerifier(_historicalVerifierAddress); } function updateRecent(bytes calldata proofData) external onlyProver { requireNotFrozen(); (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 UpdatingIncorrectNumberOfBlocks(); if (startBlockNumber % BLOCK_BATCH_SIZE != 0) revert StartingBlockNotMultipleOfBatchSize(); if (endBlockNumber >= block.number) revert NotRecentEndBlock(); if (block.number - endBlockNumber > 256) revert NotRecentEndBlock(); if (blockhash(endBlockNumber) != endHash) revert BlockHashIncorrect(); if (!_verifyRaw(proofData)) { revert SNARKVerificationFailed(); } 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 = 0; round < BLOCK_BATCH_DEPTH; round++) { bytes32 peak = getAuxMmrPeak(proofData, BLOCK_BATCH_DEPTH - 1 - round); if (peak != 0) { root = keccak256(abi.encodePacked(peak, root)); } else { root = keccak256(abi.encodePacked(root, MerkleTree.getEmptyHash(round))); } } } else { // this indicates numFinal = BLOCK_BATCH_SIZE and root is the Merkle root of blockhashes for blocks [startBlockNumber, startBlockNumber + BLOCK_BATCH_SIZE) if (historicalMMR.len == (startBlockNumber >> BLOCK_BATCH_DEPTH)) { // the historicalMMR holds a commitment to blocks [0, startBlockNumber), so we can now extend it by 1024 blocks // we copy to memory as a gas optimization because we need to compute the commitment to store in the ring buffer MerkleMountainRange.MMR memory mmr = historicalMMR.clone(); uint32 peaksChanged = mmr.appendSingle(root); mmr.index = (mmr.index + 1) % MMR_RING_BUFFER_SIZE; mmrRingBuffer[mmr.index] = mmr.commit(); historicalMMR.copyFrom(mmr, peaksChanged); emit MerkleMountainRangeEvent(mmr.len, mmr.index); } } historicalRoots[startBlockNumber] = keccak256(abi.encodePacked(prevHash, root, numFinal)); emit UpdateEvent(startBlockNumber, prevHash, root, numFinal); } function updateOld(bytes32 nextRoot, uint32 nextNumFinal, bytes calldata proofData) external onlyProver { requireNotFrozen(); (bytes32 prevHash, bytes32 endHash, uint32 startBlockNumber, uint32 endBlockNumber, bytes32 root) = getBoundaryBlockData(proofData); if (startBlockNumber % BLOCK_BATCH_SIZE != 0) revert StartingBlockNotMultipleOfBatchSize(); if (endBlockNumber - startBlockNumber != BLOCK_BATCH_SIZE - 1) { revert UpdatingIncorrectNumberOfBlocks(); } 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 UpdateEvent(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 { requireNotFrozen(); (bytes32 _prevHash, bytes32 _endHash, uint32 startBlockNumber, uint32 endBlockNumber, bytes32 aggregateRoot) = getBoundaryBlockData(proofData); if (startBlockNumber % BLOCK_BATCH_SIZE != 0) revert StartingBlockNotMultipleOfBatchSize(); if (endBlockNumber - startBlockNumber != HISTORICAL_BLOCK_BATCH_SIZE - 1) { revert UpdatingIncorrectNumberOfBlocks(); } 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 = 0; i < HISTORICAL_NUM_ROOTS; i++) { if (i != HISTORICAL_NUM_ROOTS - 1) { bytes32 proofCheck = endHashProofs[i][BLOCK_BATCH_DEPTH]; for (uint256 j = 0; j < BLOCK_BATCH_DEPTH; j++) { proofCheck = keccak256(abi.encodePacked(endHashProofs[i][BLOCK_BATCH_DEPTH - 1 - j], proofCheck)); } 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 UpdateEvent(start, prevHash, roots[i], BLOCK_BATCH_SIZE); } } function appendHistoricalMMR(uint32 startBlockNumber, bytes32[] calldata roots, bytes32[] calldata prevHashes) external { requireNotFrozen(); if (roots.length == 0) revert(); // must append non-empty list if (roots.length != prevHashes.length) revert(); // roots and prevHashes must be same length if (startBlockNumber != historicalMMR.len * BLOCK_BATCH_SIZE) revert(); // startBlockNumber must be historicalMMR.len * BLOCK_BATCH_SIZE MerkleMountainRange.MMR memory mmr = historicalMMR.clone(); for (uint256 i = 0; i < roots.length; i++) { // roots[i] = (prevHash, root) bytes32 commitment = keccak256(abi.encodePacked(prevHashes[i], roots[i], BLOCK_BATCH_SIZE)); if (historicalRoots[startBlockNumber] != commitment) revert AxiomBlockVerificationFailed(); startBlockNumber += BLOCK_BATCH_SIZE; } uint32 peaksChanged = mmr.append(roots); mmr.index = (mmr.index + 1) % MMR_RING_BUFFER_SIZE; mmrRingBuffer[mmr.index] = mmr.commit(); historicalMMR.copyFrom(mmr, peaksChanged); emit MerkleMountainRangeEvent(mmr.len, mmr.index); } /// @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) { 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) { historicalVerifierAddress = _historicalVerifierAddress; emit UpgradeHistoricalSnarkVerifier(_historicalVerifierAddress); } function historicalMMRPeaks(uint32 i) external view returns (bytes32) { return historicalMMR.peaks[i]; } function isRecentBlockHashValid(uint32 blockNumber, bytes32 claimedBlockHash) public view returns (bool) { bytes32 blockHash = blockhash(blockNumber); if (blockHash == 0x0) revert(); // 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(); // 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(); // Merkle root must be stored already // compute Merkle root of blockhash bytes32 root = witness.claimedBlockHash; for (uint256 i = 0; i < BLOCK_BATCH_DEPTH; i++) { // depth = BLOCK_BATCH_DEPTH - i // 0 for left, 1 for right if ((side >> i) & 1 == 0) { root = keccak256(abi.encodePacked(root, witness.merkleProof[i])); } else { root = keccak256(abi.encodePacked(witness.merkleProof[i], root)); } } return (merkleRoot == keccak256(abi.encodePacked(witness.prevHash, root, witness.numFinal))); } function mmrVerifyBlockHash( bytes32[] calldata mmr, uint8 bufferId, uint32 blockNumber, bytes32 claimedBlockHash, bytes32[] calldata merkleProof ) public view { if (keccak256(abi.encodePacked(mmr)) != mmrRingBuffer[bufferId]) { revert AxiomBlockVerificationFailed(); } // mmr.length <= 32 uint32 peakId = uint32(mmr.length - 1); uint32 side = blockNumber; while ((BLOCK_BATCH_SIZE << peakId) <= side) { if (peakId == 0) revert(); // blockNumber outside of range of MMR peakId--; side -= BLOCK_BATCH_SIZE << peakId; } // merkleProof is a merkle proof of claimedBlockHash into the tree with root mmr[peakId] require(merkleProof.length == BLOCK_BATCH_DEPTH + peakId); bytes32 root = claimedBlockHash; for (uint256 i = 0; i < merkleProof.length; i++) { // 0 for left, 1 for right if ((side >> i) & 1 == 0) { root = keccak256(abi.encodePacked(root, merkleProof[i])); } else { root = keccak256(abi.encodePacked(merkleProof[i], root)); } } if (root != mmr[peakId]) { revert AxiomBlockVerificationFailed(); } } function _verifyRaw(bytes calldata input) private returns (bool) { (bool success,) = verifierAddress.call(input); return success; } function _verifyHistoricalRaw(bytes calldata input) private returns (bool) { (bool success,) = historicalVerifierAddress.call(input); return success; } /** * @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 <0.9.0; import {AccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; /// @title Axiom V1 Access /// @notice Abstract contract controlling permissions of AxiomV1 /// @dev For use in a UUPS upgradeable contract. abstract contract AxiomV1Access 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 'prover'. bytes32 public constant PROVER_ROLE = keccak256("PROVER_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(); /** * @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() { if (!hasRole(PROVER_ROLE, address(0)) && !hasRole(PROVER_ROLE, _msgSender())) { revert NotProverRole(); } _; } function __AxiomV1Access_init() internal onlyInitializing { __AxiomV1Access_init_unchained(); } function __AxiomV1Access_init_unchained() internal onlyInitializing { frozen = false; } function freezeAll() external onlyRole(GUARDIAN_ROLE) { frozen = true; emit FreezeAll(); } function unfreezeAll() external onlyRole(GUARDIAN_ROLE) { frozen = false; emit UnfreezeAll(); } /// @notice Checks that the contract is not frozen. function requireNotFrozen() internal view { if (frozen) { revert ContractIsFrozen(); } } /** * @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.19; import "./core/IAxiomV1Verifier.sol"; import "./core/IAxiomV1Update.sol"; import "./core/IAxiomV1State.sol"; import "./core/IAxiomV1Events.sol"; /// @title The interface for the core Axiom V1 contract /// @notice The Axiom V1 contract stores a continually updated cache of all historical block hashes /// @dev The interface is broken up into many smaller pieces interface IAxiomV1 is IAxiomV1Events, IAxiomV1State, IAxiomV1Update, IAxiomV1Verifier {}
// 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.19; import {HISTORICAL_NUM_ROOTS} from "./configuration/AxiomV1Configuration.sol"; /// @title Merkle Tree /// @notice Helper functions for computing Merkle roots of Merkle trees library MerkleTree { /// @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 = 0; i < HISTORICAL_NUM_ROOTS / 2; i++) { hashes[i] = keccak256(abi.encodePacked(leaves[i << 1], leaves[(i << 1) | 1])); } uint256 len = HISTORICAL_NUM_ROOTS / 4; while (len != 0) { for (uint256 i = 0; i < len; i++) { hashes[i] = keccak256(abi.encodePacked(hashes[i << 1], hashes[(i << 1) | 1])); } 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); } else if (depth == 1) { return bytes32(0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5); } else if (depth == 2) { return bytes32(0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30); } else if (depth == 3) { return bytes32(0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85); } else if (depth == 4) { return bytes32(0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344); } else if (depth == 5) { return bytes32(0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d); } else if (depth == 6) { return bytes32(0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968); } else if (depth == 7) { return bytes32(0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83); } else if (depth == 8) { return bytes32(0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af); } else if (depth == 9) { return bytes32(0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0); } else { revert("depth must be in range [0, 10)"); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; /// @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 numPeaks The actual number of peaks in the MMR /// @param len The length of the original list that this MMR is a commitment to; the implementation guarantees that `numPeaks = bit_length(len)` /// @param index For external use: keeps track of the current index of this MMR in the ring buffer (see `AxiomV1Core`) /// @dev peaks stores `numPeaks := 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`, `numPeaks = 0`, and all `peaks[i] = 0` struct MMR { // the peaks bytes32[32] peaks; // bit_length(len) or 0 if len = 0 uint32 numPeaks; // the length of the original list that this MMR is a commitment to, so `peaks` has `bit_length(len)` elements uint32 len; // the current index in the ring buffer; this is free storage since `numPeaks, len, index` get packed into a single word in EVM storage uint32 index; } /// @notice Copies the MMR to memory /// @dev Only reads the peaks up to `numPeaks` /// @param self The MMR /// @return out The MMR in memory function clone(MMR storage self) internal view returns (MMR memory out) { out.numPeaks = self.numPeaks; out.len = self.len; out.index = self.index; for (uint32 i = 0; i < out.numPeaks; i++) { out.peaks[i] = self.peaks[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 copyFrom(MMR storage self, MMR memory newMMR, uint32 peaksChanged) internal { self.numPeaks = newMMR.numPeaks; self.len = newMMR.len; self.index = newMMR.index; for (uint32 i = 0; i < peaksChanged; i++) { self.peaks[i] = newMMR.peaks[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.numPeaks); for (uint32 i = 0; i < self.numPeaks; i++) { peaks[i] = self.peaks[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 appendSingle(MMR memory self, bytes32 leaf) internal pure returns (uint32 peaksChanged) { uint32 i = 0; bytes32 new_peak = leaf; uint32 len = self.len; while ((len >> i) & 1 == 1) { new_peak = keccak256(abi.encodePacked(self.peaks[i], new_peak)); self.peaks[i] = 0; i += 1; } self.peaks[i] = new_peak; self.len += 1; if (i >= self.numPeaks) { self.numPeaks = 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 `appendSingle` /// @param self The MMR /// @param leaves The new elements to append /// @return peaksChanged self.peaks[0 : peaksChanged] have been changed function append(MMR memory self, bytes32[] memory leaves) internal pure returns (uint32 peaksChanged) { uint32 prevLen = self.len; // keeps track of running length of `leaves` uint32 toAdd = uint32(leaves.length); self.len += toAdd; uint32 i = 0; uint32 shift; while (toAdd != 0) { // shift records whether there is an existing peak in the range we should hash with shift = (prevLen >> i) & 1; // if shift, add peaks[i] to beginning of leaves // then hash all leaves uint32 next_add = (toAdd + shift) >> 1; for (uint32 j = 0; j < next_add; j++) { bytes32 left; bytes32 right; if (shift == 1) { left = (j == 0 ? self.peaks[i] : leaves[2 * j - 1]); right = leaves[2 * j]; } else { left = leaves[2 * j]; right = leaves[2 * j + 1]; } leaves[j] = keccak256(abi.encodePacked(left, right)); } // if to_add + shift is odd, the last element is new self.peaks[i], otherwise 0 if (toAdd & 1 != shift) { 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 = next_add; i += 1; } if (i > self.numPeaks) { self.numPeaks = i; } peaksChanged = i; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; // Constants and free functions to be inlined into by AxiomV1Core // ZK circuit constants: // AxiomV1 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 = 131072; // 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 AUX_PEAKS_START_IDX = 608; // PUBLIC_BYTES_START_IDX + 7 * 32 // Historical MMR Ring Buffer constants uint32 constant MMR_RING_BUFFER_SIZE = 8; /// @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[384: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:608]))); } // 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])) ); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; import {BLOCK_BATCH_DEPTH} from "../../libraries/configuration/AxiomV1Configuration.sol"; interface IAxiomV1Verifier { /// @notice A merkle proof to verify a block against the verified blocks cached by Axiom /// @dev `BLOCK_BATCH_DEPTH = 10` struct BlockHashWitness { uint32 blockNumber; bytes32 claimedBlockHash; bytes32 prevHash; uint32 numFinal; bytes32[BLOCK_BATCH_DEPTH] 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); /// @notice Verify the blockhash of block blockNumber equals claimedBlockHash by checking against Axiom's cache of historical Merkle mountain ranges in #mmrRingBuffer. /// @dev Use event logs to determine the correct bufferId and get the MMR at that index in the ring buffer. /// @param mmr The Merkle mountain range commited to in #mmrRingBuffer(bufferId), must be correct length /// @param bufferId The index in the ring buffer of #mmrRingBuffer /// @param blockNumber The block number to verify /// @param claimedBlockHash The claimed blockhash of block blockNumber /// @param merkleProof The Merkle inclusion proof of claimedBlockHash to the corresponding peak in mmr. The correct peak is calculated from mmr.length and blockNumber. function mmrVerifyBlockHash( bytes32[] calldata mmr, uint8 bufferId, uint32 blockNumber, bytes32 claimedBlockHash, bytes32[] calldata merkleProof ) external view; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; interface IAxiomV1Update { /// @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 Extended the stored historical Merkle Mountain Range with a multiple of 1024 blockhash commitments /// @dev The blocks to append must have already been cached by Axiom. /// startBlockNumber must equal historicalMMR.len * 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 - 1 /// @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. function appendHistoricalMMR(uint32 startBlockNumber, bytes32[] calldata roots, bytes32[] calldata prevHashes) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; interface IAxiomV1State { /// @notice Returns the hash of a batch of consecutive blocks previously verified by the contract /// @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 Returns metadata about the number of consecutive blocks from genesis stored in the contract /// The Merkle mountain range stores a commitment to the variable length list where `list[i]` is the Merkle root of the binary tree with leaves the blockhashes of blocks [1024 * i, 1024 * (i + 1)) /// @return numPeaks = bit_length(len) is the number of peaks in the Merkle mountain range /// @return len indicates that the historicalMMR commits to blockhashes of blocks [0, 1024 * len) /// @return index the current index in the ring buffer storing commitments to historicalMMRs function historicalMMR() external view returns (uint32 numPeaks, uint32 len, uint32 index); /// @notice Returns the i-th Merkle root in the historical Merkle Mountain Range /// @param i The index, `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, /// list is the variable length list where `list[i]` is the Merkle root of the binary tree with leaves the blockhashes of blocks [1024 * i, 1024 * (i + 1)) function historicalMMRPeaks(uint32 i) external view returns (bytes32); /// @notice A ring buffer storing commitments to past historicalMMR states /// @param index The index in the ring buffer function mmrRingBuffer(uint256 index) external view returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; interface IAxiomV1Events { /// @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 UpdateEvent(uint32 startBlockNumber, bytes32 prevHash, bytes32 root, uint32 numFinal); /// @notice Emitted when the size of the historicalMMR changes. /// @param len The historicalMMR now stores commitment to blocks [0, 1024 * len) /// @param index The new index in the ring buffer storing the commitment to historicalMMR event MerkleMountainRangeEvent(uint32 len, uint32 index); /// @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": [ "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 1000000, "details": { "constantOptimizer": false, "yul": false } }, "metadata": { "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AxiomBlockVerificationFailed","type":"error"},{"inputs":[],"name":"BlockHashIncorrect","type":"error"},{"inputs":[],"name":"ContractIsFrozen","type":"error"},{"inputs":[],"name":"MerkleProofFailed","type":"error"},{"inputs":[],"name":"NotProverRole","type":"error"},{"inputs":[],"name":"NotRecentEndBlock","type":"error"},{"inputs":[],"name":"SNARKVerificationFailed","type":"error"},{"inputs":[],"name":"StartingBlockNotMultipleOfBatchSize","type":"error"},{"inputs":[],"name":"UpdatingIncorrectNumberOfBlocks","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":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"len","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"index","type":"uint32"}],"name":"MerkleMountainRangeEvent","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":"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":"UpdateEvent","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":"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":[{"internalType":"uint32","name":"startBlockNumber","type":"uint32"},{"internalType":"bytes32[]","name":"roots","type":"bytes32[]"},{"internalType":"bytes32[]","name":"prevHashes","type":"bytes32[]"}],"name":"appendHistoricalMMR","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"freezeAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"frozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[],"name":"historicalMMR","outputs":[{"internalType":"uint32","name":"numPeaks","type":"uint32"},{"internalType":"uint32","name":"len","type":"uint32"},{"internalType":"uint32","name":"index","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"i","type":"uint32"}],"name":"historicalMMRPeaks","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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"}],"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[10]","name":"merkleProof","type":"bytes32[10]"}],"internalType":"struct IAxiomV1Verifier.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":"uint256","name":"","type":"uint256"}],"name":"mmrRingBuffer","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"mmr","type":"bytes32[]"},{"internalType":"uint8","name":"bufferId","type":"uint8"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"claimedBlockHash","type":"bytes32"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"mmrVerifyBlockHash","outputs":[],"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
60a0604052306080523480156200001557600080fd5b506200002062000026565b62000164565b600054610100900460ff161562000074576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200006b90620000ec565b60405180910390fd5b60005460ff9081161015620000ea57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff9081179091556040517f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249891620000e19162000154565b60405180910390a15b565b602080825281016200014e81602781527f496e697469616c697a61626c653a20636f6e747261637420697320696e69746960208201527f616c697a696e6700000000000000000000000000000000000000000000000000604082015260600190565b92915050565b60ff82168152602081016200014e565b608051614e366200019c600039600081816111c20152818161121c0152818161131b0152818161137501526114640152614e366000f3fe6080604052600436106101e35760003560e01c80636f193b8311610102578063c1f7cae211610095578063ef4fcb1711610064578063ef4fcb1714610608578063f288a2e214610628578063f8c8765e1461065c578063fe9ccb601461067c57600080fd5b8063c1f7cae214610567578063c6ca475314610587578063d547741f146105b4578063dc9a4ef6146105d457600080fd5b806391d14854116100d157806391d14854146104ca57806399464c891461051d578063a217fddf14610532578063ac59e61c1461054757600080fd5b80636f193b831461044a5780637225fb211461046a578063853ead4a1461048a57806389ea365d146104aa57600080fd5b8063282bf5c91161017a5780634f1ef286116101495780634f1ef286146103c5578063529ad9f3146103d857806352d1902d1461042057806366c5c4a01461043557600080fd5b8063282bf5c9146103455780632f2ff15d1461036557806336568abe146103855780633659cfe6146103a557600080fd5b806311b63d01116101b657806311b63d011461028757806318bdffbb146102a7578063248a9ca3146102e157806324ea54f41461031157600080fd5b806301ef3afa146101e857806301ffc9a71461020a578063054f7d9c14610240578063074144d61461025a575b600080fd5b3480156101f457600080fd5b50610208610203366004613bc9565b6106a9565b005b34801561021657600080fd5b5061022a610225366004613c4b565b610b7e565b6040516102379190613c7e565b60405180910390f35b34801561024c57600080fd5b5060975461022a9060ff1681565b34801561026657600080fd5b5061027a610275366004613c9d565b610bb9565b6040516102379190613cc4565b34801561029357600080fd5b506102086102a2366004613ce9565b610bd0565b3480156102b357600080fd5b5060c0546102d49073ffffffffffffffffffffffffffffffffffffffff1681565b6040516102379190613d7e565b3480156102ed57600080fd5b5061027a6102fc366004613c9d565b60009081526065602052604090206001015490565b34801561031d57600080fd5b5061027a7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504181565b34801561035157600080fd5b50610208610360366004613dd7565b610ed1565b34801561037157600080fd5b50610208610380366004613e7b565b61111b565b34801561039157600080fd5b506102086103a0366004613e7b565b611145565b3480156103b157600080fd5b506102086103c0366004613eb8565b6111ab565b6102086103d3366004614024565b611304565b3480156103e457600080fd5b5060e3546104119063ffffffff808216916401000000008104821691680100000000000000009091041683565b6040516102379392919061407e565b34801561042c57600080fd5b5061027a61144a565b34801561044157600080fd5b506102086114e0565b34801561045657600080fd5b5061022a6104653660046140bc565b61155e565b34801561047657600080fd5b50610208610485366004614108565b6116dd565b34801561049657600080fd5b506102086104a5366004613eb8565b611c11565b3480156104b657600080fd5b506102086104c53660046141b5565b611cb7565b3480156104d657600080fd5b5061022a6104e5366004613e7b565b600091825260656020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561052957600080fd5b50610208611ed0565b34801561053e57600080fd5b5061027a600081565b34801561055357600080fd5b50610208610562366004613eb8565b611f51565b34801561057357600080fd5b5061022a61058236600461426b565b611feb565b34801561059357600080fd5b5061027a6105a236600461429e565b60c26020526000908152604090205481565b3480156105c057600080fd5b506102086105cf366004613e7b565b61200a565b3480156105e057600080fd5b5061027a7f60044782a422109ac08a415e44260ad5d3bad63d96ebe1fac0363399642ee3f281565b34801561061457600080fd5b5061027a61062336600461429e565b61202f565b34801561063457600080fd5b5061027a7ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f0581565b34801561066857600080fd5b506102086106773660046142bf565b612052565b34801561068857600080fd5b5060c1546102d49073ffffffffffffffffffffffffffffffffffffffff1681565b600080527f16d6d09ad43c2e13327e8e85b0f16a19ef2e63b72c391bfd77d21c5d499021856020527fdf4fae2a9d03ddefae2c9e431bd1ae49d400972b66abd41187abff73623b3c4b5460ff1615801561073257503360009081527f16d6d09ad43c2e13327e8e85b0f16a19ef2e63b72c391bfd77d21c5d49902185602052604090205460ff16155b15610769576040517f6692e47700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107716121f8565b60008060008060006107838787612237565b945094509450945094506000838361079b9190614352565b6107a6906001614372565b905061040063ffffffff821611156107ea576040517f0a004fe500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107f6610400856143c1565b63ffffffff1615610833576040517f7478cfa900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b438363ffffffff1610610872576040517faef3422900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010061088563ffffffff8516436143df565b11156108bd576040517faef3422900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b848363ffffffff1640146108fd576040517fa46ad57500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109078888612334565b61093d576040517f1355d9a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816109fc5760005b600a8110156109f65760006109778a8a846109626001600a614352565b63ffffffff1661097291906143df565b6123b2565b905080156109af5780846040516020016109929291906143f2565b6040516020818303038152906040528051906020012093506109e3565b836109b983612472565b6040516020016109ca9291906143f2565b6040516020818303038152906040528051906020012093505b50806109ee81614418565b915050610945565b50610ad9565b60e354623fffff600a86901c1664010000000090910463ffffffff1603610ad9576000610a2960c3612662565b90506000610a37828561270b565b9050600882606001516001610a4c9190614372565b610a5691906143c1565b63ffffffff166060830152610a6a8261282a565b60e4836060015163ffffffff1660088110610a8757610a87614450565b0155610a9560c3838361291a565b7f39145329d5ae3858c6f1192667af1d01792c69c7f88d143b0312872011e5cbcb82604001518360600151604051610ace92919061447f565b60405180910390a150505b858282604051602001610aee939291906144b5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012063ffffffff8816600090815260c2909252919020557f8b1606624b2f737eaf245dca9fba97deb930da8f4c71fb05a3f1b77d6bb8dfeb90610b6c9086908990869086906144ec565b60405180910390a15050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082161580610bb35750610bb382612a0b565b92915050565b60e48160088110610bc957600080fd5b0154905081565b600080527f16d6d09ad43c2e13327e8e85b0f16a19ef2e63b72c391bfd77d21c5d499021856020527fdf4fae2a9d03ddefae2c9e431bd1ae49d400972b66abd41187abff73623b3c4b5460ff16158015610c5957503360009081527f16d6d09ad43c2e13327e8e85b0f16a19ef2e63b72c391bfd77d21c5d49902185602052604090205460ff16155b15610c90576040517f6692e47700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c986121f8565b6000806000806000610caa8787612237565b9450945094509450945061040083610cc291906143c1565b63ffffffff1615610cff576040517f7478cfa900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d0c6001610400614352565b63ffffffff16610d1c8484614352565b63ffffffff1614610d59576040517f0a004fe500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b838989604051602001610d6e939291906144b5565b6040516020818303038152906040528051906020012060c26000846001610d959190614372565b63ffffffff1663ffffffff1681526020019081526020016000205414610de7576040517fa46ad57500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610df18787612334565b610e27576040517f1355d9a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8481610400604051602001610e3e939291906144b5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012063ffffffff8716600090815260c2909252919020557f8b1606624b2f737eaf245dca9fba97deb930da8f4c71fb05a3f1b77d6bb8dfeb90610ebe90859088908590610400906144ec565b60405180910390a1505050505050505050565b610ed96121f8565b6000839003610ee757600080fd5b828114610ef357600080fd5b60e354610f119061040090640100000000900463ffffffff16614521565b63ffffffff168563ffffffff1614610f2857600080fd5b6000610f3460c3612662565b905060005b84811015611031576000848483818110610f5557610f55614450565b90506020020135878784818110610f6e57610f6e614450565b90506020020135610400604051602001610f8a939291906144b5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012063ffffffff8b16600090815260c2909352912054909150811461100f576040517f612489a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61101b61040089614372565b975050808061102990614418565b915050610f39565b5060006110738686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508693925050612aa29050565b90506008826060015160016110889190614372565b61109291906143c1565b63ffffffff1660608301526110a68261282a565b60e4836060015163ffffffff16600881106110c3576110c3614450565b01556110d160c3838361291a565b7f39145329d5ae3858c6f1192667af1d01792c69c7f88d143b0312872011e5cbcb8260400151836060015160405161110a92919061447f565b60405180910390a150505050505050565b60008281526065602052604090206001015461113681612d5a565b6111408383612d64565b505050565b73ffffffffffffffffffffffffffffffffffffffff8116331461119d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611194906145a8565b60405180910390fd5b6111a78282612e58565b5050565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016300361121a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614612565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1661128f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16146112dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111949061467c565b6112e581612f13565b6040805160008082526020820190925261130191839190612f3d565b50565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163003611373576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614612565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166113e87f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614611435576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111949061467c565b61143e82612f13565b6111a782826001612f3d565b60003073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146114bb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611194906146e6565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504161150a81612d5a565b609780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517fe6fdbf73945dd61794a752b9181ea29f77170a7b1ffd37e0a7ff9d2c6f7258b990600090a150565b60006020820135810361157057600080fd5b6000610400611582602085018561429e565b61158c91906143c1565b905060008161159e602086018661429e565b6115a89190614352565b63ffffffff8116600090815260c260205260408120549192508190036115cd57600080fd5b602085013560005b600a81101561169157600163ffffffff8616821c1660000361163a57818760800182600a811061160757611607614450565b602002013560405160200161161d9291906143f2565b60405160208183030381529060405280519060200120915061167f565b8660800181600a811061164f5761164f614450565b6020020135826040516020016116669291906143f2565b6040516020818303038152906040528051906020012091505b8061168981614418565b9150506115d5565b506040860135816116a86080890160608a0161429e565b6040516020016116ba939291906144b5565b604051602081830303815290604052805190602001208214945050505050919050565b600080527f16d6d09ad43c2e13327e8e85b0f16a19ef2e63b72c391bfd77d21c5d499021856020527fdf4fae2a9d03ddefae2c9e431bd1ae49d400972b66abd41187abff73623b3c4b5460ff1615801561176657503360009081527f16d6d09ad43c2e13327e8e85b0f16a19ef2e63b72c391bfd77d21c5d49902185602052604090205460ff16155b1561179d576040517f6692e47700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117a56121f8565b60008060008060006117b78787612237565b94509450945094509450610400836117cf91906143c1565b63ffffffff161561180c576040517f7478cfa900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61181a600162020000614352565b63ffffffff1661182a8484614352565b63ffffffff1614611867576040517f0a004fe500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b838b8b60405160200161187c939291906144b5565b6040516020818303038152906040528051906020012060c260008460016118a39190614372565b63ffffffff1663ffffffff16815260200190815260200160002054146118f5576040517fa46ad57500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806119288a6080806020026040519081016040528092919082608060200280828437600092019190915250613090915050565b1461195f576040517ff4c360f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611969878761327d565b61199f576040517f1355d9a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b6080811015611c03576119b760016080614352565b63ffffffff168114611ac95760008982607f81106119d7576119d7614450565b6101600201600a6020020135905060005b600a811015611a77578a83607f8110611a0357611a03614450565b610160020181611a156001600a614352565b63ffffffff16611a2591906143df565b600b8110611a3557611a35614450565b602002013582604051602001611a4c9291906143f2565b6040516020818303038152906040528051906020012091508080611a6f90614418565b9150506119e8565b508a8260808110611a8a57611a8a614450565b60200201358114611ac7576040517ff4c360f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60008115611afe5789611add6001846143df565b607f8110611aed57611aed614450565b6101600201600a6020020135611b00565b865b90506000611b10610400846146f6565b611b209063ffffffff881661470e565b9050818c8460808110611b3557611b35614450565b6020020135610400604051602001611b4f939291906144b5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012063ffffffff8416600090815260c29093529120557f8b1606624b2f737eaf245dca9fba97deb930da8f4c71fb05a3f1b77d6bb8dfeb81838e8660808110611bce57611bce614450565b6020020135610400604051611be694939291906144ec565b60405180910390a150508080611bfb90614418565b9150506119a2565b505050505050505050505050565b7ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f05611c3b81612d5a565b60c080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556040517f0f7ba11d4e9d02c6ec9175a0134522c2f112de7cfdb2cea3f888e7eeae24c9dd90611cab908490613d7e565b60405180910390a15050565b60e48560ff1660088110611ccd57611ccd614450565b01548787604051602001611ce2929190614773565b6040516020818303038152906040528051906020012014611d2f576040517f612489a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611d3c6001886143df565b9050845b63ffffffff8082166104008483161b90911611611d93578163ffffffff16600003611d6a57600080fd5b81611d7481614780565b9250611d8c905061040063ffffffff84161b82614352565b9050611d40565b611d9e82600a614372565b63ffffffff168314611daf57600080fd5b8460005b84811015611e6c57600163ffffffff8416821c16600003611e165781868683818110611de157611de1614450565b90506020020135604051602001611df99291906143f2565b604051602081830303815290604052805190602001209150611e5a565b858582818110611e2857611e28614450565b9050602002013582604051602001611e419291906143f2565b6040516020818303038152906040528051906020012091505b80611e6481614418565b915050611db3565b5089898463ffffffff16818110611e8557611e85614450565b905060200201358114611ec4576040517f612489a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050505050565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041611efa81612d5a565b609780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f61340a1b154d5d21d259a74bf95379201799b9d12cc6509bb46cb56dc281df5590600090a150565b7ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f05611f7b81612d5a565b60c180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556040517f1431075dc15e519b4b9b0b93ea4f7f3e2a34fde5e39f552bb899b7ea4bda134190611cab908490613d7e565b600063ffffffff83164080820361200157600080fd5b90911492915050565b60008281526065602052604090206001015461202581612d5a565b6111408383612e58565b600060c363ffffffff83166020811061204a5761204a614450565b015492915050565b600054610100900460ff16158080156120725750600054600160ff909116105b8061208c5750303b15801561208c575060005460ff166001145b6120c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614819565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561212057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b73ffffffffffffffffffffffffffffffffffffffff831661214057600080fd5b6121486132ae565b612154858584336132ef565b61215f600084612d64565b6121897ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f0584612d64565b80156121f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690556040517f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906121e89060019061483d565b60405180910390a15b5050505050565b60975460ff1615612235576040517f379dfc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60008080808061224d6101c06101a0888a61484b565b6122569161487b565b60806122686101a06101808a8c61484b565b6122719161487b565b901b1794506122866102006101e0888a61484b565b61228f9161487b565b60806122a16101e06101c08a8c61484b565b6122aa9161487b565b901b1793506122bf61021c610218888a61484b565b6122c8916148c4565b60e01c92506122dd61022061021c888a61484b565b6122e6916148c4565b60e01c91506122fb610260610240888a61484b565b6123049161487b565b60806123166102406102208a8c61484b565b61231f9161487b565b60001c901b1760001b90509295509295909350565b60c054604051600091829173ffffffffffffffffffffffffffffffffffffffff90911690612365908690869061492f565b6000604051808303816000865af19150503d80600081146123a2576040519150601f19603f3d011682016040523d82523d6000602084013e6123a7565b606091505b509095945050505050565b600083836123c18460406146f6565b6123cd9061026061470e565b6123d890602061470e565b906123e485600161470e565b6123ef9060406146f6565b6123fb9061026061470e565b926124089392919061484b565b6124119161487b565b608085856124208660406146f6565b61242c9061026061470e565b906124388760406146f6565b6124449061026061470e565b61244f90602061470e565b9261245c9392919061484b565b6124659161487b565b901b1790505b9392505050565b60008160000361248457506000919050565b816001036124b357507fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5919050565b816002036124e257507fb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30919050565b8160030361251157507f21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85919050565b8160040361254057507fe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344919050565b8160050361256f57507f0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d919050565b8160060361259e57507f887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968919050565b816007036125cd57507fffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83919050565b816008036125fc57507f9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af919050565b8160090361262b57507fcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0919050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614973565b919050565b61266a613b2a565b60208083015463ffffffff8082169284019290925264010000000081048216604084015268010000000000000000900416606082015260005b816020015163ffffffff168163ffffffff161015612705578263ffffffff8216602081106126d3576126d3614450565b0154825163ffffffff8316602081106126ee576126ee614450565b6020020152806126fd81614983565b9150506126a3565b50919050565b6040820151600090819083905b600163ffffffff8281169085161c811690036127ad57855163ffffffff84166020811061274757612747614450565b60200201518260405160200161275e9291906143f2565b6040516020818303038152906040528051906020012091506000801b86600001518463ffffffff166020811061279657612796614450565b60200201526127a6600184614372565b9250612718565b8551829063ffffffff8516602081106127c8576127c8614450565b6020020152604086018051600191906127e2908390614372565b63ffffffff9081169091526020880151811690851610905061281557612809836001614372565b63ffffffff1660208701525b612820836001614372565b9695505050505050565b600080826020015163ffffffff1667ffffffffffffffff81111561285057612850613ed9565b604051908082528060200260200182016040528015612879578160200160208202803683370190505b50905060005b836020015163ffffffff168163ffffffff1610156128ea57835163ffffffff8216602081106128b0576128b0614450565b6020020151828263ffffffff16815181106128cd576128cd614450565b6020908102919091010152806128e281614983565b91505061287f565b50806040516020016128fc9190614a10565b60405160208183030381529060405280519060200120915050919050565b60208083015190840180546040850151606086015163ffffffff90811668010000000000000000027fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff928216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009094169190951617919091171691909117905560005b8163ffffffff168163ffffffff161015612a0557825163ffffffff8216602081106129d1576129d1614450565b6020020151846000018263ffffffff16602081106129f1576129f1614450565b0155806129fd81614983565b9150506129a4565b50505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b000000000000000000000000000000000000000000000000000000001480610bb357507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610bb3565b60408201805182516000928190612ab98285614372565b63ffffffff169052506000805b63ffffffff831615612d2b5750600163ffffffff8481169083161c811690600090612af18386614372565b63ffffffff16901c905060005b8163ffffffff168163ffffffff161015612c84576000808463ffffffff16600103612bbc5763ffffffff831615612b6a57896001612b3d856002614521565b612b479190614352565b63ffffffff1681518110612b5d57612b5d614450565b6020026020010151612b89565b8a5163ffffffff871660208110612b8357612b83614450565b60200201515b915089612b97846002614521565b63ffffffff1681518110612bad57612bad614450565b60200260200101519050612c22565b89612bc8846002614521565b63ffffffff1681518110612bde57612bde614450565b6020026020010151915089836002612bf69190614521565b612c01906001614372565b63ffffffff1681518110612c1757612c17614450565b602002602001015190505b8181604051602001612c359291906143f2565b604051602081830303815290604052805190602001208a8463ffffffff1681518110612c6357612c63614450565b60200260200101818152505050508080612c7c90614983565b915050612afe565b506001841663ffffffff831614612ce55786612ca1600186614352565b63ffffffff1681518110612cb757612cb7614450565b602002602001015188600001518463ffffffff1660208110612cdb57612cdb614450565b6020020152612d15565b8163ffffffff16600103612d1557875160009063ffffffff851660208110612d0f57612d0f614450565b60200201525b925082612d23600184614372565b925050612ac6565b866020015163ffffffff168263ffffffff161115612d505763ffffffff821660208801525b5095945050505050565b6113018133613344565b600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166111a757600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055612dfa3390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156111a757600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b7ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f056111a781612d5a565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612f7057611140836133fe565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612ff5575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252612ff291810190614a27565b60015b61302b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614aa2565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114613084576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614b0c565b506111408383836134b2565b60008061309f60026080614b1c565b63ffffffff1667ffffffffffffffff8111156130bd576130bd613ed9565b6040519080825280602002602001820160405280156130e6578160200160208202803683370190505b50905060005b6130f860026080614b1c565b63ffffffff168110156131925783600182901b6080811061311b5761311b614450565b602002015184600183811b176080811061313757613137614450565b602002015160405160200161314d9291906143f2565b6040516020818303038152906040528051906020012082828151811061317557613175614450565b60209081029190910101528061318a81614418565b9150506130ec565b5060006131a160046080614b1c565b63ffffffff1690505b80156132595760005b818110156132505782600182901b815181106131d1576131d1614450565b602002602001015183600183901b600117815181106131f2576131f2614450565b602002602001015160405160200161320b9291906143f2565b6040516020818303038152906040528051906020012083828151811061323357613233614450565b60209081029190910101528061324881614418565b9150506131b3565b5060011c6131aa565b8160008151811061326c5761326c614450565b602002602001015192505050919050565b60c154604051600091829173ffffffffffffffffffffffffffffffffffffffff90911690612365908690869061492f565b600054610100900460ff16612235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614b94565b600054610100900460ff16613330576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614b94565b6133386134d7565b612a0584848484613520565b600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166111a757613384816136ff565b61338f83602061371e565b6040516020016133a0929190614bea565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a000000000000000000000000000000000000000000000000000000000825261119491600401614c9e565b73ffffffffffffffffffffffffffffffffffffffff81163b61344c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614d09565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6134bb83613931565b6000825111806134c85750805b1561114057612a05838361397e565b600054610100900460ff16613518576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614b94565b612235613a67565b600054610100900460ff16613561576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614b94565b73ffffffffffffffffffffffffffffffffffffffff841661358157600080fd5b73ffffffffffffffffffffffffffffffffffffffff83166135a157600080fd5b73ffffffffffffffffffffffffffffffffffffffff82166135c157600080fd5b73ffffffffffffffffffffffffffffffffffffffff81166135e157600080fd5b61360b7f60044782a422109ac08a415e44260ad5d3bad63d96ebe1fac0363399642ee3f282612d64565b6136357f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504183612d64565b60c0805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560c18054928616929091169190911790556040517f0f7ba11d4e9d02c6ec9175a0134522c2f112de7cfdb2cea3f888e7eeae24c9dd906136ba908690613d7e565b60405180910390a17f1431075dc15e519b4b9b0b93ea4f7f3e2a34fde5e39f552bb899b7ea4bda1341836040516136f19190613d7e565b60405180910390a150505050565b6060610bb373ffffffffffffffffffffffffffffffffffffffff831660145b6060600061372d8360026146f6565b61373890600261470e565b67ffffffffffffffff81111561375057613750613ed9565b6040519080825280601f01601f19166020018201604052801561377a576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106137b1576137b1614450565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061381457613814614450565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060006138508460026146f6565b61385b90600161470e565b90505b60018111156138f8577f303132333435363738396162636465660000000000000000000000000000000085600f166010811061389c5761389c614450565b1a60f81b8282815181106138b2576138b2614450565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c936138f181614d19565b905061385e565b50831561246b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614d53565b61393a816133fe565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606073ffffffffffffffffffffffffffffffffffffffff83163b6139ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614dbd565b6000808473ffffffffffffffffffffffffffffffffffffffff16846040516139f69190614dcd565b600060405180830381855af49150503d8060008114613a31576040519150601f19603f3d011682016040523d82523d6000602084013e613a36565b606091505b5091509150613a5e8282604051806060016040528060278152602001614dda60279139613ad2565b95945050505050565b600054610100900460ff16613aa8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614b94565b609780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b60608315613ae157508161246b565b61246b8383815115613af65781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111949190614c9e565b6040518060800160405280613b3d613b58565b81526000602082018190526040820181905260609091015290565b6040518061040001604052806020906020820280368337509192915050565b60008083601f840112613b8c57613b8c600080fd5b50813567ffffffffffffffff811115613ba757613ba7600080fd5b602083019150836001820283011115613bc257613bc2600080fd5b9250929050565b60008060208385031215613bdf57613bdf600080fd5b823567ffffffffffffffff811115613bf957613bf9600080fd5b613c0585828601613b77565b92509250509250929050565b7fffffffff0000000000000000000000000000000000000000000000000000000081165b811461130157600080fd5b8035610bb381613c11565b600060208284031215613c6057613c60600080fd5b6000613c6c8484613c40565b949350505050565b8015155b82525050565b60208101610bb38284613c74565b80613c35565b8035610bb381613c8c565b600060208284031215613cb257613cb2600080fd5b6000613c6c8484613c92565b80613c78565b60208101610bb38284613cbe565b63ffffffff8116613c35565b8035610bb381613cd2565b60008060008060608587031215613d0257613d02600080fd5b6000613d0e8787613c92565b9450506020613d1f87828801613cde565b935050604085013567ffffffffffffffff811115613d3f57613d3f600080fd5b613d4b87828801613b77565b95989497509550505050565b600073ffffffffffffffffffffffffffffffffffffffff8216610bb3565b613c7881613d57565b60208101610bb38284613d75565b60008083601f840112613da157613da1600080fd5b50813567ffffffffffffffff811115613dbc57613dbc600080fd5b602083019150836020820283011115613bc257613bc2600080fd5b600080600080600060608688031215613df257613df2600080fd5b6000613dfe8888613cde565b955050602086013567ffffffffffffffff811115613e1e57613e1e600080fd5b613e2a88828901613d8c565b9450945050604086013567ffffffffffffffff811115613e4c57613e4c600080fd5b613e5888828901613d8c565b92509250509295509295909350565b613c3581613d57565b8035610bb381613e67565b60008060408385031215613e9157613e91600080fd5b6000613e9d8585613c92565b9250506020613eae85828601613e70565b9150509250929050565b600060208284031215613ecd57613ecd600080fd5b6000613c6c8484613e70565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116810181811067ffffffffffffffff82111715613f4c57613f4c613ed9565b6040525050565b6000613f5e60405190565b905061265d8282613f08565b600067ffffffffffffffff821115613f8457613f84613ed9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011660200192915050565b82818337506000910152565b6000613fd2613fcd84613f6a565b613f53565b905082815260208101848484011115613fed57613fed600080fd5b613ff8848285613fb3565b509392505050565b600082601f83011261401457614014600080fd5b8135613c6c848260208601613fbf565b6000806040838503121561403a5761403a600080fd5b60006140468585613e70565b925050602083013567ffffffffffffffff81111561406657614066600080fd5b613eae85828601614000565b63ffffffff8116613c78565b6060810161408c8286614072565b6140996020830185614072565b613c6c6040830184614072565b60006101c0828403121561270557612705600080fd5b60006101c082840312156140d2576140d2600080fd5b6000613c6c84846140a6565b806110008101831015610bb357610bb3600080fd5b8061aea08101831015610bb357610bb3600080fd5b60008060008060008061bf00878903121561412557614125600080fd5b60006141318989613c92565b965050602061414289828a01613cde565b955050604061415389828a016140de565b94505061104061416589828a016140f3565b93505061bee087013567ffffffffffffffff81111561418657614186600080fd5b61419289828a01613b77565b92509250509295509295509295565b60ff8116613c35565b8035610bb3816141a1565b600080600080600080600060a0888a0312156141d3576141d3600080fd5b873567ffffffffffffffff8111156141ed576141ed600080fd5b6141f98a828b01613d8c565b9750975050602061420c8a828b016141aa565b955050604061421d8a828b01613cde565b945050606061422e8a828b01613c92565b935050608088013567ffffffffffffffff81111561424e5761424e600080fd5b61425a8a828b01613d8c565b925092505092959891949750929550565b6000806040838503121561428157614281600080fd5b600061428d8585613cde565b9250506020613eae85828601613c92565b6000602082840312156142b3576142b3600080fd5b6000613c6c8484613cde565b600080600080608085870312156142d8576142d8600080fd5b60006142e48787613e70565b94505060206142f587828801613e70565b935050604061430687828801613e70565b925050606061431787828801613e70565b91505092959194509250565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff918216919081169082820390811115610bb357610bb3614323565b63ffffffff918216919081169082820190811115610bb357610bb3614323565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b63ffffffff91821691166000826143da576143da614392565b500690565b81810381811115610bb357610bb3614323565b60006143fe8285613cbe565b60208201915061440e8284613cbe565b5060200192915050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361444957614449614323565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6040810161448d8285614072565b61246b6020830184614072565b6000610bb38260e01b90565b613c7863ffffffff821661449a565b60006144c18286613cbe565b6020820191506144d18285613cbe565b6020820191506144e182846144a6565b506004019392505050565b608081016144fa8287614072565b6145076020830186613cbe565b6145146040830185613cbe565b613a5e6060830184614072565b63ffffffff91821691908116908282029081169081811461454457614544614323565b5092915050565b602f81526000602082017f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636581527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015291505b5060400190565b60208082528101610bb38161454b565b602c81526000602082017f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682081527f64656c656761746563616c6c0000000000000000000000000000000000000000602082015291506145a1565b60208082528101610bb3816145b8565b602c81526000602082017f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682081527f6163746976652070726f78790000000000000000000000000000000000000000602082015291506145a1565b60208082528101610bb381614622565b603881526000602082017f555550535570677261646561626c653a206d757374206e6f742062652063616c81527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000602082015291506145a1565b60208082528101610bb38161468c565b81810280821583820485141761454457614544614323565b80820180821115610bb357610bb3614323565b82818337505050565b60007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561475c5761475c600080fd5b60208302925061476d838584614721565b50500190565b6000613c6c82848661472a565b600063ffffffff82165b91508161479957614799614323565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b602e81526000602082017f496e697469616c697a61626c653a20636f6e747261637420697320616c72656181527f647920696e697469616c697a6564000000000000000000000000000000000000602082015291506145a1565b60208082528101610bb3816147bf565b600060ff8216610bb3565b613c7881614829565b60208101610bb38284614834565b6000808585111561485e5761485e600080fd5b8386111561486e5761486e600080fd5b5050820193919092039150565b8035828260208210156148bc576148b77fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff836020036008021b90565b831692505b505092915050565b80357fffffffff0000000000000000000000000000000000000000000000000000000016828260048210156148bc576148b77fffffffff00000000000000000000000000000000000000000000000000000000836004036008021b90565b600061476d838584613fb3565b6000613c6c828486614922565b601e81526000602082017f6465707468206d75737420626520696e2072616e6765205b302c203130290000815291505b5060200190565b60208082528101610bb38161493c565b63ffffffff1660007fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000001820161444957614449614323565b60006149c68383613cbe565b505060200190565b60006149d8825190565b602083018060005b83811015614a055781516149f488826149ba565b9750602083019250506001016149e0565b509495945050505050565b600061246b82846149ce565b8051610bb381613c8c565b600060208284031215614a3c57614a3c600080fd5b6000613c6c8484614a1c565b602e81526000602082017f45524331393637557067726164653a206e657720696d706c656d656e7461746981527f6f6e206973206e6f742055555053000000000000000000000000000000000000602082015291506145a1565b60208082528101610bb381614a48565b602981526000602082017f45524331393637557067726164653a20756e737570706f727465642070726f7881527f6961626c65555549440000000000000000000000000000000000000000000000602082015291506145a1565b60208082528101610bb381614ab2565b63ffffffff9182169116600082614b3557614b35614392565b500490565b602b81526000602082017f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206981527f6e697469616c697a696e67000000000000000000000000000000000000000000602082015291506145a1565b60208082528101610bb381614b3a565b60005b83811015614bbf578181015183820152602001614ba7565b50506000910152565b6000614bd2825190565b614be0818560208601614ba4565b9290920192915050565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526017016000614c1c8285614bc8565b7f206973206d697373696e6720726f6c652000000000000000000000000000000081526011019150613c6c8284614bc8565b6000614c58825190565b808452602084019350614c6f818560208601614ba4565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920192915050565b6020808252810161246b8184614c4e565b602d81526000602082017f455243313936373a206e657720696d706c656d656e746174696f6e206973206e81527f6f74206120636f6e747261637400000000000000000000000000000000000000602082015291506145a1565b60208082528101610bb381614caf565b60008161478a565b60208082527f537472696e67733a20686578206c656e67746820696e73756666696369656e749101908152600061496c565b60208082528101610bb381614d21565b602681526000602082017f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f81527f6e74726163740000000000000000000000000000000000000000000000000000602082015291506145a1565b60208082528101610bb381614d63565b600061246b8284614bc856fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220cb7c6136e814c6f9d19968b9e0f9ddb0ebbe8a64edda4aa2557cdbe360f33bfa64736f6c63430008130033
Deployed Bytecode
0x6080604052600436106101e35760003560e01c80636f193b8311610102578063c1f7cae211610095578063ef4fcb1711610064578063ef4fcb1714610608578063f288a2e214610628578063f8c8765e1461065c578063fe9ccb601461067c57600080fd5b8063c1f7cae214610567578063c6ca475314610587578063d547741f146105b4578063dc9a4ef6146105d457600080fd5b806391d14854116100d157806391d14854146104ca57806399464c891461051d578063a217fddf14610532578063ac59e61c1461054757600080fd5b80636f193b831461044a5780637225fb211461046a578063853ead4a1461048a57806389ea365d146104aa57600080fd5b8063282bf5c91161017a5780634f1ef286116101495780634f1ef286146103c5578063529ad9f3146103d857806352d1902d1461042057806366c5c4a01461043557600080fd5b8063282bf5c9146103455780632f2ff15d1461036557806336568abe146103855780633659cfe6146103a557600080fd5b806311b63d01116101b657806311b63d011461028757806318bdffbb146102a7578063248a9ca3146102e157806324ea54f41461031157600080fd5b806301ef3afa146101e857806301ffc9a71461020a578063054f7d9c14610240578063074144d61461025a575b600080fd5b3480156101f457600080fd5b50610208610203366004613bc9565b6106a9565b005b34801561021657600080fd5b5061022a610225366004613c4b565b610b7e565b6040516102379190613c7e565b60405180910390f35b34801561024c57600080fd5b5060975461022a9060ff1681565b34801561026657600080fd5b5061027a610275366004613c9d565b610bb9565b6040516102379190613cc4565b34801561029357600080fd5b506102086102a2366004613ce9565b610bd0565b3480156102b357600080fd5b5060c0546102d49073ffffffffffffffffffffffffffffffffffffffff1681565b6040516102379190613d7e565b3480156102ed57600080fd5b5061027a6102fc366004613c9d565b60009081526065602052604090206001015490565b34801561031d57600080fd5b5061027a7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504181565b34801561035157600080fd5b50610208610360366004613dd7565b610ed1565b34801561037157600080fd5b50610208610380366004613e7b565b61111b565b34801561039157600080fd5b506102086103a0366004613e7b565b611145565b3480156103b157600080fd5b506102086103c0366004613eb8565b6111ab565b6102086103d3366004614024565b611304565b3480156103e457600080fd5b5060e3546104119063ffffffff808216916401000000008104821691680100000000000000009091041683565b6040516102379392919061407e565b34801561042c57600080fd5b5061027a61144a565b34801561044157600080fd5b506102086114e0565b34801561045657600080fd5b5061022a6104653660046140bc565b61155e565b34801561047657600080fd5b50610208610485366004614108565b6116dd565b34801561049657600080fd5b506102086104a5366004613eb8565b611c11565b3480156104b657600080fd5b506102086104c53660046141b5565b611cb7565b3480156104d657600080fd5b5061022a6104e5366004613e7b565b600091825260656020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561052957600080fd5b50610208611ed0565b34801561053e57600080fd5b5061027a600081565b34801561055357600080fd5b50610208610562366004613eb8565b611f51565b34801561057357600080fd5b5061022a61058236600461426b565b611feb565b34801561059357600080fd5b5061027a6105a236600461429e565b60c26020526000908152604090205481565b3480156105c057600080fd5b506102086105cf366004613e7b565b61200a565b3480156105e057600080fd5b5061027a7f60044782a422109ac08a415e44260ad5d3bad63d96ebe1fac0363399642ee3f281565b34801561061457600080fd5b5061027a61062336600461429e565b61202f565b34801561063457600080fd5b5061027a7ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f0581565b34801561066857600080fd5b506102086106773660046142bf565b612052565b34801561068857600080fd5b5060c1546102d49073ffffffffffffffffffffffffffffffffffffffff1681565b600080527f16d6d09ad43c2e13327e8e85b0f16a19ef2e63b72c391bfd77d21c5d499021856020527fdf4fae2a9d03ddefae2c9e431bd1ae49d400972b66abd41187abff73623b3c4b5460ff1615801561073257503360009081527f16d6d09ad43c2e13327e8e85b0f16a19ef2e63b72c391bfd77d21c5d49902185602052604090205460ff16155b15610769576040517f6692e47700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107716121f8565b60008060008060006107838787612237565b945094509450945094506000838361079b9190614352565b6107a6906001614372565b905061040063ffffffff821611156107ea576040517f0a004fe500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107f6610400856143c1565b63ffffffff1615610833576040517f7478cfa900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b438363ffffffff1610610872576040517faef3422900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010061088563ffffffff8516436143df565b11156108bd576040517faef3422900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b848363ffffffff1640146108fd576040517fa46ad57500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109078888612334565b61093d576040517f1355d9a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816109fc5760005b600a8110156109f65760006109778a8a846109626001600a614352565b63ffffffff1661097291906143df565b6123b2565b905080156109af5780846040516020016109929291906143f2565b6040516020818303038152906040528051906020012093506109e3565b836109b983612472565b6040516020016109ca9291906143f2565b6040516020818303038152906040528051906020012093505b50806109ee81614418565b915050610945565b50610ad9565b60e354623fffff600a86901c1664010000000090910463ffffffff1603610ad9576000610a2960c3612662565b90506000610a37828561270b565b9050600882606001516001610a4c9190614372565b610a5691906143c1565b63ffffffff166060830152610a6a8261282a565b60e4836060015163ffffffff1660088110610a8757610a87614450565b0155610a9560c3838361291a565b7f39145329d5ae3858c6f1192667af1d01792c69c7f88d143b0312872011e5cbcb82604001518360600151604051610ace92919061447f565b60405180910390a150505b858282604051602001610aee939291906144b5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012063ffffffff8816600090815260c2909252919020557f8b1606624b2f737eaf245dca9fba97deb930da8f4c71fb05a3f1b77d6bb8dfeb90610b6c9086908990869086906144ec565b60405180910390a15050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082161580610bb35750610bb382612a0b565b92915050565b60e48160088110610bc957600080fd5b0154905081565b600080527f16d6d09ad43c2e13327e8e85b0f16a19ef2e63b72c391bfd77d21c5d499021856020527fdf4fae2a9d03ddefae2c9e431bd1ae49d400972b66abd41187abff73623b3c4b5460ff16158015610c5957503360009081527f16d6d09ad43c2e13327e8e85b0f16a19ef2e63b72c391bfd77d21c5d49902185602052604090205460ff16155b15610c90576040517f6692e47700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c986121f8565b6000806000806000610caa8787612237565b9450945094509450945061040083610cc291906143c1565b63ffffffff1615610cff576040517f7478cfa900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d0c6001610400614352565b63ffffffff16610d1c8484614352565b63ffffffff1614610d59576040517f0a004fe500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b838989604051602001610d6e939291906144b5565b6040516020818303038152906040528051906020012060c26000846001610d959190614372565b63ffffffff1663ffffffff1681526020019081526020016000205414610de7576040517fa46ad57500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610df18787612334565b610e27576040517f1355d9a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8481610400604051602001610e3e939291906144b5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012063ffffffff8716600090815260c2909252919020557f8b1606624b2f737eaf245dca9fba97deb930da8f4c71fb05a3f1b77d6bb8dfeb90610ebe90859088908590610400906144ec565b60405180910390a1505050505050505050565b610ed96121f8565b6000839003610ee757600080fd5b828114610ef357600080fd5b60e354610f119061040090640100000000900463ffffffff16614521565b63ffffffff168563ffffffff1614610f2857600080fd5b6000610f3460c3612662565b905060005b84811015611031576000848483818110610f5557610f55614450565b90506020020135878784818110610f6e57610f6e614450565b90506020020135610400604051602001610f8a939291906144b5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012063ffffffff8b16600090815260c2909352912054909150811461100f576040517f612489a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61101b61040089614372565b975050808061102990614418565b915050610f39565b5060006110738686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508693925050612aa29050565b90506008826060015160016110889190614372565b61109291906143c1565b63ffffffff1660608301526110a68261282a565b60e4836060015163ffffffff16600881106110c3576110c3614450565b01556110d160c3838361291a565b7f39145329d5ae3858c6f1192667af1d01792c69c7f88d143b0312872011e5cbcb8260400151836060015160405161110a92919061447f565b60405180910390a150505050505050565b60008281526065602052604090206001015461113681612d5a565b6111408383612d64565b505050565b73ffffffffffffffffffffffffffffffffffffffff8116331461119d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611194906145a8565b60405180910390fd5b6111a78282612e58565b5050565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000003a4bfb0ce7b50b6c61579c6d92e85a145350846f16300361121a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614612565b7f0000000000000000000000003a4bfb0ce7b50b6c61579c6d92e85a145350846f73ffffffffffffffffffffffffffffffffffffffff1661128f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16146112dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111949061467c565b6112e581612f13565b6040805160008082526020820190925261130191839190612f3d565b50565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000003a4bfb0ce7b50b6c61579c6d92e85a145350846f163003611373576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614612565b7f0000000000000000000000003a4bfb0ce7b50b6c61579c6d92e85a145350846f73ffffffffffffffffffffffffffffffffffffffff166113e87f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614611435576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111949061467c565b61143e82612f13565b6111a782826001612f3d565b60003073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000003a4bfb0ce7b50b6c61579c6d92e85a145350846f16146114bb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611194906146e6565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504161150a81612d5a565b609780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517fe6fdbf73945dd61794a752b9181ea29f77170a7b1ffd37e0a7ff9d2c6f7258b990600090a150565b60006020820135810361157057600080fd5b6000610400611582602085018561429e565b61158c91906143c1565b905060008161159e602086018661429e565b6115a89190614352565b63ffffffff8116600090815260c260205260408120549192508190036115cd57600080fd5b602085013560005b600a81101561169157600163ffffffff8616821c1660000361163a57818760800182600a811061160757611607614450565b602002013560405160200161161d9291906143f2565b60405160208183030381529060405280519060200120915061167f565b8660800181600a811061164f5761164f614450565b6020020135826040516020016116669291906143f2565b6040516020818303038152906040528051906020012091505b8061168981614418565b9150506115d5565b506040860135816116a86080890160608a0161429e565b6040516020016116ba939291906144b5565b604051602081830303815290604052805190602001208214945050505050919050565b600080527f16d6d09ad43c2e13327e8e85b0f16a19ef2e63b72c391bfd77d21c5d499021856020527fdf4fae2a9d03ddefae2c9e431bd1ae49d400972b66abd41187abff73623b3c4b5460ff1615801561176657503360009081527f16d6d09ad43c2e13327e8e85b0f16a19ef2e63b72c391bfd77d21c5d49902185602052604090205460ff16155b1561179d576040517f6692e47700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117a56121f8565b60008060008060006117b78787612237565b94509450945094509450610400836117cf91906143c1565b63ffffffff161561180c576040517f7478cfa900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61181a600162020000614352565b63ffffffff1661182a8484614352565b63ffffffff1614611867576040517f0a004fe500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b838b8b60405160200161187c939291906144b5565b6040516020818303038152906040528051906020012060c260008460016118a39190614372565b63ffffffff1663ffffffff16815260200190815260200160002054146118f5576040517fa46ad57500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806119288a6080806020026040519081016040528092919082608060200280828437600092019190915250613090915050565b1461195f576040517ff4c360f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611969878761327d565b61199f576040517f1355d9a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b6080811015611c03576119b760016080614352565b63ffffffff168114611ac95760008982607f81106119d7576119d7614450565b6101600201600a6020020135905060005b600a811015611a77578a83607f8110611a0357611a03614450565b610160020181611a156001600a614352565b63ffffffff16611a2591906143df565b600b8110611a3557611a35614450565b602002013582604051602001611a4c9291906143f2565b6040516020818303038152906040528051906020012091508080611a6f90614418565b9150506119e8565b508a8260808110611a8a57611a8a614450565b60200201358114611ac7576040517ff4c360f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60008115611afe5789611add6001846143df565b607f8110611aed57611aed614450565b6101600201600a6020020135611b00565b865b90506000611b10610400846146f6565b611b209063ffffffff881661470e565b9050818c8460808110611b3557611b35614450565b6020020135610400604051602001611b4f939291906144b5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012063ffffffff8416600090815260c29093529120557f8b1606624b2f737eaf245dca9fba97deb930da8f4c71fb05a3f1b77d6bb8dfeb81838e8660808110611bce57611bce614450565b6020020135610400604051611be694939291906144ec565b60405180910390a150508080611bfb90614418565b9150506119a2565b505050505050505050505050565b7ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f05611c3b81612d5a565b60c080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556040517f0f7ba11d4e9d02c6ec9175a0134522c2f112de7cfdb2cea3f888e7eeae24c9dd90611cab908490613d7e565b60405180910390a15050565b60e48560ff1660088110611ccd57611ccd614450565b01548787604051602001611ce2929190614773565b6040516020818303038152906040528051906020012014611d2f576040517f612489a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611d3c6001886143df565b9050845b63ffffffff8082166104008483161b90911611611d93578163ffffffff16600003611d6a57600080fd5b81611d7481614780565b9250611d8c905061040063ffffffff84161b82614352565b9050611d40565b611d9e82600a614372565b63ffffffff168314611daf57600080fd5b8460005b84811015611e6c57600163ffffffff8416821c16600003611e165781868683818110611de157611de1614450565b90506020020135604051602001611df99291906143f2565b604051602081830303815290604052805190602001209150611e5a565b858582818110611e2857611e28614450565b9050602002013582604051602001611e419291906143f2565b6040516020818303038152906040528051906020012091505b80611e6481614418565b915050611db3565b5089898463ffffffff16818110611e8557611e85614450565b905060200201358114611ec4576040517f612489a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050505050565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041611efa81612d5a565b609780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f61340a1b154d5d21d259a74bf95379201799b9d12cc6509bb46cb56dc281df5590600090a150565b7ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f05611f7b81612d5a565b60c180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556040517f1431075dc15e519b4b9b0b93ea4f7f3e2a34fde5e39f552bb899b7ea4bda134190611cab908490613d7e565b600063ffffffff83164080820361200157600080fd5b90911492915050565b60008281526065602052604090206001015461202581612d5a565b6111408383612e58565b600060c363ffffffff83166020811061204a5761204a614450565b015492915050565b600054610100900460ff16158080156120725750600054600160ff909116105b8061208c5750303b15801561208c575060005460ff166001145b6120c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614819565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561212057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b73ffffffffffffffffffffffffffffffffffffffff831661214057600080fd5b6121486132ae565b612154858584336132ef565b61215f600084612d64565b6121897ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f0584612d64565b80156121f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690556040517f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906121e89060019061483d565b60405180910390a15b5050505050565b60975460ff1615612235576040517f379dfc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60008080808061224d6101c06101a0888a61484b565b6122569161487b565b60806122686101a06101808a8c61484b565b6122719161487b565b901b1794506122866102006101e0888a61484b565b61228f9161487b565b60806122a16101e06101c08a8c61484b565b6122aa9161487b565b901b1793506122bf61021c610218888a61484b565b6122c8916148c4565b60e01c92506122dd61022061021c888a61484b565b6122e6916148c4565b60e01c91506122fb610260610240888a61484b565b6123049161487b565b60806123166102406102208a8c61484b565b61231f9161487b565b60001c901b1760001b90509295509295909350565b60c054604051600091829173ffffffffffffffffffffffffffffffffffffffff90911690612365908690869061492f565b6000604051808303816000865af19150503d80600081146123a2576040519150601f19603f3d011682016040523d82523d6000602084013e6123a7565b606091505b509095945050505050565b600083836123c18460406146f6565b6123cd9061026061470e565b6123d890602061470e565b906123e485600161470e565b6123ef9060406146f6565b6123fb9061026061470e565b926124089392919061484b565b6124119161487b565b608085856124208660406146f6565b61242c9061026061470e565b906124388760406146f6565b6124449061026061470e565b61244f90602061470e565b9261245c9392919061484b565b6124659161487b565b901b1790505b9392505050565b60008160000361248457506000919050565b816001036124b357507fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5919050565b816002036124e257507fb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30919050565b8160030361251157507f21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85919050565b8160040361254057507fe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344919050565b8160050361256f57507f0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d919050565b8160060361259e57507f887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968919050565b816007036125cd57507fffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83919050565b816008036125fc57507f9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af919050565b8160090361262b57507fcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0919050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614973565b919050565b61266a613b2a565b60208083015463ffffffff8082169284019290925264010000000081048216604084015268010000000000000000900416606082015260005b816020015163ffffffff168163ffffffff161015612705578263ffffffff8216602081106126d3576126d3614450565b0154825163ffffffff8316602081106126ee576126ee614450565b6020020152806126fd81614983565b9150506126a3565b50919050565b6040820151600090819083905b600163ffffffff8281169085161c811690036127ad57855163ffffffff84166020811061274757612747614450565b60200201518260405160200161275e9291906143f2565b6040516020818303038152906040528051906020012091506000801b86600001518463ffffffff166020811061279657612796614450565b60200201526127a6600184614372565b9250612718565b8551829063ffffffff8516602081106127c8576127c8614450565b6020020152604086018051600191906127e2908390614372565b63ffffffff9081169091526020880151811690851610905061281557612809836001614372565b63ffffffff1660208701525b612820836001614372565b9695505050505050565b600080826020015163ffffffff1667ffffffffffffffff81111561285057612850613ed9565b604051908082528060200260200182016040528015612879578160200160208202803683370190505b50905060005b836020015163ffffffff168163ffffffff1610156128ea57835163ffffffff8216602081106128b0576128b0614450565b6020020151828263ffffffff16815181106128cd576128cd614450565b6020908102919091010152806128e281614983565b91505061287f565b50806040516020016128fc9190614a10565b60405160208183030381529060405280519060200120915050919050565b60208083015190840180546040850151606086015163ffffffff90811668010000000000000000027fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff928216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009094169190951617919091171691909117905560005b8163ffffffff168163ffffffff161015612a0557825163ffffffff8216602081106129d1576129d1614450565b6020020151846000018263ffffffff16602081106129f1576129f1614450565b0155806129fd81614983565b9150506129a4565b50505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b000000000000000000000000000000000000000000000000000000001480610bb357507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610bb3565b60408201805182516000928190612ab98285614372565b63ffffffff169052506000805b63ffffffff831615612d2b5750600163ffffffff8481169083161c811690600090612af18386614372565b63ffffffff16901c905060005b8163ffffffff168163ffffffff161015612c84576000808463ffffffff16600103612bbc5763ffffffff831615612b6a57896001612b3d856002614521565b612b479190614352565b63ffffffff1681518110612b5d57612b5d614450565b6020026020010151612b89565b8a5163ffffffff871660208110612b8357612b83614450565b60200201515b915089612b97846002614521565b63ffffffff1681518110612bad57612bad614450565b60200260200101519050612c22565b89612bc8846002614521565b63ffffffff1681518110612bde57612bde614450565b6020026020010151915089836002612bf69190614521565b612c01906001614372565b63ffffffff1681518110612c1757612c17614450565b602002602001015190505b8181604051602001612c359291906143f2565b604051602081830303815290604052805190602001208a8463ffffffff1681518110612c6357612c63614450565b60200260200101818152505050508080612c7c90614983565b915050612afe565b506001841663ffffffff831614612ce55786612ca1600186614352565b63ffffffff1681518110612cb757612cb7614450565b602002602001015188600001518463ffffffff1660208110612cdb57612cdb614450565b6020020152612d15565b8163ffffffff16600103612d1557875160009063ffffffff851660208110612d0f57612d0f614450565b60200201525b925082612d23600184614372565b925050612ac6565b866020015163ffffffff168263ffffffff161115612d505763ffffffff821660208801525b5095945050505050565b6113018133613344565b600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166111a757600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055612dfa3390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156111a757600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b7ff66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f056111a781612d5a565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612f7057611140836133fe565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612ff5575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252612ff291810190614a27565b60015b61302b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614aa2565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114613084576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614b0c565b506111408383836134b2565b60008061309f60026080614b1c565b63ffffffff1667ffffffffffffffff8111156130bd576130bd613ed9565b6040519080825280602002602001820160405280156130e6578160200160208202803683370190505b50905060005b6130f860026080614b1c565b63ffffffff168110156131925783600182901b6080811061311b5761311b614450565b602002015184600183811b176080811061313757613137614450565b602002015160405160200161314d9291906143f2565b6040516020818303038152906040528051906020012082828151811061317557613175614450565b60209081029190910101528061318a81614418565b9150506130ec565b5060006131a160046080614b1c565b63ffffffff1690505b80156132595760005b818110156132505782600182901b815181106131d1576131d1614450565b602002602001015183600183901b600117815181106131f2576131f2614450565b602002602001015160405160200161320b9291906143f2565b6040516020818303038152906040528051906020012083828151811061323357613233614450565b60209081029190910101528061324881614418565b9150506131b3565b5060011c6131aa565b8160008151811061326c5761326c614450565b602002602001015192505050919050565b60c154604051600091829173ffffffffffffffffffffffffffffffffffffffff90911690612365908690869061492f565b600054610100900460ff16612235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614b94565b600054610100900460ff16613330576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614b94565b6133386134d7565b612a0584848484613520565b600082815260656020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166111a757613384816136ff565b61338f83602061371e565b6040516020016133a0929190614bea565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a000000000000000000000000000000000000000000000000000000000825261119491600401614c9e565b73ffffffffffffffffffffffffffffffffffffffff81163b61344c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614d09565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6134bb83613931565b6000825111806134c85750805b1561114057612a05838361397e565b600054610100900460ff16613518576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614b94565b612235613a67565b600054610100900460ff16613561576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614b94565b73ffffffffffffffffffffffffffffffffffffffff841661358157600080fd5b73ffffffffffffffffffffffffffffffffffffffff83166135a157600080fd5b73ffffffffffffffffffffffffffffffffffffffff82166135c157600080fd5b73ffffffffffffffffffffffffffffffffffffffff81166135e157600080fd5b61360b7f60044782a422109ac08a415e44260ad5d3bad63d96ebe1fac0363399642ee3f282612d64565b6136357f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504183612d64565b60c0805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560c18054928616929091169190911790556040517f0f7ba11d4e9d02c6ec9175a0134522c2f112de7cfdb2cea3f888e7eeae24c9dd906136ba908690613d7e565b60405180910390a17f1431075dc15e519b4b9b0b93ea4f7f3e2a34fde5e39f552bb899b7ea4bda1341836040516136f19190613d7e565b60405180910390a150505050565b6060610bb373ffffffffffffffffffffffffffffffffffffffff831660145b6060600061372d8360026146f6565b61373890600261470e565b67ffffffffffffffff81111561375057613750613ed9565b6040519080825280601f01601f19166020018201604052801561377a576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106137b1576137b1614450565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061381457613814614450565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060006138508460026146f6565b61385b90600161470e565b90505b60018111156138f8577f303132333435363738396162636465660000000000000000000000000000000085600f166010811061389c5761389c614450565b1a60f81b8282815181106138b2576138b2614450565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c936138f181614d19565b905061385e565b50831561246b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614d53565b61393a816133fe565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606073ffffffffffffffffffffffffffffffffffffffff83163b6139ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614dbd565b6000808473ffffffffffffffffffffffffffffffffffffffff16846040516139f69190614dcd565b600060405180830381855af49150503d8060008114613a31576040519150601f19603f3d011682016040523d82523d6000602084013e613a36565b606091505b5091509150613a5e8282604051806060016040528060278152602001614dda60279139613ad2565b95945050505050565b600054610100900460ff16613aa8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119490614b94565b609780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b60608315613ae157508161246b565b61246b8383815115613af65781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111949190614c9e565b6040518060800160405280613b3d613b58565b81526000602082018190526040820181905260609091015290565b6040518061040001604052806020906020820280368337509192915050565b60008083601f840112613b8c57613b8c600080fd5b50813567ffffffffffffffff811115613ba757613ba7600080fd5b602083019150836001820283011115613bc257613bc2600080fd5b9250929050565b60008060208385031215613bdf57613bdf600080fd5b823567ffffffffffffffff811115613bf957613bf9600080fd5b613c0585828601613b77565b92509250509250929050565b7fffffffff0000000000000000000000000000000000000000000000000000000081165b811461130157600080fd5b8035610bb381613c11565b600060208284031215613c6057613c60600080fd5b6000613c6c8484613c40565b949350505050565b8015155b82525050565b60208101610bb38284613c74565b80613c35565b8035610bb381613c8c565b600060208284031215613cb257613cb2600080fd5b6000613c6c8484613c92565b80613c78565b60208101610bb38284613cbe565b63ffffffff8116613c35565b8035610bb381613cd2565b60008060008060608587031215613d0257613d02600080fd5b6000613d0e8787613c92565b9450506020613d1f87828801613cde565b935050604085013567ffffffffffffffff811115613d3f57613d3f600080fd5b613d4b87828801613b77565b95989497509550505050565b600073ffffffffffffffffffffffffffffffffffffffff8216610bb3565b613c7881613d57565b60208101610bb38284613d75565b60008083601f840112613da157613da1600080fd5b50813567ffffffffffffffff811115613dbc57613dbc600080fd5b602083019150836020820283011115613bc257613bc2600080fd5b600080600080600060608688031215613df257613df2600080fd5b6000613dfe8888613cde565b955050602086013567ffffffffffffffff811115613e1e57613e1e600080fd5b613e2a88828901613d8c565b9450945050604086013567ffffffffffffffff811115613e4c57613e4c600080fd5b613e5888828901613d8c565b92509250509295509295909350565b613c3581613d57565b8035610bb381613e67565b60008060408385031215613e9157613e91600080fd5b6000613e9d8585613c92565b9250506020613eae85828601613e70565b9150509250929050565b600060208284031215613ecd57613ecd600080fd5b6000613c6c8484613e70565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116810181811067ffffffffffffffff82111715613f4c57613f4c613ed9565b6040525050565b6000613f5e60405190565b905061265d8282613f08565b600067ffffffffffffffff821115613f8457613f84613ed9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011660200192915050565b82818337506000910152565b6000613fd2613fcd84613f6a565b613f53565b905082815260208101848484011115613fed57613fed600080fd5b613ff8848285613fb3565b509392505050565b600082601f83011261401457614014600080fd5b8135613c6c848260208601613fbf565b6000806040838503121561403a5761403a600080fd5b60006140468585613e70565b925050602083013567ffffffffffffffff81111561406657614066600080fd5b613eae85828601614000565b63ffffffff8116613c78565b6060810161408c8286614072565b6140996020830185614072565b613c6c6040830184614072565b60006101c0828403121561270557612705600080fd5b60006101c082840312156140d2576140d2600080fd5b6000613c6c84846140a6565b806110008101831015610bb357610bb3600080fd5b8061aea08101831015610bb357610bb3600080fd5b60008060008060008061bf00878903121561412557614125600080fd5b60006141318989613c92565b965050602061414289828a01613cde565b955050604061415389828a016140de565b94505061104061416589828a016140f3565b93505061bee087013567ffffffffffffffff81111561418657614186600080fd5b61419289828a01613b77565b92509250509295509295509295565b60ff8116613c35565b8035610bb3816141a1565b600080600080600080600060a0888a0312156141d3576141d3600080fd5b873567ffffffffffffffff8111156141ed576141ed600080fd5b6141f98a828b01613d8c565b9750975050602061420c8a828b016141aa565b955050604061421d8a828b01613cde565b945050606061422e8a828b01613c92565b935050608088013567ffffffffffffffff81111561424e5761424e600080fd5b61425a8a828b01613d8c565b925092505092959891949750929550565b6000806040838503121561428157614281600080fd5b600061428d8585613cde565b9250506020613eae85828601613c92565b6000602082840312156142b3576142b3600080fd5b6000613c6c8484613cde565b600080600080608085870312156142d8576142d8600080fd5b60006142e48787613e70565b94505060206142f587828801613e70565b935050604061430687828801613e70565b925050606061431787828801613e70565b91505092959194509250565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff918216919081169082820390811115610bb357610bb3614323565b63ffffffff918216919081169082820190811115610bb357610bb3614323565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b63ffffffff91821691166000826143da576143da614392565b500690565b81810381811115610bb357610bb3614323565b60006143fe8285613cbe565b60208201915061440e8284613cbe565b5060200192915050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361444957614449614323565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6040810161448d8285614072565b61246b6020830184614072565b6000610bb38260e01b90565b613c7863ffffffff821661449a565b60006144c18286613cbe565b6020820191506144d18285613cbe565b6020820191506144e182846144a6565b506004019392505050565b608081016144fa8287614072565b6145076020830186613cbe565b6145146040830185613cbe565b613a5e6060830184614072565b63ffffffff91821691908116908282029081169081811461454457614544614323565b5092915050565b602f81526000602082017f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636581527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015291505b5060400190565b60208082528101610bb38161454b565b602c81526000602082017f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682081527f64656c656761746563616c6c0000000000000000000000000000000000000000602082015291506145a1565b60208082528101610bb3816145b8565b602c81526000602082017f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682081527f6163746976652070726f78790000000000000000000000000000000000000000602082015291506145a1565b60208082528101610bb381614622565b603881526000602082017f555550535570677261646561626c653a206d757374206e6f742062652063616c81527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000602082015291506145a1565b60208082528101610bb38161468c565b81810280821583820485141761454457614544614323565b80820180821115610bb357610bb3614323565b82818337505050565b60007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561475c5761475c600080fd5b60208302925061476d838584614721565b50500190565b6000613c6c82848661472a565b600063ffffffff82165b91508161479957614799614323565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b602e81526000602082017f496e697469616c697a61626c653a20636f6e747261637420697320616c72656181527f647920696e697469616c697a6564000000000000000000000000000000000000602082015291506145a1565b60208082528101610bb3816147bf565b600060ff8216610bb3565b613c7881614829565b60208101610bb38284614834565b6000808585111561485e5761485e600080fd5b8386111561486e5761486e600080fd5b5050820193919092039150565b8035828260208210156148bc576148b77fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff836020036008021b90565b831692505b505092915050565b80357fffffffff0000000000000000000000000000000000000000000000000000000016828260048210156148bc576148b77fffffffff00000000000000000000000000000000000000000000000000000000836004036008021b90565b600061476d838584613fb3565b6000613c6c828486614922565b601e81526000602082017f6465707468206d75737420626520696e2072616e6765205b302c203130290000815291505b5060200190565b60208082528101610bb38161493c565b63ffffffff1660007fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000001820161444957614449614323565b60006149c68383613cbe565b505060200190565b60006149d8825190565b602083018060005b83811015614a055781516149f488826149ba565b9750602083019250506001016149e0565b509495945050505050565b600061246b82846149ce565b8051610bb381613c8c565b600060208284031215614a3c57614a3c600080fd5b6000613c6c8484614a1c565b602e81526000602082017f45524331393637557067726164653a206e657720696d706c656d656e7461746981527f6f6e206973206e6f742055555053000000000000000000000000000000000000602082015291506145a1565b60208082528101610bb381614a48565b602981526000602082017f45524331393637557067726164653a20756e737570706f727465642070726f7881527f6961626c65555549440000000000000000000000000000000000000000000000602082015291506145a1565b60208082528101610bb381614ab2565b63ffffffff9182169116600082614b3557614b35614392565b500490565b602b81526000602082017f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206981527f6e697469616c697a696e67000000000000000000000000000000000000000000602082015291506145a1565b60208082528101610bb381614b3a565b60005b83811015614bbf578181015183820152602001614ba7565b50506000910152565b6000614bd2825190565b614be0818560208601614ba4565b9290920192915050565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526017016000614c1c8285614bc8565b7f206973206d697373696e6720726f6c652000000000000000000000000000000081526011019150613c6c8284614bc8565b6000614c58825190565b808452602084019350614c6f818560208601614ba4565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920192915050565b6020808252810161246b8184614c4e565b602d81526000602082017f455243313936373a206e657720696d706c656d656e746174696f6e206973206e81527f6f74206120636f6e747261637400000000000000000000000000000000000000602082015291506145a1565b60208082528101610bb381614caf565b60008161478a565b60208082527f537472696e67733a20686578206c656e67746820696e73756666696369656e749101908152600061496c565b60208082528101610bb381614d21565b602681526000602082017f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f81527f6e74726163740000000000000000000000000000000000000000000000000000602082015291506145a1565b60208082528101610bb381614d63565b600061246b8284614bc856fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220cb7c6136e814c6f9d19968b9e0f9ddb0ebbe8a64edda4aa2557cdbe360f33bfa64736f6c63430008130033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.