Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 760 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Register New Ran... | 21070320 | 83 days ago | IN | 0 ETH | 0.0004591 | ||||
Aggregate Sharp ... | 21049177 | 86 days ago | IN | 0 ETH | 0.00050909 | ||||
Register New Ran... | 21047436 | 86 days ago | IN | 0 ETH | 0.00020641 | ||||
Aggregate Sharp ... | 21042655 | 87 days ago | IN | 0 ETH | 0.00068504 | ||||
Register New Ran... | 21038604 | 87 days ago | IN | 0 ETH | 0.00040057 | ||||
Aggregate Sharp ... | 21035909 | 88 days ago | IN | 0 ETH | 0.00116455 | ||||
Register New Ran... | 21032484 | 88 days ago | IN | 0 ETH | 0.00034681 | ||||
Aggregate Sharp ... | 21029223 | 88 days ago | IN | 0 ETH | 0.00257425 | ||||
Register New Ran... | 21027477 | 89 days ago | IN | 0 ETH | 0.00036138 | ||||
Aggregate Sharp ... | 21025970 | 89 days ago | IN | 0 ETH | 0.00049828 | ||||
Register New Ran... | 21022472 | 89 days ago | IN | 0 ETH | 0.00078472 | ||||
Aggregate Sharp ... | 21019208 | 90 days ago | IN | 0 ETH | 0.00052017 | ||||
Register New Ran... | 21017465 | 90 days ago | IN | 0 ETH | 0.0002829 | ||||
Aggregate Sharp ... | 21015918 | 90 days ago | IN | 0 ETH | 0.0009078 | ||||
Register New Ran... | 21012460 | 91 days ago | IN | 0 ETH | 0.00056357 | ||||
Aggregate Sharp ... | 21008993 | 91 days ago | IN | 0 ETH | 0.00090797 | ||||
Register New Ran... | 21007446 | 92 days ago | IN | 0 ETH | 0.00091788 | ||||
Aggregate Sharp ... | 21005624 | 92 days ago | IN | 0 ETH | 0.0009097 | ||||
Register New Ran... | 21002426 | 92 days ago | IN | 0 ETH | 0.00042151 | ||||
Aggregate Sharp ... | 20998981 | 93 days ago | IN | 0 ETH | 0.00086212 | ||||
Register New Ran... | 20997419 | 93 days ago | IN | 0 ETH | 0.00045524 | ||||
Aggregate Sharp ... | 20995654 | 93 days ago | IN | 0 ETH | 0.00099944 | ||||
Register New Ran... | 20992414 | 94 days ago | IN | 0 ETH | 0.00166661 | ||||
Aggregate Sharp ... | 20992371 | 94 days ago | IN | 0 ETH | 0.01253455 | ||||
Register New Ran... | 20987409 | 94 days ago | IN | 0 ETH | 0.00114208 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
18119063 | 496 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Minimal Proxy Contract for 0xba5c971c3178ea8755bfb6996a42f3ae24e81344
Contract Name:
SharpFactsAggregator
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 20000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Initializable} from "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol"; import {AccessControlUpgradeable} from "openzeppelin-contracts-upgradeable/contracts/access/AccessControlUpgradeable.sol"; import {IFactsRegistry} from "./interfaces/IFactsRegistry.sol"; import {Uint256Splitter} from "./lib/Uint256Splitter.sol"; /// @title SharpFactsAggregator /// @dev Aggregator contract to handle SHARP job outputs and update the global aggregator state. /// @author Herodotus Dev /// ------------------ /// Example: /// Blocks inside brackets are the ones processed during their SHARP job execution // 7 [8 9 10] 11 /// n = 10 /// r = 3 /// `r` is the number of blocks processed on a single SHARP job execution /// `blockNMinusRPlusOneParentHash` = 8.parentHash (oldestHash) /// `blockNPlusOneParentHash` = 11.parentHash (newestHash) /// ------------------ contract SharpFactsAggregator is Initializable, AccessControlUpgradeable { // Using inline library for efficient splitting and joining of uint256 values using Uint256Splitter for uint256; // Role definitions for access control bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); bytes32 public constant UNLOCKER_ROLE = keccak256("UNLOCKER_ROLE"); uint256 public constant MINIMUM_BLOCKS_CONFIRMATIONS = 20; uint256 public constant MAXIMUM_BLOCKS_CONFIRMATIONS = 255; // Sharp Facts Registry IFactsRegistry public immutable FACTS_REGISTRY; // Cairo program hash (i.e., the off-chain block headers accumulator program) bytes32 public constant PROGRAM_HASH = bytes32( uint256( 0x1eca36d586f5356fba096edbf7414017d51cd0ed24b8fde80f78b61a9216ed2 ) ); // Global aggregator state struct AggregatorState { bytes32 poseidonMmrRoot; bytes32 keccakMmrRoot; uint256 mmrSize; bytes32 continuableParentHash; } // Current __global__ state of this aggregator AggregatorState public aggregatorState; // Mapping to keep track of block number to its parent hash mapping(uint256 => bytes32) public blockNumberToParentHash; // Flag to control operator role requirements bool public isOperatorRequired; // Representation of the Cairo program's output (raw unpacked) struct JobOutput { uint256 fromBlockNumberHigh; uint256 toBlockNumberLow; bytes32 blockNPlusOneParentHashLow; bytes32 blockNPlusOneParentHashHigh; bytes32 blockNMinusRPlusOneParentHashLow; bytes32 blockNMinusRPlusOneParentHashHigh; bytes32 mmrPreviousRootPoseidon; bytes32 mmrPreviousRootKeccakLow; bytes32 mmrPreviousRootKeccakHigh; uint256 mmrPreviousSize; bytes32 mmrNewRootPoseidon; bytes32 mmrNewRootKeccakLow; bytes32 mmrNewRootKeccakHigh; uint256 mmrNewSize; } // Packed representation of the Cairo program's output (for gas efficiency) struct JobOutputPacked { uint256 blockNumbersPacked; bytes32 blockNPlusOneParentHash; bytes32 blockNMinusRPlusOneParentHash; bytes32 mmrPreviousRootPoseidon; bytes32 mmrPreviousRootKeccak; bytes32 mmrNewRootPoseidon; bytes32 mmrNewRootKeccak; uint256 mmrSizesPacked; } // Custom errors for better error handling and clarity error NotEnoughBlockConfirmations(); error TooManyBlocksConfirmations(); error NotEnoughJobs(); error UnknownParentHash(); error AggregationError(string message); // Generic error with a message error AggregationBlockMismatch(); error GenesisBlockReached(); error InvalidFact(); // Event emitted when a new range is registered // (i.e, when we want to allow aggregating from a more recent block) event NewRangeRegistered( uint256 targetBlock, bytes32 targetBlockParentHash ); // Event emitted when __at least__ one SHARP job is aggregated event Aggregate( uint256 fromBlockNumberHigh, uint256 toBlockNumberLow, bytes32 poseidonMmrRoot, bytes32 keccakMmrRoot, uint256 mmrSize, bytes32 continuableParentHash ); event OperatorRequirementChange( bool newRequirement ); constructor(IFactsRegistry factsRegistry) { FACTS_REGISTRY = factsRegistry; } /** * @notice Initializes the contract with given parameters. * @param initialAggregatorState Initial state of the aggregator (i.e., initial trees state). */ function initialize( AggregatorState calldata initialAggregatorState ) public initializer { __AccessControl_init(); aggregatorState = initialAggregatorState; _setRoleAdmin(OPERATOR_ROLE, OPERATOR_ROLE); _setRoleAdmin(UNLOCKER_ROLE, OPERATOR_ROLE); // Grant operator role to the contract deployer // to be able to define new aggregate ranges _grantRole(OPERATOR_ROLE, _msgSender()); _grantRole(UNLOCKER_ROLE, _msgSender()); // Set operator role requirement to true by default isOperatorRequired = true; } /// @notice Reverts if the caller is not an operator and the operator role requirement is enabled modifier onlyOperator() { if (isOperatorRequired) { require( hasRole(OPERATOR_ROLE, _msgSender()), "Caller is not an operator" ); } _; } /// @notice Reverts if the caller is not an unlocker modifier onlyUnlocker() { require( hasRole(UNLOCKER_ROLE, _msgSender()), "Caller is not an unlocker" ); _; } /// @dev Modifies the contract's operator requirement function setOperatorRequired( bool _isOperatorRequired ) external onlyUnlocker { isOperatorRequired = _isOperatorRequired; emit OperatorRequirementChange(_isOperatorRequired); } /// Registers a new range to aggregate from /// @notice Caches a recent block hash (MINIMUM_BLOCKS_CONFIRMATIONS to -MAXIMUM_BLOCKS_CONFIRMATIONS from present), relying on the global `blockhash` Solidity function /// @param blocksConfirmations Number of blocks preceding the current block function registerNewRange( uint256 blocksConfirmations ) external onlyOperator { // Minimum blocks confirmations to avoid reorgs if (blocksConfirmations < MINIMUM_BLOCKS_CONFIRMATIONS) { revert NotEnoughBlockConfirmations(); } // Maximum MAXIMUM_BLOCKS_CONFIRMATIONS blocks confirmations to capture // an available block hash with Solidity `blockhash()` if (blocksConfirmations > MAXIMUM_BLOCKS_CONFIRMATIONS) { revert TooManyBlocksConfirmations(); } // Determine the target block number (i.e. the child block) uint256 targetBlock = block.number - blocksConfirmations; // Extract its parent hash. bytes32 targetBlockParentHash = blockhash(targetBlock - 1); // If the parent hash is not available, revert // (This should never happen under the current EVM rules) if (targetBlockParentHash == bytes32(0)) { revert UnknownParentHash(); } // Cache the parent hash so that we can later on continue accumlating from it blockNumberToParentHash[targetBlock] = targetBlockParentHash; // If we cannot aggregate further in the past (e.g., genesis block is reached or it's a new tree) if (aggregatorState.continuableParentHash == bytes32(0)) { // Set the aggregator state's `continuableParentHash` to the target block's parent hash // so we can easily continue aggregating from it without specifying `rightBoundStartBlock` in `aggregateSharpJobs` aggregatorState.continuableParentHash = targetBlockParentHash; } emit NewRangeRegistered(targetBlock, targetBlockParentHash); } /// @notice Aggregate SHARP jobs outputs (min. 1) to update the global aggregator state /// @param rightBoundStartBlock The reference block to start from. Defaults to continuing from the global state if set to `0` /// @param outputs Array of SHARP jobs outputs (packed for Solidity) function aggregateSharpJobs( uint256 rightBoundStartBlock, JobOutputPacked[] calldata outputs ) external onlyOperator { // Ensuring at least one job output is provided if (outputs.length < 1) { revert NotEnoughJobs(); } bytes32 rightBoundStartBlockParentHash = bytes32(0); // Start from a different block than the current state if `rightBoundStartBlock` is specified if (rightBoundStartBlock != 0) { // Retrieve from cache the parent hash of the block to start from rightBoundStartBlockParentHash = blockNumberToParentHash[ rightBoundStartBlock ]; // If not present in the cache, hash is not authenticated and we cannot continue from it if (rightBoundStartBlockParentHash == bytes32(0)) { revert UnknownParentHash(); } } JobOutputPacked calldata firstOutput = outputs[0]; // Ensure the first job is continuable ensureContinuable(rightBoundStartBlockParentHash, firstOutput); if (rightBoundStartBlockParentHash != bytes32(0)) { (uint256 fromBlockHighStart, ) = firstOutput .blockNumbersPacked .split128(); // We check that block numbers are consecutives if (fromBlockHighStart != rightBoundStartBlock - 1) { revert AggregationBlockMismatch(); } } uint256 limit = outputs.length - 1; // Iterate over the jobs outputs (aside from the last one) // and ensure jobs are correctly linked and valid for (uint256 i = 0; i < limit; ++i) { JobOutputPacked calldata curOutput = outputs[i]; JobOutputPacked calldata nextOutput = outputs[i + 1]; ensureValidFact(curOutput); ensureConsecutiveJobs(curOutput, nextOutput); } JobOutputPacked calldata lastOutput = outputs[limit]; ensureValidFact(lastOutput); // We save the latest output in the contract state for future calls (, uint256 mmrNewSize) = lastOutput.mmrSizesPacked.split128(); aggregatorState.poseidonMmrRoot = lastOutput.mmrNewRootPoseidon; aggregatorState.keccakMmrRoot = lastOutput.mmrNewRootKeccak; aggregatorState.mmrSize = mmrNewSize; aggregatorState.continuableParentHash = lastOutput .blockNMinusRPlusOneParentHash; (uint256 fromBlock, ) = firstOutput.blockNumbersPacked.split128(); (, uint256 toBlock) = lastOutput.blockNumbersPacked.split128(); emit Aggregate( fromBlock, toBlock, lastOutput.mmrNewRootPoseidon, lastOutput.mmrNewRootKeccak, mmrNewSize, lastOutput.blockNMinusRPlusOneParentHash ); } /// @notice Ensures the fact is registered on SHARP Facts Registry /// @param output SHARP job output (packed for Solidity) function ensureValidFact(JobOutputPacked memory output) internal view { (uint256 fromBlock, uint256 toBlock) = output .blockNumbersPacked .split128(); (uint256 mmrPreviousSize, uint256 mmrNewSize) = output .mmrSizesPacked .split128(); ( uint256 blockNPlusOneParentHashLow, uint256 blockNPlusOneParentHashHigh ) = uint256(output.blockNPlusOneParentHash).split128(); ( uint256 blockNMinusRPlusOneParentHashLow, uint256 blockNMinusRPlusOneParentHashHigh ) = uint256(output.blockNMinusRPlusOneParentHash).split128(); ( uint256 mmrPreviousRootKeccakLow, uint256 mmrPreviousRootKeccakHigh ) = uint256(output.mmrPreviousRootKeccak).split128(); (uint256 mmrNewRootKeccakLow, uint256 mmrNewRootKeccakHigh) = uint256( output.mmrNewRootKeccak ).split128(); // We assemble the outputs in a uint256 array uint256[] memory outputs = new uint256[](14); outputs[0] = fromBlock; outputs[1] = toBlock; outputs[2] = blockNPlusOneParentHashLow; outputs[3] = blockNPlusOneParentHashHigh; outputs[4] = blockNMinusRPlusOneParentHashLow; outputs[5] = blockNMinusRPlusOneParentHashHigh; outputs[6] = uint256(output.mmrPreviousRootPoseidon); outputs[7] = mmrPreviousRootKeccakLow; outputs[8] = mmrPreviousRootKeccakHigh; outputs[9] = mmrPreviousSize; outputs[10] = uint256(output.mmrNewRootPoseidon); outputs[11] = mmrNewRootKeccakLow; outputs[12] = mmrNewRootKeccakHigh; outputs[13] = mmrNewSize; // We hash the outputs bytes32 outputHash = keccak256(abi.encodePacked(outputs)); // We compute the deterministic fact bytes32 value bytes32 fact = keccak256(abi.encode(PROGRAM_HASH, outputHash)); // We ensure this fact has been registered on SHARP Facts Registry if (!FACTS_REGISTRY.isValid(fact)) { revert InvalidFact(); } } /// @notice Ensures the job output is cryptographically sound to continue from /// @param rightBoundStartParentHash The parent hash of the block to start from /// @param output The job output to check function ensureContinuable( bytes32 rightBoundStartParentHash, JobOutputPacked memory output ) internal view { (uint256 mmrPreviousSize, ) = output.mmrSizesPacked.split128(); // Check that the job's previous Poseidon MMR root is the same as the one stored in the contract state if (output.mmrPreviousRootPoseidon != aggregatorState.poseidonMmrRoot) revert AggregationError("Poseidon root mismatch"); // Check that the job's previous Keccak MMR root is the same as the one stored in the contract state if (output.mmrPreviousRootKeccak != aggregatorState.keccakMmrRoot) revert AggregationError("Keccak root mismatch"); // Check that the job's previous MMR size is the same as the one stored in the contract state if (mmrPreviousSize != aggregatorState.mmrSize) revert AggregationError("MMR size mismatch"); if (rightBoundStartParentHash == bytes32(0)) { // If the right bound start parent hash __is not__ specified, // we check that the job's `blockN + 1 parent hash` is matching with the previously stored parent hash if ( output.blockNPlusOneParentHash != aggregatorState.continuableParentHash ) { revert AggregationError("Global state: Parent hash mismatch"); } } else { // If the right bound start parent hash __is__ specified, // we check that the job's `blockN + 1 parent hash` is matching with a previously stored parent hash if (output.blockNPlusOneParentHash != rightBoundStartParentHash) { revert AggregationError("Parent hash mismatch"); } } } /// @notice Ensures the job outputs are correctly linked /// @param output The job output to check /// @param nextOutput The next job output to check function ensureConsecutiveJobs( JobOutputPacked memory output, JobOutputPacked memory nextOutput ) internal pure { (, uint256 toBlock) = output.blockNumbersPacked.split128(); // We cannot aggregate further past the genesis block if (toBlock == 0) { revert GenesisBlockReached(); } (uint256 nextFromBlock, ) = nextOutput.blockNumbersPacked.split128(); // We check that the next job's `from block` is the same as the previous job's `to block + 1` if (toBlock - 1 != nextFromBlock) revert AggregationBlockMismatch(); (, uint256 outputMmrNewSize) = output.mmrSizesPacked.split128(); (uint256 nextOutputMmrPreviousSize, ) = nextOutput .mmrSizesPacked .split128(); // We check that the previous job's new Poseidon MMR root matches the next job's previous Poseidon MMR root if (output.mmrNewRootPoseidon != nextOutput.mmrPreviousRootPoseidon) revert AggregationError("Poseidon root mismatch"); // We check that the previous job's new Keccak MMR root matches the next job's previous Keccak MMR root if (output.mmrNewRootKeccak != nextOutput.mmrPreviousRootKeccak) revert AggregationError("Keccak root mismatch"); // We check that the previous job's new MMR size matches the next job's previous MMR size if (outputMmrNewSize != nextOutputMmrPreviousSize) revert AggregationError("MMR size mismatch"); // We check that the previous job's lowest block hash matches the next job's highest block hash if ( output.blockNMinusRPlusOneParentHash != nextOutput.blockNPlusOneParentHash ) revert AggregationError("Parent hash mismatch"); } /// @dev Helper function to verify a fact based on a job output function verifyFact(uint256[] memory outputs) external view returns (bool) { bytes32 outputHash = keccak256(abi.encodePacked(outputs)); bytes32 fact = keccak256(abi.encode(PROGRAM_HASH, outputHash)); return FACTS_REGISTRY.isValid(fact); } /// @notice Returns the current root hash of the Keccak Merkle Mountain Range (MMR) tree function getMMRKeccakRoot() external view returns (bytes32) { return aggregatorState.keccakMmrRoot; } /// @notice Returns the current root hash of the Poseidon Merkle Mountain Range (MMR) tree function getMMRPoseidonRoot() external view returns (bytes32) { return aggregatorState.poseidonMmrRoot; } /// @notice Returns the current size of the Merkle Mountain Range (MMR) trees function getMMRSize() external view returns (uint256) { return aggregatorState.mmrSize; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @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] * ```solidity * 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. */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev The contract is already initialized. */ error AlreadyInitialized(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @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; if (!(isTopLevelCall && _initialized < 1) && !(address(this).code.length == 0 && _initialized == 1)) { revert AlreadyInitialized(); } _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) { if (_initializing || _initialized >= version) { revert AlreadyInitialized(); } _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() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_initializing) { revert NotInitializing(); } } /** * @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 { if (_initializing) { revert AlreadyInitialized(); } 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.9.0) (access/AccessControl.sol) pragma solidity ^0.8.20; import { IAccessControlUpgradeable } from "./IAccessControlUpgradeable.sol"; import { ContextUpgradeable } from "../utils/ContextUpgradeable.sol"; import { ERC165Upgradeable } from "../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: * * ```solidity * 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}: * * ```solidity * 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. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ 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 an {AccessControlUnauthorizedAccount} error including the required role. */ 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 returns (bool) { return _roles[role].members[account]; } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` * is missing `role`. */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert AccessControlUnauthorizedAccount(account, role); } } /** * @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 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 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 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 `callerConfirmation`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address callerConfirmation) public virtual { if (callerConfirmation != _msgSender()) { revert AccessControlBadConfirmation(); } _revokeRole(role, callerConfirmation); } /** * @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 Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual returns (bool) { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); return true; } else { return false; } } /** * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); return true; } else { return false; } } /** * @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 pragma solidity ^0.8.0; interface IFactsRegistry { function isValid(bytes32 fact) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library Uint256Splitter { uint256 constant _MASK = type(uint128).max; /// @notice Splits a uint256 into two uint128s (low, high) represented as uint256s. /// @param a The uint256 to split. function split128( uint256 a ) internal pure returns (uint256 lower, uint256 upper) { return (a & _MASK, a >> 128); } /// @notice Merges two uint128s (low, high) into one uint256. /// @param lower The lower uint256. The caller is required to pass a value that is less than 2^128 - 1. /// @param upper The upper uint256. function merge128( uint256 lower, uint256 upper ) internal pure returns (uint256 a) { require(lower <= _MASK, "Uint256Splitter: lower exceeds uint128"); // return (upper << 128) | lower; assembly { a := or(shl(128, upper), lower) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControlUpgradeable { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @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. */ 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 `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.20; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import { IERC165Upgradeable } from "./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); * } * ``` */ 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 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 v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @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); }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/" ], "optimizer": { "enabled": true, "runs": 20000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
[{"inputs":[{"internalType":"contract IFactsRegistry","name":"factsRegistry","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"AggregationBlockMismatch","type":"error"},{"inputs":[{"internalType":"string","name":"message","type":"string"}],"name":"AggregationError","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"GenesisBlockReached","type":"error"},{"inputs":[],"name":"InvalidFact","type":"error"},{"inputs":[],"name":"NotEnoughBlockConfirmations","type":"error"},{"inputs":[],"name":"NotEnoughJobs","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"TooManyBlocksConfirmations","type":"error"},{"inputs":[],"name":"UnknownParentHash","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fromBlockNumberHigh","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toBlockNumberLow","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"poseidonMmrRoot","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"keccakMmrRoot","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"mmrSize","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"continuableParentHash","type":"bytes32"}],"name":"Aggregate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"targetBlock","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"targetBlockParentHash","type":"bytes32"}],"name":"NewRangeRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"newRequirement","type":"bool"}],"name":"OperatorRequirementChange","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"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FACTS_REGISTRY","outputs":[{"internalType":"contract IFactsRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAXIMUM_BLOCKS_CONFIRMATIONS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINIMUM_BLOCKS_CONFIRMATIONS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPERATOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROGRAM_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNLOCKER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"rightBoundStartBlock","type":"uint256"},{"components":[{"internalType":"uint256","name":"blockNumbersPacked","type":"uint256"},{"internalType":"bytes32","name":"blockNPlusOneParentHash","type":"bytes32"},{"internalType":"bytes32","name":"blockNMinusRPlusOneParentHash","type":"bytes32"},{"internalType":"bytes32","name":"mmrPreviousRootPoseidon","type":"bytes32"},{"internalType":"bytes32","name":"mmrPreviousRootKeccak","type":"bytes32"},{"internalType":"bytes32","name":"mmrNewRootPoseidon","type":"bytes32"},{"internalType":"bytes32","name":"mmrNewRootKeccak","type":"bytes32"},{"internalType":"uint256","name":"mmrSizesPacked","type":"uint256"}],"internalType":"struct SharpFactsAggregator.JobOutputPacked[]","name":"outputs","type":"tuple[]"}],"name":"aggregateSharpJobs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"aggregatorState","outputs":[{"internalType":"bytes32","name":"poseidonMmrRoot","type":"bytes32"},{"internalType":"bytes32","name":"keccakMmrRoot","type":"bytes32"},{"internalType":"uint256","name":"mmrSize","type":"uint256"},{"internalType":"bytes32","name":"continuableParentHash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"blockNumberToParentHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMMRKeccakRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMMRPoseidonRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMMRSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[{"components":[{"internalType":"bytes32","name":"poseidonMmrRoot","type":"bytes32"},{"internalType":"bytes32","name":"keccakMmrRoot","type":"bytes32"},{"internalType":"uint256","name":"mmrSize","type":"uint256"},{"internalType":"bytes32","name":"continuableParentHash","type":"bytes32"}],"internalType":"struct SharpFactsAggregator.AggregatorState","name":"initialAggregatorState","type":"tuple"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isOperatorRequired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blocksConfirmations","type":"uint256"}],"name":"registerNewRange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","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":"bool","name":"_isOperatorRequired","type":"bool"}],"name":"setOperatorRequired","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":[{"internalType":"uint256[]","name":"outputs","type":"uint256[]"}],"name":"verifyFact","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.