Base Sepolia Testnet

Contract

0x6D645eD60073a37880AF9B2ac10a01049C74F368
Source Code Source Code

Overview

ETH Balance

0 ETH

More Info

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Amount
0x0d32f061399821682026-04-09 11:03:445 days ago1775732624IN
0x6D645eD6...49C74F368
0 ETH0.000001580.006
0x0d32f061399818832026-04-09 10:54:145 days ago1775732054IN
0x6D645eD6...49C74F368
0 ETH0.000001590.006
0x0d32f061399813182026-04-09 10:35:245 days ago1775730924IN
0x6D645eD6...49C74F368
0 ETH0.000001590.006
0x0d32f061380486442026-02-23 16:52:5650 days ago1771865576IN
0x6D645eD6...49C74F368
0 ETH0.000001390.006
0x0d32f061375735722026-02-12 16:57:1261 days ago1770915432IN
0x6D645eD6...49C74F368
0 ETH0.00000130.003
0x0d32f061375735182026-02-12 16:55:2461 days ago1770915324IN
0x6D645eD6...49C74F368
0 ETH0.000001270.003
0x0d32f061375735012026-02-12 16:54:5061 days ago1770915290IN
0x6D645eD6...49C74F368
0 ETH0.00000130.003
0x0d32f061375734252026-02-12 16:52:1861 days ago1770915138IN
0x6D645eD6...49C74F368
0 ETH0.000001310.003
0x0d32f061375734172026-02-12 16:52:0261 days ago1770915122IN
0x6D645eD6...49C74F368
0 ETH0.000001310.003
0x0d32f061375734062026-02-12 16:51:4061 days ago1770915100IN
0x6D645eD6...49C74F368
0 ETH0.000001260.003
0x0d32f061375734002026-02-12 16:51:2861 days ago1770915088IN
0x6D645eD6...49C74F368
0 ETH0.000001250.003
0x0d32f061375733852026-02-12 16:50:5861 days ago1770915058IN
0x6D645eD6...49C74F368
0 ETH0.000001230.003
0x0d32f061375733832026-02-12 16:50:5461 days ago1770915054IN
0x6D645eD6...49C74F368
0 ETH0.000001240.003
0x0d32f061375733652026-02-12 16:50:1861 days ago1770915018IN
0x6D645eD6...49C74F368
0 ETH0.000001280.003
0x0d32f061375733292026-02-12 16:49:0661 days ago1770914946IN
0x6D645eD6...49C74F368
0 ETH0.000001360.003
0x0d32f061375731322026-02-12 16:42:3261 days ago1770914552IN
0x6D645eD6...49C74F368
0 ETH0.000001340.003
0x0d32f061375731142026-02-12 16:41:5661 days ago1770914516IN
0x6D645eD6...49C74F368
0 ETH0.00000130.003
0x0d32f061375730962026-02-12 16:41:2061 days ago1770914480IN
0x6D645eD6...49C74F368
0 ETH0.000001240.003
0x0d32f061375730772026-02-12 16:40:4261 days ago1770914442IN
0x6D645eD6...49C74F368
0 ETH0.000001270.003
0x0d32f061375730592026-02-12 16:40:0661 days ago1770914406IN
0x6D645eD6...49C74F368
0 ETH0.000001270.003
0x0d32f061375730412026-02-12 16:39:3061 days ago1770914370IN
0x6D645eD6...49C74F368
0 ETH0.000001340.003
0x0d32f061375730222026-02-12 16:38:5261 days ago1770914332IN
0x6D645eD6...49C74F368
0 ETH0.000001350.003
0x0d32f061375730032026-02-12 16:38:1461 days ago1770914294IN
0x6D645eD6...49C74F368
0 ETH0.000001390.003
0x0d32f061375710242026-02-12 15:32:1661 days ago1770910336IN
0x6D645eD6...49C74F368
0 ETH0.000001240.003
0x0d32f061375663262026-02-12 12:55:4061 days ago1770900940IN
0x6D645eD6...49C74F368
0 ETH0.000001290.003
View all transactions

Parent Transaction Hash Block From To Amount
View All Internal Transactions

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Groth16Verifier

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 200 runs

Other Settings:
shanghai EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import "./BN254.sol";
import "./IGroth16Bn254Verifier.sol";

/**
 * @title Groth16Verifier
 * @notice Generic Groth16 verifier over BN254 that reverts on malformed input and
 *         emits `ProofVerificationResult` with the verification outcome.
 * @dev Follows the snarkjs/libsnark pairing equation:
 *      e(A,B) * e(-alpha1,beta2) * e(-vk_x,gamma2) * e(-C,delta2) == 1.
 */
