Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 11922634 | 70 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
RiscZeroGroth16Verifier
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 10000 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// Copyright 2024 RISC Zero, Inc.
//
// The RiscZeroGroth16Verifier is a free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// The RiscZeroGroth16Verifier is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// the RiscZeroGroth16Verifier. If not, see <https://www.gnu.org/licenses/>.
//
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.9;
import {SafeCast} from "openzeppelin/contracts/utils/math/SafeCast.sol";
import {ControlID} from "./ControlID.sol";
import {Groth16Verifier} from "./Groth16Verifier.sol";
import {
ExitCode,
IRiscZeroVerifier,
Output,
OutputLib,
Receipt,
ReceiptClaim,
ReceiptClaimLib,
SystemExitCode,
VerificationFailed
} from "../IRiscZeroVerifier.sol";
import {StructHash} from "../StructHash.sol";
import {reverseByteOrderUint256, reverseByteOrderUint32} from "../Util.sol";
import {IRiscZeroSelectable} from "../IRiscZeroSelectable.sol";
/// @notice A Groth16 seal over the claimed receipt claim.
struct Seal {
uint256[2] a;
uint256[2][2] b;
uint256[2] c;
}
/// @notice Error raised when this verifier receives a receipt with a selector that does not match
/// its own. The selector value is calculated from the verifier parameters, and so this
/// usually indicates a mismatch between the version of the prover and this verifier.
error SelectorMismatch(bytes4 received, bytes4 expected);
/// @notice Groth16 verifier contract for RISC Zero receipts of execution.
contract RiscZeroGroth16Verifier is IRiscZeroVerifier, IRiscZeroSelectable, Groth16Verifier {
using ReceiptClaimLib for ReceiptClaim;
using OutputLib for Output;
using SafeCast for uint256;
/// @notice Semantic version of the RISC Zero system of which this contract is part.
/// @dev This is set to be equal to the version of the risc0-zkvm crate.
string public constant VERSION = "3.0.0";
/// @notice Control root hash binding the set of circuits in the RISC Zero system.
/// @dev This value controls what set of recursion programs (e.g. lift, join, resolve), and
/// therefore what version of the zkVM circuit, will be accepted by this contract. Each
/// instance of this verifier contract will accept a single release of the RISC Zero circuits.
///
/// New releases of RISC Zero's zkVM require updating these values. These values can be
/// calculated from the [risc0 monorepo][1] using: `cargo xtask bootstrap`.
///
/// [1]: https://github.com/risc0/risc0
bytes16 public immutable CONTROL_ROOT_0;
bytes16 public immutable CONTROL_ROOT_1;
bytes32 public immutable BN254_CONTROL_ID;
/// @notice A short key attached to the seal to select the correct verifier implementation.
/// @dev The selector is taken from the hash of the verifier parameters including the Groth16
/// verification key and the control IDs that commit to the RISC Zero circuits. If two
/// receipts have different selectors (i.e. different verifier parameters), then it can
/// generally be assumed that they need distinct verifier implementations. This is used as
/// part of the RISC Zero versioning mechanism.
///
/// A selector is not intended to be collision resistant, in that it is possible to find
/// two preimages that result in the same selector. This is acceptable since it's purpose
/// to a route a request among a set of trusted verifiers, and to make errors of sending a
/// receipt to a mismatching verifiers easier to debug. It is analogous to the ABI
/// function selectors.
bytes4 public immutable SELECTOR;
/// @notice Identifier for the Groth16 verification key encoded into the base contract.
/// @dev This value is computed at compile time.
function verifier_key_digest() internal pure returns (bytes32) {
bytes32[] memory ic_digests = new bytes32[](6);
ic_digests[0] = sha256(abi.encodePacked(IC0x, IC0y));
ic_digests[1] = sha256(abi.encodePacked(IC1x, IC1y));
ic_digests[2] = sha256(abi.encodePacked(IC2x, IC2y));
ic_digests[3] = sha256(abi.encodePacked(IC3x, IC3y));
ic_digests[4] = sha256(abi.encodePacked(IC4x, IC4y));
ic_digests[5] = sha256(abi.encodePacked(IC5x, IC5y));
return sha256(
abi.encodePacked(
// tag
sha256("risc0_groth16.VerifyingKey"),
// down
sha256(abi.encodePacked(alphax, alphay)),
sha256(abi.encodePacked(betax1, betax2, betay1, betay2)),
sha256(abi.encodePacked(gammax1, gammax2, gammay1, gammay2)),
sha256(abi.encodePacked(deltax1, deltax2, deltay1, deltay2)),
StructHash.taggedList(sha256("risc0_groth16.VerifyingKey.IC"), ic_digests),
// down length
uint16(5) << 8
)
);
}
constructor(bytes32 control_root, bytes32 bn254_control_id) {
(CONTROL_ROOT_0, CONTROL_ROOT_1) = splitDigest(control_root);
BN254_CONTROL_ID = bn254_control_id;
SELECTOR = bytes4(
sha256(
abi.encodePacked(
// tag
sha256("risc0.Groth16ReceiptVerifierParameters"),
// down
control_root,
reverseByteOrderUint256(uint256(bn254_control_id)),
verifier_key_digest(),
// down length
uint16(3) << 8
)
)
);
}
/// @notice splits a digest into two 128-bit halves to use as public signal inputs.
/// @dev RISC Zero's Circom verifier circuit takes each of two hash digests in two 128-bit
/// chunks. These values can be derived from the digest by splitting the digest in half and
/// then reversing the bytes of each.
function splitDigest(bytes32 digest) internal pure returns (bytes16, bytes16) {
uint256 reversed = reverseByteOrderUint256(uint256(digest));
return (bytes16(uint128(reversed)), bytes16(uint128(reversed >> 128)));
}
/// @inheritdoc IRiscZeroVerifier
function verify(bytes calldata seal, bytes32 imageId, bytes32 journalDigest) external view {
_verifyIntegrity(seal, ReceiptClaimLib.ok(imageId, journalDigest).digest());
}
/// @inheritdoc IRiscZeroVerifier
function verifyIntegrity(Receipt calldata receipt) external view {
return _verifyIntegrity(receipt.seal, receipt.claimDigest);
}
/// @notice internal implementation of verifyIntegrity, factored to avoid copying calldata bytes to memory.
function _verifyIntegrity(bytes calldata seal, bytes32 claimDigest) internal view {
// Check that the seal has a matching selector. Mismatch generally indicates that the
// prover and this verifier are using different parameters, and so the verification
// will not succeed.
if (SELECTOR != bytes4(seal[:4])) {
revert SelectorMismatch({received: bytes4(seal[:4]), expected: SELECTOR});
}
// Run the Groth16 verify procedure.
(bytes16 claim0, bytes16 claim1) = splitDigest(claimDigest);
Seal memory decodedSeal = abi.decode(seal[4:], (Seal));
bool verified = this.verifyProof(
decodedSeal.a,
decodedSeal.b,
decodedSeal.c,
[
uint256(uint128(CONTROL_ROOT_0)),
uint256(uint128(CONTROL_ROOT_1)),
uint256(uint128(claim0)),
uint256(uint128(claim1)),
uint256(BN254_CONTROL_ID)
]
);
// Revert is verification failed.
if (!verified) {
revert VerificationFailed();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.20;
/**
* @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeCast {
/**
* @dev Value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
/**
* @dev An int value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedIntToUint(int256 value);
/**
* @dev Value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
/**
* @dev An uint value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedUintToInt(uint256 value);
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toUint248(uint256 value) internal pure returns (uint248) {
if (value > type(uint248).max) {
revert SafeCastOverflowedUintDowncast(248, value);
}
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toUint240(uint256 value) internal pure returns (uint240) {
if (value > type(uint240).max) {
revert SafeCastOverflowedUintDowncast(240, value);
}
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toUint232(uint256 value) internal pure returns (uint232) {
if (value > type(uint232).max) {
revert SafeCastOverflowedUintDowncast(232, value);
}
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
if (value > type(uint224).max) {
revert SafeCastOverflowedUintDowncast(224, value);
}
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toUint216(uint256 value) internal pure returns (uint216) {
if (value > type(uint216).max) {
revert SafeCastOverflowedUintDowncast(216, value);
}
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toUint208(uint256 value) internal pure returns (uint208) {
if (value > type(uint208).max) {
revert SafeCastOverflowedUintDowncast(208, value);
}
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toUint200(uint256 value) internal pure returns (uint200) {
if (value > type(uint200).max) {
revert SafeCastOverflowedUintDowncast(200, value);
}
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toUint192(uint256 value) internal pure returns (uint192) {
if (value > type(uint192).max) {
revert SafeCastOverflowedUintDowncast(192, value);
}
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toUint184(uint256 value) internal pure returns (uint184) {
if (value > type(uint184).max) {
revert SafeCastOverflowedUintDowncast(184, value);
}
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toUint176(uint256 value) internal pure returns (uint176) {
if (value > type(uint176).max) {
revert SafeCastOverflowedUintDowncast(176, value);
}
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toUint168(uint256 value) internal pure returns (uint168) {
if (value > type(uint168).max) {
revert SafeCastOverflowedUintDowncast(168, value);
}
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toUint160(uint256 value) internal pure returns (uint160) {
if (value > type(uint160).max) {
revert SafeCastOverflowedUintDowncast(160, value);
}
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toUint152(uint256 value) internal pure returns (uint152) {
if (value > type(uint152).max) {
revert SafeCastOverflowedUintDowncast(152, value);
}
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toUint144(uint256 value) internal pure returns (uint144) {
if (value > type(uint144).max) {
revert SafeCastOverflowedUintDowncast(144, value);
}
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toUint136(uint256 value) internal pure returns (uint136) {
if (value > type(uint136).max) {
revert SafeCastOverflowedUintDowncast(136, value);
}
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
if (value > type(uint128).max) {
revert SafeCastOverflowedUintDowncast(128, value);
}
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toUint120(uint256 value) internal pure returns (uint120) {
if (value > type(uint120).max) {
revert SafeCastOverflowedUintDowncast(120, value);
}
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toUint112(uint256 value) internal pure returns (uint112) {
if (value > type(uint112).max) {
revert SafeCastOverflowedUintDowncast(112, value);
}
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toUint104(uint256 value) internal pure returns (uint104) {
if (value > type(uint104).max) {
revert SafeCastOverflowedUintDowncast(104, value);
}
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
if (value > type(uint96).max) {
revert SafeCastOverflowedUintDowncast(96, value);
}
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toUint88(uint256 value) internal pure returns (uint88) {
if (value > type(uint88).max) {
revert SafeCastOverflowedUintDowncast(88, value);
}
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toUint80(uint256 value) internal pure returns (uint80) {
if (value > type(uint80).max) {
revert SafeCastOverflowedUintDowncast(80, value);
}
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toUint72(uint256 value) internal pure returns (uint72) {
if (value > type(uint72).max) {
revert SafeCastOverflowedUintDowncast(72, value);
}
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
if (value > type(uint64).max) {
revert SafeCastOverflowedUintDowncast(64, value);
}
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toUint56(uint256 value) internal pure returns (uint56) {
if (value > type(uint56).max) {
revert SafeCastOverflowedUintDowncast(56, value);
}
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toUint48(uint256 value) internal pure returns (uint48) {
if (value > type(uint48).max) {
revert SafeCastOverflowedUintDowncast(48, value);
}
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toUint40(uint256 value) internal pure returns (uint40) {
if (value > type(uint40).max) {
revert SafeCastOverflowedUintDowncast(40, value);
}
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
if (value > type(uint32).max) {
revert SafeCastOverflowedUintDowncast(32, value);
}
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toUint24(uint256 value) internal pure returns (uint24) {
if (value > type(uint24).max) {
revert SafeCastOverflowedUintDowncast(24, value);
}
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
if (value > type(uint16).max) {
revert SafeCastOverflowedUintDowncast(16, value);
}
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toUint8(uint256 value) internal pure returns (uint8) {
if (value > type(uint8).max) {
revert SafeCastOverflowedUintDowncast(8, value);
}
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
if (value < 0) {
revert SafeCastOverflowedIntToUint(value);
}
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(248, value);
}
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(240, value);
}
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(232, value);
}
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(224, value);
}
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(216, value);
}
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(208, value);
}
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(200, value);
}
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(192, value);
}
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(184, value);
}
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(176, value);
}
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(168, value);
}
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(160, value);
}
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(152, value);
}
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(144, value);
}
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(136, value);
}
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(128, value);
}
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(120, value);
}
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(112, value);
}
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(104, value);
}
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(96, value);
}
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(88, value);
}
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(80, value);
}
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(72, value);
}
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(64, value);
}
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(56, value);
}
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(48, value);
}
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(40, value);
}
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(32, value);
}
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(24, value);
}
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(16, value);
}
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(8, value);
}
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
if (value > uint256(type(int256).max)) {
revert SafeCastOverflowedUintToInt(value);
}
return int256(value);
}
/**
* @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
*/
function toUint(bool b) internal pure returns (uint256 u) {
assembly ("memory-safe") {
u := iszero(iszero(b))
}
}
}// 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
// This file is automatically generated by:
// cargo xtask bootstrap-groth16
pragma solidity ^0.8.9;
library ControlID {
bytes32 public constant CONTROL_ROOT = hex"a54dc85ac99f851c92d7c96d7318af41dbe7c0194edfcc37eb4d422a998c1f56";
// NOTE: This has the opposite byte order to the value in the risc0 repository.
bytes32 public constant BN254_CONTROL_ID = hex"04446e66d300eb7fb45c9726bb53c793dda407a62e9601618bb43c5c14657ac0";
}// SPDX-License-Identifier: GPL-3.0
/*
Copyright 2021 0KIMS association.
This file is generated with [snarkJS](https://github.com/iden3/snarkjs).
snarkJS is a free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
snarkJS is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.7.0 <0.9.0;
contract Groth16Verifier {
// Scalar field size
uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
// Base field size
uint256 constant q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
// Verification Key data
uint256 constant alphax = 20491192805390485299153009773594534940189261866228447918068658471970481763042;
uint256 constant alphay = 9383485363053290200918347156157836566562967994039712273449902621266178545958;
uint256 constant betax1 = 4252822878758300859123897981450591353533073413197771768651442665752259397132;
uint256 constant betax2 = 6375614351688725206403948262868962793625744043794305715222011528459656738731;
uint256 constant betay1 = 21847035105528745403288232691147584728191162732299865338377159692350059136679;
uint256 constant betay2 = 10505242626370262277552901082094356697409835680220590971873171140371331206856;
uint256 constant gammax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
uint256 constant deltax1 = 1668323501672964604911431804142266013250380587483576094566949227275849579036;
uint256 constant deltax2 = 12043754404802191763554326994664886008979042643626290185762540825416902247219;
uint256 constant deltay1 = 7710631539206257456743780535472368339139328733484942210876916214502466455394;
uint256 constant deltay2 = 13740680757317479711909903993315946540841369848973133181051452051592786724563;
uint256 constant IC0x = 8446592859352799428420270221449902464741693648963397251242447530457567083492;
uint256 constant IC0y = 1064796367193003797175961162477173481551615790032213185848276823815288302804;
uint256 constant IC1x = 3179835575189816632597428042194253779818690147323192973511715175294048485951;
uint256 constant IC1y = 20895841676865356752879376687052266198216014795822152491318012491767775979074;
uint256 constant IC2x = 5332723250224941161709478398807683311971555792614491788690328996478511465287;
uint256 constant IC2y = 21199491073419440416471372042641226693637837098357067793586556692319371762571;
uint256 constant IC3x = 12457994489566736295787256452575216703923664299075106359829199968023158780583;
uint256 constant IC3y = 19706766271952591897761291684837117091856807401404423804318744964752784280790;
uint256 constant IC4x = 19617808913178163826953378459323299110911217259216006187355745713323154132237;
uint256 constant IC4y = 21663537384585072695701846972542344484111393047775983928357046779215877070466;
uint256 constant IC5x = 6834578911681792552110317589222010969491336870276623105249474534788043166867;
uint256 constant IC5y = 15060583660288623605191393599883223885678013570733629274538391874953353488393;
// Memory data
uint16 constant pVk = 0;
uint16 constant pPairing = 128;
uint16 constant pLastMem = 896;
function verifyProof(
uint256[2] calldata _pA,
uint256[2][2] calldata _pB,
uint256[2] calldata _pC,
uint256[5] calldata _pubSignals
) public view returns (bool) {
assembly {
function checkField(v) {
if iszero(lt(v, r)) {
mstore(0, 0)
return(0, 0x20)
}
}
// G1 function to multiply a G1 value(x,y) to value in an address
function g1_mulAccC(pR, x, y, s) {
let success
let mIn := mload(0x40)
mstore(mIn, x)
mstore(add(mIn, 32), y)
mstore(add(mIn, 64), s)
success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
if iszero(success) {
mstore(0, 0)
return(0, 0x20)
}
mstore(add(mIn, 64), mload(pR))
mstore(add(mIn, 96), mload(add(pR, 32)))
success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
if iszero(success) {
mstore(0, 0)
return(0, 0x20)
}
}
function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk {
let _pPairing := add(pMem, pPairing)
let _pVk := add(pMem, pVk)
mstore(_pVk, IC0x)
mstore(add(_pVk, 32), IC0y)
// Compute the linear combination vk_x
g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0)))
g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32)))
g1_mulAccC(_pVk, IC3x, IC3y, calldataload(add(pubSignals, 64)))
g1_mulAccC(_pVk, IC4x, IC4y, calldataload(add(pubSignals, 96)))
g1_mulAccC(_pVk, IC5x, IC5y, calldataload(add(pubSignals, 128)))
// -A
mstore(_pPairing, calldataload(pA))
mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q))
// B
mstore(add(_pPairing, 64), calldataload(pB))
mstore(add(_pPairing, 96), calldataload(add(pB, 32)))
mstore(add(_pPairing, 128), calldataload(add(pB, 64)))
mstore(add(_pPairing, 160), calldataload(add(pB, 96)))
// alpha1
mstore(add(_pPairing, 192), alphax)
mstore(add(_pPairing, 224), alphay)
// beta2
mstore(add(_pPairing, 256), betax1)
mstore(add(_pPairing, 288), betax2)
mstore(add(_pPairing, 320), betay1)
mstore(add(_pPairing, 352), betay2)
// vk_x
mstore(add(_pPairing, 384), mload(add(pMem, pVk)))
mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32))))
// gamma2
mstore(add(_pPairing, 448), gammax1)
mstore(add(_pPairing, 480), gammax2)
mstore(add(_pPairing, 512), gammay1)
mstore(add(_pPairing, 544), gammay2)
// C
mstore(add(_pPairing, 576), calldataload(pC))
mstore(add(_pPairing, 608), calldataload(add(pC, 32)))
// delta2
mstore(add(_pPairing, 640), deltax1)
mstore(add(_pPairing, 672), deltax2)
mstore(add(_pPairing, 704), deltay1)
mstore(add(_pPairing, 736), deltay2)
let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20)
isOk := and(success, mload(_pPairing))
}
let pMem := mload(0x40)
mstore(0x40, add(pMem, pLastMem))
// Validate that all evaluations ∈ F
checkField(calldataload(add(_pubSignals, 0)))
checkField(calldataload(add(_pubSignals, 32)))
checkField(calldataload(add(_pubSignals, 64)))
checkField(calldataload(add(_pubSignals, 96)))
checkField(calldataload(add(_pubSignals, 128)))
// Validate all evaluations
let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem)
mstore(0, isValid)
return(0, 0x20)
}
}
}// 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;
}// 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;
import {SafeCast} from "openzeppelin/contracts/utils/math/SafeCast.sol";
import {reverseByteOrderUint16} from "./Util.sol";
/// @notice Structural hashing routines used for RISC Zero data structures.
/// @dev
/// StructHash implements hashing for structs, incorporating type tags for domain separation.
/// The goals of this library are:
/// * Collision resistance: it should not be possible to find two semantically distinct values that
/// produce the same digest.
/// * Simplicity: implementations should be simple to understand and write, as these methods must
/// be implemented in multiple languages and environments, including zkSNARK circuits.
/// * Incremental openings: it should be possible to incrementally open a nested struct without
/// needing to open (very many) extra fields (i.e. the struct should be "Merkle-ized").
library StructHash {
using SafeCast for uint256;
// @notice Compute the struct digest with the given tag digest and digest fields down.
function taggedStruct(bytes32 tagDigest, bytes32[] memory down) internal pure returns (bytes32) {
bytes memory data = new bytes(0);
return taggedStruct(tagDigest, down, data);
}
// @notice Compute the struct digest with the given tag digest, digest fields down, and data.
function taggedStruct(bytes32 tagDigest, bytes32[] memory down, bytes memory data)
internal
pure
returns (bytes32)
{
uint16 downLen = down.length.toUint16();
// swap the byte order to encode as little-endian.
bytes2 downLenLE = bytes2((downLen << 8) | (downLen >> 8));
return sha256(abi.encodePacked(tagDigest, down, data, downLenLE));
}
// @notice Add an element (head) to the incremental hash of a list (tail).
function taggedListCons(bytes32 tagDigest, bytes32 head, bytes32 tail) internal pure returns (bytes32) {
bytes32[] memory down = new bytes32[](2);
down[0] = head;
down[1] = tail;
return taggedStruct(tagDigest, down);
}
// @notice Hash the list by using taggedListCons to repeatedly add to the head of the list.
function taggedList(bytes32 tagDigest, bytes32[] memory list) internal pure returns (bytes32) {
bytes32 curr = bytes32(0x0000000000000000000000000000000000000000000000000000000000000000);
for (uint256 i = 0; i < list.length; i++) {
curr = taggedListCons(tagDigest, list[list.length - 1 - i], curr);
}
return curr;
}
}// 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);
}// 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;
/// @notice Selectable interface for RISC Zero verifier.
interface IRiscZeroSelectable {
/// @notice A short key attached to the seal to select the correct verifier implementation.
/// @dev The selector is taken from the hash of the verifier parameters. If two
/// receipts have different selectors (i.e. different verifier parameters), then it can
/// generally be assumed that they need distinct verifier implementations. This is used as
/// part of the RISC Zero versioning mechanism.
///
/// A selector is not intended to be collision resistant, in that it is possible to find
/// two preimages that result in the same selector. This is acceptable since it's purpose
/// to a route a request among a set of trusted verifiers, and to make errors of sending a
/// receipt to a mismatching verifiers easier to debug. It is analogous to the ABI
/// function selectors.
function SELECTOR() external view returns (bytes4);
}{
"remappings": [
"forge-std/=../lib/forge-std/src/",
"openzeppelin/=../lib/openzeppelin-contracts/",
"@openzeppelin/contracts/=/Users/victorgraf/risc0/ethereum/lib/openzeppelin-contracts/contracts/",
"erc4626-tests/=/Users/victorgraf/risc0/ethereum/lib/openzeppelin-contracts/lib/erc4626-tests/",
"openzeppelin-contracts/=/Users/victorgraf/risc0/ethereum/lib/openzeppelin-contracts/contracts/"
],
"optimizer": {
"enabled": true,
"runs": 10000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": true
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"bytes32","name":"control_root","type":"bytes32"},{"internalType":"bytes32","name":"bn254_control_id","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"inputs":[{"internalType":"bytes4","name":"received","type":"bytes4"},{"internalType":"bytes4","name":"expected","type":"bytes4"}],"name":"SelectorMismatch","type":"error"},{"inputs":[],"name":"VerificationFailed","type":"error"},{"inputs":[],"name":"BN254_CONTROL_ID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CONTROL_ROOT_0","outputs":[{"internalType":"bytes16","name":"","type":"bytes16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CONTROL_ROOT_1","outputs":[{"internalType":"bytes16","name":"","type":"bytes16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SELECTOR","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"seal","type":"bytes"},{"internalType":"bytes32","name":"imageId","type":"bytes32"},{"internalType":"bytes32","name":"journalDigest","type":"bytes32"}],"name":"verify","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"seal","type":"bytes"},{"internalType":"bytes32","name":"claimDigest","type":"bytes32"}],"internalType":"struct Receipt","name":"receipt","type":"tuple"}],"name":"verifyIntegrity","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[2]","name":"_pA","type":"uint256[2]"},{"internalType":"uint256[2][2]","name":"_pB","type":"uint256[2][2]"},{"internalType":"uint256[2]","name":"_pC","type":"uint256[2]"},{"internalType":"uint256[5]","name":"_pubSignals","type":"uint256[5]"}],"name":"verifyProof","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]Contract Creation Code
6101808060405234610c92576040816121ac80380380916100208285610c96565b833981010312610c925780516020918201519091600883811c7eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff169084901b7fff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff001617601081811c7dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff1691901b7fffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000161780821c7bffffffff00000000ffffffff00000000ffffffff00000000ffffffff16911b7fffffffff00000000ffffffff00000000ffffffff00000000ffffffff000000001617604081811c77ffffffffffffffff0000000000000000ffffffffffffffff1691901b7fffffffffffffffff0000000000000000ffffffffffffffff00000000000000001617608081811c91901b176001600160801b031981811660a052608091821b16905260c08190526040517f72697363302e47726f74683136526563656970745665726966696572506172618152656d657465727360d01b602082810191909152905f9060269060025afa15610b11575f5190600881811c7eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff1691901b7fff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff001617601081811c7dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff1691901b7fffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff00001617602081811c7bffffffff00000000ffffffff00000000ffffffff00000000ffffffff1691901b7fffffffff00000000ffffffff00000000ffffffff00000000ffffffff000000001617604081811c77ffffffffffffffff0000000000000000ffffffffffffffff1691901b7fffffffffffffffff0000000000000000ffffffffffffffff00000000000000001617608081811c91901b179160e0604051916103068284610c96565b60068352601f19820136602085013760205f604051828101907f12ac9a25dcd5e1a832a9061a082c15dd1d61aa9c4d553505739d0f5d65dc3be482527f025aa744581ebe7ad91731911c898569106ff5a2d30f3eee2b23c60ee980acd4604082015260408152610377606082610c96565b604051918291518091835e8101838152039060025afa15610b11575f5161039d84610ccd565b5260205f604051828101907f0707b920bc978c02f292fae2036e057be54294114ccc3c8769d883f688a1423f82527f2e32a094b7589554f7bc357bf63481acd2d55555c203383782a4650787ff6642604082015260408152610400606082610c96565b604051918291518091835e8101838152039060025afa15610b11575f5161042684610cda565b5260205f604051828101907f0bca36e2cbe6394b3e249751853f961511011c7148e336f4fd974644850fc34782527f2ede7c9acf48cf3a3729fa3d68714e2a8435d4fa6db8f7f409c153b1fcdf9b8b604082015260408152610489606082610c96565b604051918291518091835e8101838152039060025afa15610b11575f51835160021015610b5257606084015260205f604051828101907f1b8af999dbfbb3927c091cc2aaf201e488cbacc3e2c6b6fb5a25f9112e04f2a782527f2b91a26aa92e1b6f5722949f192a81c850d586d81a60157f3e9cf04f679cccd6604082015260408152610517606082610c96565b604051918291518091835e8101838152039060025afa15610b11575f51835160031015610b5257608084015260205f604051828101907f2b5f494ed674235b8ac1750bdfd5a7615f002d4a1dcefeddd06eda5a076ccd0d82527f2fe520ad2020aab9cbba817fcbb9a863b8a76ff88f14f912c5e71665b2ad5e826040820152604081526105a5606082610c96565b604051918291518091835e8101838152039060025afa15610b11575f51835160041015610b525760a084015260205f604051828101907f0f1c3c0d5d9da0fa03666843cde4e82e869ba5252fce3c25d5940320b1c4d49382527f214bfcff74f425f6fe8c0d07b307482d8bc8bb2f3608f68287aa01bd0b69e809604082015260408152610633606082610c96565b604051918291518091835e8101838152039060025afa15610b11575f51835160051015610b525760c084015260205f601a6040517f72697363305f67726f746831362e566572696679696e674b6579000000000000815260025afa15610b11575f519460205f604051828101907f2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e282527f14bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d19266040820152604081526106f8606082610c96565b604051918291518091835e8101838152039060025afa15610b11575f519460205f604051828101907f0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c82527f0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab60408201527f304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a760608201527f1739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec86080820152608081526107c460a082610c96565b604051918291518091835e8101838152039060025afa15610b11575f519560205f604051828101907f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c282527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60408201527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60608201527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60808201526080815261089060a082610c96565b604051918291518091835e8101838152039060025afa15610b11575f519760205f604051828101907f03b03cd5effa95ac9bee94f1f5ef907157bda4812ccf0b4c91f42bb629f83a1c82527f1aa085ff28179a12d922dba0547057ccaae94b9d69cfaa4e60401fea7f3e033360408201527f110c10134f200b19f6490846d518c9aea868366efb7228ca5c91d2940d03076260608201527f1e60f31fcbf757e837e867178318832d0b2d74d59e2fea1c7142df187d3fc6d360808201526080815261095c60a082610c96565b604051918291518091835e8101838152039060025afa15610b11575f5160205f601d6040517f72697363305f67726f746831362e566572696679696e674b65792e4943000000815260025afa15610b11575f8051610140526101008190526060610120526020610160525b885180610100511015610b7a575f19810190808211610b66576101005190035f1901908111610b66578951811015610b5257610160519060051b8a0101519060405191610a176101205184610c96565b60028352610160516040903690850137610a3083610ccd565b52610a3a82610cda565b52604051610a4b6101605182610c96565b5f8152601f196101605101366101605183013781519061ffff8211610b3a5791604051928391610140516101605184015260408301815190916101605101905f905b808210610b1c575050509281610ad994600294935180926101605101825e019061ffff60f01b9061ff0060ff8260081c169160081b161760f01b16815203601d19810184520182610c96565b5f60405191805180916101605101845e820191818352806101605193039060025afa15610b11575f51610100805160010190526109c7565b6040513d5f823e3d90fd5b82518452610160518896509384019390920191600190910190610a8d565b506306dfcc6560e41b5f52601060045260245260445ffd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b505f92918b8b6040519661016051880195865260408801526060870152608086015260a085015260c0840152600560f81b8784015260c28352610bbe60e284610c96565b60405192518091845e820191818352806101605193039060025afa15610b11575f9182519060405194610160518601938452604086015260608501526080840152600360f81b60a084015260828352610c1860a284610c96565b60405192518091845e820191818352806101605193039060025afa15610b11575f516001600160e01b03191681526040516114c19182610ceb833960805182818161062c0152610efc015260a0518281816105d00152610f22015260c0518281816101a00152610f5a01525181818160c70152610e380152f35b5f80fd5b601f909101601f19168101906001600160401b03821190821017610cb957604052565b634e487b7160e01b5f52604160045260245ffd5b805115610b525760200190565b805160011015610b52576040019056fe60806040526004361015610011575f80fd5b5f3560e01c8063053c238d146100945780631599ead51461008f578063258038e21461008a57806334baeab9146100855780638989fa2e146100805780639181e4b11461007b578063ab750e75146100765763ffa1ad7414610071575f80fd5b6107a8565b610650565b6105f4565b610598565b6101de565b610189565b6100f4565b346100f0575f6003193601126100f0577fffffffff000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000001660805260206080f35b5f80fd5b346100f05760206003193601126100f05760043567ffffffffffffffff81116100f05780360360406003198201126100f0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd826004013591018112156100f057810160048101359067ffffffffffffffff82116100f0576024019080360382136100f057602461018793013591610e34565b005b346100f0575f6003193601126100f05760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b906004916044116100f057565b9060c491610104116100f057565b346100f0576101a06003193601126100f0576101f9366101c3565b3660c4116100f05761020a366101d0565b366101a4116100f0576040519061038082016040526101043561022c8161083b565b610124359361023a8561083b565b610144356102478161083b565b610164356102548161083b565b61018435916102628361083b565b60808701977f12ac9a25dcd5e1a832a9061a082c15dd1d61aa9c4d553505739d0f5d65dc3be4885260208801957f025aa744581ebe7ad91731911c898569106ff5a2d30f3eee2b23c60ee980acd487526102bc908961086c565b6102c690886108f8565b6102d09087610984565b6102da9086610a10565b6102e49085610a9c565b803585527f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4760209182013581030660a085015260443560c085015260643560e085015260843561010085015260a4356101208501527f2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e26101408501527f14bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d19266101608501527f0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c6101808501527f0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab6101a08501527f304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a76101c08501527f1739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec86101e0850152835161020085015290516102208401527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c26102408401527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6102608401527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b6102808401527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa6102a084015281356102c084015201356102e08201527f03b03cd5effa95ac9bee94f1f5ef907157bda4812ccf0b4c91f42bb629f83a1c6103008201527f1aa085ff28179a12d922dba0547057ccaae94b9d69cfaa4e60401fea7f3e03336103208201527f110c10134f200b19f6490846d518c9aea868366efb7228ca5c91d2940d0307626103408201527f1e60f31fcbf757e837e867178318832d0b2d74d59e2fea1c7142df187d3fc6d36103609091015280805a6107cf1901602092600861030092fa9051165f5260205ff35b346100f0575f6003193601126100f05760206040517fffffffffffffffffffffffffffffffff000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000168152f35b346100f0575f6003193601126100f05760206040517fffffffffffffffffffffffffffffffff000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000168152f35b346100f05760606003193601126100f05760043567ffffffffffffffff81116100f057366023820112156100f05780600401359067ffffffffffffffff82116100f05736602483830101116100f057610187916024359060246044359301610b28565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040810190811067ffffffffffffffff8211176106fc57604052565b6106b3565b60a0810190811067ffffffffffffffff8211176106fc57604052565b6060810190811067ffffffffffffffff8211176106fc57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176106fc57604052565b60405190610789604083610739565b565b6040519061078960a083610739565b906107896040519283610739565b346100f0575f6003193601126100f0576040516107c4816106e0565b60058152604060208201917f332e302e3000000000000000000000000000000000000000000000000000000083527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8351948593602085525180918160208701528686015e5f85828601015201168101030190f35b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001111561086457565b5f805260205ff35b604051917f0707b920bc978c02f292fae2036e057be54294114ccc3c8769d883f688a1423f83527f2e32a094b7589554f7bc357bf63481acd2d55555c203383782a4650787ff664260208401526040830190815260408360608160076107cf195a01fa1561086457604092608091835190526020830151606082015260066107cf195a01fa1561086457565b604051917f0bca36e2cbe6394b3e249751853f961511011c7148e336f4fd974644850fc34783527f2ede7c9acf48cf3a3729fa3d68714e2a8435d4fa6db8f7f409c153b1fcdf9b8b60208401526040830190815260408360608160076107cf195a01fa1561086457604092608091835190526020830151606082015260066107cf195a01fa1561086457565b604051917f1b8af999dbfbb3927c091cc2aaf201e488cbacc3e2c6b6fb5a25f9112e04f2a783527f2b91a26aa92e1b6f5722949f192a81c850d586d81a60157f3e9cf04f679cccd660208401526040830190815260408360608160076107cf195a01fa1561086457604092608091835190526020830151606082015260066107cf195a01fa1561086457565b604051917f2b5f494ed674235b8ac1750bdfd5a7615f002d4a1dcefeddd06eda5a076ccd0d83527f2fe520ad2020aab9cbba817fcbb9a863b8a76ff88f14f912c5e71665b2ad5e8260208401526040830190815260408360608160076107cf195a01fa1561086457604092608091835190526020830151606082015260066107cf195a01fa1561086457565b604051917f0f1c3c0d5d9da0fa03666843cde4e82e869ba5252fce3c25d5940320b1c4d49383527f214bfcff74f425f6fe8c0d07b307482d8bc8bb2f3608f68287aa01bd0b69e80960208401526040830190815260408360608160076107cf195a01fa1561086457604092608091835190526020830151606082015260066107cf195a01fa1561086457565b91610bdd90610789945f6080604051610b4081610701565b828152826020820152604051610b55816106e0565b83815283602082015260408201528260608201520152610b96610b7661077a565b915f83525f6020840152610b8861077a565b9081525f6020820152611426565b90610b9f61078b565b9283527fa3acc27117418996340b84e5a90f3ef4c49d22c79e44aad822ec9c313e1eb8e2602084015260408301525f6060830152608082015261111f565b91610e34565b906004116100f05790600490565b90929192836004116100f05783116100f057600401916003190190565b919091357fffffffff0000000000000000000000000000000000000000000000000000000081169260048110610c42575050565b7fffffffff00000000000000000000000000000000000000000000000000000000929350829060040360031b1b161690565b9080601f830112156100f05760405191610c8f604084610739565b8290604081019283116100f057905b828210610cab5750505090565b8135815260209182019101610c9e565b610100818303126100f05760405191610cd38361071d565b610cdd8183610c74565b835280605f830112156100f0576040918251610cf98482610739565b8060c08301928484116100f05785809101915b848310610d2c575050506020850152610d259190610c74565b9082015290565b602090610d398785610c74565b8152019101908590610d0c565b908160209103126100f0575180151581036100f05790565b905f905b60028210610d6f57505050565b6020806001928551815201930191019091610d62565b905f905b60058210610d9657505050565b6020806001928551815201930191019091610d89565b919493929094610dc1836101a0810197610d5e565b5f604084015b60028210610def5750505081610de86101009260c061078996950190610d5e565b0190610d85565b82515f90825b60028310610e13575050506020604060019201930191019091610dc7565b6020806001928451815201920192019190610df5565b6040513d5f823e3d90fd5b90917f0000000000000000000000000000000000000000000000000000000000000000610e92610e6d610e678686610be3565b90610c0e565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b7fffffffff00000000000000000000000000000000000000000000000000000000821603611029575090610ede610ed684610ece602095611261565b969094610bf1565b810190610cbb565b90610fb282519160408585015194015195610ef960a061079a565b917f000000000000000000000000000000000000000000000000000000000000000060801c83527f000000000000000000000000000000000000000000000000000000000000000060801c8784015260801c604083015260801c60608201527f0000000000000000000000000000000000000000000000000000000000000000608082015260405195869485947f34baeab900000000000000000000000000000000000000000000000000000000865260048601610dac565b0381305afa908115611024575f91610ff5575b5015610fcd57565b7f439cc0cd000000000000000000000000000000000000000000000000000000005f5260045ffd5b611017915060203d60201161101d575b61100f8183610739565b810190610d46565b5f610fc5565b503d611005565b610e29565b61108d9061103a610e678686610be3565b7fb8b38d4c000000000000000000000000000000000000000000000000000000005f527fffffffff0000000000000000000000000000000000000000000000000000000090811660045216602452604490565b5ffd5b6003111561109a57565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60205f60126040517f72697363302e52656365697074436c61696d0000000000000000000000000000815260025afa15611024575f5190565b51600381101561109a5790565b805191908290602001825e015f815290565b5f6112516020926112456111316110c7565b61121960608401519380519088810151906040608082015191019061118861116c6111828d6111786111638751611100565b61116c81611090565b60181b63ff0000001690565b9551015160ff1690565b60ff1690565b9261040094604051998a988e8a019692947fffffffff000000000000000000000000000000000000000000000000000000009460aa999686947fffff00000000000000000000000000000000000000000000000000000000000099948b5260208b015260408a01526060890152608088015260e01b1660a086015260e01b1660a484015260f01b1660a88201520190565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610739565b6040519182809261110d565b039060025afa15611024575f5190565b8060081c9060081b907cff000000ff000000ff000000ff000000ff000000ff000000ff000000ff7dff000000ff000000ff000000ff000000ff000000ff000000ff000000ff007fff000000ff000000ff000000ff000000ff000000ff000000ff000000ff00000084167eff000000ff000000ff000000ff000000ff000000ff000000ff000000ff000084161760101c931691161760101b176113477bffffffff00000000ffffffff00000000ffffffff00000000ffffffff7fffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000831660201c921660201b90565b1761139877ffffffffffffffff0000000000000000ffffffffffffffff6113907fffffffffffffffff0000000000000000ffffffffffffffff0000000000000000841660401c90565b921660401b90565b176113ad6113a68260801c90565b9160801b90565b17907fffffffffffffffffffffffffffffffff0000000000000000000000000000000061141d6113f56113e08560801c90565b6fffffffffffffffffffffffffffffffff1690565b60801b7fffffffffffffffffffffffffffffffff000000000000000000000000000000001690565b9260801b169190565b60205f600c6040517f72697363302e4f75747075740000000000000000000000000000000000000000815260025afa15611024575f80518251602093840151604080518087019490945283019190915260608201527f02000000000000000000000000000000000000000000000000000000000000006080820152606281526112519061124560828261073956fea164736f6c634300081a000aa54dc85ac99f851c92d7c96d7318af41dbe7c0194edfcc37eb4d422a998c1f5604446e66d300eb7fb45c9726bb53c793dda407a62e9601618bb43c5c14657ac0
Deployed Bytecode
0x60806040526004361015610011575f80fd5b5f3560e01c8063053c238d146100945780631599ead51461008f578063258038e21461008a57806334baeab9146100855780638989fa2e146100805780639181e4b11461007b578063ab750e75146100765763ffa1ad7414610071575f80fd5b6107a8565b610650565b6105f4565b610598565b6101de565b610189565b6100f4565b346100f0575f6003193601126100f0577fffffffff000000000000000000000000000000000000000000000000000000007f73c457ba000000000000000000000000000000000000000000000000000000001660805260206080f35b5f80fd5b346100f05760206003193601126100f05760043567ffffffffffffffff81116100f05780360360406003198201126100f0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd826004013591018112156100f057810160048101359067ffffffffffffffff82116100f0576024019080360382136100f057602461018793013591610e34565b005b346100f0575f6003193601126100f05760206040517f04446e66d300eb7fb45c9726bb53c793dda407a62e9601618bb43c5c14657ac08152f35b906004916044116100f057565b9060c491610104116100f057565b346100f0576101a06003193601126100f0576101f9366101c3565b3660c4116100f05761020a366101d0565b366101a4116100f0576040519061038082016040526101043561022c8161083b565b610124359361023a8561083b565b610144356102478161083b565b610164356102548161083b565b61018435916102628361083b565b60808701977f12ac9a25dcd5e1a832a9061a082c15dd1d61aa9c4d553505739d0f5d65dc3be4885260208801957f025aa744581ebe7ad91731911c898569106ff5a2d30f3eee2b23c60ee980acd487526102bc908961086c565b6102c690886108f8565b6102d09087610984565b6102da9086610a10565b6102e49085610a9c565b803585527f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4760209182013581030660a085015260443560c085015260643560e085015260843561010085015260a4356101208501527f2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e26101408501527f14bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d19266101608501527f0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c6101808501527f0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab6101a08501527f304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a76101c08501527f1739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec86101e0850152835161020085015290516102208401527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c26102408401527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6102608401527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b6102808401527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa6102a084015281356102c084015201356102e08201527f03b03cd5effa95ac9bee94f1f5ef907157bda4812ccf0b4c91f42bb629f83a1c6103008201527f1aa085ff28179a12d922dba0547057ccaae94b9d69cfaa4e60401fea7f3e03336103208201527f110c10134f200b19f6490846d518c9aea868366efb7228ca5c91d2940d0307626103408201527f1e60f31fcbf757e837e867178318832d0b2d74d59e2fea1c7142df187d3fc6d36103609091015280805a6107cf1901602092600861030092fa9051165f5260205ff35b346100f0575f6003193601126100f05760206040517fffffffffffffffffffffffffffffffff000000000000000000000000000000007f561f8c992a424deb37ccdf4e19c0e7db00000000000000000000000000000000168152f35b346100f0575f6003193601126100f05760206040517fffffffffffffffffffffffffffffffff000000000000000000000000000000007f41af18736dc9d7921c859fc95ac84da500000000000000000000000000000000168152f35b346100f05760606003193601126100f05760043567ffffffffffffffff81116100f057366023820112156100f05780600401359067ffffffffffffffff82116100f05736602483830101116100f057610187916024359060246044359301610b28565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040810190811067ffffffffffffffff8211176106fc57604052565b6106b3565b60a0810190811067ffffffffffffffff8211176106fc57604052565b6060810190811067ffffffffffffffff8211176106fc57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176106fc57604052565b60405190610789604083610739565b565b6040519061078960a083610739565b906107896040519283610739565b346100f0575f6003193601126100f0576040516107c4816106e0565b60058152604060208201917f332e302e3000000000000000000000000000000000000000000000000000000083527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8351948593602085525180918160208701528686015e5f85828601015201168101030190f35b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001111561086457565b5f805260205ff35b604051917f0707b920bc978c02f292fae2036e057be54294114ccc3c8769d883f688a1423f83527f2e32a094b7589554f7bc357bf63481acd2d55555c203383782a4650787ff664260208401526040830190815260408360608160076107cf195a01fa1561086457604092608091835190526020830151606082015260066107cf195a01fa1561086457565b604051917f0bca36e2cbe6394b3e249751853f961511011c7148e336f4fd974644850fc34783527f2ede7c9acf48cf3a3729fa3d68714e2a8435d4fa6db8f7f409c153b1fcdf9b8b60208401526040830190815260408360608160076107cf195a01fa1561086457604092608091835190526020830151606082015260066107cf195a01fa1561086457565b604051917f1b8af999dbfbb3927c091cc2aaf201e488cbacc3e2c6b6fb5a25f9112e04f2a783527f2b91a26aa92e1b6f5722949f192a81c850d586d81a60157f3e9cf04f679cccd660208401526040830190815260408360608160076107cf195a01fa1561086457604092608091835190526020830151606082015260066107cf195a01fa1561086457565b604051917f2b5f494ed674235b8ac1750bdfd5a7615f002d4a1dcefeddd06eda5a076ccd0d83527f2fe520ad2020aab9cbba817fcbb9a863b8a76ff88f14f912c5e71665b2ad5e8260208401526040830190815260408360608160076107cf195a01fa1561086457604092608091835190526020830151606082015260066107cf195a01fa1561086457565b604051917f0f1c3c0d5d9da0fa03666843cde4e82e869ba5252fce3c25d5940320b1c4d49383527f214bfcff74f425f6fe8c0d07b307482d8bc8bb2f3608f68287aa01bd0b69e80960208401526040830190815260408360608160076107cf195a01fa1561086457604092608091835190526020830151606082015260066107cf195a01fa1561086457565b91610bdd90610789945f6080604051610b4081610701565b828152826020820152604051610b55816106e0565b83815283602082015260408201528260608201520152610b96610b7661077a565b915f83525f6020840152610b8861077a565b9081525f6020820152611426565b90610b9f61078b565b9283527fa3acc27117418996340b84e5a90f3ef4c49d22c79e44aad822ec9c313e1eb8e2602084015260408301525f6060830152608082015261111f565b91610e34565b906004116100f05790600490565b90929192836004116100f05783116100f057600401916003190190565b919091357fffffffff0000000000000000000000000000000000000000000000000000000081169260048110610c42575050565b7fffffffff00000000000000000000000000000000000000000000000000000000929350829060040360031b1b161690565b9080601f830112156100f05760405191610c8f604084610739565b8290604081019283116100f057905b828210610cab5750505090565b8135815260209182019101610c9e565b610100818303126100f05760405191610cd38361071d565b610cdd8183610c74565b835280605f830112156100f0576040918251610cf98482610739565b8060c08301928484116100f05785809101915b848310610d2c575050506020850152610d259190610c74565b9082015290565b602090610d398785610c74565b8152019101908590610d0c565b908160209103126100f0575180151581036100f05790565b905f905b60028210610d6f57505050565b6020806001928551815201930191019091610d62565b905f905b60058210610d9657505050565b6020806001928551815201930191019091610d89565b919493929094610dc1836101a0810197610d5e565b5f604084015b60028210610def5750505081610de86101009260c061078996950190610d5e565b0190610d85565b82515f90825b60028310610e13575050506020604060019201930191019091610dc7565b6020806001928451815201920192019190610df5565b6040513d5f823e3d90fd5b90917f73c457ba00000000000000000000000000000000000000000000000000000000610e92610e6d610e678686610be3565b90610c0e565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b7fffffffff00000000000000000000000000000000000000000000000000000000821603611029575090610ede610ed684610ece602095611261565b969094610bf1565b810190610cbb565b90610fb282519160408585015194015195610ef960a061079a565b917f41af18736dc9d7921c859fc95ac84da50000000000000000000000000000000060801c83527f561f8c992a424deb37ccdf4e19c0e7db0000000000000000000000000000000060801c8784015260801c604083015260801c60608201527f04446e66d300eb7fb45c9726bb53c793dda407a62e9601618bb43c5c14657ac0608082015260405195869485947f34baeab900000000000000000000000000000000000000000000000000000000865260048601610dac565b0381305afa908115611024575f91610ff5575b5015610fcd57565b7f439cc0cd000000000000000000000000000000000000000000000000000000005f5260045ffd5b611017915060203d60201161101d575b61100f8183610739565b810190610d46565b5f610fc5565b503d611005565b610e29565b61108d9061103a610e678686610be3565b7fb8b38d4c000000000000000000000000000000000000000000000000000000005f527fffffffff0000000000000000000000000000000000000000000000000000000090811660045216602452604490565b5ffd5b6003111561109a57565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60205f60126040517f72697363302e52656365697074436c61696d0000000000000000000000000000815260025afa15611024575f5190565b51600381101561109a5790565b805191908290602001825e015f815290565b5f6112516020926112456111316110c7565b61121960608401519380519088810151906040608082015191019061118861116c6111828d6111786111638751611100565b61116c81611090565b60181b63ff0000001690565b9551015160ff1690565b60ff1690565b9261040094604051998a988e8a019692947fffffffff000000000000000000000000000000000000000000000000000000009460aa999686947fffff00000000000000000000000000000000000000000000000000000000000099948b5260208b015260408a01526060890152608088015260e01b1660a086015260e01b1660a484015260f01b1660a88201520190565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610739565b6040519182809261110d565b039060025afa15611024575f5190565b8060081c9060081b907cff000000ff000000ff000000ff000000ff000000ff000000ff000000ff7dff000000ff000000ff000000ff000000ff000000ff000000ff000000ff007fff000000ff000000ff000000ff000000ff000000ff000000ff000000ff00000084167eff000000ff000000ff000000ff000000ff000000ff000000ff000000ff000084161760101c931691161760101b176113477bffffffff00000000ffffffff00000000ffffffff00000000ffffffff7fffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000831660201c921660201b90565b1761139877ffffffffffffffff0000000000000000ffffffffffffffff6113907fffffffffffffffff0000000000000000ffffffffffffffff0000000000000000841660401c90565b921660401b90565b176113ad6113a68260801c90565b9160801b90565b17907fffffffffffffffffffffffffffffffff0000000000000000000000000000000061141d6113f56113e08560801c90565b6fffffffffffffffffffffffffffffffff1690565b60801b7fffffffffffffffffffffffffffffffff000000000000000000000000000000001690565b9260801b169190565b60205f600c6040517f72697363302e4f75747075740000000000000000000000000000000000000000815260025afa15611024575f80518251602093840151604080518087019490945283019190915260608201527f02000000000000000000000000000000000000000000000000000000000000006080820152606281526112519061124560828261073956fea164736f6c634300081a000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
a54dc85ac99f851c92d7c96d7318af41dbe7c0194edfcc37eb4d422a998c1f5604446e66d300eb7fb45c9726bb53c793dda407a62e9601618bb43c5c14657ac0
-----Decoded View---------------
Arg [0] : control_root (bytes32): 0xa54dc85ac99f851c92d7c96d7318af41dbe7c0194edfcc37eb4d422a998c1f56
Arg [1] : bn254_control_id (bytes32): 0x04446e66d300eb7fb45c9726bb53c793dda407a62e9601618bb43c5c14657ac0
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : a54dc85ac99f851c92d7c96d7318af41dbe7c0194edfcc37eb4d422a998c1f56
Arg [1] : 04446e66d300eb7fb45c9726bb53c793dda407a62e9601618bb43c5c14657ac0
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.