Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
DataProcessorModule
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.20;
import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import {IFactsRegistry} from "src/interfaces/external/IFactsRegistry.sol";
import {ISatellite} from "src/interfaces/ISatellite.sol";
import {LibSatellite} from "src/libraries/LibSatellite.sol";
import {ModuleTask, ModuleCodecs} from "src/libraries/internal/data-processor/ModuleCodecs.sol";
import {IDataProcessorModule} from "src/interfaces/modules/IDataProcessorModule.sol";
import {AccessController} from "src/libraries/AccessController.sol";
/// @title DataProcessorModule
/// @author Herodotus Dev Ltd
/// @notice A contract to store the execution results of HDP tasks
contract DataProcessorModule is IDataProcessorModule, AccessController {
// ========================= Types ========================= //
using MerkleProof for bytes32[];
using ModuleCodecs for ModuleTask;
// ========================= Constants ========================= //
bytes32 constant POSEIDON_HASHING_FUNCTION = keccak256("poseidon");
// ========================= Satellite Module Storage ========================= //
bytes32 constant MODULE_STORAGE_POSITION = keccak256("diamond.standard.satellite.module.storage.data-processor");
function moduleStorage() internal pure returns (DataProcessorModuleStorage storage s) {
bytes32 position = MODULE_STORAGE_POSITION;
assembly {
s.slot := position
}
}
// ========================= Owner-only Functions ========================= //
/// @inheritdoc IDataProcessorModule
function setDataProcessorProgramHash(bytes32 programHash) external onlyOwner {
DataProcessorModuleStorage storage ms = moduleStorage();
ms.authorizedProgramHashes[programHash] = true;
emit ProgramHashEnabled(programHash);
}
/// @inheritdoc IDataProcessorModule
function disableProgramHashes(bytes32[] calldata programHashes) external onlyOwner {
DataProcessorModuleStorage storage ms = moduleStorage();
for (uint256 i = 0; i < programHashes.length; i++) {
ms.authorizedProgramHashes[programHashes[i]] = false;
}
emit ProgramHashesDisabled(programHashes);
}
/// @inheritdoc IDataProcessorModule
function setDataProcessorFactsRegistry(IFactsRegistry factsRegistry) external onlyOwner {
DataProcessorModuleStorage storage ms = moduleStorage();
ms.factsRegistry = factsRegistry;
}
// ========================= Core Functions ========================= //
/// @inheritdoc IDataProcessorModule
function requestDataProcessorExecutionOfTask(ModuleTask calldata moduleTask) external {
DataProcessorModuleStorage storage ms = moduleStorage();
bytes32 taskCommitment = moduleTask.commit();
if (ms.cachedTasksResult[taskCommitment].status == TaskStatus.FINALIZED) {
emit TaskAlreadyStored(taskCommitment);
} else {
// Ensure task is not already scheduled
if (ms.cachedTasksResult[taskCommitment].status != TaskStatus.NONE) {
revert DoubleRegistration();
}
// Store the task result
ms.cachedTasksResult[taskCommitment] = TaskResult({status: TaskStatus.SCHEDULED, result: ""});
emit ModuleTaskScheduled(moduleTask);
}
}
/// @inheritdoc IDataProcessorModule
function authenticateDataProcessorTaskExecution(TaskData calldata taskData) external {
DataProcessorModuleStorage storage ms = moduleStorage();
bytes32 taskHash = bytes32((taskData.taskHashHigh << 128) | taskData.taskHashLow);
if (ms.cachedTasksResult[taskHash].status == TaskStatus.FINALIZED) {
revert TaskAlreadyFinalized();
}
if (!isProgramHashAuthorized(taskData.programHash)) {
revert UnauthorizedProgramHash();
}
// Initialize an array of uint256 to store the program output
uint256[] memory programOutput = new uint256[](4 + taskData.mmrData.length * 4);
// Assign values to the program output array
// This needs to be compatible with cairo program
// https://github.com/HerodotusDev/hdp-cairo/blob/main/src/utils/utils.cairo#L27-L48
programOutput[0] = taskData.taskHashLow;
programOutput[1] = taskData.taskHashHigh;
programOutput[2] = taskData.taskResultLow;
programOutput[3] = taskData.taskResultHigh;
for (uint8 i = 0; i < taskData.mmrData.length; i++) {
MmrData memory mmr = taskData.mmrData[i];
bytes32 usedMmrRoot = loadMmrRoot(mmr.mmrId, mmr.mmrSize, mmr.chainId);
if (usedMmrRoot == bytes32(0)) {
revert InvalidMmrRoot();
}
programOutput[4 + i * 4] = mmr.mmrId;
programOutput[4 + i * 4 + 1] = mmr.mmrSize;
programOutput[4 + i * 4 + 2] = mmr.chainId;
programOutput[4 + i * 4 + 3] = uint256(usedMmrRoot);
}
// Compute program output hash
bytes32 programOutputHash = keccak256(abi.encodePacked(programOutput));
// Compute GPS fact hash
bytes32 gpsFactHash = keccak256(abi.encode(taskData.programHash, programOutputHash));
// Ensure GPS fact is registered
if (!ms.factsRegistry.isValid(gpsFactHash)) {
revert InvalidFact();
}
bytes32 taskResult = bytes32((taskData.taskResultHigh << 128) | taskData.taskResultLow);
// Store the task result
ms.cachedTasksResult[taskHash] = TaskResult({status: TaskStatus.FINALIZED, result: taskResult});
emit TaskFinalized(taskHash, taskResult);
}
// ========================= View Functions ========================= //
/// @inheritdoc IDataProcessorModule
function getDataProcessorFactsRegistry() external view returns (address) {
DataProcessorModuleStorage storage ms = moduleStorage();
return address(ms.factsRegistry);
}
/// @inheritdoc IDataProcessorModule
function getDataProcessorFinalizedTaskResult(bytes32 taskCommitment) external view returns (bytes32) {
DataProcessorModuleStorage storage ms = moduleStorage();
// Ensure task is finalized
if (ms.cachedTasksResult[taskCommitment].status != TaskStatus.FINALIZED) {
revert NotFinalized();
}
return ms.cachedTasksResult[taskCommitment].result;
}
/// @inheritdoc IDataProcessorModule
function getDataProcessorTaskStatus(bytes32 taskCommitment) external view returns (TaskStatus) {
DataProcessorModuleStorage storage ms = moduleStorage();
return ms.cachedTasksResult[taskCommitment].status;
}
/// @inheritdoc IDataProcessorModule
function isProgramHashAuthorized(bytes32 programHash) public view returns (bool) {
DataProcessorModuleStorage storage ms = moduleStorage();
return ms.authorizedProgramHashes[programHash];
}
// ========================= Internal Functions ========================= //
/// @notice Load MMR root from cache with given mmrId and mmrSize
function loadMmrRoot(uint256 mmrId, uint256 mmrSize, uint256 chainId) internal view returns (bytes32) {
ISatellite.SatelliteStorage storage s = LibSatellite.satelliteStorage();
return s.mmrs[chainId][mmrId][POSEIDON_HASHING_FUNCTION].mmrSizeToRoot[mmrSize];
}
/// @notice Returns the leaf of standard merkle tree
function standardEvmHDPLeafHash(bytes32 value) internal pure returns (bytes32) {
bytes32 firstHash = keccak256(abi.encode(value));
bytes32 leaf = keccak256(abi.encode(firstHash));
return leaf;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/Hashes.sol)
pragma solidity ^0.8.20;
/**
* @dev Library of standard hash functions.
*
* _Available since v5.1._
*/
library Hashes {
/**
* @dev Commutative Keccak256 hash of a sorted pair of bytes32. Frequently used when working with merkle proofs.
*
* NOTE: Equivalent to the `standardNodeHash` in our https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
*/
function commutativeKeccak256(bytes32 a, bytes32 b) internal pure returns (bytes32) {
return a < b ? _efficientKeccak256(a, b) : _efficientKeccak256(b, a);
}
/**
* @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory.
*/
function _efficientKeccak256(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
assembly ("memory-safe") {
mstore(0x00, a)
mstore(0x20, b)
value := keccak256(0x00, 0x40)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/MerkleProof.sol)
// This file was procedurally generated from scripts/generate/templates/MerkleProof.js.
pragma solidity ^0.8.20;
import {Hashes} from "./Hashes.sol";
/**
* @dev These functions deal with verification of Merkle Tree proofs.
*
* The tree and the proofs can be generated using our
* https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
* You will find a quickstart guide in the readme.
*
* WARNING: You should avoid using leaf values that are 64 bytes long prior to
* hashing, or use a hash function other than keccak256 for hashing leaves.
* This is because the concatenation of a sorted pair of internal nodes in
* the Merkle tree could be reinterpreted as a leaf value.
* OpenZeppelin's JavaScript library generates Merkle trees that are safe
* against this attack out of the box.
*
* IMPORTANT: Consider memory side-effects when using custom hashing functions
* that access memory in an unsafe way.
*
* NOTE: This library supports proof verification for merkle trees built using
* custom _commutative_ hashing functions (i.e. `H(a, b) == H(b, a)`). Proving
* leaf inclusion in trees built using non-commutative hashing functions requires
* additional logic that is not supported by this library.
*/
library MerkleProof {
/**
*@dev The multiproof provided is not valid.
*/
error MerkleProofInvalidMultiproof();
/**
* @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
* defined by `root`. For this, a `proof` must be provided, containing
* sibling hashes on the branch from the leaf to the root of the tree. Each
* pair of leaves and each pair of pre-images are assumed to be sorted.
*
* This version handles proofs in memory with the default hashing function.
*/
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
return processProof(proof, leaf) == root;
}
/**
* @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
* from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
* hash matches the root of the tree. When processing the proof, the pairs
* of leaves & pre-images are assumed to be sorted.
*
* This version handles proofs in memory with the default hashing function.
*/
function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = Hashes.commutativeKeccak256(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
* defined by `root`. For this, a `proof` must be provided, containing
* sibling hashes on the branch from the leaf to the root of the tree. Each
* pair of leaves and each pair of pre-images are assumed to be sorted.
*
* This version handles proofs in memory with a custom hashing function.
*/
function verify(
bytes32[] memory proof,
bytes32 root,
bytes32 leaf,
function(bytes32, bytes32) view returns (bytes32) hasher
) internal view returns (bool) {
return processProof(proof, leaf, hasher) == root;
}
/**
* @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
* from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
* hash matches the root of the tree. When processing the proof, the pairs
* of leaves & pre-images are assumed to be sorted.
*
* This version handles proofs in memory with a custom hashing function.
*/
function processProof(
bytes32[] memory proof,
bytes32 leaf,
function(bytes32, bytes32) view returns (bytes32) hasher
) internal view returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = hasher(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
* defined by `root`. For this, a `proof` must be provided, containing
* sibling hashes on the branch from the leaf to the root of the tree. Each
* pair of leaves and each pair of pre-images are assumed to be sorted.
*
* This version handles proofs in calldata with the default hashing function.
*/
function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
return processProofCalldata(proof, leaf) == root;
}
/**
* @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
* from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
* hash matches the root of the tree. When processing the proof, the pairs
* of leaves & pre-images are assumed to be sorted.
*
* This version handles proofs in calldata with the default hashing function.
*/
function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = Hashes.commutativeKeccak256(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
* defined by `root`. For this, a `proof` must be provided, containing
* sibling hashes on the branch from the leaf to the root of the tree. Each
* pair of leaves and each pair of pre-images are assumed to be sorted.
*
* This version handles proofs in calldata with a custom hashing function.
*/
function verifyCalldata(
bytes32[] calldata proof,
bytes32 root,
bytes32 leaf,
function(bytes32, bytes32) view returns (bytes32) hasher
) internal view returns (bool) {
return processProofCalldata(proof, leaf, hasher) == root;
}
/**
* @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
* from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
* hash matches the root of the tree. When processing the proof, the pairs
* of leaves & pre-images are assumed to be sorted.
*
* This version handles proofs in calldata with a custom hashing function.
*/
function processProofCalldata(
bytes32[] calldata proof,
bytes32 leaf,
function(bytes32, bytes32) view returns (bytes32) hasher
) internal view returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = hasher(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
* `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
*
* This version handles multiproofs in memory with the default hashing function.
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*
* NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
* The `leaves` must be validated independently. See {processMultiProof}.
*/
function multiProofVerify(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProof(proof, proofFlags, leaves) == root;
}
/**
* @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
* proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
* leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
* respectively.
*
* This version handles multiproofs in memory with the default hashing function.
*
* CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
* is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
* tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
*
* NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,
* and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not
* validating the leaves elsewhere.
*/
function processMultiProof(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the Merkle tree.
uint256 leavesLen = leaves.length;
uint256 proofFlagsLen = proofFlags.length;
// Check proof validity.
if (leavesLen + proof.length != proofFlagsLen + 1) {
revert MerkleProofInvalidMultiproof();
}
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](proofFlagsLen);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < proofFlagsLen; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = Hashes.commutativeKeccak256(a, b);
}
if (proofFlagsLen > 0) {
if (proofPos != proof.length) {
revert MerkleProofInvalidMultiproof();
}
unchecked {
return hashes[proofFlagsLen - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
/**
* @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
* `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
*
* This version handles multiproofs in memory with a custom hashing function.
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*
* NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
* The `leaves` must be validated independently. See {processMultiProof}.
*/
function multiProofVerify(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32 root,
bytes32[] memory leaves,
function(bytes32, bytes32) view returns (bytes32) hasher
) internal view returns (bool) {
return processMultiProof(proof, proofFlags, leaves, hasher) == root;
}
/**
* @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
* proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
* leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
* respectively.
*
* This version handles multiproofs in memory with a custom hashing function.
*
* CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
* is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
* tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
*
* NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,
* and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not
* validating the leaves elsewhere.
*/
function processMultiProof(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32[] memory leaves,
function(bytes32, bytes32) view returns (bytes32) hasher
) internal view returns (bytes32 merkleRoot) {
// This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the Merkle tree.
uint256 leavesLen = leaves.length;
uint256 proofFlagsLen = proofFlags.length;
// Check proof validity.
if (leavesLen + proof.length != proofFlagsLen + 1) {
revert MerkleProofInvalidMultiproof();
}
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](proofFlagsLen);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < proofFlagsLen; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = hasher(a, b);
}
if (proofFlagsLen > 0) {
if (proofPos != proof.length) {
revert MerkleProofInvalidMultiproof();
}
unchecked {
return hashes[proofFlagsLen - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
/**
* @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
* `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
*
* This version handles multiproofs in calldata with the default hashing function.
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*
* NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
* The `leaves` must be validated independently. See {processMultiProofCalldata}.
*/
function multiProofVerifyCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProofCalldata(proof, proofFlags, leaves) == root;
}
/**
* @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
* proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
* leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
* respectively.
*
* This version handles multiproofs in calldata with the default hashing function.
*
* CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
* is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
* tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
*
* NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,
* and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not
* validating the leaves elsewhere.
*/
function processMultiProofCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the Merkle tree.
uint256 leavesLen = leaves.length;
uint256 proofFlagsLen = proofFlags.length;
// Check proof validity.
if (leavesLen + proof.length != proofFlagsLen + 1) {
revert MerkleProofInvalidMultiproof();
}
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](proofFlagsLen);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < proofFlagsLen; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = Hashes.commutativeKeccak256(a, b);
}
if (proofFlagsLen > 0) {
if (proofPos != proof.length) {
revert MerkleProofInvalidMultiproof();
}
unchecked {
return hashes[proofFlagsLen - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
/**
* @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
* `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
*
* This version handles multiproofs in calldata with a custom hashing function.
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*
* NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
* The `leaves` must be validated independently. See {processMultiProofCalldata}.
*/
function multiProofVerifyCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32 root,
bytes32[] memory leaves,
function(bytes32, bytes32) view returns (bytes32) hasher
) internal view returns (bool) {
return processMultiProofCalldata(proof, proofFlags, leaves, hasher) == root;
}
/**
* @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
* proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
* leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
* respectively.
*
* This version handles multiproofs in calldata with a custom hashing function.
*
* CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
* is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
* tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
*
* NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,
* and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not
* validating the leaves elsewhere.
*/
function processMultiProofCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32[] memory leaves,
function(bytes32, bytes32) view returns (bytes32) hasher
) internal view returns (bytes32 merkleRoot) {
// This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the Merkle tree.
uint256 leavesLen = leaves.length;
uint256 proofFlagsLen = proofFlags.length;
// Check proof validity.
if (leavesLen + proof.length != proofFlagsLen + 1) {
revert MerkleProofInvalidMultiproof();
}
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](proofFlagsLen);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < proofFlagsLen; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = hasher(a, b);
}
if (proofFlagsLen > 0) {
if (proofPos != proof.length) {
revert MerkleProofInvalidMultiproof();
}
unchecked {
return hashes[proofFlagsLen - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.17;
import "./StatelessMmrHelpers.sol";
/// _____ _ _ _ _ _ __ __ __ __ _____
/// / ____| | (_) | (_) | | \/ | \/ | __ \
/// | (___ ___ | |_ __| |_| |_ _ _ | \ / | \ / | |__) |
/// \___ \ / _ \| | |/ _` | | __| | | | | |\/| | |\/| | _ /
/// ____) | (_) | | | (_| | | |_| |_| | | | | | | | | | \ \
/// |_____/ \___/|_|_|\__,_|_|\__|\__, | |_| |_|_| |_|_| \_\
/// __/ |
/// |___/
///
/// @title StatelessMmr -- A Solidity implementation of Merkle Mountain Range
/// @author Herodotus Ltd
/// @notice Library for appending bytes32 values (i.e., acting as an accumulator)
/// and verifying Merkle inclusion proofs
///
library StatelessMmr {
error InvalidProof();
error IndexOutOfBounds();
error InvalidRoot();
error InvalidPeaksArrayLength();
///
/// @notice Append a new element to the MMR
/// @param elem Element to append
/// @param peaks The latest peaks
/// @param lastElementsCount The latest elements count
/// @param lastRoot The latest root
/// @return The updated elements count and the new root hash of the tree
///
function append(
bytes32 elem,
bytes32[] memory peaks,
uint lastElementsCount,
bytes32 lastRoot
) internal pure returns (uint, bytes32) {
(uint updatedElementsCount, bytes32 newRoot, ) = doAppend(
elem,
peaks,
lastElementsCount,
lastRoot
);
return (updatedElementsCount, newRoot);
}
///
/// Same as `append` but also returns the updated peaks
///
function appendWithPeaksRetrieval(
bytes32 elem,
bytes32[] memory peaks,
uint lastElementsCount,
bytes32 lastRoot
) internal pure returns (uint, bytes32, bytes32[] memory) {
(
uint updatedElementsCount,
bytes32 newRoot,
bytes32[] memory updatedPeaks
) = doAppend(elem, peaks, lastElementsCount, lastRoot);
return (updatedElementsCount, newRoot, updatedPeaks);
}
///
/// @param elems Elements to append (in order)
/// @param peaks The latest peaks
/// @param lastElementsCount The latest elements count
/// @param lastRoot The latest tree root hash
/// @return The newest elements count and the newest tree root hash
///
function multiAppend(
bytes32[] memory elems,
bytes32[] memory peaks,
uint lastElementsCount,
bytes32 lastRoot
) internal pure returns (uint, bytes32) {
uint elementsCount = lastElementsCount;
bytes32 root = lastRoot;
bytes32[] memory updatedPeaks = peaks;
for (uint i = 0; i < elems.length; ++i) {
(elementsCount, root, updatedPeaks) = appendWithPeaksRetrieval(
elems[i],
updatedPeaks,
elementsCount,
root
);
}
return (elementsCount, root);
}
///
/// Same as `multiAppend` but also returns the updated peaks
///
function multiAppendWithPeaksRetrieval(
bytes32[] memory elems,
bytes32[] memory peaks,
uint lastElementsCount,
bytes32 lastRoot
) internal pure returns (uint, bytes32, bytes32[] memory) {
uint elementsCount = lastElementsCount;
bytes32 root = lastRoot;
bytes32[] memory updatedPeaks = peaks;
for (uint i = 0; i < elems.length; ++i) {
(elementsCount, root, updatedPeaks) = appendWithPeaksRetrieval(
elems[i],
updatedPeaks,
elementsCount,
root
);
}
return (elementsCount, root, updatedPeaks);
}
///
/// @notice Efficient version of `multiAppend` that takes in all the precomputed peaks
/// @param elems Elements to append (in order)
/// @param allPeaks All the precomputed peaks computed off-chain (more gas efficient)
/// @param lastElementsCount The latest elements count
/// @param lastRoot The latest tree root hash
/// @return The newest elements count and the newest tree root hash
///
function multiAppendWithPrecomputedPeaks(
bytes32[] memory elems,
bytes32[][] memory allPeaks,
uint lastElementsCount,
bytes32 lastRoot
) internal pure returns (uint, bytes32) {
uint elementsCount = lastElementsCount;
bytes32 root = lastRoot;
for (uint i = 0; i < elems.length; ++i) {
(elementsCount, root) = append(
elems[i],
allPeaks[i],
elementsCount,
root
);
}
return (elementsCount, root);
}
///
/// @notice Verify a Merkle inclusion proof
/// @dev Reverts if the proof is invalid
/// @param proof The Merkle inclusion proof
/// @param peaks The peaks at the time of inclusion
/// @param elementsCount The element count at the time of inclusion
/// @param root The tree root hash at the time of inclusion
///
function verifyProof(
uint index,
bytes32 value,
bytes32[] memory proof,
bytes32[] memory peaks,
uint elementsCount,
bytes32 root
) internal pure {
if (index > elementsCount) {
revert IndexOutOfBounds();
}
bytes32 computedRoot = computeRoot(peaks, bytes32(elementsCount));
if (computedRoot != root) {
revert InvalidRoot();
}
bytes32 topPeak = getProofTopPeak(0, value, index, proof);
bool isValid = StatelessMmrHelpers.arrayContains(topPeak, peaks);
if (!isValid) {
revert InvalidProof();
}
}
/// _ _ _ ______ _ _
/// | | | | | | | ____| | | (_)
/// | |__| | ___| |_ __ ___ _ __ | |__ _ _ _ __ ___| |_ _ ___ _ __ ___
/// | __ |/ _ \ | '_ \ / _ \ '__| | __| | | | '_ \ / __| __| |/ _ \| '_ \/ __|
/// | | | | __/ | |_) | __/ | | | | |_| | | | | (__| |_| | (_) | | | \__ \
/// |_| |_|\___|_| .__/ \___|_| |_| \__,_|_| |_|\___|\__|_|\___/|_| |_|___/
/// | |
/// |_|
///
/// @notice Computes the root hash of the given peaks and tree size
/// @param peaks Peaks to compute the root from
/// @param size Tree size to to compute the root from
/// @return The root hash of the following peaks and tree size
///
function computeRoot(
bytes32[] memory peaks,
bytes32 size
) internal pure returns (bytes32) {
bytes32 baggedPeaks = bagPeaks(peaks);
return keccak256(abi.encode(size, baggedPeaks));
}
///
/// @notice Bag the peaks: recursively hashing peaks together to form a single hash
/// @param peaks The peaks to bag
/// @return The bagged peaks
///
function bagPeaks(bytes32[] memory peaks) internal pure returns (bytes32) {
if (peaks.length < 1) {
revert InvalidPeaksArrayLength();
}
if (peaks.length == 1) {
return peaks[0];
}
uint len = peaks.length;
bytes32 root0 = keccak256(abi.encode(peaks[len - 2], peaks[len - 1]));
bytes32[] memory reversedPeaks = new bytes32[](len - 2);
for (uint i = 0; i < len - 2; i++) {
reversedPeaks[i] = peaks[len - 3 - i];
}
bytes32 bags = root0;
for (uint i = 0; i < reversedPeaks.length; i++) {
bags = keccak256(abi.encode(reversedPeaks[i], bags));
}
return bags;
}
function doAppend(
bytes32 elem,
bytes32[] memory peaks,
uint lastElementsCount,
bytes32 lastRoot
) internal pure returns (uint, bytes32, bytes32[] memory) {
uint elementsCount = lastElementsCount + 1;
if (lastElementsCount == 0) {
bytes32 root0 = elem;
bytes32 firstRoot = keccak256(abi.encode(uint(1), root0));
bytes32[] memory newPeaks = new bytes32[](1);
newPeaks[0] = root0;
return (elementsCount, firstRoot, newPeaks);
}
uint leafCount = StatelessMmrHelpers.mmrSizeToLeafCount(
elementsCount - 1
);
uint numberOfPeaks = StatelessMmrHelpers.countOnes(leafCount);
if (peaks.length != numberOfPeaks) {
revert InvalidPeaksArrayLength();
}
bytes32 computedRoot = computeRoot(peaks, bytes32(lastElementsCount));
if (computedRoot != lastRoot) {
revert InvalidRoot();
}
bytes32[] memory appendPeaks = StatelessMmrHelpers.newArrWithElem(
peaks,
elem
);
uint appendNoMerges = StatelessMmrHelpers.leafCountToAppendNoMerges(leafCount);
bytes32[] memory updatedPeaks = appendPerformMerging(
appendPeaks,
appendNoMerges
);
uint updatedElementsCount = elementsCount + appendNoMerges;
bytes32 newRoot = computeRoot(
updatedPeaks,
bytes32(updatedElementsCount)
);
return (updatedElementsCount, newRoot, updatedPeaks);
}
function appendPerformMerging(
bytes32[] memory peaks,
uint noMerges
) internal pure returns (bytes32[] memory) {
uint peaksLen = peaks.length;
bytes32 accHash = peaks[peaksLen - 1];
for (uint i = 0; i < noMerges; i++) {
bytes32 hash = peaks[peaksLen - i - 2];
accHash = keccak256(abi.encode(hash, accHash));
}
bytes32[] memory newPeaks = new bytes32[](peaksLen - noMerges);
for (uint i = 0; i < peaksLen - noMerges - 1; i++) {
newPeaks[i] = peaks[i];
}
newPeaks[peaksLen - noMerges - 1] = accHash;
return newPeaks;
}
function getProofTopPeak(
uint height,
bytes32 hash,
uint elementsCount,
bytes32[] memory proof
) internal pure returns (bytes32) {
uint leafIndex = StatelessMmrHelpers.mmrIndexToLeafIndex(elementsCount);
for (uint i = 0; i < proof.length; ++i) {
bytes32 currentSibling = proof[i];
bool isRightChild = leafIndex % 2 == 1;
if (isRightChild) {
bytes32 hashed = keccak256(abi.encode(currentSibling, hash));
elementsCount += 1;
hash = hashed;
} else {
bytes32 hashed = keccak256(abi.encode(hash, currentSibling));
elementsCount += 2 << height;
hash = hashed;
}
++height;
leafIndex /= 2;
}
return hash;
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.17;
library StatelessMmrHelpers {
// Returns the height of a given `index`. The height of the root is 0
function getHeight(uint index) internal pure returns (uint) {
require(index >= 1, "index must be at least 1");
uint bits = bitLength(index);
uint ones = allOnes(bits);
if (index != ones) {
uint shifted = 1 << (bits - 1);
uint recHeight = getHeight(index - (shifted - 1));
return recHeight;
}
return bits - 1;
}
// Returns the number of bits in `num`
function bitLength(uint256 num) internal pure returns (uint256) {
require(num >= 0, "num must be greater than or equal to zero");
uint256 bitPosition = 0;
uint256 curN = 1;
while (num >= curN) {
bitPosition += 1;
curN <<= 1;
}
return bitPosition;
}
// Returns a number having all its bits set to 1 for a given `bitsLength`
function allOnes(uint256 bitsLength) internal pure returns (uint256) {
require(bitsLength >= 0, "bitsLength must be greater or equal to zero");
return (1 << bitsLength) - 1;
}
// Returns a number of ones in bit representation of a number
function countOnes(uint256 num) internal pure returns (uint256) {
uint256 count = 0;
for (; num > 0; count++) {
num = num & (num - 1);
}
return count;
}
// Returns the sibling offset from `height`
function siblingOffset(uint256 height) internal pure returns (uint256) {
return (2 << height) - 1;
}
// Returns the parent offset from `height`
function parentOffset(uint256 height) internal pure returns (uint256) {
return 2 << height;
}
// Returns number of leaves for a given mmr size
function mmrSizeToLeafCount(uint256 mmrSize) internal pure returns (uint256) {
uint256 leafCount = 0;
uint256 mountainLeafCount = 1 << bitLength(mmrSize);
for(; mountainLeafCount > 0; mountainLeafCount /= 2) {
uint256 mountainSize = 2 * mountainLeafCount - 1;
if (mountainSize <= mmrSize) {
leafCount += mountainLeafCount;
mmrSize -= mountainSize;
}
}
require(mmrSize == 0, "mmrSize can't be associated with a valid MMR size");
return leafCount;
}
// Returns leaf index (0-based) for a given mmr (element) index
function mmrIndexToLeafIndex(uint256 mmrIndex) internal pure returns (uint256) {
return mmrSizeToLeafCount(mmrIndex - 1);
}
function leafCountToAppendNoMerges(uint256 leafCount) internal pure returns (uint256) {
uint256 count = 0;
while(leafCount > 0 && (leafCount & 1) == 1) {
count += 1;
leafCount /= 2;
}
return count;
}
// Creates a new array from source and returns a new one containing all previous elements + `elem`
function newArrWithElem(
bytes32[] memory sourceArr,
bytes32 elem
) internal pure returns (bytes32[] memory) {
bytes32[] memory outputArray = new bytes32[](sourceArr.length + 1);
uint i = 0;
for (; i < sourceArr.length; i++) {
outputArray[i] = sourceArr[i];
}
outputArray[i] = elem;
return outputArray;
}
// Returns true if `elem` is in `arr`
function arrayContains(
bytes32 elem,
bytes32[] memory arr
) internal pure returns (bool) {
for (uint i = 0; i < arr.length; ++i) {
if (arr[i] == elem) {
return true;
}
}
return false;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
library console {
address constant CONSOLE_ADDRESS =
0x000000000000000000636F6e736F6c652e6c6f67;
function _sendLogPayloadImplementation(bytes memory payload) internal view {
address consoleAddress = CONSOLE_ADDRESS;
/// @solidity memory-safe-assembly
assembly {
pop(
staticcall(
gas(),
consoleAddress,
add(payload, 32),
mload(payload),
0,
0
)
)
}
}
function _castToPure(
function(bytes memory) internal view fnIn
) internal pure returns (function(bytes memory) pure fnOut) {
assembly {
fnOut := fnIn
}
}
function _sendLogPayload(bytes memory payload) internal pure {
_castToPure(_sendLogPayloadImplementation)(payload);
}
function log() internal pure {
_sendLogPayload(abi.encodeWithSignature("log()"));
}
function logInt(int256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
}
function logUint(uint256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function logString(string memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function logBool(bool p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function logAddress(address p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function logBytes(bytes memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
}
function logBytes1(bytes1 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
}
function logBytes2(bytes2 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
}
function logBytes3(bytes3 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
}
function logBytes4(bytes4 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
}
function logBytes5(bytes5 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
}
function logBytes6(bytes6 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
}
function logBytes7(bytes7 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
}
function logBytes8(bytes8 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
}
function logBytes9(bytes9 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
}
function logBytes10(bytes10 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
}
function logBytes11(bytes11 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
}
function logBytes12(bytes12 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
}
function logBytes13(bytes13 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
}
function logBytes14(bytes14 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
}
function logBytes15(bytes15 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
}
function logBytes16(bytes16 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
}
function logBytes17(bytes17 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
}
function logBytes18(bytes18 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
}
function logBytes19(bytes19 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
}
function logBytes20(bytes20 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
}
function logBytes21(bytes21 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
}
function logBytes22(bytes22 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
}
function logBytes23(bytes23 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
}
function logBytes24(bytes24 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
}
function logBytes25(bytes25 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
}
function logBytes26(bytes26 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
}
function logBytes27(bytes27 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
}
function logBytes28(bytes28 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
}
function logBytes29(bytes29 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
}
function logBytes30(bytes30 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
}
function logBytes31(bytes31 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
}
function logBytes32(bytes32 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
}
function log(uint256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function log(int256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
}
function log(string memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function log(bool p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function log(address p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function log(uint256 p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1));
}
function log(uint256 p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1));
}
function log(uint256 p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1));
}
function log(uint256 p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1));
}
function log(string memory p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
}
function log(string memory p0, int256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,int256)", p0, p1));
}
function log(string memory p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
}
function log(string memory p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
}
function log(string memory p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
}
function log(bool p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1));
}
function log(bool p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
}
function log(bool p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
}
function log(bool p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
}
function log(address p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1));
}
function log(address p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
}
function log(address p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
}
function log(address p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
}
function log(uint256 p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2));
}
function log(uint256 p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2));
}
function log(uint256 p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2));
}
function log(uint256 p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2));
}
function log(uint256 p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2));
}
function log(uint256 p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2));
}
function log(uint256 p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2));
}
function log(uint256 p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2));
}
function log(uint256 p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2));
}
function log(string memory p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2));
}
function log(string memory p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
}
function log(string memory p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
}
function log(string memory p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
}
function log(string memory p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2));
}
function log(string memory p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
}
function log(string memory p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
}
function log(string memory p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
}
function log(string memory p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2));
}
function log(string memory p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
}
function log(string memory p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
}
function log(string memory p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
}
function log(bool p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2));
}
function log(bool p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2));
}
function log(bool p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2));
}
function log(bool p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2));
}
function log(bool p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2));
}
function log(bool p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
}
function log(bool p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
}
function log(bool p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
}
function log(bool p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2));
}
function log(bool p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
}
function log(bool p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
}
function log(bool p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
}
function log(bool p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2));
}
function log(bool p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
}
function log(bool p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
}
function log(bool p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
}
function log(address p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2));
}
function log(address p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2));
}
function log(address p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2));
}
function log(address p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2));
}
function log(address p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2));
}
function log(address p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
}
function log(address p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
}
function log(address p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
}
function log(address p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2));
}
function log(address p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
}
function log(address p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
}
function log(address p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
}
function log(address p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2));
}
function log(address p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
}
function log(address p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
}
function log(address p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;
interface IAggregatorsFactory {
error AccessControlBadConfirmation();
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
error ERC1167FailedCreateClone();
event AggregatorCreation(address aggregator, uint256 newAggregatorId, uint256 detachedFromAggregatorId);
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
event Upgrade(address oldTemplate, address newTemplate);
event UpgradeProposal(address newTemplate);
function DEFAULT_ADMIN_ROLE() external view returns (bytes32);
function DELAY() external view returns (uint256);
function KECCAK_MMR_INITIAL_ROOT() external view returns (bytes32);
function OPERATOR_ROLE() external view returns (bytes32);
function POSEIDON_MMR_INITIAL_ROOT() external view returns (bytes32);
function aggregatorsById(uint256) external view returns (address);
function aggregatorsCount() external view returns (uint256);
function createAggregator(uint256 aggregatorId) external returns (address);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function hasRole(bytes32 role, address account) external view returns (bool);
function proposeUpgrade(address newTemplate) external;
function renounceRole(bytes32 role, address callerConfirmation) external;
function revokeRole(bytes32 role, address account) external;
function supportsInterface(bytes4 interfaceId) external view returns (bool);
function template() external view returns (address);
function upgrade(uint256 updateId) external;
function upgrades(uint256) external view returns (uint256 timestamp, address newTemplate);
function upgradesCount() external view returns (uint256);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
interface IFactsRegistry {
function isValid(bytes32 fact) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IStarknet {
function stateBlockNumber() external view returns (int256);
function stateBlockHash() external view returns (uint256);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
/// @notice This is IMMUTABLE! without re-deploying the whole Satellite Diamond!
interface ILibSatellite {
// ========================= Types ========================= //
struct Module {
address moduleAddress;
bytes4[] functionSelectors;
}
struct ModuleAddressAndPosition {
address moduleAddress;
uint96 functionSelectorPosition; // position in moduleFunctionSelectors.functionSelectors array
}
struct ModuleFunctionSelectors {
bytes4[] functionSelectors;
uint256 moduleAddressPosition; // position of moduleAddress in moduleAddresses array
}
/// @dev Add=0, Replace=1, Remove=2
enum ModuleMaintenanceAction {
Add,
Replace,
Remove
}
struct ModuleMaintenance {
address moduleAddress;
ModuleMaintenanceAction action;
bytes4[] functionSelectors;
}
/// @notice This struct represents a Merkle Mountain Range accumulating provably valid block hashes
/// @dev each MMR is mapped to a unique ID also referred to as mmrId
struct MmrInfo {
/// @notice isSiblingSynced informs if the MMR has it's siblings (MMRs with different hash functions) and has to be grown in sync with them - used when growing off-chain and growing multiple hash functions at once, for example, this could be a keccak MMR sibling synced to a poseidon MMR
bool isSiblingSynced;
/// @notice latestSize represents the latest size of the MMR
uint256 latestSize;
/// @notice mmrSizeToRoot maps the MMR size => the MMR root, that way we have automatic versioning
mapping(uint256 => bytes32) mmrSizeToRoot;
}
struct SatelliteConnection {
/// @notice satelliteAddress is the address of the satellite deployed on the destination chain
/// @dev it is uint256 because Starknet addresses must fit
uint256 satelliteAddress;
/// @notice inboxAddress is the address of the contract that sends messages from our chain to the chain of the satellite
address inboxAddress;
/// @notice sendMessageSelector is the selector of the satellite's function that sends message to the destination chain
bytes4 sendMessageSelector;
}
struct SatelliteStorage {
// ========================= Diamond-related storage ========================= //
/// @dev maps function selector to the module address and the position of the selector in the moduleFunctionSelectors.selectors array
mapping(bytes4 => ModuleAddressAndPosition) selectorToModuleAndPosition;
/// @dev maps module addresses to function selectors
mapping(address => ModuleFunctionSelectors) moduleFunctionSelectors;
/// @dev module addresses
address[] moduleAddresses;
/// @dev owner of the contract
address contractOwner;
//
// ========================= Core Satellite storage ========================= //
/// @dev mapping of ChainId => MMR ID => hashing function => MMR info
/// @dev hashingFunction is a 32 byte keccak hash of the hashing function name, eg: keccak256("keccak256"), keccak256("poseidon")
mapping(uint256 => mapping(uint256 => mapping(bytes32 => MmrInfo))) mmrs;
/// @notice mapping of ChainId => hashing function => block number => block parent hash
mapping(uint256 => mapping(bytes32 => mapping(uint256 => bytes32))) receivedParentHashes;
//
// ======================= Satellite Registry storage ======================= //
/// @dev mapping of ChainId => SatelliteConnection struct
mapping(uint256 => SatelliteConnection) satelliteConnectionRegistry;
/// @dev set of (aliased) addresses of satellites that can send messages to our chain
mapping(address => bool) senderSatellites;
}
// ========================= Errors ========================= //
/// @notice Error indicating the caller must be a satellite module
error MustBeSatelliteModule();
/// @notice Error indicating the caller must be the contract owner
error MustBeContractOwner();
/// @notice Error indicating the module maintenance action is incorrect
error IncorrectModuleMaintenanceAction(ModuleMaintenanceAction action);
/// @notice Error indicating there are no selectors in the module to maintenance
error NoSelectorsInModuleToMaintenance();
/// @notice Error indicating the module address is zero
error AddModuleAddressZero();
/// @notice Error indicating the function already exists
error AddFunctionAlreadyExists(bytes4 selector);
/// @notice Error indicating the function already exists
error ReplaceFunctionWithSameFunction(bytes4 selector);
/// @notice Error indicating the function does not exist
error RemoveFunctionDoesNotExist();
/// @notice Error indicating the function is immutable and cannot be removed
error RemoveImmutableFunction();
/// @notice Error indicating the init address is zero but calldata is not empty
error InitAddressZeroButCalldataNotEmpty();
/// @notice Error indicating the calldata is empty but init is not address(0)
error CalldataEmptyButInitNotEmpty();
/// @notice Error indicating the init function reverted
error InitFunctionReverted(string errors);
/// @notice Error indicating the address has no code
error AddressHasNoCode(string details);
// ========================= Events ========================= //
/// @notice Event emitted when satellite maintenance occurs
event SatelliteMaintenance(ModuleMaintenance[] _satelliteMaintenance, address _init, bytes _calldata);
/// @notice Event emitted when ownership is transferred
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
import {ILibSatellite} from "./ILibSatellite.sol";
import {IOwnershipModule} from "./modules/IOwnershipModule.sol";
import {ISatelliteConnectionRegistryModule} from "./modules/ISatelliteConnectionRegistryModule.sol";
import {IMmrCoreModule} from "./modules/IMmrCoreModule.sol";
import {ISatelliteInspectorModule} from "./modules/ISatelliteInspectorModule.sol";
import {ISatelliteMaintenanceModule} from "./modules/ISatelliteMaintenanceModule.sol";
import {IEvmSharpMmrGrowingModule} from "./modules/growing/IEvmSharpMmrGrowingModule.sol";
import {IStarknetSharpMmrGrowingModule} from "./modules/growing/IStarknetSharpMmrGrowingModule.sol";
import {IEvmFactRegistryModule} from "./modules/IEvmFactRegistryModule.sol";
import {INativeParentHashFetcherModule} from "./modules/parent-hash-fetching/INativeParentHashFetcherModule.sol";
import {IStarknetParentHashFetcherModule} from "./modules/parent-hash-fetching/IStarknetParentHashFetcherModule.sol";
import {IReceiverModule} from "./modules/messaging/receiver/IReceiverModule.sol";
import {IEvmOnChainGrowingModule} from "./modules/growing/IEvmOnChainGrowingModule.sol";
import {IDataProcessorModule} from "./modules/IDataProcessorModule.sol";
import {IUniversalSenderModule} from "./modules/messaging/sender/IUniversalSenderModule.sol";
import {IL1ToArbitrumSenderModule} from "./modules/messaging/sender/IL1ToArbitrumSenderModule.sol";
import {IL1ToOptimismSenderModule} from "./modules/messaging/sender/IL1ToOptimismSenderModule.sol";
import {IArbitrumToApeChainSenderModule} from "./modules/messaging/sender/IArbitrumToApeChainSenderModule.sol";
import {IL1ToStarknetSenderModule} from "./modules/messaging/sender/IL1ToStarknetSenderModule.sol";
import {ILegacyContractsInteractionModule} from "./modules/growing/ILegacyContractsInteractionModule.sol";
import {IArbitrumParentHashFetcherModule} from "./modules/parent-hash-fetching/IArbitrumParentHashFetcherModule.sol";
interface ISatellite is
ILibSatellite,
IOwnershipModule,
ISatelliteConnectionRegistryModule,
IMmrCoreModule,
ISatelliteInspectorModule,
ISatelliteMaintenanceModule,
IEvmSharpMmrGrowingModule,
IEvmFactRegistryModule,
INativeParentHashFetcherModule,
IEvmOnChainGrowingModule,
IStarknetSharpMmrGrowingModule,
IReceiverModule,
IUniversalSenderModule,
IL1ToArbitrumSenderModule,
IL1ToOptimismSenderModule,
IStarknetParentHashFetcherModule,
IArbitrumParentHashFetcherModule,
IDataProcessorModule,
IArbitrumToApeChainSenderModule,
IL1ToStarknetSenderModule,
ILegacyContractsInteractionModule
{}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
interface IFactsRegistryCommon {
error InvalidFact();
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
import {IFactsRegistryCommon} from "./IFactsRegistryCommon.sol";
interface ISharpMmrGrowingCommon is IFactsRegistryCommon {
// Custom errors for better error handling and clarity
error NotEnoughJobs();
error UnknownParentHash();
error AggregationError(string message); // Generic error with a message
error AggregationBlockMismatch(string message);
error GenesisBlockReached();
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
import {Lib_RLPReader as RLPReader} from "src/libraries/external/optimism/rlp/Lib_RLPReader.sol";
import {StatelessMmr} from "@solidity-mmr/lib/StatelessMmr.sol";
interface IEvmOnChainGrowingModule {
// ========================= Types ========================= //
struct MMRGrowResult {
uint256 firstAppendedBlock;
uint256 lastAppendedBlock;
uint256 newMMRSize;
bytes32 newMMRRoot;
}
// ========================= Functions ========================= //
function onchainEvmAppendBlocksBatch(
uint256 accumulatedChainId,
uint256 mmrId,
bool processFromReceivedBlockHash,
bytes calldata ctx,
bytes[] calldata headersSerialized
) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
import {Uint256Splitter} from "src/libraries/internal/Uint256Splitter.sol";
import {IFactsRegistry} from "src/interfaces/external/IFactsRegistry.sol";
import {ISharpMmrGrowingCommon} from "src/interfaces/modules/common/ISharpMmrGrowingCommon.sol";
interface IEvmSharpMmrGrowingModule is ISharpMmrGrowingCommon {
// Representation of the Cairo program's output (raw unpacked)
struct EvmJobOutput {
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;
}
struct EvmSharpMmrGrowingModuleStorage {
IFactsRegistry factsRegistry;
uint256 aggregatedChainId;
// Cairo program hash calculated with Poseidon (i.e., the off-chain block headers accumulator program)
uint256 programHash;
}
function initEvmSharpMmrGrowingModule() external;
function setEvmSharpMmrGrowingModuleProgramHash(uint256 programHash) external;
function setEvmSharpMmrGrowingModuleFactsRegistry(address factsRegistry) external;
function getEvmSharpMmrGrowingModuleProgramHash() external view returns (uint256);
function getEvmSharpMmrGrowingModuleFactsRegistry() external view returns (address);
function createEvmSharpMmr(uint256 newMmrId, uint256 originalMmrId, uint256 mmrSize) external;
function aggregateEvmSharpJobs(uint256 mmrId, JobOutputPacked[] calldata outputs) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
import {IAggregatorsFactory} from "src/interfaces/external/IAggregatorsFactory.sol";
import {RootForHashingFunction} from "src/interfaces/modules/IMmrCoreModule.sol";
interface ILegacyContractsInteractionModule {
function initLegacyContractsInteractionModule(IAggregatorsFactory aggregatorsFactory) external;
function loadLegacyEvmAggregatorMmr(uint256 legacyMmrId, uint256 newMmrId) external;
struct LegacyContractsInteractionModuleStorage {
IAggregatorsFactory aggregatorsFactory;
uint256 aggregatedChainId;
}
event LegacyEvmAggregatorMmrLoadedV2(
RootForHashingFunction[] rootsForHashingFunctions,
uint256 size,
uint256 newMmrId,
uint256 legacyMmrId,
uint256 aggregatedChainId,
address sharpFactsAggregatorAddress
);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
import {Uint256Splitter} from "src/libraries/internal/Uint256Splitter.sol";
import {IFactsRegistry} from "src/interfaces/external/IFactsRegistry.sol";
import {ISharpMmrGrowingCommon} from "src/interfaces/modules/common/ISharpMmrGrowingCommon.sol";
interface IStarknetSharpMmrGrowingModule is ISharpMmrGrowingCommon {
// Representation of the Cairo program's output
struct StarknetJobOutput {
uint256 fromBlockNumberHigh;
uint256 toBlockNumberLow;
bytes32 blockNPlusOneParentHash;
bytes32 blockNMinusRPlusOneParentHash;
bytes32 mmrPreviousRootPoseidon;
uint256 mmrPreviousSize;
bytes32 mmrNewRootPoseidon;
uint256 mmrNewSize;
}
struct StarknetSharpMmrGrowingModuleStorage {
IFactsRegistry factsRegistry;
// Either Starknet or Starknet Sepolia chain ID
uint256 aggregatedChainId;
// Cairo program hash calculated with Poseidon (i.e., the off-chain block headers accumulator program)
uint256 programHash;
}
function initStarknetSharpMmrGrowingModule(uint256 starknetChainId) external;
function setStarknetSharpMmrGrowingModuleFactsRegistry(address factsRegistry) external;
function setStarknetSharpMmrGrowingModuleProgramHash(uint256 programHash) external;
function getStarknetSharpMmrGrowingModuleFactsRegistry() external view returns (address);
function getStarknetSharpMmrGrowingModuleProgramHash() external view returns (uint256);
function createStarknetSharpMmr(uint256 newMmrId, uint256 originalMmrId, uint256 mmrSize) external;
function aggregateStarknetSharpJobs(uint256 mmrId, StarknetJobOutput[] calldata outputs) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.20;
import {IFactsRegistry} from "src/interfaces/external/IFactsRegistry.sol";
import {ModuleTask} from "src/libraries/internal/data-processor/ModuleCodecs.sol";
import {IFactsRegistryCommon} from "src/interfaces/modules/common/IFactsRegistryCommon.sol";
interface IDataProcessorModule is IFactsRegistryCommon {
/// @notice The status of a task
enum TaskStatus {
NONE,
SCHEDULED,
FINALIZED
}
/// @notice The struct representing a task result
struct TaskResult {
TaskStatus status;
bytes32 result;
}
/// @notice Storage structure for the module
struct DataProcessorModuleStorage {
IFactsRegistry factsRegistry;
mapping(bytes32 => TaskResult) cachedTasksResult;
mapping(bytes32 => bool) authorizedProgramHashes;
}
struct MmrData {
uint256 chainId;
uint256 mmrId;
uint256 mmrSize;
}
/// @param mmrData For each used MMR, its chain ID, ID and size
/// @param taskResultLow The low part of the task result
/// @param taskResultHigh The high part of the task result
/// @param taskHashLow The low part of the task hash
/// @param taskHashHigh The high part of the task hash
/// @param programHash The program hash that was used to compute the task
struct TaskData {
MmrData[] mmrData;
uint256 taskResultLow;
uint256 taskResultHigh;
uint256 taskHashLow;
uint256 taskHashHigh;
bytes32 programHash;
}
/// @notice emitted when a task already stored
event TaskAlreadyStored(bytes32 result);
/// @notice emitted when a new module task is scheduled
event ModuleTaskScheduled(ModuleTask moduleTask);
/// Task is already registered
error DoubleRegistration();
/// Element is not in the batch
error NotInBatch();
/// Task is not finalized
error NotFinalized();
/// Unauthorized or inactive program hash
error UnauthorizedProgramHash();
/// Invalid MMR root
error InvalidMmrRoot();
/// Task is already finalized
error TaskAlreadyFinalized();
/// @notice Emitted when a task is finalized
event TaskFinalized(bytes32 taskHash, bytes32 taskResult);
/// @notice Emitted when a program hash is enabled
event ProgramHashEnabled(bytes32 enabledProgramHash);
/// @notice Emitted when some program hashes are disabled
event ProgramHashesDisabled(bytes32[] disabledProgramHashes);
/// @notice Set the program hash for the HDP program
function setDataProcessorProgramHash(bytes32 programHash) external;
/// @notice Disable some program hashes
function disableProgramHashes(bytes32[] calldata programHashes) external;
/// @notice Set the facts registry contract
function setDataProcessorFactsRegistry(IFactsRegistry factsRegistry) external;
/// @notice Requests the execution of a task with a module
/// @param moduleTask module task
function requestDataProcessorExecutionOfTask(ModuleTask calldata moduleTask) external;
/// @notice Authenticates the execution of a task is finalized
/// by verifying the locally computed fact with the FactsRegistry
/// @param taskData The task data
function authenticateDataProcessorTaskExecution(TaskData calldata taskData) external;
/// @notice Returns address of the facts registry
function getDataProcessorFactsRegistry() external view returns (address);
/// @notice Returns the result of a finalized task
function getDataProcessorFinalizedTaskResult(bytes32 taskCommitment) external view returns (bytes32);
/// @notice Returns the status of a task
function getDataProcessorTaskStatus(bytes32 taskCommitment) external view returns (TaskStatus);
/// @notice Checks if a program hash is currently authorized
function isProgramHashAuthorized(bytes32 programHash) external view returns (bool);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
interface IEvmFactRegistryModule {
struct BlockHeaderProof {
uint256 treeId;
uint128 mmrTreeSize;
uint256 blockNumber;
uint256 blockProofLeafIndex;
bytes32[] mmrPeaks;
bytes32[] mmrElementInclusionProof;
bytes provenBlockHeader;
}
enum AccountField {
NONCE,
BALANCE,
STORAGE_ROOT,
CODE_HASH
}
struct StorageSlot {
bytes32 value;
bool exists;
}
struct Account {
/// @dev Bitmask of saved fields (4 bits)
uint8 savedFields;
mapping(AccountField => bytes32) fields;
}
struct EvmFactRegistryModuleStorage {
/// @dev chain_id => address => block_number => Account
mapping(uint256 => mapping(address => mapping(uint256 => Account))) accountField;
/// @dev chain_id => address => block_number => slot => value
mapping(uint256 => mapping(address => mapping(uint256 => mapping(bytes32 => StorageSlot)))) accountStorageSlotValues;
/// @dev chain_id => timestamp => block_number + 1 (0 means no data)
mapping(uint256 => mapping(uint256 => uint256)) timestampToBlockNumber;
}
// ===================== Functions for End Users ===================== //
/// @notice Returns nonce, balance, storage root or code hash of a given account, at a given block number and chainId
function accountField(uint256 chainId, address account, uint256 blockNumber, AccountField field) external view returns (bytes32);
/// @notice Returns value of a given storage slot of a given account, at a given block number and chainId
function storageSlot(uint256 chainId, address account, uint256 blockNumber, bytes32 slot) external view returns (bytes32);
/// @notice Returns block number of the closest block with timestamp less than or equal to the given timestamp
function timestamp(uint256 chainId, uint256 timestamp) external view returns (uint256);
// ========================= Core Functions ========================= //
/// @notice Stores account fields after verifying the headerProof against saved MMRs
/// @param chainId Chain ID where the account lives
/// @param account Address of the account
/// @param headerProof Header proof of the block that contains the account
/// @param accountTrieProof MPT proof for the account (has to hash to the state root)
function proveAccount(uint256 chainId, address account, uint8 accountFieldsToSave, BlockHeaderProof calldata headerProof, bytes calldata accountTrieProof) external;
/// @notice Stores storage slot value after verifying the storageSlotTrieProof against saved MMRs
/// @notice Account's storage root has to be proven before calling this function
/// @param chainId Chain ID where the queried block lives
/// @param account Address of the account that contains the storage slot
/// @param blockNumber Block number at which the storage slot is stored
/// @param slot Index of the storage slot
/// @param storageSlotTrieProof MPT proof for the storage slot (has to hash to the storage root)
function proveStorage(uint256 chainId, address account, uint256 blockNumber, bytes32 slot, bytes calldata storageSlotTrieProof) external;
/// @notice Stores closest timestamp to a block after verifying header proofs of two consecutive blocks,
/// @notice where the first block is the closest block with timestamp less than or equal to the given timestamp
/// @param chainId Chain ID where the queried block lives
/// @param timestamp Timestamp for which you are looking for the closest block
/// @param headerProof Header proof of the block that is the answer for the given timestamp
/// @param headerProofNext Header proof of the next block
function proveTimestamp(uint256 chainId, uint256 timestamp, BlockHeaderProof calldata headerProof, BlockHeaderProof calldata headerProofNext) external;
// ========================= View functions ========================= //
/// @notice Verifies the headerProof against saved MMRs
/// @param chainId Chain ID where the account lives
/// @param account Address of the account
/// @param headerProof Header proof of the block that contains the account
/// @param accountTrieProof MPT proof for the account (has to hash to the state root)
/// @return nonce
/// @return accountBalance
/// @return codeHash
/// @return storageRoot
function verifyAccount(
uint256 chainId,
address account,
BlockHeaderProof calldata headerProof,
bytes calldata accountTrieProof
) external view returns (uint256 nonce, uint256 accountBalance, bytes32 codeHash, bytes32 storageRoot);
/// @notice Verifies the storageSlotTrieProof against saved MMRs
/// @notice Account's storage root has to be proven before calling this function
/// @param chainId Chain ID where the queried block lives
/// @param account Address of the account that contains the storage slot
/// @param blockNumber Block number at which the storage slot is stored
/// @param slot Index of the storage slot
/// @param storageSlotTrieProof MPT proof for the storage slot (has to hash to the storage root)
/// @return slotValue Value of the storage slot
function verifyStorage(uint256 chainId, address account, uint256 blockNumber, bytes32 slot, bytes calldata storageSlotTrieProof) external view returns (bytes32 slotValue);
/// @notice Verifies header proofs of two consecutive blocks, where the first block is the closest block with timestamp less than or equal to the given timestamp
/// @param chainId Chain ID where the queried block lives
/// @param timestamp Timestamp for which you are looking for the closest block
/// @param headerProof Header proof of the block that is the answer for the given timestamp
/// @param headerProofNext Header proof of the next block
/// @return blockNumber Block number of the closest block with timestamp that is less than or equal to the given timestamp
function verifyTimestamp(uint256 chainId, uint256 timestamp, BlockHeaderProof calldata headerProof, BlockHeaderProof calldata headerProofNext) external view returns (uint256);
// ========================= Events ========================= //
/// @notice Emitted when account fields are proven
event ProvenAccount(uint256 chainId, address account, uint256 blockNumber, uint8 savedFields, uint256 nonce, uint256 balance, bytes32 codeHash, bytes32 storageHash);
/// @notice Emitted when storage slot value is proven
event ProvenStorage(uint256 chainId, address account, uint256 blockNumber, bytes32 slot, bytes32 slotValue);
/// @notice Emitted when timestamp is proven
event ProvenTimestamp(uint256 chainId, uint256 timestamp, uint256 blockNumber);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
import {Lib_RLPReader as RLPReader} from "src/libraries/external/optimism/rlp/Lib_RLPReader.sol";
import {StatelessMmr} from "@solidity-mmr/lib/StatelessMmr.sol";
struct RootForHashingFunction {
bytes32 root;
bytes32 hashingFunction;
}
enum GrownBy {
/// @dev GrownBy.EVM_ON_CHAIN_GROWER - appended by EvmOnChainGrowingModule
EVM_ON_CHAIN_GROWER,
/// @dev GrownBy.EVM_SHARP_GROWER - appended by EvmSharpGrowingModule
EVM_SHARP_GROWER,
/// @dev GrownBy.STARKNET_SHARP_GROWER - appended by StarknetSharpMmrGrowingModule
STARKNET_SHARP_GROWER
}
enum CreatedFrom {
FOREIGN,
DOMESTIC
}
interface IMmrCoreModule {
// ========================= Other Satellite Modules Only Functions ========================= //
/// @notice Receiving a recent parent hash obtained on-chain directly on this chain or sent in a message from another one (eg. L1 -> L2)
/// @dev saves the parent hash of the block number (from a given chain) in the contract storage
function _receiveParentHash(uint256 chainId, bytes32 hashingFunction, uint256 blockNumber, bytes32 parentHash) external;
/// @notice Creates a new branch from message sent from satellite on another chain
/// @param newMmrId the ID of the MMR to create
/// @param rootsForHashingFunctions the roots of the MMR -> ABI encoded hashing function => MMR root
/// @param mmrSize the size of the MMR
/// @param accumulatedChainId the ID of the chain that the MMR accumulates (where block is?)
/// @param originChainId the ID of the chain from which the new MMR will be created (who is sending msg?)
/// @param originalMmrId the ID of the MMR from which the new MMR will be created
/// @param isSiblingSynced whether the MMR is sibling synced
function _createMmrFromForeign(
uint256 newMmrId,
RootForHashingFunction[] calldata rootsForHashingFunctions,
uint256 mmrSize,
uint256 accumulatedChainId,
uint256 originChainId,
uint256 originalMmrId,
bool isSiblingSynced
) external;
// ========================= Core Functions ========================= //
/// @notice Creates a new MMR that is a clone of an already existing MMR or an empty MMR if originalMmrId is 0 (in that case mmrSize is ignored)
/// @param newMmrId the ID of the new MMR
/// @param originalMmrId the ID of the MMR from which the new MMR will be created - if 0 it means an empty MMR will be created
/// @param accumulatedChainId the ID of the chain that the MMR accumulates
/// @param mmrSize size at which the MMR will be copied
/// @param hashingFunctions the hashing functions used in the MMR - if more than one, the MMR will be sibling synced and require being a satellite module to call
function createMmrFromDomestic(uint256 newMmrId, uint256 originalMmrId, uint256 accumulatedChainId, uint256 mmrSize, bytes32[] calldata hashingFunctions) external;
// ========================= View functions ========================= //
function POSEIDON_HASHING_FUNCTION() external view returns (bytes32);
function KECCAK_HASHING_FUNCTION() external view returns (bytes32);
function POSEIDON_MMR_INITIAL_ROOT() external view returns (bytes32);
function KECCAK_MMR_INITIAL_ROOT() external view returns (bytes32);
function getMmrRoot(uint256 mmrId, uint256 mmrSize, uint256 accumulatedChainId, bytes32 hashingFunction) external view returns (bytes32);
function getLatestMmrRoot(uint256 mmrId, uint256 accumulatedChainId, bytes32 hashingFunction) external view returns (bytes32);
function getLatestMmrSize(uint256 mmrId, uint256 accumulatedChainId, bytes32 hashingFunction) external view returns (uint256);
function getReceivedParentHash(uint256 chainId, bytes32 hashingFunction, uint256 blockNumber) external view returns (bytes32);
// ========================= Events ========================= //
/// @notice emitted when a block hash is received
/// @param chainId the ID of the chain that the block hash is from
/// @param blockNumber the block number
/// @param parentHash the parent hash of the block number
/// @param hashingFunction the hashing function use to hash the block, e.g. Keccak on Ethereum and Poseidon on Starknet
/// @dev hashingFunction is a 32 byte keccak hash of the hashing function name, eg: keccak256("keccak256"), keccak256("poseidon")
event ReceivedParentHash(uint256 chainId, uint256 blockNumber, bytes32 parentHash, bytes32 hashingFunction);
/// @notice emitted when a new MMR is created from a domestic or foreign source
/// @notice - foreign source - sent from another chain, or off-chain computation proven on-chain
/// @notice - domestic source - created from another MMR on the same chain, or a standalone new empty MMR
/// @param newMmrId the ID of the new MMR
/// @param mmrSize the size of the MMR
/// @param accumulatedChainId the ID of the chain that the MMR accumulates
/// @param originalMmrId the ID of the MMR from which the new MMR is created - if 0, it means an new empty MMR was created
/// @param rootsForHashingFunctions list of pairs (mmrRoot, hashingFunction) representing mmr roots for each hashing function
/// @dev every hashingFunction should occur at most once in the list
/// @dev hashingFunction is a 32 byte keccak hash of the hashing function name, eg: keccak256("keccak256"), keccak256("poseidon")
/// @param originChainId the ID of the chain from which the new MMR comes from
/// @dev if originChainId equal to accumulatedChainId, it means the MMR is created from domestic source, otherwise it is created from foreign source
/// @param createdFrom enum representing the source of the MMR creation - DOMESTIC or FOREIGN
event CreatedMmr(
uint256 newMmrId,
uint256 mmrSize,
uint256 accumulatedChainId,
uint256 originalMmrId,
RootForHashingFunction[] rootsForHashingFunctions,
uint256 originChainId,
CreatedFrom createdFrom
);
/// @notice emitted when a batch of blocks is appended to the MMR
/// @param firstAppendedBlock the block number of the first block appended
/// @param lastAppendedBlock the block number of the last block appended
/// @param rootsForHashingFunctions list of pairs (mmrRoot, hashingFunction) representing mmr roots for each hashing function
/// @dev every hashingFunction should occur at most once in the list
/// @param mmrSize the size of the MMR after the batch of blocks is appended
/// @param mmrId the ID of the MMR that was grown
/// @param accumulatedChainId the ID of the chain that the MMR accumulates
/// @param grownBy enum representing which growing module appended blocks to MMR
event GrownMmr(
uint256 firstAppendedBlock,
uint256 lastAppendedBlock,
RootForHashingFunction[] rootsForHashingFunctions,
uint256 mmrSize,
uint256 mmrId,
uint256 accumulatedChainId,
GrownBy grownBy
);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
/// @title ERC-173 Contract Ownership Standard
/// Note: the ERC-165 identifier for this interface is 0x7f5828d0
/* is ERC165 */
interface IOwnershipModule {
/// @notice Get the address of the owner
/// @return owner_ The address of the owner.
function owner() external view returns (address owner_);
/// @notice Set the address of the new owner of the contract
/// @dev Set _newOwner to address(0) to renounce any ownership.
/// @param _newOwner The address of the new owner of the contract
function transferOwnership(address _newOwner) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
import {ILibSatellite} from "src/interfaces/ILibSatellite.sol";
interface ISatelliteConnectionRegistryModule {
/// @param chainId - chain id of other side of the connection
/// @param satellite - address of the satellite deployed on `chainId`
/// @param inbox - address of the contract deployed on our chain responsible for sending message to `chainId`
/// @dev message can be sent to `chainId` if and only if `inbox` is set to non-zero address
/// @param senderSatelliteAlias - (aliased) address of the satellite deployed on `chainId` that sends message to our chain
/// @dev message can be received from `chainId` if and only if `senderSatelliteAlias` is set to non-zero address
/// @param sendMessageSelector - selector of the function responsible for sending message to `chainId`, this function should be part of `messaging/sender/*.sol`
function registerSatelliteConnection(uint256 chainId, uint256 satellite, address inbox, address senderSatelliteAlias, bytes4 sendMessageSelector) external;
/// @param chainId - chain id of other side of the connection
/// @param senderSatelliteAlias - (aliased) address of the satellite deployed on `chainId` that sends message to our chain
/// @dev `senderSatelliteAlias` should be the same as the one used when registering the connection
function removeSatelliteConnection(uint256 chainId, address senderSatelliteAlias) external;
/// @param chainId - chain id of other side of the connection
/// @return SatelliteConnection struct, which contains the satellite address, inbox address, and sendMessageSelector
function getSatelliteConnection(uint256 chainId) external view returns (ILibSatellite.SatelliteConnection memory);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
import {ILibSatellite} from "src/interfaces/ILibSatellite.sol";
interface ISatelliteInspectorModule {
/// @notice Gets all module addresses and their four byte function selectors.
/// @return modules_ Modules
function modules() external view returns (ILibSatellite.Module[] memory modules_);
/// @notice Gets all the function selectors supported by a specific module.
/// @param _module The module address.
/// @return moduleFunctionSelectors_
function moduleFunctionSelectors(address _module) external view returns (bytes4[] memory moduleFunctionSelectors_);
/// @notice Get all the module addresses used by a satellite.
/// @return moduleAddresses_
function moduleAddresses() external view returns (address[] memory moduleAddresses_);
/// @notice Gets the module that supports the given selector.
/// @dev If module is not found return address(0).
/// @param _functionSelector The function selector.
/// @return moduleAddress_ The module address.
function moduleAddress(bytes4 _functionSelector) external view returns (address moduleAddress_);
// Facet versions for compatibility
function facets() external view returns (ILibSatellite.Module[] memory facets_);
function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory facetFunctionSelectors_);
function facetAddresses() external view returns (address[] memory facetAddresses_);
function facetAddress(bytes4 _functionSelector) external view returns (address facetAddress_);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
import {ILibSatellite} from "src/interfaces/ILibSatellite.sol";
interface ISatelliteMaintenanceModule {
/// @notice Add/replace/remove any number of functions and optionally exemaintenancee
/// a function with delegatecall
/// @param _satelliteMaintenance Contains the module addresses and function selectors
/// @param _init The address of the contract or module to exemaintenancee _calldata
/// @param _calldata A function call, including function selector and arguments
/// _calldata is exemaintenanceed with delegatecall on _init
function satelliteMaintenance(ILibSatellite.ModuleMaintenance[] calldata _satelliteMaintenance, address _init, bytes calldata _calldata) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
import {RootForHashingFunction} from "src/interfaces/modules/IMmrCoreModule.sol";
/// @notice Receives messages from satellites deployed on other chains
interface IReceiverModule {
function receiveParentHash(uint256 chainId, bytes32 hashingFunction, uint256 blockNumber, bytes32 parentHash) external;
function receiveMmr(
uint256 newMmrId,
RootForHashingFunction[] calldata rootsForHashingFunctions,
uint256 mmrSize,
uint256 accumulatedChainId,
uint256 originChainId,
uint256 originalMmrId,
bool isSiblingSynced
) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
interface IArbitrumToApeChainSenderModule {
/// @notice Storage structure for the module
struct ArbitrumToApeChainSenderModuleStorage {
address apeChainTokenAddress;
}
/// @notice Set the address of the ApeChain token
/// @param tokenAddress the address of the native token in https://docs.apechain.com/contracts/Testnet/contract-information#chaininfo
function setApeChainTokenAddress(address tokenAddress) external;
/// @notice Send message from Arbitrum to ApeChain
/// @param satelliteAddress the address of the satellite on ApeChain
/// @param inboxAddress the address of the ApeChain Inbox
/// @dev inboxAddress - Inbox in https://docs.apechain.com/contracts/Testnet/contract-information#corecontracts
function sendMessageArbitrumToApeChain(uint256 satelliteAddress, address inboxAddress, bytes memory _data, bytes memory _xDomainMsgGasData) external payable;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
interface IL1ToArbitrumSenderModule {
/// @notice Send message from L1 to Arbitrum
/// @param satelliteAddress the address of the satellite on Arbitrum
/// @param inboxAddress the address of the Arbitrum Inbox
/// @dev inboxAddress - Delayed Inbox in https://docs.arbitrum.io/build-decentralized-apps/reference/contract-addresses
function sendMessageL1ToArbitrum(uint256 satelliteAddress, address inboxAddress, bytes memory _data, bytes memory _xDomainMsgGasData) external payable;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
interface IL1ToOptimismSenderModule {
/// @notice Send message from L1 to Arbitrum
/// @param satelliteAddress the address of the satellite on Arbitrum
/// @param inboxAddress the address of the Arbitrum Inbox
/// @dev inboxAddress - L1CrossDomainMessengerProxy in https://docs.optimism.io/chain/addresses
function sendMessageL1ToOptimism(uint256 satelliteAddress, address inboxAddress, bytes memory _data, bytes memory _xDomainMsgGasData) external payable;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
interface IL1ToStarknetSenderModule {
/// @notice Send message from L1 to Starknet
/// @param satelliteAddress the address of the satellite on Starknet
/// @param inboxAddress the address of the Starknet Core
function sendMessageL1ToStarknet(uint256 satelliteAddress, address inboxAddress, bytes memory _data, bytes memory _xDomainMsgGasData) external payable;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
/// @notice Interface for the sender module that can send messages to any chain registered in Satellite Connection Registry
interface IUniversalSenderModule {
/// @notice Send parent hash that was registered on our chain to the destination chain
/// @param destinationChainId the chain ID of the destination chain
/// @param accumulatedChainId the chain ID of the block that is being sent
/// @param hashingFunction the hashing function used to hash the parent hash
/// @param blockNumber the block number being sent
/// @param _xDomainMsgGasData the gas data for the cross-domain message, depends on the destination chain
function sendParentHash(
uint256 destinationChainId,
uint256 accumulatedChainId,
bytes32 hashingFunction,
uint256 blockNumber,
bytes calldata _xDomainMsgGasData
) external payable;
/// @notice Send MMR that was registered on our chain to the destination chain
/// @param destinationChainId the chain ID of the destination chain
/// @param accumulatedChainId the chain ID of the block that is being sent
/// @param originalMmrId the ID of the original MMR
/// @param newMmrId the ID of the new MMR
/// @param hashingFunctions the hashing functions used to hash the MMR
/// @param isSiblingSyncedForSending if true, MMR will be required to be sibling synced and all hashing functions must be sent;
/// if false, MMRs will be sent with sibling synced set to false (all hashing functions will be sent)
/// @param _xDomainMsgGasData the gas data for the cross-domain message, depends on the destination chain
function sendMmr(
uint256 destinationChainId,
uint256 accumulatedChainId,
uint256 originalMmrId,
uint256 newMmrId,
bytes32[] calldata hashingFunctions,
bool isSiblingSyncedForSending,
bytes calldata _xDomainMsgGasData
) external payable;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
interface IERC20Outbox {
function roots(bytes32 input) external view returns (bytes32);
}
/// @notice Module that fetches the parent hash of blocks from Arbitrum
/// @dev It needs to be deployed on the chain that Arbitrum settles on (L1)
interface IArbitrumParentHashFetcherModule {
struct ArbitrumParentHashFetcherModuleStorage {
IERC20Outbox outboxContract;
// Chain ID of blocks being fetched
uint256 chainId;
}
function initArbitrumParentHashFetcherModule(address outboxAddress, uint256 chainId) external;
function arbitrumFetchParentHash(bytes32 rootHash, bytes memory blockHeader) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
/// @notice Module that fetches the parent hash of blocks from the chain it's deployed on
interface INativeParentHashFetcherModule {
/// @notice Fetches the parent hash of a given block
function nativeFetchParentHash(uint256 blockNumber) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
import {IStarknet} from "src/interfaces/external/IStarknet.sol";
/// @notice Module that fetches the parent hash of blocks from Starknet
/// @dev It needs to be deployed on the chain that Starknet settles on (L1)
interface IStarknetParentHashFetcherModule {
struct StarknetParentHashFetcherModuleStorage {
IStarknet starknetContract;
// Either Starknet or Starknet Sepolia chain ID
uint256 chainId;
}
function initStarknetParentHashFetcherModule(IStarknet starknetContract, uint256 chainId) external;
/// @notice Fetches the parent hash of the latest block
function starknetFetchParentHash() external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.20;
import {LibSatellite} from "src/libraries/LibSatellite.sol";
abstract contract AccessController {
modifier onlyModule() {
LibSatellite.enforceIsSatelliteModule();
_;
}
modifier onlyOwner() {
LibSatellite.enforceIsContractOwner();
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity >0.5.0;
/**
* @title Lib_RLPReader
* @dev Adapted from "RLPReader" by Hamdi Allam (hamdi.allam97@gmail.com).
*/
library Lib_RLPReader {
/**
*
* Constants *
*
*/
uint256 internal constant MAX_LIST_LENGTH = 32;
/**
*
* Enums *
*
*/
enum RLPItemType {
DATA_ITEM,
LIST_ITEM
}
/**
*
* Structs *
*
*/
struct RLPItem {
uint256 length;
uint256 ptr;
}
/**
*
* Internal Functions *
*
*/
/**
* Converts bytes to a reference to memory position and length.
* @param _in Input bytes to convert.
* @return Output memory reference.
*/
function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory) {
uint256 ptr;
assembly {
ptr := add(_in, 32)
}
return RLPItem({length: _in.length, ptr: ptr});
}
/**
* Reads an RLP list value into a list of RLP items.
* @param _in RLP list value.
* @return Decoded RLP list items.
*/
function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory) {
(uint256 listOffset, , RLPItemType itemType) = _decodeLength(_in);
require(itemType == RLPItemType.LIST_ITEM, "Invalid RLP list value.");
// Solidity in-memory arrays can't be increased in size, but *can* be decreased in size by
// writing to the length. Since we can't know the number of RLP items without looping over
// the entire input, we'd have to loop twice to accurately size this array. It's easier to
// simply set a reasonable maximum list length and decrease the size before we finish.
RLPItem[] memory out = new RLPItem[](MAX_LIST_LENGTH);
uint256 itemCount = 0;
uint256 offset = listOffset;
while (offset < _in.length) {
require(itemCount < MAX_LIST_LENGTH, "Provided RLP list exceeds max list length.");
(uint256 itemOffset, uint256 itemLength, ) = _decodeLength(RLPItem({length: _in.length - offset, ptr: _in.ptr + offset}));
out[itemCount] = RLPItem({length: itemLength + itemOffset, ptr: _in.ptr + offset});
itemCount += 1;
offset += itemOffset + itemLength;
}
// Decrease the array size to match the actual item count.
assembly {
mstore(out, itemCount)
}
return out;
}
/**
* Reads an RLP list value into a list of RLP items.
* @param _in RLP list value.
* @return Decoded RLP list items.
*/
function readList(bytes memory _in) internal pure returns (RLPItem[] memory) {
return readList(toRLPItem(_in));
}
/**
* Reads an RLP bytes value into bytes.
* @param _in RLP bytes value.
* @return Decoded bytes.
*/
function readBytes(RLPItem memory _in) internal pure returns (bytes memory) {
(uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in);
require(itemType == RLPItemType.DATA_ITEM, "Invalid RLP bytes value.");
return _copy(_in.ptr, itemOffset, itemLength);
}
/**
* Reads an RLP bytes value into bytes.
* @param _in RLP bytes value.
* @return Decoded bytes.
*/
function readBytes(bytes memory _in) internal pure returns (bytes memory) {
return readBytes(toRLPItem(_in));
}
/**
* Reads an RLP string value into a string.
* @param _in RLP string value.
* @return Decoded string.
*/
function readString(RLPItem memory _in) internal pure returns (string memory) {
return string(readBytes(_in));
}
/**
* Reads an RLP string value into a string.
* @param _in RLP string value.
* @return Decoded string.
*/
function readString(bytes memory _in) internal pure returns (string memory) {
return readString(toRLPItem(_in));
}
/**
* Reads an RLP bytes32 value into a bytes32.
* @param _in RLP bytes32 value.
* @return Decoded bytes32.
*/
function readBytes32(RLPItem memory _in) internal pure returns (bytes32) {
require(_in.length <= 33, "Invalid RLP bytes32 value.");
(uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in);
require(itemType == RLPItemType.DATA_ITEM, "Invalid RLP bytes32 value.");
uint256 ptr = _in.ptr + itemOffset;
bytes32 out;
assembly {
out := mload(ptr)
// Shift the bytes over to match the item size.
if lt(itemLength, 32) {
out := div(out, exp(256, sub(32, itemLength)))
}
}
return out;
}
/**
* Reads an RLP bytes32 value into a bytes32.
* @param _in RLP bytes32 value.
* @return Decoded bytes32.
*/
function readBytes32(bytes memory _in) internal pure returns (bytes32) {
return readBytes32(toRLPItem(_in));
}
/**
* Reads an RLP uint256 value into a uint256.
* @param _in RLP uint256 value.
* @return Decoded uint256.
*/
function readUint256(RLPItem memory _in) internal pure returns (uint256) {
return uint256(readBytes32(_in));
}
/**
* Reads an RLP uint256 value into a uint256.
* @param _in RLP uint256 value.
* @return Decoded uint256.
*/
function readUint256(bytes memory _in) internal pure returns (uint256) {
return readUint256(toRLPItem(_in));
}
/**
* Reads an RLP bool value into a bool.
* @param _in RLP bool value.
* @return Decoded bool.
*/
function readBool(RLPItem memory _in) internal pure returns (bool) {
require(_in.length == 1, "Invalid RLP boolean value.");
uint256 ptr = _in.ptr;
uint256 out;
assembly {
out := byte(0, mload(ptr))
}
require(out == 0 || out == 1, "Lib_RLPReader: Invalid RLP boolean value, must be 0 or 1");
return out != 0;
}
/**
* Reads an RLP bool value into a bool.
* @param _in RLP bool value.
* @return Decoded bool.
*/
function readBool(bytes memory _in) internal pure returns (bool) {
return readBool(toRLPItem(_in));
}
/**
* Reads an RLP address value into a address.
* @param _in RLP address value.
* @return Decoded address.
*/
function readAddress(RLPItem memory _in) internal pure returns (address) {
if (_in.length == 1) {
return address(0);
}
require(_in.length == 21, "Invalid RLP address value.");
return address(uint160(readUint256(_in)));
}
/**
* Reads an RLP address value into a address.
* @param _in RLP address value.
* @return Decoded address.
*/
function readAddress(bytes memory _in) internal pure returns (address) {
return readAddress(toRLPItem(_in));
}
/**
* Reads the raw bytes of an RLP item.
* @param _in RLP item to read.
* @return Raw RLP bytes.
*/
function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory) {
return _copy(_in);
}
/**
*
* Private Functions *
*
*/
/**
* Decodes the length of an RLP item.
* @param _in RLP item to decode.
* @return Offset of the encoded data.
* @return Length of the encoded data.
* @return RLP item type (LIST_ITEM or DATA_ITEM).
*/
function _decodeLength(RLPItem memory _in) private pure returns (uint256, uint256, RLPItemType) {
unchecked {
require(_in.length > 0, "RLP item cannot be null.");
uint256 ptr = _in.ptr;
uint256 prefix;
assembly {
prefix := byte(0, mload(ptr))
}
if (prefix <= 0x7f) {
// Single byte.
return (0, 1, RLPItemType.DATA_ITEM);
} else if (prefix <= 0xb7) {
// Short string.
uint256 strLen = prefix - 0x80;
require(_in.length > strLen, "Invalid RLP short string.");
return (1, strLen, RLPItemType.DATA_ITEM);
} else if (prefix <= 0xbf) {
// Long string.
uint256 lenOfStrLen = prefix - 0xb7;
require(_in.length > lenOfStrLen, "Invalid RLP long string length.");
uint256 strLen;
assembly {
// Pick out the string length.
strLen := div(mload(add(ptr, 1)), exp(256, sub(32, lenOfStrLen)))
}
require(_in.length > lenOfStrLen + strLen, "Invalid RLP long string.");
return (1 + lenOfStrLen, strLen, RLPItemType.DATA_ITEM);
} else if (prefix <= 0xf7) {
// Short list.
uint256 listLen = prefix - 0xc0;
require(_in.length > listLen, "Invalid RLP short list.");
return (1, listLen, RLPItemType.LIST_ITEM);
} else {
// Long list.
uint256 lenOfListLen = prefix - 0xf7;
require(_in.length > lenOfListLen, "Invalid RLP long list length.");
uint256 listLen;
assembly {
// Pick out the list length.
listLen := div(mload(add(ptr, 1)), exp(256, sub(32, lenOfListLen)))
}
require(_in.length > lenOfListLen + listLen, "Invalid RLP long list.");
return (1 + lenOfListLen, listLen, RLPItemType.LIST_ITEM);
}
}
}
/**
* Copies the bytes from a memory location.
* @param _src Pointer to the location to read from.
* @param _offset Offset to start reading from.
* @param _length Number of bytes to read.
* @return Copied bytes.
*/
function _copy(uint256 _src, uint256 _offset, uint256 _length) private pure returns (bytes memory) {
unchecked {
bytes memory out = new bytes(_length);
if (out.length == 0) {
return out;
}
uint256 src = _src + _offset;
uint256 dest;
assembly {
dest := add(out, 32)
}
// Copy over as many complete words as we can.
for (uint256 i = 0; i < _length / 32; i++) {
assembly {
mstore(dest, mload(src))
}
src += 32;
dest += 32;
}
// Pick out the remaining bytes.
uint256 mask = 256 ** (32 - (_length % 32)) - 1;
assembly {
mstore(dest, or(and(mload(src), not(mask)), and(mload(dest), mask)))
}
return out;
}
}
/**
* Copies an RLP item into bytes.
* @param _in RLP item to copy.
* @return Copied bytes.
*/
function _copy(RLPItem memory _in) private pure returns (bytes memory) {
return _copy(_in.ptr, 0, _in.length);
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.20;
import {TaskCode} from "./Task.sol";
/// @dev A module task.
/// @param programHash The program hash of the module.
/// @param inputs The inputs to the module.
struct ModuleTask {
bytes32 programHash;
bytes32[] inputs;
}
/// @notice Codecs for ModuleTask.
/// @dev Represent module with a program hash and inputs.
library ModuleCodecs {
/// @dev Get the commitment of a Module.
/// @param module The Module to commit.
function commit(ModuleTask memory module) internal pure returns (bytes32) {
return keccak256(abi.encode(module.programHash, module.inputs));
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.20;
/// @notice Task type.
enum TaskCode {
// Datalake,
Module
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.27;
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: GPL-3.0
pragma solidity ^0.8.27;
import {console} from "forge-std/console.sol";
import {ISatellite} from "src/interfaces/ISatellite.sol";
import {ILibSatellite} from "src/interfaces/ILibSatellite.sol";
library LibSatellite {
// ========================= Constants ========================= //
/// @notice non existent MMR size
uint256 constant NO_MMR_SIZE = 0;
/// @notice non existent MMR root
bytes32 constant NO_MMR_ROOT = 0;
/// @notice non existent MMR id
uint256 constant EMPTY_MMR_ID = 0;
/// @notice empty MMR size
uint256 constant EMPTY_MMR_SIZE = 1;
/// @notice diamond storage position
bytes32 constant DIAMOND_STORAGE_POSITION = keccak256("diamond.standard.satellite.storage");
function satelliteStorage() internal pure returns (ILibSatellite.SatelliteStorage storage s) {
bytes32 position = DIAMOND_STORAGE_POSITION;
assembly {
s.slot := position
}
}
function setContractOwner(address _newOwner) internal {
ILibSatellite.SatelliteStorage storage s = satelliteStorage();
address previousOwner = s.contractOwner;
s.contractOwner = _newOwner;
emit ILibSatellite.OwnershipTransferred(previousOwner, _newOwner);
}
function contractOwner() internal view returns (address contractOwner_) {
contractOwner_ = satelliteStorage().contractOwner;
}
function enforceIsContractOwner() internal view {
if (msg.sender != satelliteStorage().contractOwner) {
revert ILibSatellite.MustBeContractOwner();
}
}
function enforceIsSatelliteModule() internal view {
if (msg.sender != address(this)) {
revert ILibSatellite.MustBeSatelliteModule();
}
}
modifier onlySatelliteModule() {
enforceIsSatelliteModule();
_;
}
event SatelliteMaintenance(ILibSatellite.ModuleMaintenance[] _satelliteMaintenance, address _init, bytes _calldata);
function satelliteMaintenance(ILibSatellite.ModuleMaintenance[] memory _satelliteMaintenance, address _init, bytes memory _calldata) internal {
for (uint256 moduleIndex; moduleIndex < _satelliteMaintenance.length; moduleIndex++) {
ILibSatellite.ModuleMaintenance memory moduleMaintenance = _satelliteMaintenance[moduleIndex];
ILibSatellite.ModuleMaintenanceAction action = moduleMaintenance.action;
if (action == ILibSatellite.ModuleMaintenanceAction.Add) {
addFunctions(moduleMaintenance.moduleAddress, moduleMaintenance.functionSelectors);
} else if (action == ILibSatellite.ModuleMaintenanceAction.Replace) {
replaceFunctions(moduleMaintenance.moduleAddress, moduleMaintenance.functionSelectors);
} else if (action == ILibSatellite.ModuleMaintenanceAction.Remove) {
removeFunctions(moduleMaintenance.moduleAddress, moduleMaintenance.functionSelectors);
} else {
revert ILibSatellite.IncorrectModuleMaintenanceAction(action);
}
}
emit SatelliteMaintenance(_satelliteMaintenance, _init, _calldata);
initializeSatelliteMaintenance(_init, _calldata);
}
function addFunctions(address _moduleAddress, bytes4[] memory _functionSelectors) internal {
if (_functionSelectors.length == 0) {
revert ILibSatellite.NoSelectorsInModuleToMaintenance();
}
if (_moduleAddress == address(0)) {
revert ILibSatellite.AddModuleAddressZero();
}
ILibSatellite.SatelliteStorage storage s = satelliteStorage();
uint96 selectorPosition = uint96(s.moduleFunctionSelectors[_moduleAddress].functionSelectors.length);
/// @dev add new module address if it does not exist
if (selectorPosition == 0) {
addModule(s, _moduleAddress);
}
for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
bytes4 selector = _functionSelectors[selectorIndex];
address oldModuleAddress = s.selectorToModuleAndPosition[selector].moduleAddress;
if (oldModuleAddress != address(0)) {
revert ILibSatellite.AddFunctionAlreadyExists(selector);
}
addFunction(s, selector, selectorPosition, _moduleAddress);
selectorPosition++;
}
}
function replaceFunctions(address _moduleAddress, bytes4[] memory _functionSelectors) internal {
if (_functionSelectors.length == 0) {
revert ILibSatellite.NoSelectorsInModuleToMaintenance();
}
if (_moduleAddress == address(0)) {
revert ILibSatellite.AddModuleAddressZero();
}
ILibSatellite.SatelliteStorage storage s = satelliteStorage();
uint96 selectorPosition = uint96(s.moduleFunctionSelectors[_moduleAddress].functionSelectors.length);
/// @dev add new module address if it does not exist
if (selectorPosition == 0) {
addModule(s, _moduleAddress);
}
for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
bytes4 selector = _functionSelectors[selectorIndex];
address oldModuleAddress = s.selectorToModuleAndPosition[selector].moduleAddress;
if (oldModuleAddress == _moduleAddress) {
revert ILibSatellite.ReplaceFunctionWithSameFunction(selector);
}
removeFunction(s, oldModuleAddress, selector);
addFunction(s, selector, selectorPosition, _moduleAddress);
selectorPosition++;
}
}
function removeFunctions(address _moduleAddress, bytes4[] memory _functionSelectors) internal {
if (_functionSelectors.length == 0) {
revert ILibSatellite.NoSelectorsInModuleToMaintenance();
}
// TODO: remove this if statement
if (_moduleAddress == address(0)) {
revert ILibSatellite.AddModuleAddressZero();
}
ILibSatellite.SatelliteStorage storage s = satelliteStorage();
for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
bytes4 selector = _functionSelectors[selectorIndex];
address oldModuleAddress = s.selectorToModuleAndPosition[selector].moduleAddress;
removeFunction(s, oldModuleAddress, selector);
}
}
function addModule(ILibSatellite.SatelliteStorage storage s, address _moduleAddress) internal {
enforceHasContractCode(_moduleAddress, "New module has no code");
s.moduleFunctionSelectors[_moduleAddress].moduleAddressPosition = s.moduleAddresses.length;
s.moduleAddresses.push(_moduleAddress);
}
function addFunction(ILibSatellite.SatelliteStorage storage s, bytes4 _selector, uint96 _selectorPosition, address _moduleAddress) internal {
s.selectorToModuleAndPosition[_selector].functionSelectorPosition = _selectorPosition;
s.moduleFunctionSelectors[_moduleAddress].functionSelectors.push(_selector);
s.selectorToModuleAndPosition[_selector].moduleAddress = _moduleAddress;
}
function removeFunction(ILibSatellite.SatelliteStorage storage s, address _moduleAddress, bytes4 _selector) internal {
if (_moduleAddress == address(0)) {
revert ILibSatellite.RemoveFunctionDoesNotExist();
}
if (_moduleAddress == address(this)) {
revert ILibSatellite.RemoveImmutableFunction();
}
uint256 selectorPosition = s.selectorToModuleAndPosition[_selector].functionSelectorPosition;
uint256 lastSelectorPosition = s.moduleFunctionSelectors[_moduleAddress].functionSelectors.length - 1;
if (selectorPosition != lastSelectorPosition) {
bytes4 lastSelector = s.moduleFunctionSelectors[_moduleAddress].functionSelectors[lastSelectorPosition];
s.moduleFunctionSelectors[_moduleAddress].functionSelectors[selectorPosition] = lastSelector;
s.selectorToModuleAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);
}
s.moduleFunctionSelectors[_moduleAddress].functionSelectors.pop();
delete s.selectorToModuleAndPosition[_selector];
/// @dev if no more selectors for module address then delete the module address
if (lastSelectorPosition == 0) {
uint256 lastModuleAddressPosition = s.moduleAddresses.length - 1;
uint256 moduleAddressPosition = s.moduleFunctionSelectors[_moduleAddress].moduleAddressPosition;
if (moduleAddressPosition != lastModuleAddressPosition) {
address lastModuleAddress = s.moduleAddresses[lastModuleAddressPosition];
s.moduleAddresses[moduleAddressPosition] = lastModuleAddress;
s.moduleFunctionSelectors[lastModuleAddress].moduleAddressPosition = moduleAddressPosition;
}
s.moduleAddresses.pop();
delete s.moduleFunctionSelectors[_moduleAddress].moduleAddressPosition;
}
}
function initializeSatelliteMaintenance(address _init, bytes memory _calldata) internal {
if (_init == address(0)) {
if (_calldata.length != 0) {
revert ILibSatellite.InitAddressZeroButCalldataNotEmpty();
}
} else {
if (_calldata.length == 0) {
revert ILibSatellite.CalldataEmptyButInitNotEmpty();
}
if (_init != address(this)) {
enforceHasContractCode(_init, "_init address has no code");
}
(bool success, bytes memory error) = _init.delegatecall(_calldata);
if (!success) {
if (error.length > 0) {
revert ILibSatellite.InitFunctionReverted(string(error));
} else {
revert ILibSatellite.InitFunctionReverted("Init function reverted");
}
}
}
}
function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {
uint256 contractSize;
assembly {
contractSize := extcodesize(_contract)
}
if (contractSize == 0) {
revert ILibSatellite.AddressHasNoCode(_errorMessage);
}
}
}{
"viaIR": true,
"optimizer": {
"enabled": true,
"runs": 200,
"details": {
"yulDetails": {
"optimizerSteps": "u"
}
}
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"DoubleRegistration","type":"error"},{"inputs":[],"name":"InvalidFact","type":"error"},{"inputs":[],"name":"InvalidMmrRoot","type":"error"},{"inputs":[],"name":"MustBeContractOwner","type":"error"},{"inputs":[],"name":"NotFinalized","type":"error"},{"inputs":[],"name":"NotInBatch","type":"error"},{"inputs":[],"name":"TaskAlreadyFinalized","type":"error"},{"inputs":[],"name":"UnauthorizedProgramHash","type":"error"},{"anonymous":false,"inputs":[{"components":[{"internalType":"bytes32","name":"programHash","type":"bytes32"},{"internalType":"bytes32[]","name":"inputs","type":"bytes32[]"}],"indexed":false,"internalType":"struct ModuleTask","name":"moduleTask","type":"tuple"}],"name":"ModuleTaskScheduled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"enabledProgramHash","type":"bytes32"}],"name":"ProgramHashEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32[]","name":"disabledProgramHashes","type":"bytes32[]"}],"name":"ProgramHashesDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"result","type":"bytes32"}],"name":"TaskAlreadyStored","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"taskHash","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"taskResult","type":"bytes32"}],"name":"TaskFinalized","type":"event"},{"inputs":[{"components":[{"components":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint256","name":"mmrId","type":"uint256"},{"internalType":"uint256","name":"mmrSize","type":"uint256"}],"internalType":"struct IDataProcessorModule.MmrData[]","name":"mmrData","type":"tuple[]"},{"internalType":"uint256","name":"taskResultLow","type":"uint256"},{"internalType":"uint256","name":"taskResultHigh","type":"uint256"},{"internalType":"uint256","name":"taskHashLow","type":"uint256"},{"internalType":"uint256","name":"taskHashHigh","type":"uint256"},{"internalType":"bytes32","name":"programHash","type":"bytes32"}],"internalType":"struct IDataProcessorModule.TaskData","name":"taskData","type":"tuple"}],"name":"authenticateDataProcessorTaskExecution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"programHashes","type":"bytes32[]"}],"name":"disableProgramHashes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getDataProcessorFactsRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"taskCommitment","type":"bytes32"}],"name":"getDataProcessorFinalizedTaskResult","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"taskCommitment","type":"bytes32"}],"name":"getDataProcessorTaskStatus","outputs":[{"internalType":"enum IDataProcessorModule.TaskStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"programHash","type":"bytes32"}],"name":"isProgramHashAuthorized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"programHash","type":"bytes32"},{"internalType":"bytes32[]","name":"inputs","type":"bytes32[]"}],"internalType":"struct ModuleTask","name":"moduleTask","type":"tuple"}],"name":"requestDataProcessorExecutionOfTask","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IFactsRegistry","name":"factsRegistry","type":"address"}],"name":"setDataProcessorFactsRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"programHash","type":"bytes32"}],"name":"setDataProcessorProgramHash","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6080604052346019576040516112f661001f82396112f690f35b600080fdfe6080604052600436101561001257600080fd5b60003560e01c80630dab05a0146100a2578063346fa9741461009d57806346ca43531461009857806360251864146100935780636d03d30e1461008e5780637112f6521461008957806374ad344d146100845780637f5dcb4e1461007f576391c6351e036100b55761035e565b610302565b6102e9565b610277565b61025f565b610204565b6101ad565b610186565b6100e3565b908160c09103126100b55790565b600080fd5b906020828203126100b557813567ffffffffffffffff81116100b5576100e092016100a7565b90565b346100b5576100fb6100f63660046100ba565b610767565b60405180805b0390f35b805b036100b557565b9050359061011b82610105565b565b906020828203126100b5576100e09161010e565b634e487b7160e01b600052602160045260246000fd5b6003111561015157565b610131565b9061011b82610147565b6100e090610156565b61017290610160565b9052565b60208101929161011b9190610169565b346100b5576101016101a161019c36600461011d565b610c34565b60405191829182610176565b346100b5576101016101c86101c336600461011d565b610c5c565b60405191829182901515815260200190565b60009103126100b557565b6001600160a01b031690565b6001600160a01b03909116815260200190565b346100b5576102143660046101da565b61010161021f610c87565b604051918291826101f1565b908160409103126100b55790565b906020828203126100b557813567ffffffffffffffff81116100b5576100e0920161022b565b346100b5576100fb610272366004610239565b610e19565b346100b5576100fb61028a36600461011d565b610f87565b909182601f830112156100b55781359167ffffffffffffffff83116100b55760200192602083028401116100b557565b906020828203126100b557813567ffffffffffffffff81116100b5576102e5920161028f565b9091565b346100b5576100fb6102fc3660046102bf565b90611056565b346100b55761010161031d61031836600461011d565b611071565b6040515b9182918290815260200190565b6001600160a01b038116610107565b9050359061011b8261032e565b906020828203126100b5576100e09161033d565b346100b5576100fb61037136600461034a565b61112a565b356100e081610105565b61038d6100e06100e09290565b60ff1690565b6100e0906103ab6103a76100e09460ff1690565b9190565b901b90565b6100e06100e06100e09290565b905b600052602052604060002090565b6100e09061038d565b6100e090546103cd565b903590601e1936829003018212156100b5570180359067ffffffffffffffff82116100b5576020019160608202360383136100b557565b634e487b7160e01b600052601160045260246000fd5b8181029291811591840414171561044057565b610417565b9190820180921161044057565b634e487b7160e01b600052604160045260246000fd5b90601f01601f1916810190811067ffffffffffffffff82111761048a57604052565b610452565b9061011b61049c60405190565b9283610468565b67ffffffffffffffff811161048a5760208091020190565b906104cd6104c8836104a3565b61048f565b918252565b369037565b9061011b6104ed6104e7846104bb565b936104a3565b601f1901602084016104d2565b634e487b7160e01b600052603260045260246000fd5b90610519825190565b81101561052a576020809102010190565b6104fa565b60ff1660ff81146104405760010190565b6100e06100e06100e09260ff1690565b919081101561052a576060020190565b91906060838203126100b5576105a190604061057c606061048f565b94610587838261010e565b8652610596836020830161010e565b60208701520161010e565b6040830152565b6100e0903690610560565b6105c29060ff165b9160ff1690565b029060ff821691820361044057565b6105dd9060ff166105bb565b019060ff821161044057565b6100e0906103b0565b0190565b90610610610609610605845190565b9290565b9260200190565b9060005b8181106106215750505090565b90919261063e6106376001928651815260200190565b9460200190565b929101610614565b6100e0916105f6565b90815260408101929161011b9160200152565b546001600160a01b031690565b6100e0906101e5906001600160a01b031682565b6100e09061066f565b6100e090610683565b801515610107565b9050519061011b82610695565b906020828203126100b5576100e09161069d565b6040513d6000823e3d90fd5b6100e0604061048f565b9061017290610156565b6100e09051610156565b9060ff905b9181191691161790565b906107076100e061070e92610160565b82546106e8565b9055565b90600019906106ed565b9061072a6100e061070e9290565b8254610712565b6001610756602061011b9461075161074b600083016106de565b866106f7565b015190565b910161071c565b9061011b91610731565b6000805160206112a18339815191529161078360808301610376565b916107986107916080610380565b8094610393565b906107b060608201926107aa84610376565b176103b0565b926107c960006107c38660018a016103bd565b016103d6565b916002926107df6107d985610156565b91610156565b14610c235760a08101916107fc6107f86101c385610376565b1590565b610c115760049561084961084361083e61083061082161081c88806103e0565b905090565b61082a8c6103b0565b9061042d565b6108398b6103b0565b610445565b6104d7565b96610376565b9861086560009a61086261085c8d6103b0565b8a610510565b52565b61088161087460808601610376565b61086261085c60016103b0565b602084016108a361089182610376565b61086261089d8a6103b0565b8b610510565b60408501996108c76108b48c610376565b6108626108c160036103b0565b8c610510565b6108d08c610380565b8c8088016108e46100e061081c838c6103e0565b6108ed84610540565b1015610a7657610912610903610917928b6103e0565b61090c86610540565b91610550565b6105a8565b6020810180519061094060408401928561092f855190565b95019461093a865190565b9161113d565b9361094d6100e0826103b0565b8514610a5a57508d8f926109e78f610a308998610a2b8a610862610a256109e7610a559f97610a0f610a509f8f6108629f8f610a159f6109dc94610a469f856108626109dc95610a156109e7610a056109fc6109ec976109f66109f0610a1b9c6109e29f8b6108626108c16109e76109c66109ec955190565b936109e26109dc6109d683610380565b8c6105b3565b91610380565b6105d1565b610540565b5190565b98610380565b906105b3565b6109e28d610380565b610a0f6001610380565b906105d1565b90610510565b996109f684610380565b89610510565b6105e9565b956109e26109dc610a4083610380565b8b6105b3565b610a0f6003610380565b61052f565b6108d0565b8f610a728291635e74387b60e01b8352820160000190565b0390fd5b505050945094610aae610ae3602092610ad3610b22959a9c969b9d979d610aba610a9f60405190565b8092610aae8983019182610646565b90810382520382610468565b610acc610ac5825190565b9160200190565b2091610376565b604051938492868401928361064f565b610aee610ac5825190565b20610b02610afd8d8a01610662565b61068c565b60405193849283918291636a93856760e01b835288830190815260200190565b03915afa8015610c0c57610b3c91600091610be357501590565b610bd157506001610bb794610ba1610b907f95367d27ac8fa4179f2186af3ae52ed0aa89414fdfc0e9fb941c113a50c477919a9b966107aa610b8a610bb298610b858d99610376565b610393565b91610376565b98610b996106ca565b9687016106d4565b610bac886020870152565b016103bd565b61075d565b610bcc610bc360405190565b9283928361064f565b0390a1565b634801faa360e01b8952880188900388fd5b6107f8915060203d602011610c05575b610bfd8183610468565b8101906106aa565b503d610bf3565b6106be565b63a7c7efab60e01b6000908152600490fd5b6256836560e91b6000908152600490fd5b60006107c36100e092610c45600090565b5060016000805160206112a1833981519152610bac565b610c826100e091610c6b600090565b5060026000805160206112a1833981519152610bac565b6103d6565b6100e0610afd60006000805160206112a18339815191525b01610662565b90929192610cb56104c8826104a3565b93818552602080860192028301928184116100b557915b838310610cd95750505050565b60208091610ce7848661010e565b815201920191610ccc565b9080601f830112156100b5578160206100e093359101610ca5565b9190916040818403126100b557610d24604061048f565b92610d2f818361010e565b8452602082013567ffffffffffffffff81116100b557610d4f9201610cf2565b6020830152565b6100e0903690610d0d565b506100e090602081019061010e565b9035601e1936839003018112156100b557016020813591019167ffffffffffffffff82116100b55760208202360383136100b557565b9037565b8183529091602001916001600160fb1b0381116100b557829160206105f29202938491610da6565b6100e0916040810191610dfa90610df0610dec8280610d61565b8452565b6020810190610d70565b916020818503910152610daa565b60208082526100e092910190610dd2565b6000805160206112a183398151915290610e3a610e3582610d56565b611214565b9160018101610e4e60006107c386846103bd565b610e5b6107d96002610156565b03610e9157505050610bcc7fa36bf0225d44e9d6e58e2e513288732737cfbc309c71b898b2247e93990f7bec9161032160405190565b60006107c385610ea493969495966103bd565b91600092610eb46107d985610156565b03610f0d57610bcc92610bb27f51ba22217059425bdb04aabf9f3ec49f8a081b44fd40faf327f7d9638056eefa95936001610f0194610ef582610b996106ca565b610bac60006020870152565b60405191829182610e08565b63b1c4a13960e01b8352600483fd5b61011b90610f28611258565b610f3d565b906107076100e061070e92151590565b610bcc7f0289142309466932bbaf0c8456e3f60ec32658d2678d66b8015fae97962c16239161031d6001610f82836002610bac6000805160206112a183398151915290565b610f2d565b61011b90610f1c565b9061011b91610f9d611258565b610fc3565b919081101561052a576020020190565b60208082526100e093910191610daa565b600092916000805160206112a1833981519152610fdf856103b0565b8281101561101a576110159061100f87610f8260028601611009611004868a8c610fa2565b610376565b906103bd565b60010190565b610fdf565b5050907f7adcf1e669e2e306406e20010fcb08639723315da6ee3b5e4871f8f1b8b258f2929350610bcc61104d60405190565b92839283610fb2565b9061011b91610f90565b6100e09081565b6100e09054611060565b7f018abc726881129aa4b18a438ecf4a6609af513f34c5bae86fe59c5b32885ea6906110a260006107c383856103bd565b6110af6107d96002610156565b036110c9576110c36001916100e0936103bd565b01611067565b630df706ad60e11b6000908152600490fd5b61011b906110e7611258565b611112565b906001600160a01b03906106ed565b9061110b6100e061070e9261068c565b82546110ec565b61011b906000805160206112a18339815191526110fb565b61011b906110db565b906103bf906103b0565b90600261117e6111896111af946111846100e097611159600090565b5060047f3566ec3f371302e261b8606f979325c5d4baa8f06afec0221cefed0d7fd9cc765b01611133565b611133565b7fd3764378578a6e2b5a09713c3e8d5015a802d8de808c962ff5c53384ac7b1450611009565b611067565b906111cd6106096111c3845190565b8084529260200190565b9060005b8181106111de5750505090565b9091926111f46106376001928651815260200190565b9291016111d1565b9081526040602082018190526100e0929101906111b4565b611249610aae91611223600090565b50602061122e825190565b9101519061123b60405190565b9384926020840192836111fc565b611254610ac5825190565b2090565b6112866101e560037f3566ec3f371302e261b8606f979325c5d4baa8f06afec0221cefed0d7fd9cc76610c9f565b330361128e57565b6313d6e5d960e11b6000908152600490fdfe018abc726881129aa4b18a438ecf4a6609af513f34c5bae86fe59c5b32885ea5a2646970667358221220dfcab5655695cd18b1b48768106e5af4df10689921b581d34eb4835759866d6964736f6c634300081c0033
Deployed Bytecode
0x6080604052600436101561001257600080fd5b60003560e01c80630dab05a0146100a2578063346fa9741461009d57806346ca43531461009857806360251864146100935780636d03d30e1461008e5780637112f6521461008957806374ad344d146100845780637f5dcb4e1461007f576391c6351e036100b55761035e565b610302565b6102e9565b610277565b61025f565b610204565b6101ad565b610186565b6100e3565b908160c09103126100b55790565b600080fd5b906020828203126100b557813567ffffffffffffffff81116100b5576100e092016100a7565b90565b346100b5576100fb6100f63660046100ba565b610767565b60405180805b0390f35b805b036100b557565b9050359061011b82610105565b565b906020828203126100b5576100e09161010e565b634e487b7160e01b600052602160045260246000fd5b6003111561015157565b610131565b9061011b82610147565b6100e090610156565b61017290610160565b9052565b60208101929161011b9190610169565b346100b5576101016101a161019c36600461011d565b610c34565b60405191829182610176565b346100b5576101016101c86101c336600461011d565b610c5c565b60405191829182901515815260200190565b60009103126100b557565b6001600160a01b031690565b6001600160a01b03909116815260200190565b346100b5576102143660046101da565b61010161021f610c87565b604051918291826101f1565b908160409103126100b55790565b906020828203126100b557813567ffffffffffffffff81116100b5576100e0920161022b565b346100b5576100fb610272366004610239565b610e19565b346100b5576100fb61028a36600461011d565b610f87565b909182601f830112156100b55781359167ffffffffffffffff83116100b55760200192602083028401116100b557565b906020828203126100b557813567ffffffffffffffff81116100b5576102e5920161028f565b9091565b346100b5576100fb6102fc3660046102bf565b90611056565b346100b55761010161031d61031836600461011d565b611071565b6040515b9182918290815260200190565b6001600160a01b038116610107565b9050359061011b8261032e565b906020828203126100b5576100e09161033d565b346100b5576100fb61037136600461034a565b61112a565b356100e081610105565b61038d6100e06100e09290565b60ff1690565b6100e0906103ab6103a76100e09460ff1690565b9190565b901b90565b6100e06100e06100e09290565b905b600052602052604060002090565b6100e09061038d565b6100e090546103cd565b903590601e1936829003018212156100b5570180359067ffffffffffffffff82116100b5576020019160608202360383136100b557565b634e487b7160e01b600052601160045260246000fd5b8181029291811591840414171561044057565b610417565b9190820180921161044057565b634e487b7160e01b600052604160045260246000fd5b90601f01601f1916810190811067ffffffffffffffff82111761048a57604052565b610452565b9061011b61049c60405190565b9283610468565b67ffffffffffffffff811161048a5760208091020190565b906104cd6104c8836104a3565b61048f565b918252565b369037565b9061011b6104ed6104e7846104bb565b936104a3565b601f1901602084016104d2565b634e487b7160e01b600052603260045260246000fd5b90610519825190565b81101561052a576020809102010190565b6104fa565b60ff1660ff81146104405760010190565b6100e06100e06100e09260ff1690565b919081101561052a576060020190565b91906060838203126100b5576105a190604061057c606061048f565b94610587838261010e565b8652610596836020830161010e565b60208701520161010e565b6040830152565b6100e0903690610560565b6105c29060ff165b9160ff1690565b029060ff821691820361044057565b6105dd9060ff166105bb565b019060ff821161044057565b6100e0906103b0565b0190565b90610610610609610605845190565b9290565b9260200190565b9060005b8181106106215750505090565b90919261063e6106376001928651815260200190565b9460200190565b929101610614565b6100e0916105f6565b90815260408101929161011b9160200152565b546001600160a01b031690565b6100e0906101e5906001600160a01b031682565b6100e09061066f565b6100e090610683565b801515610107565b9050519061011b82610695565b906020828203126100b5576100e09161069d565b6040513d6000823e3d90fd5b6100e0604061048f565b9061017290610156565b6100e09051610156565b9060ff905b9181191691161790565b906107076100e061070e92610160565b82546106e8565b9055565b90600019906106ed565b9061072a6100e061070e9290565b8254610712565b6001610756602061011b9461075161074b600083016106de565b866106f7565b015190565b910161071c565b9061011b91610731565b6000805160206112a18339815191529161078360808301610376565b916107986107916080610380565b8094610393565b906107b060608201926107aa84610376565b176103b0565b926107c960006107c38660018a016103bd565b016103d6565b916002926107df6107d985610156565b91610156565b14610c235760a08101916107fc6107f86101c385610376565b1590565b610c115760049561084961084361083e61083061082161081c88806103e0565b905090565b61082a8c6103b0565b9061042d565b6108398b6103b0565b610445565b6104d7565b96610376565b9861086560009a61086261085c8d6103b0565b8a610510565b52565b61088161087460808601610376565b61086261085c60016103b0565b602084016108a361089182610376565b61086261089d8a6103b0565b8b610510565b60408501996108c76108b48c610376565b6108626108c160036103b0565b8c610510565b6108d08c610380565b8c8088016108e46100e061081c838c6103e0565b6108ed84610540565b1015610a7657610912610903610917928b6103e0565b61090c86610540565b91610550565b6105a8565b6020810180519061094060408401928561092f855190565b95019461093a865190565b9161113d565b9361094d6100e0826103b0565b8514610a5a57508d8f926109e78f610a308998610a2b8a610862610a256109e7610a559f97610a0f610a509f8f6108629f8f610a159f6109dc94610a469f856108626109dc95610a156109e7610a056109fc6109ec976109f66109f0610a1b9c6109e29f8b6108626108c16109e76109c66109ec955190565b936109e26109dc6109d683610380565b8c6105b3565b91610380565b6105d1565b610540565b5190565b98610380565b906105b3565b6109e28d610380565b610a0f6001610380565b906105d1565b90610510565b996109f684610380565b89610510565b6105e9565b956109e26109dc610a4083610380565b8b6105b3565b610a0f6003610380565b61052f565b6108d0565b8f610a728291635e74387b60e01b8352820160000190565b0390fd5b505050945094610aae610ae3602092610ad3610b22959a9c969b9d979d610aba610a9f60405190565b8092610aae8983019182610646565b90810382520382610468565b610acc610ac5825190565b9160200190565b2091610376565b604051938492868401928361064f565b610aee610ac5825190565b20610b02610afd8d8a01610662565b61068c565b60405193849283918291636a93856760e01b835288830190815260200190565b03915afa8015610c0c57610b3c91600091610be357501590565b610bd157506001610bb794610ba1610b907f95367d27ac8fa4179f2186af3ae52ed0aa89414fdfc0e9fb941c113a50c477919a9b966107aa610b8a610bb298610b858d99610376565b610393565b91610376565b98610b996106ca565b9687016106d4565b610bac886020870152565b016103bd565b61075d565b610bcc610bc360405190565b9283928361064f565b0390a1565b634801faa360e01b8952880188900388fd5b6107f8915060203d602011610c05575b610bfd8183610468565b8101906106aa565b503d610bf3565b6106be565b63a7c7efab60e01b6000908152600490fd5b6256836560e91b6000908152600490fd5b60006107c36100e092610c45600090565b5060016000805160206112a1833981519152610bac565b610c826100e091610c6b600090565b5060026000805160206112a1833981519152610bac565b6103d6565b6100e0610afd60006000805160206112a18339815191525b01610662565b90929192610cb56104c8826104a3565b93818552602080860192028301928184116100b557915b838310610cd95750505050565b60208091610ce7848661010e565b815201920191610ccc565b9080601f830112156100b5578160206100e093359101610ca5565b9190916040818403126100b557610d24604061048f565b92610d2f818361010e565b8452602082013567ffffffffffffffff81116100b557610d4f9201610cf2565b6020830152565b6100e0903690610d0d565b506100e090602081019061010e565b9035601e1936839003018112156100b557016020813591019167ffffffffffffffff82116100b55760208202360383136100b557565b9037565b8183529091602001916001600160fb1b0381116100b557829160206105f29202938491610da6565b6100e0916040810191610dfa90610df0610dec8280610d61565b8452565b6020810190610d70565b916020818503910152610daa565b60208082526100e092910190610dd2565b6000805160206112a183398151915290610e3a610e3582610d56565b611214565b9160018101610e4e60006107c386846103bd565b610e5b6107d96002610156565b03610e9157505050610bcc7fa36bf0225d44e9d6e58e2e513288732737cfbc309c71b898b2247e93990f7bec9161032160405190565b60006107c385610ea493969495966103bd565b91600092610eb46107d985610156565b03610f0d57610bcc92610bb27f51ba22217059425bdb04aabf9f3ec49f8a081b44fd40faf327f7d9638056eefa95936001610f0194610ef582610b996106ca565b610bac60006020870152565b60405191829182610e08565b63b1c4a13960e01b8352600483fd5b61011b90610f28611258565b610f3d565b906107076100e061070e92151590565b610bcc7f0289142309466932bbaf0c8456e3f60ec32658d2678d66b8015fae97962c16239161031d6001610f82836002610bac6000805160206112a183398151915290565b610f2d565b61011b90610f1c565b9061011b91610f9d611258565b610fc3565b919081101561052a576020020190565b60208082526100e093910191610daa565b600092916000805160206112a1833981519152610fdf856103b0565b8281101561101a576110159061100f87610f8260028601611009611004868a8c610fa2565b610376565b906103bd565b60010190565b610fdf565b5050907f7adcf1e669e2e306406e20010fcb08639723315da6ee3b5e4871f8f1b8b258f2929350610bcc61104d60405190565b92839283610fb2565b9061011b91610f90565b6100e09081565b6100e09054611060565b7f018abc726881129aa4b18a438ecf4a6609af513f34c5bae86fe59c5b32885ea6906110a260006107c383856103bd565b6110af6107d96002610156565b036110c9576110c36001916100e0936103bd565b01611067565b630df706ad60e11b6000908152600490fd5b61011b906110e7611258565b611112565b906001600160a01b03906106ed565b9061110b6100e061070e9261068c565b82546110ec565b61011b906000805160206112a18339815191526110fb565b61011b906110db565b906103bf906103b0565b90600261117e6111896111af946111846100e097611159600090565b5060047f3566ec3f371302e261b8606f979325c5d4baa8f06afec0221cefed0d7fd9cc765b01611133565b611133565b7fd3764378578a6e2b5a09713c3e8d5015a802d8de808c962ff5c53384ac7b1450611009565b611067565b906111cd6106096111c3845190565b8084529260200190565b9060005b8181106111de5750505090565b9091926111f46106376001928651815260200190565b9291016111d1565b9081526040602082018190526100e0929101906111b4565b611249610aae91611223600090565b50602061122e825190565b9101519061123b60405190565b9384926020840192836111fc565b611254610ac5825190565b2090565b6112866101e560037f3566ec3f371302e261b8606f979325c5d4baa8f06afec0221cefed0d7fd9cc76610c9f565b330361128e57565b6313d6e5d960e11b6000908152600490fdfe018abc726881129aa4b18a438ecf4a6609af513f34c5bae86fe59c5b32885ea5a2646970667358221220dfcab5655695cd18b1b48768106e5af4df10689921b581d34eb4835759866d6964736f6c634300081c0033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.