contract Groth16Verifier is IGroth16Bn254Verifier {
    using BN254 for BN254.G1Point;
    using BN254 for BN254.G2Point;

    /// @notice Scalar field modulus r (NOT the base field p).
    uint256 private constant SNARK_SCALAR_FIELD =
        21888242871839275222246405745257275088548364400416034343698204186575808495617;

    /// @notice Custom errors for gas-efficient failures.
    error InvalidICLength();
    error InputOutOfBounds();    // public input >= r

    /* ----------------------------- Verifier ----------------------------- */

    /**
     * @notice Verifies a Groth16 proof and reports the result via event and return value.
     * @dev Reverts if IC length mismatches or public inputs >= scalar field.
     *      Point validation (coordinates, curve membership) is performed by EVM precompiles.
     */
    function verifyProof(
        bytes16 zkVerifyId,
        bytes32 proofHash,
        VerificationKey calldata vk,
        Proof calldata proof,
        uint256[] calldata publicInputs
    ) external returns (bool success) {
        uint256 n = publicInputs.length;
        if (vk.ic.length != n + 1) revert InvalidICLength();

        // Validate public inputs < r (scalar field modulus)
        // Note: Point coordinate validation is handled by EVM precompiles (ec_add, ec_mul, ec_pairing)
        for (uint256 i = 0; i < n; ) {
            if (publicInputs[i] >= SNARK_SCALAR_FIELD) revert InputOutOfBounds();
            unchecked { ++i; }
        }

        // Build VK components
        BN254.G1Point memory alpha1 = BN254.G1Point(vk.alpha1[0], vk.alpha1[1]);
        BN254.G2Point memory beta2  = BN254.G2Point([vk.beta2[0][0], vk.beta2[0][1]], [vk.beta2[1][0], vk.beta2[1][1]]);
        BN254.G2Point memory gamma2 = BN254.G2Point([vk.gamma2[0][0], vk.gamma2[0][1]], [vk.gamma2[1][0], vk.gamma2[1][1]]);
        BN254.G2Point memory delta2 = BN254.G2Point([vk.delta2[0][0], vk.delta2[0][1]], [vk.delta2[1][0], vk.delta2[1][1]]);

        // Build proof components
        BN254.G1Point memory A = BN254.G1Point(proof.a[0], proof.a[1]);
        BN254.G2Point memory B = BN254.G2Point([proof.b[0][0], proof.b[0][1]], [proof.b[1][0], proof.b[1][1]]);
        BN254.G1Point memory C = BN254.G1Point(proof.c[0], proof.c[1]);

        // vk_x = IC[0] + Σ_i IC[i+1] * publicInputs[i]
        BN254.G1Point memory vk_x = BN254.G1Point(vk.ic[0][0], vk.ic[0][1]);
        for (uint256 i = 0; i < n; ) {
            BN254.G1Point memory ic = BN254.G1Point(vk.ic[i + 1][0], vk.ic[i + 1][1]);
            vk_x.mulAccC(ic, publicInputs[i]);
            unchecked { ++i; }
        }

        // Pairing product:
        // e(A, B) * e(-alpha1, beta2) * e(-vk_x, gamma2) * e(-C, delta2) == 1
        success = BN254.pairing4(
            A, B,
            alpha1.negate(), beta2,
            vk_x.negate(),  gamma2,
            C.negate(),     delta2
        );

        // Emit result and return success
        emit ProofVerificationResult(zkVerifyId, proofHash, msg.sender, success);
        return success;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

/**
 * @title BN254
 * @notice Minimal BN254 (alt_bn128) primitives backed by the EVM precompiles.
 */
library BN254 {
    /// @notice Base field modulus p.
    uint256 public constant FIELD_MODULUS =
        0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47;


    struct G1Point {
        uint256 x;
        uint256 y;
    }

    /// @dev G2 limbs are stored as [real, imaginary].
    struct G2Point {
        uint256[2] x;
        uint256[2] y;
    }

    /* --------------------------- G1 operations --------------------------- */

    function negate(G1Point memory p) internal pure returns (G1Point memory) {
        if (p.x == 0 && p.y == 0) return G1Point(0, 0);
        return G1Point(p.x, FIELD_MODULUS - p.y);
    }

    /// @notice G1 function to multiply a G1 value(x,y) to value in an address
    /// @dev From snarkJS verifier template
    function mulAccC(G1Point memory result, G1Point memory p, uint256 s)
        internal
        view
    {
        assembly {
            let mIn := mload(0x40)
            
            mstore(mIn, mload(p))
            mstore(add(mIn, 32), mload(add(p, 32)))
            mstore(add(mIn, 64), s)
            let success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
            
            if iszero(success) {
                mstore(0, 0)
                return(0, 0x20)
            }
            
            mstore(add(mIn, 64), mload(result))
            mstore(add(mIn, 96), mload(add(result, 32)))
            success := staticcall(sub(gas(), 2000), 6, mIn, 128, result, 64)
            
            if iszero(success) {
                mstore(0, 0)
                return(0, 0x20)
            }
        }
    }

    /* --------------------------- Pairing helpers ------------------------- */

    function _writePair24(
        uint256[24] memory dst,
        uint256 o,
        G1Point memory p1,
        G2Point memory p2
    ) private pure {
        dst[o + 0] = p1.x;
        dst[o + 1] = p1.y;
        dst[o + 2] = p2.x[1]; // X imaginary limb
        dst[o + 3] = p2.x[0]; // X real limb
        dst[o + 4] = p2.y[1]; // Y imaginary limb
        dst[o + 5] = p2.y[0]; // Y real limb
    }

    /// @notice Pairing for 4 pairs (optimized for Groth16).
    function pairing4(
        G1Point memory a1,
        G2Point memory a2,
        G1Point memory b1,
        G2Point memory b2,
        G1Point memory c1,
        G2Point memory c2,
        G1Point memory d1,
        G2Point memory d2
    ) internal view returns (bool) {
        uint256[24] memory input;
        _writePair24(input, 0, a1, a2);
        _writePair24(input, 6, b1, b2);
        _writePair24(input, 12, c1, c2);
        _writePair24(input, 18, d1, d2);

        uint256[1] memory out;
        bool success;
        assembly {
            success := staticcall(gas(), 8, input, 0x300, out, 0x20)
        }
        if (!success) return false;
        return out[0] != 0;
    }
}

File 3 of 3 : IGroth16Bn254Verifier.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

/**
 * @title IGroth16Bn254Verifier
 * @notice Interface for Groth16 verifiers over BN254 that surface success via event and return value.
 */
interface IGroth16Bn254Verifier {
    struct VerificationKey {
        uint256[2] alpha1;
        uint256[2][2] beta2;
        uint256[2][2] gamma2;
        uint256[2][2] delta2;
        uint256[2][] ic;
    }

    struct Proof {
        uint256[2] a;
        uint256[2][2] b;
        uint256[2] c;
    }

    /// @notice Emitted after each verification attempt.
    event ProofVerificationResult(
        bytes16 indexed zkVerifyId,
        bytes32 indexed proofHash,
        address indexed requestor,
        bool success
    );

    /**
     * @notice Verifies a Groth16 proof and returns whether it succeeded.
     * @dev Implementations should revert only for malformed input (length/field violations).
     */
    function verifyProof(
        bytes16 zkVerifyId,
        bytes32 proofHash,
        VerificationKey calldata vk,
        Proof calldata proof,
        uint256[] calldata publicInputs
    ) external returns (bool success);
}

Settings
{
  "remappings": [
    "forge-std/=lib/forge-std/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "shanghai",
  "viaIR": true
}

Contract ABI

API
[{"inputs":[],"name":"InputOutOfBounds","type":"error"},{"inputs":[],"name":"InvalidICLength","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes16","name":"zkVerifyId","type":"bytes16"},{"indexed":true,"internalType":"bytes32","name":"proofHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"requestor","type":"address"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"}],"name":"ProofVerificationResult","type":"event"},{"inputs":[{"internalType":"bytes16","name":"zkVerifyId","type":"bytes16"},{"internalType":"bytes32","name":"proofHash","type":"bytes32"},{"components":[{"internalType":"uint256[2]","name":"alpha1","type":"uint256[2]"},{"internalType":"uint256[2][2]","name":"beta2","type":"uint256[2][2]"},{"internalType":"uint256[2][2]","name":"gamma2","type":"uint256[2][2]"},{"internalType":"uint256[2][2]","name":"delta2","type":"uint256[2][2]"},{"internalType":"uint256[2][]","name":"ic","type":"uint256[2][]"}],"internalType":"struct IGroth16Bn254Verifier.VerificationKey","name":"vk","type":"tuple"},{"components":[{"internalType":"uint256[2]","name":"a","type":"uint256[2]"},{"internalType":"uint256[2][2]","name":"b","type":"uint256[2][2]"},{"internalType":"uint256[2]","name":"c","type":"uint256[2]"}],"internalType":"struct IGroth16Bn254Verifier.Proof","name":"proof","type":"tuple"},{"internalType":"uint256[]","name":"publicInputs","type":"uint256[]"}],"name":"verifyProof","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]

6080806040523461001657610790908161001b8239f35b5f80fdfe60806040526004361015610011575f80fd5b5f803560e01c630d32f06114610025575f80fd5b346100c4576101803660031901126100c4576004356fffffffffffffffffffffffffffffffff19811681036100c75767ffffffffffffffff916044358381116100c7576100769036906004016100cb565b92610080366100de565b91610164359182116100c4576100c06100ae8686866100a236600489016100f0565b9390926024359061023a565b60405190151581529081906020820190565b0390f35b80fd5b5080fd5b90816101e09103126100da5790565b5f80fd5b6101009060631901126100da57606490565b9181601f840112156100da5782359167ffffffffffffffff83116100da576020808501948460051b0101116100da57565b903590601e19813603018212156100da570180359067ffffffffffffffff82116100da57602001918160061b360383136100da57565b634e487b7160e01b5f52601160045260245ffd5b906001820180921161017957565b610157565b634e487b7160e01b5f52603260045260245ffd5b91908110156101a25760051b0190565b61017e565b634e487b7160e01b5f52604160045260245ffd5b604051906040820182811067ffffffffffffffff8211176101db57604052565b6101a7565b60405190610300820182811067ffffffffffffffff8211176101db57604052565b604051906020820182811067ffffffffffffffff8211176101db57604052565b90156101a25790565b91908110156101a25760061b0190565b929594939190936101c08201966102518884610121565b905061025c8361016b565b03610540575f5b8281106104f357506102736101bb565b9183358352602084013560208401528861028b6101bb565b9160408601358352606086013560208401526102a56101bb565b6080870135815260a087013560208201526102be6101bb565b93845260208401526102ce6101bb565b9460c0870135865260e087013560208701526102e86101bb565b610100880135815261012088013560208201526103036101bb565b96875260208701526103136101bb565b97610140880135895261016088013560208a015261032f6101bb565b61018089013581526101a0890135602082015261034a6101bb565b998a5260208a015261035a6101bb565b9786358952602087013560208a01526103716101bb565b93604088013585526060880135602086015261038b6101bb565b6080890135815260a089013560208201526103a46101bb565b958652602086015260e06103b66101bb565b9860c08101358a52013560208901526103ef6103e96103db6103e16103db8a87610121565b90610221565b359885610121565b60200190565b356103f86101bb565b96875260208701525f5b81811061048b575050505061043698999a9b5061042a61042461043092610552565b93610552565b94610552565b9561062c565b916040517fc868c4ce3b3f615ef1d4b8508e065b8bbe61d75e45df10ae190575242e15c75c33936fffffffffffffffffffffffffffffffff191691806104858782919091602081019215159052565b0390a490565b8f906104ed826104c96103e96104c06104b86104a96001988b610121565b6104b28961016b565b9161022a565b359389610121565b6104b28761016b565b356104d26101bb565b91825260208201526104e5838689610192565b35908a6105d5565b01610402565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000161051f828588610192565b35101561052e57600101610263565b60405163102cad1b60e01b8152600490fd5b60405163bb7a0e5760e01b8152600490fd5b5f602061055d6101bb565b8281520152805115806105c9575b6105b457602081519101517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47908103908111610179576105a96101bb565b918252602082015290565b506105bd6101bb565b5f81525f602082015290565b5060208101511561056b565b906020604051918051835201516020820152604081019283526107cf19906040816060816007865a01fa1561062457600660809260409585519052602085015160608401525a01fa1561062457565b5f805260205ff35b969392959491909561063c6101e0565b966103009889368a3780518952602090810151818a0152815101516040890152805151606089015260200180516106739060200190565b516080890152515160a0880152815160c088015260209182015160e088015280518201516101008801528051516101208801528101805182015161014088015251516101608701528251610180870152918201516101a086015280518201516101c08601528051516101e086015281018051820151610200860152515161022085015282516102408501529182015161026084015280518201516102808401528051516102a084015281018051909101516102c083015251516102e082015261073a610201565b80923660209083375a926008602094fa156107555751151590565b505f9056fea264697066735822122050ad4e6658718aee47ce805bb1e5e3d251fd7858dbc432f68f79f6ab7cfd63fb64736f6c63430008140033

Deployed Bytecode

0x60806040526004361015610011575f80fd5b5f803560e01c630d32f06114610025575f80fd5b346100c4576101803660031901126100c4576004356fffffffffffffffffffffffffffffffff19811681036100c75767ffffffffffffffff916044358381116100c7576100769036906004016100cb565b92610080366100de565b91610164359182116100c4576100c06100ae8686866100a236600489016100f0565b9390926024359061023a565b60405190151581529081906020820190565b0390f35b80fd5b5080fd5b90816101e09103126100da5790565b5f80fd5b6101009060631901126100da57606490565b9181601f840112156100da5782359167ffffffffffffffff83116100da576020808501948460051b0101116100da57565b903590601e19813603018212156100da570180359067ffffffffffffffff82116100da57602001918160061b360383136100da57565b634e487b7160e01b5f52601160045260245ffd5b906001820180921161017957565b610157565b634e487b7160e01b5f52603260045260245ffd5b91908110156101a25760051b0190565b61017e565b634e487b7160e01b5f52604160045260245ffd5b604051906040820182811067ffffffffffffffff8211176101db57604052565b6101a7565b60405190610300820182811067ffffffffffffffff8211176101db57604052565b604051906020820182811067ffffffffffffffff8211176101db57604052565b90156101a25790565b91908110156101a25760061b0190565b929594939190936101c08201966102518884610121565b905061025c8361016b565b03610540575f5b8281106104f357506102736101bb565b9183358352602084013560208401528861028b6101bb565b9160408601358352606086013560208401526102a56101bb565b6080870135815260a087013560208201526102be6101bb565b93845260208401526102ce6101bb565b9460c0870135865260e087013560208701526102e86101bb565b610100880135815261012088013560208201526103036101bb565b96875260208701526103136101bb565b97610140880135895261016088013560208a015261032f6101bb565b61018089013581526101a0890135602082015261034a6101bb565b998a5260208a015261035a6101bb565b9786358952602087013560208a01526103716101bb565b93604088013585526060880135602086015261038b6101bb565b6080890135815260a089013560208201526103a46101bb565b958652602086015260e06103b66101bb565b9860c08101358a52013560208901526103ef6103e96103db6103e16103db8a87610121565b90610221565b359885610121565b60200190565b356103f86101bb565b96875260208701525f5b81811061048b575050505061043698999a9b5061042a61042461043092610552565b93610552565b94610552565b9561062c565b916040517fc868c4ce3b3f615ef1d4b8508e065b8bbe61d75e45df10ae190575242e15c75c33936fffffffffffffffffffffffffffffffff191691806104858782919091602081019215159052565b0390a490565b8f906104ed826104c96103e96104c06104b86104a96001988b610121565b6104b28961016b565b9161022a565b359389610121565b6104b28761016b565b356104d26101bb565b91825260208201526104e5838689610192565b35908a6105d5565b01610402565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000161051f828588610192565b35101561052e57600101610263565b60405163102cad1b60e01b8152600490fd5b60405163bb7a0e5760e01b8152600490fd5b5f602061055d6101bb565b8281520152805115806105c9575b6105b457602081519101517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47908103908111610179576105a96101bb565b918252602082015290565b506105bd6101bb565b5f81525f602082015290565b5060208101511561056b565b906020604051918051835201516020820152604081019283526107cf19906040816060816007865a01fa1561062457600660809260409585519052602085015160608401525a01fa1561062457565b5f805260205ff35b969392959491909561063c6101e0565b966103009889368a3780518952602090810151818a0152815101516040890152805151606089015260200180516106739060200190565b516080890152515160a0880152815160c088015260209182015160e088015280518201516101008801528051516101208801528101805182015161014088015251516101608701528251610180870152918201516101a086015280518201516101c08601528051516101e086015281018051820151610200860152515161022085015282516102408501529182015161026084015280518201516102808401528051516102a084015281018051909101516102c083015251516102e082015261073a610201565b80923660209083375a926008602094fa156107555751151590565b505f9056fea264697066735822122050ad4e6658718aee47ce805bb1e5e3d251fd7858dbc432f68f79f6ab7cfd63fb64736f6c63430008140033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
0x6D645eD60073a37880AF9B2ac10a01049C74F368
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.