Description:
Multi-signature wallet contract requiring multiple confirmations for transaction execution.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"contracts/layer1/verifiers/Risc0Verifier.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@risc0/contracts/IRiscZeroVerifier.sol";
import "src/shared/common/EssentialContract.sol";
import "src/shared/libs/LibStrings.sol";
import "../based/ITaikoInbox.sol";
import "./LibPublicInput.sol";
import "./IVerifier.sol";
/// @title Risc0Verifier
/// @custom:security-contact security@taiko.xyz
contract Risc0Verifier is EssentialContract, IVerifier {
bytes32 internal constant RISCZERO_GROTH16_VERIFIER = bytes32("risc0_groth16_verifier");
// [32, 0, 0, 0] -- big-endian uint32(32) for hash bytes len
bytes private constant FIXED_JOURNAL_HEADER = hex"20000000";
uint64 public immutable taikoChainId;
address public immutable riscoGroth16Verifier;
/// @notice Trusted imageId mapping
mapping(bytes32 imageId => bool trusted) public isImageTrusted;
uint256[49] private __gap;
/// @dev Emitted when a trusted image is set / unset.
/// @param imageId The id of the image
/// @param trusted True if trusted, false otherwise
event ImageTrusted(bytes32 imageId, bool trusted);
error RISC_ZERO_INVALID_BLOCK_PROOF_IMAGE_ID();
error RISC_ZERO_INVALID_AGGREGATION_IMAGE_ID();
error RISC_ZERO_INVALID_PROOF();
constructor(
uint64 _taikoChainId,
address _riscoGroth16Verifier
)
EssentialContract(address(0))
{
taikoChainId = _taikoChainId;
riscoGroth16Verifier = _riscoGroth16Verifier;
}
/// @notice Initializes the contract with the provided address manager.
/// @param _owner The address of the owner.
function init(address _owner) external initializer {
__Essential_init(_owner);
}
/// @notice Sets/unsets an the imageId as trusted entity
/// @param _imageId The id of the image.
/// @param _trusted True if trusted, false otherwise.
function setImageIdTrusted(bytes32 _imageId, bool _trusted) external onlyOwner {
isImageTrusted[_imageId] = _trusted;
emit ImageTrusted(_imageId, _trusted);
}
/// @inheritdoc IVerifier
function verifyProof(Context[] calldata _ctxs, bytes calldata _proof) external view {
// Decode will throw if not proper length/encoding
(bytes memory seal, bytes32 blockImageId, bytes32 aggregationImageId) =
abi.decode(_proof, (bytes, bytes32, bytes32));
// Check if the aggregation program is trusted
require(isImageTrusted[aggregationImageId], RISC_ZERO_INVALID_AGGREGATION_IMAGE_ID());
// Check if the block proving program is trusted
require(isImageTrusted[blockImageId], RISC_ZERO_INVALID_BLOCK_PROOF_IMAGE_ID());
// Collect public inputs
bytes32[] memory publicInputs = new bytes32[](_ctxs.length + 1);
// First public input is the block proving program key
publicInputs[0] = blockImageId;
// All other inputs are the block program public inputs (a single 32 byte value)
uint256 size = _ctxs.length;
for (uint256 i; i < size; ++i) {
publicInputs[i + 1] = LibPublicInput.hashPublicInputs(
_ctxs[i].transition, address(this), address(0), _ctxs[i].metaHash, taikoChainId
);
}
// journalDigest is the sha256 hash of the hashed public input
bytes32 journalDigest = sha256(abi.encodePacked(publicInputs));
// call risc0 verifier contract
(bool success,) = riscoGroth16Verifier.staticcall(
abi.encodeCall(IRiscZeroVerifier.verify, (seal, aggregationImageId, journalDigest))
);
require(success, RISC_ZERO_INVALID_PROOF());
}
}
"
},
"node_modules/risc0-ethereum/contracts/src/IRiscZeroVerifier.sol": {
"content": "// Copyright 2025 RISC Zero, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.9;
import {reverseByteOrderUint32} from "./Util.sol";
/// @notice A receipt attesting to a claim using the RISC Zero proof system.
/// @dev A receipt contains two parts: a seal and a claim.
///
/// The seal is a zero-knowledge proof attesting to knowledge of a witness for the claim. The claim
/// is a set of public outputs, and for zkVM execution is the hash of a `ReceiptClaim` struct.
///
/// IMPORTANT: The `claimDigest` field must be a hash computed by the caller for verification to
/// have meaningful guarantees. Treat this similar to verifying an ECDSA signature, in that hashing
/// is a key operation in verification. The most common way to calculate this hash is to use the
/// `ReceiptClaimLib.ok(imageId, journalDigest).digest()` for successful executions.
struct Receipt {
bytes seal;
bytes32 claimDigest;
}
/// @notice Public claims about a zkVM guest execution, such as the journal committed to by the guest.
/// @dev Also includes important information such as the exit code and the starting and ending system
/// state (i.e. the state of memory). `ReceiptClaim` is a "Merkle-ized struct" supporting
/// partial openings of the underlying fields from a hash commitment to the full structure.
struct ReceiptClaim {
/// @notice Digest of the SystemState just before execution has begun.
bytes32 preStateDigest;
/// @notice Digest of the SystemState just after execution has completed.
bytes32 postStateDigest;
/// @notice The exit code for the execution.
ExitCode exitCode;
/// @notice A digest of the input to the guest.
/// @dev This field is currently unused and must be set to the zero digest.
bytes32 input;
/// @notice Digest of the Output of the guest, including the journal
/// and assumptions set during execution.
bytes32 output;
}
library ReceiptClaimLib {
using OutputLib for Output;
using SystemStateLib for SystemState;
bytes32 constant TAG_DIGEST = sha256("risc0.ReceiptClaim");
// Define a constant to ensure hashing is done at compile time. Can't use the
// SystemStateLib.digest method here because the Solidity compiler complains.
bytes32 constant SYSTEM_STATE_ZERO_DIGEST = 0xa3acc27117418996340b84e5a90f3ef4c49d22c79e44aad822ec9c313e1eb8e2;
/// @notice Construct a ReceiptClaim from the given imageId and journalDigest.
/// Returned ReceiptClaim will represent a successful execution of the zkVM, running
/// the program committed by imageId and resulting in the journal specified by
/// journalDigest.
/// @param imageId The identifier for the guest program.
/// @param journalDigest The SHA-256 digest of the journal bytes.
/// @dev Input hash and postStateDigest are set to all-zeros (i.e. no committed input, or
/// final memory state), the exit code is (Halted, 0), and there are no assumptions
/// (i.e. the receipt is unconditional).
function ok(bytes32 imageId, bytes32 journalDigest) internal pure returns (ReceiptClaim memory) {
return ReceiptClaim(
imageId,
SYSTEM_STATE_ZERO_DIGEST,
ExitCode(SystemExitCode.Halted, 0),
bytes32(0),
Output(journalDigest, bytes32(0)).digest()
);
}
function digest(ReceiptClaim memory claim) internal pure returns (bytes32) {
return sha256(
abi.encodePacked(
TAG_DIGEST,
// down
claim.input,
claim.preStateDigest,
claim.postStateDigest,
claim.output,
// data
uint32(claim.exitCode.system) << 24,
uint32(claim.exitCode.user) << 24,
// down.length
uint16(4) << 8
)
);
}
}
/// @notice Commitment to the memory state and program counter (pc) of the zkVM.
/// @dev The "pre" and "post" fields of the ReceiptClaim are digests of the system state at the
/// start are stop of execution. Programs are loaded into the zkVM by creating a memory image
/// of the loaded program, and creating a system state for initializing the zkVM. This is
/// known as the "image ID".
struct SystemState {
/// @notice Program counter.
uint32 pc;
/// @notice Root hash of a merkle tree which confirms the integrity of the memory image.
bytes32 merkle_root;
}
library SystemStateLib {
bytes32 constant TAG_DIGEST = sha256("risc0.SystemState");
function digest(SystemState memory state) internal pure returns (bytes32) {
return sha256(
abi.encodePacked(
TAG_DIGEST,
// down
state.merkle_root,
// data
reverseByteOrderUint32(state.pc),
// down.length
uint16(1) << 8
)
);
}
}
/// @notice Exit condition indicated by the zkVM at the end of the guest execution.
/// @dev Exit codes have a "system" part and a "user" part. Semantically, the system part is set to
/// indicate the type of exit (e.g. halt, pause, or system split) and is directly controlled by the
/// zkVM. The user part is an exit code, similar to exit codes used in Linux, chosen by the guest
/// program to indicate additional information (e.g. 0 to indicate success or 1 to indicate an
/// error).
struct ExitCode {
SystemExitCode system;
uint8 user;
}
/// @notice Exit condition indicated by the zkVM at the end of the execution covered by this proof.
/// @dev
/// `Halted` indicates normal termination of a program with an interior exit code returned from the
/// guest program. A halted program cannot be resumed.
///
/// `Paused` indicates the execution ended in a paused state with an interior exit code set by the
/// guest program. A paused program can be resumed such that execution picks up where it left
/// of, with the same memory state.
///
/// `SystemSplit` indicates the execution ended on a host-initiated system split. System split is
/// mechanism by which the host can temporarily stop execution of the execution ended in a system
/// split has no output and no conclusions can be drawn about whether the program will eventually
/// halt. System split is used in continuations to split execution into individually provable segments.
enum SystemExitCode {
Halted,
Paused,
SystemSplit
}
/// @notice Output field in the `ReceiptClaim`, committing to a claimed journal and assumptions list.
struct Output {
/// @notice Digest of the journal committed to by the guest execution.
bytes32 journalDigest;
/// @notice Digest of the ordered list of `ReceiptClaim` digests corresponding to the
/// calls to `env::verify` and `env::verify_integrity`.
/// @dev Verifying the integrity of a `Receipt` corresponding to a `ReceiptClaim` with a
/// non-empty assumptions list does not guarantee unconditionally any of the claims over the
/// guest execution (i.e. if the assumptions list is non-empty, then the journal digest cannot
/// be trusted to correspond to a genuine execution). The claims can be checked by additional
/// verifying a `Receipt` for every digest in the assumptions list.
bytes32 assumptionsDigest;
}
library OutputLib {
bytes32 constant TAG_DIGEST = sha256("risc0.Output");
function digest(Output memory output) internal pure returns (bytes32) {
return sha256(
abi.encodePacked(
TAG_DIGEST,
// down
output.journalDigest,
output.assumptionsDigest,
// down.length
uint16(2) << 8
)
);
}
}
/// @notice Error raised when cryptographic verification of the zero-knowledge proof fails.
error VerificationFailed();
/// @notice Verifier interface for RISC Zero receipts of execution.
interface IRiscZeroVerifier {
/// @notice Verify that the given seal is a valid RISC Zero proof of execution with the
/// given image ID and journal digest. Reverts on failure.
/// @dev This method additionally ensures that the input hash is all-zeros (i.e. no
/// committed input), the exit code is (Halted, 0), and there are no assumptions (i.e. the
/// receipt is unconditional).
/// @param seal The encoded cryptographic proof (i.e. SNARK).
/// @param imageId The identifier for the guest program.
/// @param journalDigest The SHA-256 digest of the journal bytes.
function verify(bytes calldata seal, bytes32 imageId, bytes32 journalDigest) external view;
/// @notice Verify that the given receipt is a valid RISC Zero receipt, ensuring the `seal` is
/// valid a cryptographic proof of the execution with the given `claim`. Reverts on failure.
/// @param receipt The receipt to be verified.
function verifyIntegrity(Receipt calldata receipt) external view;
}
"
},
"contracts/shared/common/EssentialContract.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
import "./IResolver.sol";
/// @title EssentialContract
/// @custom:security-contact security@taiko.xyz
abstract contract EssentialContract is UUPSUpgradeable, Ownable2StepUpgradeable {
uint8 internal constant _FALSE = 1;
uint8 internal constant _TRUE = 2;
address private immutable __resolver;
uint256[50] private __gapFromOldAddressResolver;
/// @dev Slot 1.
uint8 internal __reentry;
uint8 internal __paused;
uint256[49] private __gap;
/// @notice Emitted when the contract is paused.
/// @param account The account that paused the contract.
event Paused(address account);
/// @notice Emitted when the contract is unpaused.
/// @param account The account that unpaused the contract.
event Unpaused(address account);
error INVALID_PAUSE_STATUS();
error FUNC_NOT_IMPLEMENTED();
error REENTRANT_CALL();
error ACCESS_DENIED();
error RESOLVER_NOT_FOUND();
error ZERO_ADDRESS();
error ZERO_VALUE();
/// @dev Modifier that ensures the caller is the owner or resolved address of a given name.
/// @param _name The name to check against.
modifier onlyFromOwnerOrNamed(bytes32 _name) {
require(msg.sender == owner() || msg.sender == resolve(_name, true), ACCESS_DENIED());
_;
}
/// @dev Modifier that ensures the caller is either the owner or a specified address.
/// @param _addr The address to check against.
modifier onlyFromOwnerOr(address _addr) {
require(msg.sender == owner() || msg.sender == _addr, ACCESS_DENIED());
_;
}
/// @dev Modifier that reverts the function call, indicating it is not implemented.
modifier notImplemented() {
revert FUNC_NOT_IMPLEMENTED();
_;
}
/// @dev Modifier that prevents reentrant calls to a function.
modifier nonReentrant() {
require(_loadReentryLock() != _TRUE, REENTRANT_CALL());
_storeReentryLock(_TRUE);
_;
_storeReentryLock(_FALSE);
}
/// @dev Modifier that allows function execution only when the contract is paused.
modifier whenPaused() {
require(paused(), INVALID_PAUSE_STATUS());
_;
}
/// @dev Modifier that allows function execution only when the contract is not paused.
modifier whenNotPaused() {
require(!paused(), INVALID_PAUSE_STATUS());
_;
}
/// @dev Modifier that ensures the provided address is not the zero address.
/// @param _addr The address to check.
modifier nonZeroAddr(address _addr) {
require(_addr != address(0), ZERO_ADDRESS());
_;
}
/// @dev Modifier that ensures the provided value is not zero.
/// @param _value The value to check.
modifier nonZeroValue(uint256 _value) {
require(_value != 0, ZERO_VALUE());
_;
}
/// @dev Modifier that ensures the provided bytes32 value is not zero.
/// @param _value The bytes32 value to check.
modifier nonZeroBytes32(bytes32 _value) {
require(_value != 0, ZERO_VALUE());
_;
}
/// @dev Modifier that ensures the caller is the resolved address of a given
/// name.
/// @param _name The name to check against.
modifier onlyFromNamed(bytes32 _name) {
require(msg.sender == resolve(_name, true), ACCESS_DENIED());
_;
}
/// @dev Modifier that ensures the caller is the resolved address of a given
/// name, if the name is set.
/// @param _name The name to check against.
modifier onlyFromOptionalNamed(bytes32 _name) {
address addr = resolve(_name, true);
require(addr == address(0) || msg.sender == addr, ACCESS_DENIED());
_;
}
/// @dev Modifier that ensures the caller is a resolved address to either _name1 or _name2
/// name.
/// @param _name1 The first name to check against.
/// @param _name2 The second name to check against.
modifier onlyFromNamedEither(bytes32 _name1, bytes32 _name2) {
require(
msg.sender == resolve(_name1, true) || msg.sender == resolve(_name2, true),
ACCESS_DENIED()
);
_;
}
/// @dev Modifier that ensures the caller is either of the two specified addresses.
/// @param _addr1 The first address to check against.
/// @param _addr2 The second address to check against.
modifier onlyFromEither(address _addr1, address _addr2) {
require(msg.sender == _addr1 || msg.sender == _addr2, ACCESS_DENIED());
_;
}
/// @dev Modifier that ensures the caller is the specified address.
/// @param _addr The address to check against.
modifier onlyFrom(address _addr) {
require(msg.sender == _addr, ACCESS_DENIED());
_;
}
/// @dev Modifier that ensures the caller is the specified address.
/// @param _addr The address to check against.
modifier onlyFromOptional(address _addr) {
require(_addr == address(0) || msg.sender == _addr, ACCESS_DENIED());
_;
}
constructor(address _resolver) {
__resolver = _resolver;
_disableInitializers();
}
/// @notice Pauses the contract.
function pause() public whenNotPaused {
_pause();
emit Paused(msg.sender);
// We call the authorize function here to avoid:
// Warning (5740): Unreachable code.
_authorizePause(msg.sender, true);
}
/// @notice Unpauses the contract.
function unpause() public whenPaused {
_unpause();
emit Unpaused(msg.sender);
// We call the authorize function here to avoid:
// Warning (5740): Unreachable code.
_authorizePause(msg.sender, false);
}
function impl() public view returns (address) {
return _getImplementation();
}
/// @notice Returns true if the contract is paused, and false otherwise.
/// @return true if paused, false otherwise.
function paused() public view virtual returns (bool) {
return __paused == _TRUE;
}
function inNonReentrant() public view returns (bool) {
return _loadReentryLock() == _TRUE;
}
/// @notice Returns the address of this contract.
/// @return The address of this contract.
function resolver() public view virtual returns (address) {
return __resolver;
}
/// @notice Resolves a name to an address on a specific chain
/// @param _chainId The chain ID to resolve the name on
/// @param _name The name to resolve
/// @param _allowZeroAddress Whether to allow resolving to the zero address
/// @return The resolved address
function resolve(
uint64 _chainId,
bytes32 _name,
bool _allowZeroAddress
)
internal
view
returns (address)
{
return IResolver(resolver()).resolve(_chainId, _name, _allowZeroAddress);
}
/// @notice Resolves a name to an address on the current chain
/// @param _name The name to resolve
/// @param _allowZeroAddress Whether to allow resolving to the zero address
/// @return The resolved address
function resolve(bytes32 _name, bool _allowZeroAddress) internal view returns (address) {
return IResolver(resolver()).resolve(block.chainid, _name, _allowZeroAddress);
}
/// @notice Initializes the contract.
/// @param _owner The owner of this contract. msg.sender will be used if this value is zero.
function __Essential_init(address _owner) internal virtual onlyInitializing {
__Context_init();
_transferOwnership(_owner == address(0) ? msg.sender : _owner);
__paused = _FALSE;
}
function _pause() internal virtual {
__paused = _TRUE;
}
function _unpause() internal virtual {
__paused = _FALSE;
}
function _authorizeUpgrade(address) internal virtual override onlyOwner { }
function _authorizePause(address, bool) internal virtual onlyOwner { }
// Stores the reentry lock
function _storeReentryLock(uint8 _reentry) internal virtual {
__reentry = _reentry;
}
// Loads the reentry lock
function _loadReentryLock() internal view virtual returns (uint8 reentry_) {
reentry_ = __reentry;
}
}
"
},
"contracts/shared/libs/LibStrings.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title LibStrings
/// @custom:security-contact security@taiko.xyz
library LibStrings {
bytes32 internal constant B_AUTOMATA_DCAP_ATTESTATION = bytes32("automata_dcap_attestation");
bytes32 internal constant B_SGX_GETH_AUTOMATA = bytes32("sgx_geth_automata");
bytes32 internal constant B_BOND_TOKEN = bytes32("bond_token");
bytes32 internal constant B_BRIDGE = bytes32("bridge");
bytes32 internal constant B_BRIDGE_WATCHDOG = bytes32("bridge_watchdog");
bytes32 internal constant B_BRIDGED_ERC1155 = bytes32("bridged_erc1155");
bytes32 internal constant B_BRIDGED_ERC20 = bytes32("bridged_erc20");
bytes32 internal constant B_BRIDGED_ERC721 = bytes32("bridged_erc721");
bytes32 internal constant B_CHAIN_WATCHDOG = bytes32("chain_watchdog");
bytes32 internal constant B_ERC1155_VAULT = bytes32("erc1155_vault");
bytes32 internal constant B_ERC20_VAULT = bytes32("erc20_vault");
bytes32 internal constant B_ERC721_VAULT = bytes32("erc721_vault");
bytes32 internal constant B_FORCED_INCLUSION_STORE = bytes32("forced_inclusion_store");
bytes32 internal constant B_PRECONF_WHITELIST = bytes32("preconf_whitelist");
bytes32 internal constant B_PRECONF_WHITELIST_OWNER = bytes32("preconf_whitelist_owner");
bytes32 internal constant B_PRECONF_ROUTER = bytes32("preconf_router");
bytes32 internal constant B_TAIKO_WRAPPER = bytes32("taiko_wrapper");
bytes32 internal constant B_PROOF_VERIFIER = bytes32("proof_verifier");
bytes32 internal constant B_SGX_RETH_VERIFIER = bytes32("sgx_reth_verifier");
bytes32 internal constant B_SGX_GETH_VERIFIER = bytes32("sgx_geth_verifier");
bytes32 internal constant B_RISC0_RETH_VERIFIER = bytes32("risc0_reth_verifier");
bytes32 internal constant B_SP1_RETH_VERIFIER = bytes32("sp1_reth_verifier");
bytes32 internal constant B_PROVER_SET = bytes32("prover_set");
bytes32 internal constant B_QUOTA_MANAGER = bytes32("quota_manager");
bytes32 internal constant B_SIGNAL_SERVICE = bytes32("signal_service");
bytes32 internal constant B_TAIKO = bytes32("taiko");
bytes32 internal constant B_TAIKO_TOKEN = bytes32("taiko_token");
bytes32 internal constant B_WITHDRAWER = bytes32("withdrawer");
bytes32 internal constant H_SIGNAL_ROOT = keccak256("SIGNAL_ROOT");
bytes32 internal constant H_STATE_ROOT = keccak256("STATE_ROOT");
}
"
},
"contracts/layer1/based/ITaikoInbox.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "src/shared/based/LibSharedData.sol";
/// @title TaikoInbox
/// @notice Acts as the inbox for the Taiko Alethia protocol, a simplified version of the
/// original Taiko-Based Contestable Rollup (BCR). The tier-based proof system and
/// contestation mechanisms have been removed.
///
/// Key assumptions of this protocol:
/// - Block proposals and proofs are asynchronous. Proofs are not available at proposal time,
/// unlike Taiko Gwyneth, which assumes synchronous composability.
/// - Proofs are presumed error-free and thoroughly validated, with proof type management
/// delegated to IVerifier contracts.
///
/// @dev Registered in the address resolver as "taiko".
/// @custom:security-contact security@taiko.xyz
interface ITaikoInbox {
struct BlockParams {
// the max number of transactions in this block. Note that if there are not enough
// transactions in calldata or blobs, the block will contains as many transactions as
// possible.
uint16 numTransactions;
// The time difference (in seconds) between the timestamp of this block and
// the timestamp of the parent block in the same batch. For the first block in a batch,
// there is not parent block in the same batch, so the time shift should be 0.
uint8 timeShift;
// Signals sent on L1 and need to sync to this L2 block.
bytes32[] signalSlots;
}
struct BlobParams {
// The hashes of the blob. Note that if this array is not empty. `firstBlobIndex` and
// `numBlobs` must be 0.
bytes32[] blobHashes;
// The index of the first blob in this batch.
uint8 firstBlobIndex;
// The number of blobs in this batch. Blobs are initially concatenated and subsequently
// decompressed via Zlib.
uint8 numBlobs;
// The byte offset of the blob in the batch.
uint32 byteOffset;
// The byte size of the blob.
uint32 byteSize;
// The block number when the blob was created. This value is only non-zero when
// `blobHashes` are non-empty.
uint64 createdIn;
}
struct BatchParams {
address proposer;
address coinbase;
bytes32 parentMetaHash;
uint64 anchorBlockId;
uint64 lastBlockTimestamp;
bool revertIfNotFirstProposal;
// Specifies the number of blocks to be generated from this batch.
BlobParams blobParams;
BlockParams[] blocks;
}
/// @dev This struct holds batch information essential for constructing blocks offchain, but it
/// does not include data necessary for batch proving.
struct BatchInfo {
bytes32 txsHash;
// Data to build L2 blocks
BlockParams[] blocks;
bytes32[] blobHashes;
bytes32 extraData;
address coinbase;
uint64 proposedIn; // Used by node/client
uint64 blobCreatedIn;
uint32 blobByteOffset;
uint32 blobByteSize;
uint32 gasLimit;
uint64 lastBlockId;
uint64 lastBlockTimestamp;
// Data for the L2 anchor transaction, shared by all blocks in the batch
uint64 anchorBlockId;
// corresponds to the `_anchorStateRoot` parameter in the anchor transaction.
// The batch's validity proof shall verify the integrity of these two values.
bytes32 anchorBlockHash;
LibSharedData.BaseFeeConfig baseFeeConfig;
}
/// @dev This struct holds batch metadata essential for proving the batch.
struct BatchMetadata {
bytes32 infoHash;
address proposer;
uint64 batchId;
uint64 proposedAt; // Used by node/client
}
/// @notice Struct representing transition to be proven.
struct Transition {
bytes32 parentHash;
bytes32 blockHash;
bytes32 stateRoot;
}
// @notice Struct representing transition storage
/// @notice 4 slots used.
struct TransitionState {
bytes32 parentHash;
bytes32 blockHash;
bytes32 stateRoot;
address prover;
bool inProvingWindow;
uint48 createdAt;
}
/// @notice 3 slots used.
struct Batch {
bytes32 metaHash; // slot 1
uint64 lastBlockId; // slot 2
uint96 reserved3;
uint96 livenessBond;
uint64 batchId; // slot 3
uint64 lastBlockTimestamp;
uint64 anchorBlockId;
uint24 nextTransitionId;
uint8 reserved4;
// The ID of the transaction that is used to verify this batch. However, if this batch is
// not verified as the last one in a transaction, verifiedTransitionId will remain zero.
uint24 verifiedTransitionId;
}
/// @notice Forge is only able to run coverage in case the contracts by default capable of
/// compiling without any optimization (neither optimizer runs, no compiling --via-ir flag).
struct Stats1 {
uint64 genesisHeight;
uint64 __reserved2;
uint64 lastSyncedBatchId;
uint64 lastSyncedAt;
}
struct Stats2 {
uint64 numBatches;
uint64 lastVerifiedBatchId;
bool paused;
uint56 lastProposedIn;
uint64 lastUnpausedAt;
}
struct ForkHeights {
uint64 ontake; // measured with block number.
uint64 pacaya; // measured with the batch Id, not block number.
uint64 shasta; // measured with the batch Id, not block number.
uint64 unzen; // measured with the batch Id, not block number.
}
/// @notice Struct holding Taiko configuration parameters. See {TaikoConfig}.
struct Config {
/// @notice The chain ID of the network where Taiko contracts are deployed.
uint64 chainId;
/// @notice The maximum number of unverified batches the protocol supports.
uint64 maxUnverifiedBatches;
/// @notice Size of the batch ring buffer, allowing extra space for proposals.
uint64 batchRingBufferSize;
/// @notice The maximum number of verifications allowed when a batch is proposed or proved.
uint64 maxBatchesToVerify;
/// @notice The maximum gas limit allowed for a block.
uint32 blockMaxGasLimit;
/// @notice The amount of Taiko token as a prover liveness bond per batch.
uint96 livenessBondBase;
/// @notice The amount of Taiko token as a prover liveness bond per block. This field is
/// deprecated and its value will be ignored.
uint96 livenessBondPerBlock;
/// @notice The number of batches between two L2-to-L1 state root sync.
uint8 stateRootSyncInternal;
/// @notice The max differences of the anchor height and the current block number.
uint64 maxAnchorHeightOffset;
/// @notice Base fee configuration
LibSharedData.BaseFeeConfig baseFeeConfig;
/// @notice The proving window in seconds.
uint16 provingWindow;
/// @notice The time required for a transition to be used for verifying a batch.
uint24 cooldownWindow;
/// @notice The maximum number of signals to be received by TaikoL2.
uint8 maxSignalsToReceive;
/// @notice The maximum number of blocks per batch.
uint16 maxBlocksPerBatch;
/// @notice Historical heights of the forks.
ForkHeights forkHeights;
}
/// @notice Struct holding the state variables for the {Taiko} contract.
struct State {
// Ring buffer for proposed batches and a some recent verified batches.
mapping(uint256 batchId_mod_batchRingBufferSize => Batch batch) batches;
// Indexing to transition ids (ring buffer not possible)
mapping(uint256 batchId => mapping(bytes32 parentHash => uint24 transitionId)) transitionIds;
// Ring buffer for transitions
mapping(
uint256 batchId_mod_batchRingBufferSize
=> mapping(uint24 transitionId => TransitionState ts)
) transitions;
bytes32 __reserve1; // slot 4 - was used as a ring buffer for Ether deposits
Stats1 stats1; // slot 5
Stats2 stats2; // slot 6
mapping(address account => uint256 bond) bondBalance;
uint256[43] __gap;
}
/// @notice Emitted when tokens are deposited into a user's bond balance.
/// @param user The address of the user who deposited the tokens.
/// @param amount The amount of tokens deposited.
event BondDeposited(address indexed user, uint256 amount);
/// @notice Emitted when tokens are withdrawn from a user's bond balance.
/// @param user The address of the user who withdrew the tokens.
/// @param amount The amount of tokens withdrawn.
event BondWithdrawn(address indexed user, uint256 amount);
/// @notice Emitted when a token is credited back to a user's bond balance.
/// @param user The address of the user whose bond balance is credited.
/// @param amount The amount of tokens credited.
event BondCredited(address indexed user, uint256 amount);
/// @notice Emitted when a token is debited from a user's bond balance.
/// @param user The address of the user whose bond balance is debited.
/// @param amount The amount of tokens debited.
event BondDebited(address indexed user, uint256 amount);
/// @notice Emitted when a batch is synced.
/// @param stats1 The Stats1 data structure.
event Stats1Updated(Stats1 stats1);
/// @notice Emitted when some state variable values changed.
/// @param stats2 The Stats2 data structure.
event Stats2Updated(Stats2 stats2);
/// @notice Emitted when a batch is proposed.
/// @param info The info of the proposed batch.
/// @param meta The metadata of the proposed batch.
/// @param txList The tx list in calldata.
event BatchProposed(BatchInfo info, BatchMetadata meta, bytes txList);
/// @notice Emitted when multiple transitions are proved.
/// @param verifier The address of the verifier.
/// @param transitions The transitions data.
event BatchesProved(address verifier, uint64[] batchIds, Transition[] transitions);
/// @notice Emitted when a transition is overwritten by a conflicting one with the same parent
/// hash but different block hash or state root.
/// @param batchId The batch ID.
/// @param oldTran The old transition overwritten.
/// @param newTran The new transition.
event ConflictingProof(uint64 batchId, TransitionState oldTran, Transition newTran);
/// @notice Emitted when a batch is verified.
/// @param batchId The ID of the verified batch.
/// @param blockHash The hash of the verified batch.
event BatchesVerified(uint64 batchId, bytes32 blockHash);
error AnchorBlockIdSmallerThanParent();
error AnchorBlockIdTooLarge();
error AnchorBlockIdTooSmall();
error ArraySizesMismatch();
error BatchNotFound();
error BatchVerified();
error BeyondCurrentFork();
error BlobNotFound();
error BlockNotFound();
error BlobNotSpecified();
error ContractPaused();
error CustomProposerMissing();
error CustomProposerNotAllowed();
error EtherNotPaidAsBond();
error FirstBlockTimeShiftNotZero();
error ForkNotActivated();
error InsufficientBond();
error InvalidBlobCreatedIn();
error InvalidBlobParams();
error InvalidGenesisBlockHash();
error InvalidParams();
error InvalidTransitionBlockHash();
error InvalidTransitionParentHash();
error InvalidTransitionStateRoot();
error MetaHashMismatch();
error MsgValueNotZero();
error NoBlocksToProve();
error NotFirstProposal();
error NotInboxWrapper();
error ParentMetaHashMismatch();
error SameTransition();
error SignalNotSent();
error TimestampSmallerThanParent();
error TimestampTooLarge();
error TimestampTooSmall();
error TooManyBatches();
error TooManyBlocks();
error TooManySignals();
error TransitionNotFound();
error ZeroAnchorBlockHash();
/// @notice Proposes a batch of blocks.
/// @param _params ABI-encoded parameters.
/// @param _txList The transaction list in calldata. If the txList is empty, blob will be used
/// for data availability.
/// @return meta_ The metadata of the proposed batch.
function proposeBatch(
bytes calldata _params,
bytes calldata _txList
)
external
returns (ITaikoInbox.BatchMetadata memory meta_, uint64 lastBlockId_);
/// @notice Proves state transitions for multiple batches with a single aggregated proof.
/// @param _params ABI-encoded parameter containing:
/// - metas: Array of metadata for each batch being proved.
/// - transitions: Array of batch transitions to be proved.
/// @param _proof The aggregated cryptographic proof proving the batches transitions.
function proveBatches(bytes calldata _params, bytes calldata _proof) external;
/// @notice Deposits TAIKO tokens into the contract to be used as liveness bond.
/// @param _amount The amount of TAIKO tokens to deposit.
function depositBond(uint256 _amount) external payable;
/// @notice Withdraws a specified amount of TAIKO tokens from the contract.
/// @param _amount The amount of TAIKO tokens to withdraw.
function withdrawBond(uint256 _amount) external;
/// @notice Returns the TAIKO token balance of a specific user.
/// @param _user The address of the user.
/// @return The TAIKO token balance of the user.
function bondBalanceOf(address _user) external view returns (uint256);
/// @notice Retrieves the Bond token address. If Ether is used as bond, this function returns
/// address(0).
/// @return The Bond token address.
function bondToken() external view returns (address);
/// @notice Retrieves the first set of protocol statistics.
/// @return Stats1 structure containing the statistics.
function getStats1() external view returns (Stats1 memory);
/// @notice Retrieves the second set of protocol statistics.
/// @return Stats2 structure containing the statistics.
function getStats2() external view returns (Stats2 memory);
/// @notice Retrieves data about a specific batch.
/// @param _batchId The ID of the batch to retrieve.
/// @return batch_ The batch data.
function getBatch(uint64 _batchId) external view returns (Batch memory batch_);
/// @notice Retrieves a specific transition by batch ID and transition ID. This function may
/// revert if the transition is not found.
/// @param _batchId The batch ID.
/// @param _tid The transition ID.
/// @return The specified transition state.
function getTransitionById(
uint64 _batchId,
uint24 _tid
)
external
view
returns (ITaikoInbox.TransitionState memory);
/// @notice Retrieves a specific transition by batch ID and parent Hash. This function may
/// revert if the transition is not found.
/// @param _batchId The batch ID.
/// @param _parentHash The parent hash.
/// @return The specified transition state.
function getTransitionByParentHash(
uint64 _batchId,
bytes32 _parentHash
)
external
view
returns (ITaikoInbox.TransitionState memory);
/// @notice Retrieves the transition used for the last verified batch.
/// @return batchId_ The batch ID of the last verified transition.
/// @return blockId_ The block ID of the last verified block.
/// @return ts_ The last verified transition.
function getLastVerifiedTransition()
external
view
returns (uint64 batchId_, uint64 blockId_, TransitionState memory ts_);
/// @notice Retrieves the transition used for the last synced batch.
/// @return batchId_ The batch ID of the last synced transition.
/// @return blockId_ The block ID of the last synced block.
/// @return ts_ The last synced transition.
function getLastSyncedTransition()
external
view
returns (uint64 batchId_, uint64 blockId_, TransitionState memory ts_);
/// @notice Retrieves the transition used for verifying a batch.
/// @param _batchId The batch ID.
/// @return The transition used for verifying the batch.
function getBatchVerifyingTransition(uint64 _batchId)
external
view
returns (TransitionState memory);
/// @notice Retrieves the current protocol configuration.
/// @return The current configuration.
function pacayaConfig() external view returns (Config memory);
}
"
},
"contracts/layer1/verifiers/LibPublicInput.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "../../layer1/based/ITaikoInbox.sol";
/// @title LibPublicInput
/// @notice A library for handling hashing the so-called public input hash, used by sgx and zk
/// proofs.
/// @custom:security-contact security@taiko.xyz
library LibPublicInput {
/// @notice Hashes the public input for the proof verification.
/// @param _transition The transition to verify.
/// @param _verifierContract The contract address which as current verifier.
/// @param _newInstance The new instance address. For SGX it is the new signer address, for ZK
/// this variable is not used and must have value address(0).
/// @param _metaHash The meta hash.
/// @param _chainId The chain id.
/// @return The public input hash.
function hashPublicInputs(
ITaikoInbox.Transition memory _transition,
address _verifierContract,
address _newInstance,
bytes32 _metaHash,
uint64 _chainId
)
internal
pure
returns (bytes32)
{
return keccak256(
abi.encode(
"VERIFY_PROOF", _chainId, _verifierContract, _transition, _newInstance, _metaHash
)
);
}
}
"
},
"contracts/layer1/verifiers/IVerifier.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "../based/ITaikoInbox.sol";
/// @title IVerifier
/// @notice Defines the function that handles proof verification.
/// @custom:security-contact security@taiko.xyz
interface IVerifier {
struct Context {
uint64 batchId;
bytes32 metaHash;
ITaikoInbox.Transition transition;
}
/// @notice Verifies multiple proofs. This function must throw if the proof cannot be verified.
/// @param _ctxs The array of contexts for the proof verifications.
/// @param _proof The batch proof to verify.
function verifyProof(Context[] calldata _ctxs, bytes calldata _proof) external;
}
"
},
"node_modules/risc0-ethereum/contracts/src/Util.sol": {
"content": "// Copyright 2024 RISC Zero, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.9;
/// @notice reverse the byte order of the uint256 value.
/// @dev Solidity uses a big-endian ABI encoding. Reversing the byte order before encoding
/// ensure that the encoded value will be little-endian.
/// Written by k06a. https://ethereum.stackexchange.com/a/83627
function reverseByteOrderUint256(uint256 input) pure returns (uint256 v) {
v = input;
// swap bytes
v = ((v & 0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00) >> 8)
| ((v & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) << 8);
// swap 2-byte long pairs
v = ((v & 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >> 16)
| ((v & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) << 16);
// swap 4-byte long pairs
v = ((v & 0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000) >> 32)
| ((v & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) << 32);
// swap 8-byte long pairs
v = ((v & 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000) >> 64)
| ((v & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) << 64);
// swap 16-byte long pairs
v = (v >> 128) | (v << 128);
}
/// @notice reverse the byte order of the uint32 value.
/// @dev Solidity uses a big-endian ABI encoding. Reversing the byte order before encoding
/// ensure that the encoded value will be little-endian.
/// Written by k06a. https://ethereum.stackexchange.com/a/83627
function reverseByteOrderUint32(uint32 input) pure returns (uint32 v) {
v = input;
// swap bytes
v = ((v & 0xFF00FF00) >> 8) | ((v & 0x00FF00FF) << 8);
// swap 2-byte long pairs
v = (v >> 16) | (v << 16);
}
/// @notice reverse the byte order of the uint16 value.
/// @dev Solidity uses a big-endian ABI encoding. Reversing the byte order before encoding
/// ensure that the encoded value will be little-endian.
/// Written by k06a. https://ethereum.stackexchange.com/a/83627
function reverseByteOrderUint16(uint16 input) pure returns (uint16 v) {
v = input;
// swap bytes
v = (v >> 8) | ((v & 0x00FF) << 8);
}
"
},
"node_modules/@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.0;
import "../../interfaces/draft-IERC1822.sol";
import "../ERC1967/ERC1967Upgrade.sol";
/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
* {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
*
* A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
* reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
* `UUPSUpgradeable` with a custom implementation of upgrades.
*
* The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
*
* _Available since v4.1._
*/
abstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address private immutable __self = address(this);
/**
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is
* a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
* function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
require(address(this) != __self, "Function must be called through delegatecall");
require(_getImplementation() == __self, "Function must be called through active proxy");
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
_;
}
/**
* @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
* implementation. It is used to validate the implementation's compatibility when performing an upgrade.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
*/
function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
return _IMPLEMENTATION_SLOT;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeTo(address newImplementation) public virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, data, true);
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeTo} and {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal override onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
}
"
},
"node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)
pragma solidity ^0.8.0;
import "./OwnableUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/
abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
function __Ownable2Step_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable2Step_init_unchained() internal onlyInitializing {
}
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @dev The new owner accepts the ownership transfer.
*/
function acceptOwnership() public virtual {
address sender = _msgSender();
require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
_transferOwnership(sender);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
"
},
"contracts/shared/common/IResolver.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title IResolver
/// @notice This contract acts as a bridge for name-to-address resolution.
/// @custom:security-contact security@taiko.xyz
interface IResolver {
error RESOLVED_TO_ZERO_ADDRESS();
/// @notice Resolves a name to its address deployed on a specified chain.
/// @param _chainId The chainId of interest.
/// @param _name Name whose address is to be resolved.
/// @param _allowZeroAddress If set to true, does not throw if the resolved
/// address is `address(0)`.
/// @return Address associated with the given name on the specified
/// chain.
function resolve(
uint256 _chainId,
bytes32 _name,
bool _allowZeroAddress
)
external
view
returns (address);
}
"
},
"contracts/shared/based/LibSharedData.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
library LibSharedData {
/// @dev Struct that represents L2 basefee configurations
struct BaseFeeConfig {
uint8 adjustmentQuotient;
uint8 sharingPctg;
uint32 gasIssuancePerSecond;
uint64 minGasExcess;
uint32 maxGasIssuancePerBlock;
}
}
"
},
"node_modules/@openzeppelin/contracts/interfaces/draft-IERC1822.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
* proxy whose upgrades are fully controlled by the current implementation.
*/
interface IERC1822Proxiable {
/**
* @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
* address.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy.
*/
function proxiableUUID() external view returns (bytes32);
}
"
},
"node_modules/@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "../beacon/IBeacon.sol";
import "../../interfaces/IERC1967.sol";
import "../../interfaces/draft-IERC1822.sol";
import "../../utils/Address.sol";
import "../../utils/StorageSlot.sol";
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*
* _Available since v4.1._
*/
abstract contract ERC1967Upgrade is IERC1967 {
// This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev Returns the current implementation address.
*/
function _getImplementation() internal view returns (address) {
return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Perform implementation upgrade
*
* Emits an {Upgraded} event.
*/
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
/**
* @dev Perform implementation upgrade with additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
_upgradeTo(newImplementation);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(newImplementation, data);
}
}
/**
* @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
// Upgrades from old implementations will perform a rollback test. This test requires the new
// implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
// this special case will break upgrade paths from old UUPS implementation to new ones.
if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
_setImplementation(newImplementation);
} else {
try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
} catch {
revert("ERC1967Upgrade: new implementation is not UUPS");
}
_upgradeToAndCall(newImplementation, data, forceCall);
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*/
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
*/
bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Returns the current beacon.
*/
function _getBeacon() internal view returns (address) {
return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
require(
Address.isContract(IBeacon(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
}
/**
* @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
* not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
*
* Emits a {BeaconUpgraded} event.
*/
function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
}
}
}
"
},
"node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the curr
Submitted on: 2025-09-30 10:48:39
Comments
Log in to comment.
No comments yet.