Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ZKProofVerifier
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 10000 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
// Contracts
import { ZKVerifier } from "contracts/L1/ZKVerifier.sol";
// Libraries
import { Hashing } from "contracts/libraries/Hashing.sol";
import { Predeploys } from "contracts/libraries/Predeploys.sol";
import { Types } from "contracts/libraries/Types.sol";
// Interfaces
import { ISemver } from "contracts/universal/ISemver.sol";
import { ISP1Verifier } from "contracts/vendor/ISP1Verifier.sol";
import { IZKMerkleTrie } from "contracts/L1/interfaces/IZKMerkleTrie.sol";
/// @custom:proxied true
/// @title ZKProofVerifier
/// @notice The ZKProofVerifier contract verifies public inputs and corresponding ZK proofs.
/// Currently it verifies zkEVM proofs using ZKVerifier contract, and zkVM proofs using
/// SP1Verifier contract.
contract ZKProofVerifier is ISemver {
/// @notice Address of the ZKVerifier contract.
ZKVerifier internal immutable ZK_VERIFIER;
/// @notice The dummy transaction hash for zkEVM proofs. This is used to pad if the
/// number of transactions is less than MAX_TXS. This is same as:
/// unsignedTx = {
/// nonce: 0,
/// gasLimit: 0,
/// gasPrice: 0,
/// to: address(0),
/// value: 0,
/// data: '0x',
/// chainId: CHAIN_ID,
/// }
/// signature = sign(unsignedTx, 0x1)
/// dummyHash = keccak256(rlp({
/// ...unsignedTx,
/// signature,
/// }))
bytes32 internal immutable DUMMY_HASH;
/// @notice The maximum number of transactions for zkEVM proofs.
uint256 internal immutable MAX_TXS;
/// @notice Address that has the ability to verify the merkle proof in ZKTrie.
address internal immutable ZK_MERKLE_TRIE;
/// @notice Address of the SP1VerifierGateway contract.
ISP1Verifier internal immutable SP1_VERIFIER;
/// @notice The verification key for the zkVM program.
bytes32 internal immutable ZKVM_PROGRAM_V_KEY;
/// @notice Reverts when the zkVM program verification key is invalid.
error InvalidZkVmVKey();
/// @notice Reverts when the public input is invalid.
error InvalidPublicInput();
/// @notice Reverts when the ZK proof is invalid.
error InvalidZkProof();
/// @notice Reverts when the inclusion proof is invalid.
error InvalidInclusionProof();
/// @notice Reverts when the block hash is mismatched between source and destination output root
/// proof. (only for zkEVM proof)
error BlockHashMismatchedBtwSrcAndDst();
/// @notice Reverts when the source output root is mismatched.
error SrcOutputMismatched();
/// @notice Reverts when the destination output root is matched. (only for fault proof)
error DstOutputMatched();
/// @notice Reverts when the block hash is mismatched.
error BlockHashMismatched();
/// @notice Reverts when the state root is mismatched.
error StateRootMismatched();
/// @notice Semantic version.
/// @custom:semver 1.0.0
string public constant version = "1.0.0";
/// @notice Constructs the ZKProofVerifier contract.
/// @param _zkVerifier Address of the ZKVerifier contract.
/// @param _dummyHash Dummy hash for zkEVM proofs.
/// @param _maxTxs Number of max transactions per block for zkEVM proofs.
/// @param _zkMerkleTrie Address of the ZKMerkleTrie contract.
/// @param _sp1Verifier Address of the SP1VerifierGateway contract.
/// @param _zkVmProgramVKey The verification key for the zkVM program.
constructor(
ZKVerifier _zkVerifier,
bytes32 _dummyHash,
uint256 _maxTxs,
address _zkMerkleTrie,
ISP1Verifier _sp1Verifier,
bytes32 _zkVmProgramVKey
) {
ZK_VERIFIER = _zkVerifier;
DUMMY_HASH = _dummyHash;
MAX_TXS = _maxTxs;
ZK_MERKLE_TRIE = _zkMerkleTrie;
SP1_VERIFIER = _sp1Verifier;
ZKVM_PROGRAM_V_KEY = _zkVmProgramVKey;
}
/// @notice Getter for the address of ZKVerifier contract.
function zkVerifier() external view returns (ZKVerifier) {
return ZK_VERIFIER;
}
/// @notice Getter for the dummy transaction hash for zkEVM proofs.
function dummyHash() external view returns (bytes32) {
return DUMMY_HASH;
}
/// @notice Getter for the maximum number of transactions for zkEVM proofs.
function maxTxs() external view returns (uint256) {
return MAX_TXS;
}
/// @notice Getter for the address of ZKMerkleTrie contract.
function zkMerkleTrie() external view returns (address) {
return ZK_MERKLE_TRIE;
}
/// @notice Getter for the address of SP1VerifierGateway contract.
function sp1Verifier() external view returns (ISP1Verifier) {
return SP1_VERIFIER;
}
/// @notice Getter for the verification key for the zkVM program.
function zkVmProgramVKey() external view returns (bytes32) {
return ZKVM_PROGRAM_V_KEY;
}
/// @notice Verifies zkEVM public inputs and proof.
/// @param _zkEvmProof The public input and proof using zkEVM.
/// @param _storedSrcOutput The stored source output root.
/// @param _storedDstOutput The stored destination output root. It will only be used for fault proving.
/// @return publicInputHash_ Hash of public input.
function verifyZkEvmProof(
Types.ZkEvmProof calldata _zkEvmProof,
bytes32 _storedSrcOutput,
bytes32 _storedDstOutput
) external view returns (bytes32 publicInputHash_) {
Types.PublicInputProof calldata publicInputProof = _zkEvmProof.publicInputProof;
if (
publicInputProof.srcOutputRootProof.nextBlockHash !=
publicInputProof.dstOutputRootProof.latestBlockhash
) revert BlockHashMismatchedBtwSrcAndDst();
_validatePublicInputOutput(
_storedSrcOutput,
_storedDstOutput,
Hashing.hashOutputRootProof(publicInputProof.srcOutputRootProof),
Hashing.hashOutputRootProof(publicInputProof.dstOutputRootProof)
);
_validateZkEvmPublicInput(
publicInputProof.dstOutputRootProof,
publicInputProof.publicInput,
publicInputProof.rlps
);
_validateWithdrawalStorageRoot(
publicInputProof.merkleProof,
publicInputProof.l2ToL1MessagePasserBalance,
publicInputProof.l2ToL1MessagePasserCodeHash,
publicInputProof.dstOutputRootProof.messagePasserStorageRoot,
publicInputProof.dstOutputRootProof.stateRoot
);
publicInputHash_ = _hashZkEvmPublicInput(
publicInputProof.srcOutputRootProof.stateRoot,
publicInputProof.publicInput
);
if (!ZK_VERIFIER.verify(_zkEvmProof.proof, _zkEvmProof.pair, publicInputHash_))
revert InvalidZkProof();
}
/// @notice Verifies zkVM public inputs and proof.
/// @param _zkVmProof The public input and proof using zkVM.
/// @param _storedSrcOutput The stored source output root.
/// @param _storedDstOutput The stored destination output root. It will only be used for fault proving.
/// @param _storedL1Head The stored L1 block hash.
/// @return publicInputHash_ Hash of public input.
function verifyZkVmProof(
Types.ZkVmProof calldata _zkVmProof,
bytes32 _storedSrcOutput,
bytes32 _storedDstOutput,
bytes32 _storedL1Head
) external view returns (bytes32 publicInputHash_) {
if (_zkVmProof.zkVmProgramVKey != ZKVM_PROGRAM_V_KEY) revert InvalidZkVmVKey();
_validatePublicInputOutput(
_storedSrcOutput,
_storedDstOutput,
bytes32(_zkVmProof.publicValues[8:40]), // skip ABI-encoding prefix at publicValues[0:8].
bytes32(_zkVmProof.publicValues[48:80]) // skip ABI-encoding prefix at publicValues[40:48].
);
// Check if the L1 block hash is correct.
// Skip ABI-encoding prefix at publicValues[80:88].
if (bytes32(_zkVmProof.publicValues[88:120]) != _storedL1Head) revert InvalidPublicInput();
SP1_VERIFIER.verifyProof(
ZKVM_PROGRAM_V_KEY,
_zkVmProof.publicValues,
_zkVmProof.proofBytes
);
publicInputHash_ = keccak256(_zkVmProof.publicValues);
}
/// @notice Checks if the public input outputs are valid. Reverts if they are invalid.
/// @param _storedSrcOutput The stored source output root.
/// @param _storedDstOutput The stored destination output root.
/// @param _publicInputSrcOutput The source output root of public input.
/// @param _publicInputDstOutput The destination output root of public input.
function _validatePublicInputOutput(
bytes32 _storedSrcOutput,
bytes32 _storedDstOutput,
bytes32 _publicInputSrcOutput,
bytes32 _publicInputDstOutput
) internal pure {
if (_storedSrcOutput != _publicInputSrcOutput) revert SrcOutputMismatched();
// If _storedDstOutput is non-zero, it is fault proving case, not validity proving.
// Then assert _publicInputDstOutput is different with on-chain stored destination output.
if (_storedDstOutput != bytes32(0)) {
if (_storedDstOutput == _publicInputDstOutput) revert DstOutputMatched();
}
}
/// @notice Checks if the public input of zkEVM proof is valid. Reverts if it is invalid.
/// @param _dstOutputRootProof Proof of the destination output root.
/// @param _publicInput Ingredients to compute the public input used by zkEVM proof verification.
/// @param _rlps Pre-encoded RLPs to compute the latest block hash of the destination output
/// root proof.
function _validateZkEvmPublicInput(
Types.OutputRootProof calldata _dstOutputRootProof,
Types.PublicInput calldata _publicInput,
Types.BlockHeaderRLP calldata _rlps
) internal pure {
if (_publicInput.stateRoot != _dstOutputRootProof.stateRoot) revert StateRootMismatched();
// parentBeaconRoot is non-zero for Cancun block
bytes32 blockHash = _publicInput.parentBeaconRoot != bytes32(0)
? Hashing.hashBlockHeaderCancun(_publicInput, _rlps)
: Hashing.hashBlockHeaderShanghai(_publicInput, _rlps);
if (_dstOutputRootProof.latestBlockhash != blockHash) revert BlockHashMismatched();
}
/// @notice Checks if the L2ToL1MesagePasser account is included in the given state root.
/// @param _merkleProof Merkle proof of L2ToL1MessagePasser account against the state root.
/// @param _l2ToL1MessagePasserBalance Balance of the L2ToL1MessagePasser account.
/// @param _l2ToL1MessagePasserCodeHash Codehash of the L2ToL1MessagePasser account.
/// @param _messagePasserStorageRoot Storage root of the L2ToL1MessagePasser account.
/// @param _stateRoot State root.
function _validateWithdrawalStorageRoot(
bytes[] calldata _merkleProof,
bytes32 _l2ToL1MessagePasserBalance,
bytes32 _l2ToL1MessagePasserCodeHash,
bytes32 _messagePasserStorageRoot,
bytes32 _stateRoot
) internal view {
// TODO(chokobole): Can we fix the codeHash?
bytes memory l2ToL1MessagePasserAccount = abi.encodePacked(
uint256(0), // nonce
_l2ToL1MessagePasserBalance, // balance,
_l2ToL1MessagePasserCodeHash, // codeHash,
_messagePasserStorageRoot // storage root
);
if (
!IZKMerkleTrie(ZK_MERKLE_TRIE).verifyInclusionProof(
bytes32(bytes20(Predeploys.L2_TO_L1_MESSAGE_PASSER)),
l2ToL1MessagePasserAccount,
_merkleProof,
_stateRoot
)
) revert InvalidInclusionProof();
}
/// @notice Hashes the public input for zkEVM proof with padding dummy transactions.
/// @param _prevStateRoot Previous state root.
/// @param _publicInput Ingredients to compute the public input used by zkEVM proof verification.
/// @return Hash of public input for zkEVM proof.
function _hashZkEvmPublicInput(
bytes32 _prevStateRoot,
Types.PublicInput calldata _publicInput
) internal view returns (bytes32) {
bytes32[] memory dummyHashes;
if (_publicInput.txHashes.length < MAX_TXS) {
dummyHashes = Hashing.generateDummyHashes(
DUMMY_HASH,
MAX_TXS - _publicInput.txHashes.length
);
}
// NOTE(chokobole): We cannot calculate the Ethereum transaction root solely
// based on transaction hashes. It is necessary to have access to the original
// transactions. Considering the imposed constraints and the difficulty
// of providing a preimage that would generate the desired public input hash
// from an attacker's perspective, we have decided to omit the verification
// using the transaction root.
return Hashing.hashZkEvmPublicInput(_prevStateRoot, _publicInput, dummyHashes);
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.15;
import { ISemver } from "../universal/ISemver.sol";
contract ZKVerifier is ISemver {
uint256 internal immutable HASH_SCALAR_VALUE;
uint256 internal immutable M_56_PX_VALUE;
uint256 internal immutable M_56_PY_VALUE;
/**
* @notice Semantic version.
* @custom:semver 0.1.5
*/
string public constant version = "0.1.5";
constructor(uint256 _hashScalar, uint256 _m56Px, uint256 _m56Py) {
HASH_SCALAR_VALUE = _hashScalar;
M_56_PX_VALUE = _m56Px;
M_56_PY_VALUE = _m56Py;
}
function pairing(G1Point[] memory p1, G2Point[] memory p2) internal view returns (bool) {
uint256 length = p1.length * 6;
uint256[] memory input = new uint256[](length);
uint256[1] memory result;
bool ret;
require(p1.length == p2.length);
for (uint256 i = 0; i < p1.length; i++) {
input[0 + i * 6] = p1[i].x;
input[1 + i * 6] = p1[i].y;
input[2 + i * 6] = p2[i].x[0];
input[3 + i * 6] = p2[i].x[1];
input[4 + i * 6] = p2[i].y[0];
input[5 + i * 6] = p2[i].y[1];
}
assembly {
ret := staticcall(gas(), 8, add(input, 0x20), mul(length, 0x20), result, 0x20)
}
require(ret);
return result[0] != 0;
}
uint256 constant q_mod =
21888242871839275222246405745257275088548364400416034343698204186575808495617;
function fr_invert(uint256 a) internal view returns (uint256) {
return fr_pow(a, q_mod - 2);
}
function fr_pow(uint256 a, uint256 power) internal view returns (uint256) {
uint256[6] memory input;
uint256[1] memory result;
bool ret;
input[0] = 32;
input[1] = 32;
input[2] = 32;
input[3] = a;
input[4] = power;
input[5] = q_mod;
assembly {
ret := staticcall(gas(), 0x05, input, 0xc0, result, 0x20)
}
require(ret);
return result[0];
}
function fr_div(uint256 a, uint256 b) internal view returns (uint256) {
require(b != 0);
return mulmod(a, fr_invert(b), q_mod);
}
function fr_mul_add(uint256 a, uint256 b, uint256 c) internal pure returns (uint256) {
return addmod(mulmod(a, b, q_mod), c, q_mod);
}
function fr_mul_add_pm(
uint256[84] memory m,
uint256[] calldata proof,
uint256 opcode,
uint256 t
) internal pure returns (uint256) {
for (uint256 i = 0; i < 32; i += 2) {
uint256 a = opcode & 0xff;
if (a != 0xff) {
opcode >>= 8;
uint256 b = opcode & 0xff;
opcode >>= 8;
t = addmod(mulmod(proof[a], m[b], q_mod), t, q_mod);
} else {
break;
}
}
return t;
}
function fr_mul_add_mt(
uint256[84] memory m,
uint256 base,
uint256 opcode,
uint256 t
) internal pure returns (uint256) {
for (uint256 i = 0; i < 32; i += 1) {
uint256 a = opcode & 0xff;
if (a != 0xff) {
opcode >>= 8;
t = addmod(mulmod(base, t, q_mod), m[a], q_mod);
} else {
break;
}
}
return t;
}
function fr_reverse(uint256 input) internal 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);
}
uint256 constant p_mod =
21888242871839275222246405745257275088696311157297823662689037894645226208583;
struct G1Point {
uint256 x;
uint256 y;
}
struct G2Point {
uint256[2] x;
uint256[2] y;
}
function ecc_from(uint256 x, uint256 y) internal pure returns (G1Point memory r) {
r.x = x;
r.y = y;
}
function ecc_add(
uint256 ax,
uint256 ay,
uint256 bx,
uint256 by
) internal view returns (uint256, uint256) {
bool ret = false;
G1Point memory r;
uint256[4] memory input_points;
input_points[0] = ax;
input_points[1] = ay;
input_points[2] = bx;
input_points[3] = by;
assembly {
ret := staticcall(gas(), 6, input_points, 0x80, r, 0x40)
}
require(ret);
return (r.x, r.y);
}
function ecc_sub(
uint256 ax,
uint256 ay,
uint256 bx,
uint256 by
) internal view returns (uint256, uint256) {
return ecc_add(ax, ay, bx, p_mod - by);
}
function ecc_mul(uint256 px, uint256 py, uint256 s) internal view returns (uint256, uint256) {
uint256[3] memory input;
bool ret = false;
G1Point memory r;
input[0] = px;
input[1] = py;
input[2] = s;
assembly {
ret := staticcall(gas(), 7, input, 0x60, r, 0x40)
}
require(ret);
return (r.x, r.y);
}
function _ecc_mul_add(uint256[5] memory input) internal view {
bool ret = false;
assembly {
ret := staticcall(gas(), 7, input, 0x60, add(input, 0x20), 0x40)
}
require(ret);
assembly {
ret := staticcall(gas(), 6, add(input, 0x20), 0x80, add(input, 0x60), 0x40)
}
require(ret);
}
function ecc_mul_add(
uint256 px,
uint256 py,
uint256 s,
uint256 qx,
uint256 qy
) internal view returns (uint256, uint256) {
uint256[5] memory input;
input[0] = px;
input[1] = py;
input[2] = s;
input[3] = qx;
input[4] = qy;
_ecc_mul_add(input);
return (input[3], input[4]);
}
function ecc_mul_add_pm(
uint256[84] memory m,
uint256[] calldata proof,
uint256 opcode,
uint256 t0,
uint256 t1
) internal view returns (uint256, uint256) {
uint256[5] memory input;
input[3] = t0;
input[4] = t1;
for (uint256 i = 0; i < 32; i += 2) {
uint256 a = opcode & 0xff;
if (a != 0xff) {
opcode >>= 8;
uint256 b = opcode & 0xff;
opcode >>= 8;
input[0] = proof[a];
input[1] = proof[a + 1];
input[2] = m[b];
_ecc_mul_add(input);
} else {
break;
}
}
return (input[3], input[4]);
}
function update_hash_scalar(
uint256 v,
uint256[144] memory absorbing,
uint256 pos
) internal pure {
absorbing[pos++] = 0x02;
absorbing[pos++] = v;
}
function update_hash_point(
uint256 x,
uint256 y,
uint256[144] memory absorbing,
uint256 pos
) internal pure {
absorbing[pos++] = 0x01;
absorbing[pos++] = x;
absorbing[pos++] = y;
}
function to_scalar(bytes32 r) private pure returns (uint256 v) {
uint256 tmp = uint256(r);
tmp = fr_reverse(tmp);
v = tmp % 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001;
}
function hash(
uint256[144] memory absorbing,
uint256 length
) private view returns (bytes32[1] memory v) {
bool success;
assembly {
success := staticcall(sub(gas(), 2000), 2, absorbing, length, v, 32)
switch success
case 0 {
invalid()
}
}
assert(success);
}
function squeeze_challenge(
uint256[144] memory absorbing,
uint32 length
) internal view returns (uint256 v) {
absorbing[length] = 0;
bytes32 res = hash(absorbing, length * 32 + 1)[0];
v = to_scalar(res);
absorbing[0] = uint256(res);
length = 1;
}
function get_verify_circuit_g2_s() internal pure returns (G2Point memory s) {
s.x[0] = uint256(
11029560635643983818885738975758839003131865733814273016801144285524936684972
);
s.x[1] = uint256(
10665153487364924395451186075663597035495902496253353881119509267933768999122
);
s.y[0] = uint256(
18790173187318184075281544452912101572166071561689308149111466352378718492148
);
s.y[1] = uint256(
18755874088236213082062601512863221433227017725453112019151604716957419045549
);
}
function get_verify_circuit_g2_n() internal pure returns (G2Point memory n) {
n.x[0] = uint256(
11559732032986387107991004021392285783925812861821192530917403151452391805634
);
n.x[1] = uint256(
10857046999023057135944570762232829481370756359578518086990519993285655852781
);
n.y[0] = uint256(
17805874995975841540914202342111839520379459829704422454583296818431106115052
);
n.y[1] = uint256(
13392588948715843804641432497768002650278120570034223513918757245338268106653
);
}
function get_target_circuit_g2_s() internal pure returns (G2Point memory s) {
s.x[0] = uint256(
11029560635643983818885738975758839003131865733814273016801144285524936684972
);
s.x[1] = uint256(
10665153487364924395451186075663597035495902496253353881119509267933768999122
);
s.y[0] = uint256(
18790173187318184075281544452912101572166071561689308149111466352378718492148
);
s.y[1] = uint256(
18755874088236213082062601512863221433227017725453112019151604716957419045549
);
}
function get_target_circuit_g2_n() internal pure returns (G2Point memory n) {
n.x[0] = uint256(
11559732032986387107991004021392285783925812861821192530917403151452391805634
);
n.x[1] = uint256(
10857046999023057135944570762232829481370756359578518086990519993285655852781
);
n.y[0] = uint256(
17805874995975841540914202342111839520379459829704422454583296818431106115052
);
n.y[1] = uint256(
13392588948715843804641432497768002650278120570034223513918757245338268106653
);
}
function get_wx_wg(
uint256[] calldata proof,
uint256[6] memory instances
) internal view returns (uint256, uint256, uint256, uint256) {
uint256[84] memory m;
uint256[144] memory absorbing;
uint256 t0 = 0;
uint256 t1 = 0;
(t0, t1) = (
ecc_mul(
17789833092049612098151701936050358897264906311798010005527050942756852717298,
10895600437035740537762783734736154159991587515994553016519128117735745182853,
instances[0]
)
);
(t0, t1) = (
ecc_mul_add(
10543918255196573445400399528935519333175023389167175628125725368018220699826,
12766487347162664556283708113947771881161039794532633041152166890738441603652,
instances[1],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
17008203783108743202559440655757700533653854901598142405028623347702668473277,
21814804208982435371780097106882418706885400711730256673026973858149650971299,
instances[2],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
16811698451652309858363601322080891018704447409836823044944128338389236089077,
18899539994854832158038246139972325143494193687503547200838261777721006548399,
instances[3],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
5494852631096636459288403096263717084869030781267238852252122493224146048270,
15370627062079108379015892130008397963684601860044622201721093508656326957966,
instances[4],
t0,
t1
)
);
(m[0], m[1]) = (
ecc_mul_add(
15605904389647533645433956766425544672547314322654580577432084020959766066522,
2981854610112145395053419471185791838523574193883358734299031423326998004318,
instances[5],
t0,
t1
)
);
update_hash_scalar(HASH_SCALAR_VALUE, absorbing, 0);
update_hash_point(m[0], m[1], absorbing, 2);
for (t0 = 0; t0 <= 4; t0++) {
update_hash_point(proof[0 + t0 * 2], proof[1 + t0 * 2], absorbing, 5 + t0 * 3);
}
m[2] = (squeeze_challenge(absorbing, 20));
for (t0 = 0; t0 <= 13; t0++) {
update_hash_point(proof[10 + t0 * 2], proof[11 + t0 * 2], absorbing, 1 + t0 * 3);
}
m[3] = (squeeze_challenge(absorbing, 43));
m[4] = (squeeze_challenge(absorbing, 1));
for (t0 = 0; t0 <= 9; t0++) {
update_hash_point(proof[38 + t0 * 2], proof[39 + t0 * 2], absorbing, 1 + t0 * 3);
}
m[5] = (squeeze_challenge(absorbing, 31));
for (t0 = 0; t0 <= 3; t0++) {
update_hash_point(proof[58 + t0 * 2], proof[59 + t0 * 2], absorbing, 1 + t0 * 3);
}
m[6] = (squeeze_challenge(absorbing, 13));
for (t0 = 0; t0 <= 70; t0++) {
update_hash_scalar(proof[66 + t0 * 1], absorbing, 1 + t0 * 2);
}
m[7] = (squeeze_challenge(absorbing, 143));
for (t0 = 0; t0 <= 3; t0++) {
update_hash_point(proof[137 + t0 * 2], proof[138 + t0 * 2], absorbing, 1 + t0 * 3);
}
m[8] = (squeeze_challenge(absorbing, 13));
m[9] = (
mulmod(
m[6],
13446667982376394161563610564587413125564757801019538732601045199901075958935,
q_mod
)
);
m[10] = (
mulmod(
m[6],
16569469942529664681363945218228869388192121720036659574609237682362097667612,
q_mod
)
);
m[11] = (
mulmod(
m[6],
14803907026430593724305438564799066516271154714737734572920456128449769927233,
q_mod
)
);
m[12] = (fr_pow(m[6], 67108864));
m[13] = (addmod(m[12], q_mod - 1, q_mod));
m[14] = (
mulmod(
21888242545679039938882419398440172875981108180010270949818755658014750055173,
m[13],
q_mod
)
);
t0 = (addmod(m[6], q_mod - 1, q_mod));
m[14] = (fr_div(m[14], t0));
m[15] = (
mulmod(
3495999257316610708652455694658595065970881061159015347599790211259094641512,
m[13],
q_mod
)
);
t0 = (
addmod(
m[6],
q_mod -
14803907026430593724305438564799066516271154714737734572920456128449769927233,
q_mod
)
);
m[15] = (fr_div(m[15], t0));
m[16] = (
mulmod(
12851378806584061886934576302961450669946047974813165594039554733293326536714,
m[13],
q_mod
)
);
t0 = (
addmod(
m[6],
q_mod -
11377606117859914088982205826922132024839443553408109299929510653283289974216,
q_mod
)
);
m[16] = (fr_div(m[16], t0));
m[17] = (
mulmod(
14638077285440018490948843142723135319134576188472316769433007423695824509066,
m[13],
q_mod
)
);
t0 = (
addmod(
m[6],
q_mod -
3693565015985198455139889557180396682968596245011005461846595820698933079918,
q_mod
)
);
m[17] = (fr_div(m[17], t0));
m[18] = (
mulmod(
18027939092386982308810165776478549635922357517986691900813373197616541191289,
m[13],
q_mod
)
);
t0 = (
addmod(
m[6],
q_mod -
17329448237240114492580865744088056414251735686965494637158808787419781175510,
q_mod
)
);
m[18] = (fr_div(m[18], t0));
m[19] = (
mulmod(
912591536032578604421866340844550116335029274442283291811906603256731601654,
m[13],
q_mod
)
);
t0 = (
addmod(
m[6],
q_mod -
6047398202650739717314770882059679662647667807426525133977681644606291529311,
q_mod
)
);
m[19] = (fr_div(m[19], t0));
m[20] = (
mulmod(
17248638560015646562374089181598815896736916575459528793494921668169819478628,
m[13],
q_mod
)
);
t0 = (
addmod(
m[6],
q_mod -
16569469942529664681363945218228869388192121720036659574609237682362097667612,
q_mod
)
);
m[20] = (fr_div(m[20], t0));
t0 = (addmod(m[15], m[16], q_mod));
t0 = (addmod(t0, m[17], q_mod));
t0 = (addmod(t0, m[18], q_mod));
m[15] = (addmod(t0, m[19], q_mod));
t0 = (fr_mul_add(proof[74], proof[72], proof[73]));
t0 = (fr_mul_add(proof[75], proof[67], t0));
t0 = (fr_mul_add(proof[76], proof[68], t0));
t0 = (fr_mul_add(proof[77], proof[69], t0));
t0 = (fr_mul_add(proof[78], proof[70], t0));
m[16] = (fr_mul_add(proof[79], proof[71], t0));
t0 = (mulmod(proof[67], proof[68], q_mod));
m[16] = (fr_mul_add(proof[80], t0, m[16]));
t0 = (mulmod(proof[69], proof[70], q_mod));
m[16] = (fr_mul_add(proof[81], t0, m[16]));
t0 = (addmod(1, q_mod - proof[97], q_mod));
m[17] = (mulmod(m[14], t0, q_mod));
t0 = (mulmod(proof[100], proof[100], q_mod));
t0 = (addmod(t0, q_mod - proof[100], q_mod));
m[18] = (mulmod(m[20], t0, q_mod));
t0 = (addmod(proof[100], q_mod - proof[99], q_mod));
m[19] = (mulmod(t0, m[14], q_mod));
m[21] = (mulmod(m[3], m[6], q_mod));
t0 = (addmod(m[20], m[15], q_mod));
m[15] = (addmod(1, q_mod - t0, q_mod));
m[22] = (addmod(proof[67], m[4], q_mod));
t0 = (fr_mul_add(proof[91], m[3], m[22]));
m[23] = (mulmod(t0, proof[98], q_mod));
t0 = (addmod(m[22], m[21], q_mod));
m[22] = (mulmod(t0, proof[97], q_mod));
m[24] = (
mulmod(
4131629893567559867359510883348571134090853742863529169391034518566172092834,
m[21],
q_mod
)
);
m[25] = (addmod(proof[68], m[4], q_mod));
t0 = (fr_mul_add(proof[92], m[3], m[25]));
m[23] = (mulmod(t0, m[23], q_mod));
t0 = (addmod(m[25], m[24], q_mod));
m[22] = (mulmod(t0, m[22], q_mod));
m[24] = (
mulmod(
4131629893567559867359510883348571134090853742863529169391034518566172092834,
m[24],
q_mod
)
);
m[25] = (addmod(proof[69], m[4], q_mod));
t0 = (fr_mul_add(proof[93], m[3], m[25]));
m[23] = (mulmod(t0, m[23], q_mod));
t0 = (addmod(m[25], m[24], q_mod));
m[22] = (mulmod(t0, m[22], q_mod));
m[24] = (
mulmod(
4131629893567559867359510883348571134090853742863529169391034518566172092834,
m[24],
q_mod
)
);
t0 = (addmod(m[23], q_mod - m[22], q_mod));
m[22] = (mulmod(t0, m[15], q_mod));
m[21] = (
mulmod(
m[21],
11166246659983828508719468090013646171463329086121580628794302409516816350802,
q_mod
)
);
m[23] = (addmod(proof[70], m[4], q_mod));
t0 = (fr_mul_add(proof[94], m[3], m[23]));
m[24] = (mulmod(t0, proof[101], q_mod));
t0 = (addmod(m[23], m[21], q_mod));
m[23] = (mulmod(t0, proof[100], q_mod));
m[21] = (
mulmod(
4131629893567559867359510883348571134090853742863529169391034518566172092834,
m[21],
q_mod
)
);
m[25] = (addmod(proof[71], m[4], q_mod));
t0 = (fr_mul_add(proof[95], m[3], m[25]));
m[24] = (mulmod(t0, m[24], q_mod));
t0 = (addmod(m[25], m[21], q_mod));
m[23] = (mulmod(t0, m[23], q_mod));
m[21] = (
mulmod(
4131629893567559867359510883348571134090853742863529169391034518566172092834,
m[21],
q_mod
)
);
m[25] = (addmod(proof[66], m[4], q_mod));
t0 = (fr_mul_add(proof[96], m[3], m[25]));
m[24] = (mulmod(t0, m[24], q_mod));
t0 = (addmod(m[25], m[21], q_mod));
m[23] = (mulmod(t0, m[23], q_mod));
m[21] = (
mulmod(
4131629893567559867359510883348571134090853742863529169391034518566172092834,
m[21],
q_mod
)
);
t0 = (addmod(m[24], q_mod - m[23], q_mod));
m[21] = (mulmod(t0, m[15], q_mod));
t0 = (addmod(proof[104], m[3], q_mod));
m[23] = (mulmod(proof[103], t0, q_mod));
t0 = (addmod(proof[106], m[4], q_mod));
m[23] = (mulmod(m[23], t0, q_mod));
m[24] = (mulmod(proof[67], proof[82], q_mod));
m[2] = (mulmod(0, m[2], q_mod));
m[24] = (addmod(m[2], m[24], q_mod));
m[25] = (addmod(m[2], proof[83], q_mod));
m[26] = (addmod(proof[104], q_mod - proof[106], q_mod));
t0 = (addmod(1, q_mod - proof[102], q_mod));
m[27] = (mulmod(m[14], t0, q_mod));
t0 = (mulmod(proof[102], proof[102], q_mod));
t0 = (addmod(t0, q_mod - proof[102], q_mod));
m[28] = (mulmod(m[20], t0, q_mod));
t0 = (addmod(m[24], m[3], q_mod));
m[24] = (mulmod(proof[102], t0, q_mod));
m[25] = (addmod(m[25], m[4], q_mod));
t0 = (mulmod(m[24], m[25], q_mod));
t0 = (addmod(m[23], q_mod - t0, q_mod));
m[23] = (mulmod(t0, m[15], q_mod));
m[24] = (mulmod(m[14], m[26], q_mod));
t0 = (addmod(proof[104], q_mod - proof[105], q_mod));
t0 = (mulmod(m[26], t0, q_mod));
m[26] = (mulmod(t0, m[15], q_mod));
t0 = (addmod(proof[109], m[3], q_mod));
m[29] = (mulmod(proof[108], t0, q_mod));
t0 = (addmod(proof[111], m[4], q_mod));
m[29] = (mulmod(m[29], t0, q_mod));
m[30] = (fr_mul_add(proof[82], proof[68], m[2]));
m[31] = (addmod(proof[109], q_mod - proof[111], q_mod));
t0 = (addmod(1, q_mod - proof[107], q_mod));
m[32] = (mulmod(m[14], t0, q_mod));
t0 = (mulmod(proof[107], proof[107], q_mod));
t0 = (addmod(t0, q_mod - proof[107], q_mod));
m[33] = (mulmod(m[20], t0, q_mod));
t0 = (addmod(m[30], m[3], q_mod));
t0 = (mulmod(proof[107], t0, q_mod));
t0 = (mulmod(t0, m[25], q_mod));
t0 = (addmod(m[29], q_mod - t0, q_mod));
m[29] = (mulmod(t0, m[15], q_mod));
m[30] = (mulmod(m[14], m[31], q_mod));
t0 = (addmod(proof[109], q_mod - proof[110], q_mod));
t0 = (mulmod(m[31], t0, q_mod));
m[31] = (mulmod(t0, m[15], q_mod));
t0 = (addmod(proof[114], m[3], q_mod));
m[34] = (mulmod(proof[113], t0, q_mod));
t0 = (addmod(proof[116], m[4], q_mod));
m[34] = (mulmod(m[34], t0, q_mod));
m[35] = (fr_mul_add(proof[82], proof[69], m[2]));
m[36] = (addmod(proof[114], q_mod - proof[116], q_mod));
t0 = (addmod(1, q_mod - proof[112], q_mod));
m[37] = (mulmod(m[14], t0, q_mod));
t0 = (mulmod(proof[112], proof[112], q_mod));
t0 = (addmod(t0, q_mod - proof[112], q_mod));
m[38] = (mulmod(m[20], t0, q_mod));
t0 = (addmod(m[35], m[3], q_mod));
t0 = (mulmod(proof[112], t0, q_mod));
t0 = (mulmod(t0, m[25], q_mod));
t0 = (addmod(m[34], q_mod - t0, q_mod));
m[34] = (mulmod(t0, m[15], q_mod));
m[35] = (mulmod(m[14], m[36], q_mod));
t0 = (addmod(proof[114], q_mod - proof[115], q_mod));
t0 = (mulmod(m[36], t0, q_mod));
m[36] = (mulmod(t0, m[15], q_mod));
t0 = (addmod(proof[119], m[3], q_mod));
m[39] = (mulmod(proof[118], t0, q_mod));
t0 = (addmod(proof[121], m[4], q_mod));
m[39] = (mulmod(m[39], t0, q_mod));
m[40] = (fr_mul_add(proof[82], proof[70], m[2]));
m[41] = (addmod(proof[119], q_mod - proof[121], q_mod));
t0 = (addmod(1, q_mod - proof[117], q_mod));
m[42] = (mulmod(m[14], t0, q_mod));
t0 = (mulmod(proof[117], proof[117], q_mod));
t0 = (addmod(t0, q_mod - proof[117], q_mod));
m[43] = (mulmod(m[20], t0, q_mod));
t0 = (addmod(m[40], m[3], q_mod));
t0 = (mulmod(proof[117], t0, q_mod));
t0 = (mulmod(t0, m[25], q_mod));
t0 = (addmod(m[39], q_mod - t0, q_mod));
m[25] = (mulmod(t0, m[15], q_mod));
m[39] = (mulmod(m[14], m[41], q_mod));
t0 = (addmod(proof[119], q_mod - proof[120], q_mod));
t0 = (mulmod(m[41], t0, q_mod));
m[40] = (mulmod(t0, m[15], q_mod));
t0 = (addmod(proof[124], m[3], q_mod));
m[41] = (mulmod(proof[123], t0, q_mod));
t0 = (addmod(proof[126], m[4], q_mod));
m[41] = (mulmod(m[41], t0, q_mod));
m[44] = (fr_mul_add(proof[84], proof[67], m[2]));
m[45] = (addmod(m[2], proof[85], q_mod));
m[46] = (addmod(proof[124], q_mod - proof[126], q_mod));
t0 = (addmod(1, q_mod - proof[122], q_mod));
m[47] = (mulmod(m[14], t0, q_mod));
t0 = (mulmod(proof[122], proof[122], q_mod));
t0 = (addmod(t0, q_mod - proof[122], q_mod));
m[48] = (mulmod(m[20], t0, q_mod));
t0 = (addmod(m[44], m[3], q_mod));
m[44] = (mulmod(proof[122], t0, q_mod));
t0 = (addmod(m[45], m[4], q_mod));
t0 = (mulmod(m[44], t0, q_mod));
t0 = (addmod(m[41], q_mod - t0, q_mod));
m[41] = (mulmod(t0, m[15], q_mod));
m[44] = (mulmod(m[14], m[46], q_mod));
t0 = (addmod(proof[124], q_mod - proof[125], q_mod));
t0 = (mulmod(m[46], t0, q_mod));
m[45] = (mulmod(t0, m[15], q_mod));
t0 = (addmod(proof[129], m[3], q_mod));
m[46] = (mulmod(proof[128], t0, q_mod));
t0 = (addmod(proof[131], m[4], q_mod));
m[46] = (mulmod(m[46], t0, q_mod));
m[49] = (fr_mul_add(proof[86], proof[67], m[2]));
m[50] = (addmod(m[2], proof[87], q_mod));
m[51] = (addmod(proof[129], q_mod - proof[131], q_mod));
t0 = (addmod(1, q_mod - proof[127], q_mod));
m[52] = (mulmod(m[14], t0, q_mod));
t0 = (mulmod(proof[127], proof[127], q_mod));
t0 = (addmod(t0, q_mod - proof[127], q_mod));
m[53] = (mulmod(m[20], t0, q_mod));
t0 = (addmod(m[49], m[3], q_mod));
m[49] = (mulmod(proof[127], t0, q_mod));
t0 = (addmod(m[50], m[4], q_mod));
t0 = (mulmod(m[49], t0, q_mod));
t0 = (addmod(m[46], q_mod - t0, q_mod));
m[46] = (mulmod(t0, m[15], q_mod));
m[49] = (mulmod(m[14], m[51], q_mod));
t0 = (addmod(proof[129], q_mod - proof[130], q_mod));
t0 = (mulmod(m[51], t0, q_mod));
m[50] = (mulmod(t0, m[15], q_mod));
t0 = (addmod(proof[134], m[3], q_mod));
m[51] = (mulmod(proof[133], t0, q_mod));
t0 = (addmod(proof[136], m[4], q_mod));
m[51] = (mulmod(m[51], t0, q_mod));
m[54] = (fr_mul_add(proof[88], proof[67], m[2]));
m[2] = (addmod(m[2], proof[89], q_mod));
m[55] = (addmod(proof[134], q_mod - proof[136], q_mod));
t0 = (addmod(1, q_mod - proof[132], q_mod));
m[56] = (mulmod(m[14], t0, q_mod));
t0 = (mulmod(proof[132], proof[132], q_mod));
t0 = (addmod(t0, q_mod - proof[132], q_mod));
m[20] = (mulmod(m[20], t0, q_mod));
t0 = (addmod(m[54], m[3], q_mod));
m[3] = (mulmod(proof[132], t0, q_mod));
t0 = (addmod(m[2], m[4], q_mod));
t0 = (mulmod(m[3], t0, q_mod));
t0 = (addmod(m[51], q_mod - t0, q_mod));
m[2] = (mulmod(t0, m[15], q_mod));
m[3] = (mulmod(m[14], m[55], q_mod));
t0 = (addmod(proof[134], q_mod - proof[135], q_mod));
t0 = (mulmod(m[55], t0, q_mod));
m[4] = (mulmod(t0, m[15], q_mod));
t0 = (fr_mul_add(m[5], 0, m[16]));
t0 = (
fr_mul_add_mt(
m,
m[5],
24064768791442479290152634096194013545513974547709823832001394403118888981009,
t0
)
);
t0 = (fr_mul_add_mt(m, m[5], 4704208815882882920750, t0));
m[2] = (fr_div(t0, m[13]));
m[3] = (mulmod(m[8], m[8], q_mod));
m[4] = (mulmod(m[3], m[8], q_mod));
(t0, t1) = (ecc_mul(proof[143], proof[144], m[4]));
(t0, t1) = (ecc_mul_add_pm(m, proof, 281470825071501, t0, t1));
(m[14], m[15]) = (ecc_add(t0, t1, proof[137], proof[138]));
m[5] = (mulmod(m[4], m[11], q_mod));
m[11] = (mulmod(m[4], m[7], q_mod));
m[13] = (mulmod(m[11], m[7], q_mod));
m[16] = (mulmod(m[13], m[7], q_mod));
m[17] = (mulmod(m[16], m[7], q_mod));
m[18] = (mulmod(m[17], m[7], q_mod));
m[19] = (mulmod(m[18], m[7], q_mod));
t0 = (mulmod(m[19], proof[135], q_mod));
t0 = (fr_mul_add_pm(m, proof, 79227007564587019091207590530, t0));
m[20] = (fr_mul_add(proof[105], m[4], t0));
m[10] = (mulmod(m[3], m[10], q_mod));
m[20] = (fr_mul_add(proof[99], m[3], m[20]));
m[9] = (mulmod(m[8], m[9], q_mod));
m[21] = (mulmod(m[8], m[7], q_mod));
for (t0 = 0; t0 < 8; t0++) {
m[22 + t0 * 1] = (mulmod(m[21 + t0 * 1], m[7 + t0 * 0], q_mod));
}
t0 = (mulmod(m[29], proof[133], q_mod));
t0 = (fr_mul_add_pm(m, proof, 1461480058012745347196003969984389955172320353408, t0));
m[20] = (addmod(m[20], t0, q_mod));
m[3] = (addmod(m[3], m[21], q_mod));
m[21] = (mulmod(m[7], m[7], q_mod));
m[30] = (mulmod(m[21], m[7], q_mod));
for (t0 = 0; t0 < 50; t0++) {
m[31 + t0 * 1] = (mulmod(m[30 + t0 * 1], m[7 + t0 * 0], q_mod));
}
m[81] = (mulmod(m[80], proof[90], q_mod));
m[82] = (mulmod(m[79], m[12], q_mod));
m[83] = (mulmod(m[82], m[12], q_mod));
m[12] = (mulmod(m[83], m[12], q_mod));
t0 = (fr_mul_add(m[79], m[2], m[81]));
t0 = (
fr_mul_add_pm(
m,
proof,
28637501128329066231612878461967933875285131620580756137874852300330784214624,
t0
)
);
t0 = (
fr_mul_add_pm(
m,
proof,
21474593857386732646168474467085622855647258609351047587832868301163767676495,
t0
)
);
t0 = (
fr_mul_add_pm(
m,
proof,
14145600374170319983429588659751245017860232382696106927048396310641433325177,
t0
)
);
t0 = (fr_mul_add_pm(m, proof, 18446470583433829957, t0));
t0 = (addmod(t0, proof[66], q_mod));
m[2] = (addmod(m[20], t0, q_mod));
m[19] = (addmod(m[19], m[54], q_mod));
m[20] = (addmod(m[29], m[53], q_mod));
m[18] = (addmod(m[18], m[51], q_mod));
m[28] = (addmod(m[28], m[50], q_mod));
m[17] = (addmod(m[17], m[48], q_mod));
m[27] = (addmod(m[27], m[47], q_mod));
m[16] = (addmod(m[16], m[45], q_mod));
m[26] = (addmod(m[26], m[44], q_mod));
m[13] = (addmod(m[13], m[42], q_mod));
m[25] = (addmod(m[25], m[41], q_mod));
m[11] = (addmod(m[11], m[39], q_mod));
m[24] = (addmod(m[24], m[38], q_mod));
m[4] = (addmod(m[4], m[36], q_mod));
m[23] = (addmod(m[23], m[35], q_mod));
m[22] = (addmod(m[22], m[34], q_mod));
m[3] = (addmod(m[3], m[33], q_mod));
m[8] = (addmod(m[8], m[32], q_mod));
(t0, t1) = (ecc_mul(proof[143], proof[144], m[5]));
(t0, t1) = (
ecc_mul_add_pm(
m,
proof,
10933423423422768024429730621579321771439401845242250760130969989159573132066,
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add_pm(m, proof, 1461486238301980199876269201563775120819706402602, t0, t1)
);
(t0, t1) = (
ecc_mul_add(
15738646021458965415875359585850781728243543812280308548595326491476474302955,
11051787057691458774492360569996861082650504993138626819003221898493178050035,
m[78],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
1475696300049442917028467159105389721116357718795651750519726871994775216295,
8164600896470502362564790171132408561435532006283737733288998283496711243676,
m[77],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
20037340314091442687430628478276133171639671164499869262269052470554953532798,
8617374172579535083448320238697316576863116103559910108651404828163902641209,
m[76],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
2590328984608469713687780064619512676013076673646564572496583030882285919986,
638589679743187931075527957989835488430425780368511997293885082437553073995,
m[75],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
12146901029446786042585650348552207198317726707649479980494243975966168586800,
21004224368627752160019614542278109958896643390087793101726552507600837692403,
m[74],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
12484898247528969713369796601188723761879994746350513864107241452597517714843,
20710920799110457828705640996188165458350589749232606705712996851057245387342,
m[73],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
19886509832083393598366465489701294384803664485460545523068306491024326504725,
3485984208124097149766319408505384162933092797198027169851040569744728509599,
m[72],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
16404659647391097455159976273992692920152024451288249273063848656492758204389,
21408247695101639349153277734734938504956965085851869757712649884779075439039,
m[71],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
17108853774466418779129374196319580280286578385405087585516556746536875115907,
19908760740801913322265695807368645417588084579607860033571444712857010186774,
m[70],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
21629254704290212852937802382494716478889797428965842728144220543246322859554,
21658265822014679146185833630076754140073759884763957789271421091032211025157,
m[69],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
19886509832083393598366465489701294384803664485460545523068306491024326504725,
3485984208124097149766319408505384162933092797198027169851040569744728509599,
m[68],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
11494485494412314036912556883437307149797432820383623637519035656794042012095,
2410489863957456775707779378033814786966154706946761951908809676618278443068,
m[67],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
21627166622184628562834675422084345034193467320009306763329316593023720936150,
2103102746100002335801212537254725041663108226492711350135413308275232360031,
m[66],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
5833003470394876828918971407337456408257193352118920119145576292426638346769,
21517803666035190572447529780797402738873790305626876614632047398304071926756,
m[65],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
15660369869316007654180594416910060098683972168851332428191944238046914461816,
619475474362397505663248548997199145354664366559823796718165155533015020663,
m[64],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
14357122501752010758022868212927876311895459359009009733271861104226260045594,
16126281904050270224623042280467621555101638794226278850100489095734549617918,
m[63],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
16761622113591657736617505151691036744631771696590303134292673377873890818119,
6686562932890286592033158402117293865477246854478945021606806487507223075395,
m[62],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
17229942418385200082062914700911519717772513320730624793493549643743556744576,
5621800961668224347956111291579888905398405975749251495793956267512617886424,
m[61],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
16719044151302115613031649349289232028937886588938900980773255912070590283284,
8996560925096856479601278542730270549020210858287011041285301443498627852162,
m[60],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
456517166543705985184166475990427022518096989415429862512544596075628104766,
4584298690582989400824123720778697263357419965108679590688166449396561305804,
m[59],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
8841671929736409341755876439864603183349976850407514895007839042769729845276,
19908694064427411410925537740321794844212081049969432136633191256148570974369,
m[58],
t0,
t1
)
);
(t0, t1) = (
ecc_mul_add(
2104154327908680857716247273517715744719141711240749880794301438788948027686,
7499686005093585017307496107151445622144347868958974916146393505438758744367,
m[57],
t0,
t1
)
);
(t0, t1) = (ecc_mul_add(M_56_PX_VALUE, M_56_PY_VALUE, m[56], t0, t1));
(t0, t1) = (
ecc_mul_add_pm(
m,
proof,
6277008573546246765208814532330797927747086570010716419876,
t0,
t1
)
);
(m[0], m[1]) = (ecc_add(t0, t1, m[0], m[1]));
(t0, t1) = (ecc_mul(1, 2, m[2]));
(m[0], m[1]) = (ecc_sub(m[0], m[1], t0, t1));
return (m[14], m[15], m[0], m[1]);
}
function verify(
uint256[] calldata proof,
uint256[] calldata target_circuit_final_pair,
bytes32 publicInputHash
) public view returns (bool) {
uint256[6] memory instances;
instances[0] = target_circuit_final_pair[0] & ((1 << 136) - 1);
instances[1] =
(target_circuit_final_pair[0] >> 136) +
((target_circuit_final_pair[1] & 1) << 136);
instances[2] = target_circuit_final_pair[2] & ((1 << 136) - 1);
instances[3] =
(target_circuit_final_pair[2] >> 136) +
((target_circuit_final_pair[3] & 1) << 136);
instances[4] = uint256(publicInputHash) >> (8 * 16);
instances[5] = uint256(publicInputHash) & uint256(2 ** 128 - 1);
uint256 x0 = 0;
uint256 x1 = 0;
uint256 y0 = 0;
uint256 y1 = 0;
G1Point[] memory g1_points = new G1Point[](2);
G2Point[] memory g2_points = new G2Point[](2);
(x0, y0, x1, y1) = get_wx_wg(proof, instances);
g1_points[0].x = x0;
g1_points[0].y = y0;
g1_points[1].x = x1;
g1_points[1].y = y1;
g2_points[0] = get_verify_circuit_g2_s();
g2_points[1] = get_verify_circuit_g2_n();
if (!pairing(g1_points, g2_points)) {
return false;
}
g1_points[0].x = target_circuit_final_pair[0];
g1_points[0].y = target_circuit_final_pair[1];
g1_points[1].x = target_circuit_final_pair[2];
g1_points[1].y = target_circuit_final_pair[3];
g2_points[0] = get_target_circuit_g2_s();
g2_points[1] = get_target_circuit_g2_n();
if (!pairing(g1_points, g2_points)) {
return false;
}
return true;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Encoding } from "./Encoding.sol";
import { RLPWriter } from "./rlp/RLPWriter.sol";
import { Types } from "./Types.sol";
/**
* @title Hashing
* @notice Hashing handles Kroma's various different hashing schemes.
*/
library Hashing {
/**
* @notice Computes the hash of the RLP encoded L2 transaction that would be generated when a
* given deposit is sent to the L2 system. Useful for searching for a deposit in the L2
* system.
*
* @param _tx User deposit transaction to hash.
* @param _isKromaDepTx Whether the given transaction is a KromaDepositTx.
*
* @return Hash of the RLP encoded L2 deposit transaction.
*/
function hashDepositTransaction(
Types.UserDepositTransaction memory _tx,
bool _isKromaDepTx
) internal pure returns (bytes32) {
return keccak256(Encoding.encodeDepositTransaction(_tx, _isKromaDepTx));
}
/**
* @notice Computes the deposit transaction's "source hash", a value that guarantees the hash
* of the L2 transaction that corresponds to a deposit is unique and is
* deterministically generated from L1 transaction data.
*
* @param _l1BlockHash Hash of the L1 block where the deposit was included.
* @param _logIndex The index of the log that created the deposit transaction.
*
* @return Hash of the deposit transaction's "source hash".
*/
function hashDepositSource(
bytes32 _l1BlockHash,
uint64 _logIndex
) internal pure returns (bytes32) {
bytes32 depositId = keccak256(abi.encode(_l1BlockHash, _logIndex));
return keccak256(abi.encode(bytes32(0), depositId));
}
/**
* @notice Hashes the cross domain message based on the version that is encoded into the
* message nonce.
*
* @param _nonce Message nonce with version encoded into the first two bytes.
* @param _sender Address of the sender of the message.
* @param _target Address of the target of the message.
* @param _value ETH value to send to the target.
* @param _gasLimit Gas limit to use for the message.
* @param _data Data to send with the message.
*
* @return Hashed cross domain message.
*/
function hashCrossDomainMessage(
uint256 _nonce,
address _sender,
address _target,
uint256 _value,
uint256 _gasLimit,
bytes memory _data
) internal pure returns (bytes32) {
(, uint16 version) = Encoding.decodeVersionedNonce(_nonce);
if (version == 0) {
return hashCrossDomainMessageV0(_nonce, _sender, _target, _value, _gasLimit, _data);
} else {
revert("Hashing: unknown cross domain message version");
}
}
/**
* @notice Hashes a cross domain message based on the V0 (current) encoding.
*
* @param _nonce Message nonce.
* @param _sender Address of the sender of the message.
* @param _target Address of the target of the message.
* @param _value ETH value to send to the target.
* @param _gasLimit Gas limit to use for the message.
* @param _data Data to send with the message.
*
* @return Hashed cross domain message.
*/
function hashCrossDomainMessageV0(
uint256 _nonce,
address _sender,
address _target,
uint256 _value,
uint256 _gasLimit,
bytes memory _data
) internal pure returns (bytes32) {
return
keccak256(
Encoding.encodeCrossDomainMessageV0(
_nonce,
_sender,
_target,
_value,
_gasLimit,
_data
)
);
}
/**
* @notice Derives the withdrawal hash according to the encoding in the L2 Withdrawer contract
*
* @param _tx Withdrawal transaction to hash.
*
* @return Hashed withdrawal transaction.
*/
function hashWithdrawal(
Types.WithdrawalTransaction memory _tx
) internal pure returns (bytes32) {
return
keccak256(
abi.encode(_tx.nonce, _tx.sender, _tx.target, _tx.value, _tx.gasLimit, _tx.data)
);
}
/**
* @notice Hashes the various elements of an output root proof into an output root hash which
* can be used to check if the proof is valid.
*
* @param _outputRootProof Output root proof which should hash to an output root.
*
* @return Hashed output root proof.
*/
function hashOutputRootProof(
Types.OutputRootProof memory _outputRootProof
) internal pure returns (bytes32) {
// Note that output root proof will be hashed including nextBlockHash (KromaOutputV0),
// otherwise not including (OutputV0).
if (_outputRootProof.nextBlockHash == bytes32(0)) {
return
keccak256(
abi.encode(
_outputRootProof.version,
_outputRootProof.stateRoot,
_outputRootProof.messagePasserStorageRoot,
_outputRootProof.latestBlockhash
)
);
}
return
keccak256(
abi.encode(
_outputRootProof.version,
_outputRootProof.stateRoot,
_outputRootProof.messagePasserStorageRoot,
_outputRootProof.latestBlockhash,
_outputRootProof.nextBlockHash
)
);
}
/**
* @notice Fills the values of the block hash fields to a given bytes.
*
* @param _publicInput Public input which should be hashed to a block hash.
* @param _rlps Pre-RLP encoded data which should be hashed to a block hash.
* @param _raw An array of bytes to be populated.
*/
function _fillBlockHashFieldsToBytes(
Types.PublicInput memory _publicInput,
Types.BlockHeaderRLP memory _rlps,
bytes[] memory _raw
) private pure {
_raw[0] = RLPWriter.writeBytes(abi.encodePacked(_publicInput.parentHash));
_raw[1] = _rlps.uncleHash;
_raw[2] = _rlps.coinbase;
_raw[3] = RLPWriter.writeBytes(abi.encodePacked(_publicInput.stateRoot));
_raw[4] = RLPWriter.writeBytes(abi.encodePacked(_publicInput.transactionsRoot));
_raw[5] = _rlps.receiptsRoot;
_raw[6] = _rlps.logsBloom;
_raw[7] = _rlps.difficulty;
_raw[8] = RLPWriter.writeUint(_publicInput.number);
_raw[9] = RLPWriter.writeUint(_publicInput.gasLimit);
_raw[10] = _rlps.gasUsed;
_raw[11] = RLPWriter.writeUint(_publicInput.timestamp);
_raw[12] = _rlps.extraData;
_raw[13] = _rlps.mixHash;
_raw[14] = _rlps.nonce;
_raw[15] = RLPWriter.writeUint(_publicInput.baseFee);
}
/**
* @notice Hashes the various elements of a block header into a block hash(before shanghai).
*
* @param _publicInput Public input which should be hashed to a block hash.
* @param _rlps Pre-RLP encoded data which should be hashed to a block hash.
*
* @return Hashed block header.
*/
function hashBlockHeader(
Types.PublicInput memory _publicInput,
Types.BlockHeaderRLP memory _rlps
) internal pure returns (bytes32) {
bytes[] memory raw = new bytes[](16);
_fillBlockHashFieldsToBytes(_publicInput, _rlps, raw);
return keccak256(RLPWriter.writeList(raw));
}
/**
* @notice Hashes the various elements of a block header into a block hash(after shanghai).
*
* @param _publicInput Public input which should be hashed to a block hash.
* @param _rlps Pre-RLP encoded data which should be hashed to a block hash.
*
* @return Hashed block header.
*/
function hashBlockHeaderShanghai(
Types.PublicInput memory _publicInput,
Types.BlockHeaderRLP memory _rlps
) internal pure returns (bytes32) {
bytes[] memory raw = new bytes[](17);
_fillBlockHashFieldsToBytes(_publicInput, _rlps, raw);
raw[16] = RLPWriter.writeBytes(abi.encodePacked(_publicInput.withdrawalsRoot));
return keccak256(RLPWriter.writeList(raw));
}
/**
* @notice Hashes the various elements of a block header into a block hash(after Cancun).
*
* @param _publicInput Public input which should be hashed to a block hash.
* @param _rlps Pre-RLP encoded data which should be hashed to a block hash.
*
* @return Hashed block header.
*/
function hashBlockHeaderCancun(
Types.PublicInput memory _publicInput,
Types.BlockHeaderRLP memory _rlps
) internal pure returns (bytes32) {
bytes[] memory raw = new bytes[](20);
_fillBlockHashFieldsToBytes(_publicInput, _rlps, raw);
raw[16] = RLPWriter.writeBytes(abi.encodePacked(_publicInput.withdrawalsRoot));
raw[17] = RLPWriter.writeUint(_publicInput.blobGasUsed);
raw[18] = RLPWriter.writeUint(_publicInput.excessBlobGas);
raw[19] = RLPWriter.writeBytes(abi.encodePacked(_publicInput.parentBeaconRoot));
return keccak256(RLPWriter.writeList(raw));
}
/**
* @notice Hashes the various elements of a public input into a public input hash for zkEVM proof.
*
* @param _prevStateRoot Previous state root.
* @param _publicInput Public input which should be hashed to a public input hash.
* @param _dummyHashes Dummy hashes returned from generateDummyHashes().
*
* @return Hash of public input for zkEVM proof.
*/
function hashZkEvmPublicInput(
bytes32 _prevStateRoot,
Types.PublicInput memory _publicInput,
bytes32[] memory _dummyHashes
) internal pure returns (bytes32) {
return
keccak256(
abi.encodePacked(
_prevStateRoot,
_publicInput.stateRoot,
// NOTE(0xHansLee): the withdrawalsRoot is not used in Scroll's zkEVM circuit, so it is filled by zero
bytes32(0),
_publicInput.blockHash,
_publicInput.parentHash,
_publicInput.number,
_publicInput.timestamp,
_publicInput.baseFee,
_publicInput.gasLimit,
uint16(_publicInput.txHashes.length),
_publicInput.txHashes,
_dummyHashes
)
);
}
/**
* @notice Generates a bytes32 array filled with a dummy hash for the given length.
*
* @param _dummyHashes Dummy hash.
* @param _length A length of the array.
*
* @return Bytes32 array filled with dummy hash.
*/
function generateDummyHashes(
bytes32 _dummyHashes,
uint256 _length
) internal pure returns (bytes32[] memory) {
bytes32[] memory hashes = new bytes32[](_length);
for (uint256 i = 0; i < _length; i++) {
hashes[i] = _dummyHashes;
}
return hashes;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title Predeploys
* @notice Contains constant addresses for contracts that are pre-deployed to the L2 system.
*/
library Predeploys {
/**
* @notice Address of the ProxyAdmin predeploy.
*/
address internal constant PROXY_ADMIN = 0x4200000000000000000000000000000000000000;
/**
* @notice Address of the KromaL1Block predeploy used before Kroma MPT hardfork.
*/
address internal constant KROMA_L1_BLOCK_ATTRIBUTES =
0x4200000000000000000000000000000000000002;
/**
* @notice Address of the L2ToL1MessagePasser predeploy.
*/
address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000003;
/**
* @notice Address of the L2CrossDomainMessenger predeploy.
*/
address internal constant L2_CROSS_DOMAIN_MESSENGER =
0x4200000000000000000000000000000000000004;
/**
* @notice Address of the GasPriceOracle predeploy. Includes fee information
* and helpers for computing the L1 portion of the transaction fee.
*/
address internal constant GAS_PRICE_ORACLE = 0x4200000000000000000000000000000000000005;
/**
* @notice Address of the ProtocolVault predeploy used before Kroma MPT hardfork.
*/
address internal constant PROTOCOL_VAULT = 0x4200000000000000000000000000000000000006;
/**
* @notice Address of the L1FeeVault predeploy used before Kroma MPT hardfork.
*/
address internal constant KROMA_L1_FEE_VAULT = 0x4200000000000000000000000000000000000007;
/**
* @notice Address of the ValidatorRewardVault predeploy used before Kroma MPT hardfork.
*/
address internal constant VALIDATOR_REWARD_VAULT = 0x4200000000000000000000000000000000000008;
/**
* @notice Address of the L2StandardBridge predeploy.
*/
address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000009;
/**
* @notice Address of the L2ERC721Bridge predeploy.
*/
address internal constant L2_ERC721_BRIDGE = 0x420000000000000000000000000000000000000A;
/**
* @notice Address of the KromaMintableERC20Factory predeploy.
*/
address internal constant KROMA_MINTABLE_ERC20_FACTORY =
0x420000000000000000000000000000000000000B;
/**
* @notice Address of the KromaMintableERC721Factory predeploy.
*/
address internal constant KROMA_MINTABLE_ERC721_FACTORY =
0x420000000000000000000000000000000000000c;
/**
* @notice Address of the SequencerFeeWallet predeploy used after Kroma MPT hardfork.
*/
address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011;
/**
* @notice Address of the L1Block predeploy used after Kroma MPT hardfork.
*/
address internal constant L1_BLOCK_ATTRIBUTES = 0x4200000000000000000000000000000000000015;
/**
* @notice Address of the BaseFeeVault predeploy used after Kroma MPT hardfork.
*/
address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019;
/**
* @notice Address of the L1FeeVault predeploy used after Kroma MPT hardfork.
*/
address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/**
* @title Types
* @notice Contains various types used throughout the Kroma contract system.
*/
library Types {
/**
* @notice CheckpointOutput represents a commitment to the state of L2 checkpoint. The timestamp
* is the L1 timestamp that the output root is posted. This timestamp is used to verify
* that the finalization period has passed since the output root was submitted.
*
* @custom:field submitter Address of the output submitter.
* @custom:field outputRoot Hash of the L2 output.
* @custom:field timestamp Timestamp of the L1 block that the output root was submitted in.
* @custom:field l2BlockNumber L2 block number that the output corresponds to.
*/
struct CheckpointOutput {
address submitter;
bytes32 outputRoot;
uint128 timestamp;
uint128 l2BlockNumber;
}
/**
* @notice Struct representing the elements that are hashed together to generate an output root
* which itself represents a snapshot of the L2 state.
*
* @custom:field version Version of the output root.
* @custom:field stateRoot Root of the state trie at the block of this output.
* @custom:field messagePasserStorageRoot Root of the message passer storage trie.
* @custom:field latestBlockhash Hash of the block this output was generated from.
* @custom:field nextBlockHash Hash of the next block. Note that it is only included in KromaOutputV0.
*/
struct OutputRootProof {
bytes32 version;
bytes32 stateRoot;
bytes32 messagePasserStorageRoot;
bytes32 latestBlockhash;
bytes32 nextBlockHash;
}
/**
* @notice Struct representing the elements that are hashed together to generate a public input
* for zkEVM proof.
*
* @custom:field blockHash The hash of the block.
* @custom:field parentHash The hash of the previous block.
* @custom:field timestamp The block time.
* @custom:field number The block number.
* @custom:field gasLimit Maximum gas allowed.
* @custom:field baseFee The base fee per gas.
* @custom:field transactionsRoot Root hash of the transactions.
* @custom:field stateRoot Root hash of the state trie.
* @custom:field withdrawalsRoot Root hash of the withdrawals.
* @custom:field txHashes Array of hash of the transaction.
* @custom:field blobGasUsed The total amount of blob gas consumed by the transactions within the block.
* @custom:field excessBlobGas A total of blob gas consumed in excess of the target, prior to the block.
* @custom:field parentBeaconRoot Root hash of the parent beacon block.
*/
struct PublicInput {
bytes32 blockHash;
bytes32 parentHash;
uint64 timestamp;
uint64 number;
uint64 gasLimit;
uint256 baseFee;
bytes32 transactionsRoot;
bytes32 stateRoot;
bytes32 withdrawalsRoot;
bytes32[] txHashes;
uint64 blobGasUsed;
uint64 excessBlobGas;
bytes32 parentBeaconRoot;
}
/**
* @notice Struct representing the elements that are hashed together to generate a block hash.
* Some of fields that are contained in PublicInput are omitted.
*
* @custom:field uncleHash RLP encoded uncle hash.
* @custom:field coinbase RLP encoded coinbase.
* @custom:field receiptsRoot RLP encoded receipts root.
* @custom:field logsBloom RLP encoded logs bloom.
* @custom:field difficulty RLP encoded difficulty.
* @custom:field gasUsed RLP encoded gas used.
* @custom:field extraData RLP encoded extra data.
* @custom:field mixHash RLP encoded mix hash.
* @custom:field nonce RLP encoded nonce.
*/
struct BlockHeaderRLP {
bytes uncleHash;
bytes coinbase;
bytes receiptsRoot;
bytes logsBloom;
bytes difficulty;
bytes gasUsed;
bytes extraData;
bytes mixHash;
bytes nonce;
}
/**
* @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end
* user (as opposed to a system deposit transaction generated by the system).
*
* @custom:field from Address of the sender of the transaction.
* @custom:field to Address of the recipient of the transaction.
* @custom:field isCreation True if the transaction is a contract creation.
* @custom:field value Value to send to the recipient.
* @custom:field mint Amount of ETH to mint.
* @custom:field gasLimit Gas limit of the transaction.
* @custom:field data Data of the transaction.
* @custom:field l1BlockHash Hash of the block the transaction was submitted in.
* @custom:field logIndex Index of the log in the block the transaction was submitted in.
*/
struct UserDepositTransaction {
address from;
address to;
bool isCreation;
uint256 value;
uint256 mint;
uint64 gasLimit;
bytes data;
bytes32 l1BlockHash;
uint64 logIndex;
}
/**
* @notice Struct representing a withdrawal transaction.
*
* @custom:field nonce Nonce of the withdrawal transaction
* @custom:field sender Address of the sender of the transaction.
* @custom:field target Address of the recipient of the transaction.
* @custom:field value Value to send to the recipient.
* @custom:field gasLimit Gas limit of the transaction.
* @custom:field data Data of the transaction.
*/
struct WithdrawalTransaction {
uint256 nonce;
address sender;
address target;
uint256 value;
uint256 gasLimit;
bytes data;
}
/**
* @notice Struct representing a challenge.
*
* @custom:field turn The current turn.
* @custom:field timeoutAt Timeout timestamp of the next turn.
* @custom:field asserter Address of the asserter.
* @custom:field challenger Address of the challenger.
* @custom:field segments Array of the segment.
* @custom:field segStart The L2 block number of the first segment.
* @custom:field segSize The number of L2 blocks.
* @custom:field l1Head Parent L1 block hash at the challenge creation time.
*/
struct Challenge {
uint8 turn;
uint64 timeoutAt;
address asserter;
address challenger;
bytes32[] segments;
uint256 segSize;
uint256 segStart;
bytes32 l1Head;
}
/**
* @notice Struct representing a validator's bond.
*
* @custom:field amount Amount of the lock.
* @custom:field expiresAt The expiration timestamp of bond.
*/
struct Bond {
uint128 amount;
uint128 expiresAt;
}
/**
* @notice Struct representing multisig transaction data.
*
* @custom:field target The destination address to run the transaction.
* @custom:field executed Record whether a transaction was executed or not.
* @custom:field value The value passed in while executing the transaction.
* @custom:field data Calldata for transaction.
*/
struct MultiSigTransaction {
address target;
bool executed;
uint256 value;
bytes data;
}
/**
* @notice Struct representing multisig confirmation data.
*
* @custom:field confirmationCount The sum of confirmations.
* @custom:field confirmedBy Map data that stores whether confirmation is performed by account.
*/
struct MultiSigConfirmation {
uint256 confirmationCount;
mapping(address => bool) confirmedBy;
}
/**
* @notice Struct representing the data for verifying the public input of zkEVM proof.
*
* @custom:field srcOutputRootProof Proof of the source output root.
* @custom:field dstOutputRootProof Proof of the destination output root.
* @custom:field publicInput Ingredients to compute the public input used by
* zkEVM proof verification.
* @custom:field rlps Pre-encoded RLPs to compute the next block hash
* of the source output root proof.
* @custom:field l2ToL1MessagePasserBalance Balance of the L2ToL1MessagePasser account.
* @custom:field l2ToL1MessagePasserCodeHash Codehash of the L2ToL1MessagePasser account.
* @custom:field merkleProof Merkle proof of L2ToL1MessagePasser account against the state root.
*/
struct PublicInputProof {
OutputRootProof srcOutputRootProof;
OutputRootProof dstOutputRootProof;
PublicInput publicInput;
BlockHeaderRLP rlps;
bytes32 l2ToL1MessagePasserBalance;
bytes32 l2ToL1MessagePasserCodeHash;
bytes[] merkleProof;
}
/**
* @notice Struct representing zkEVM public input and proof.
*
* @param publicInputProof Data for verifying the public input.
* @param proof Halo2 proofs composed of points and scalars.
* See https://zcash.github.io/halo2/design/implementation/proofs.html.
* @param pair Aggregated multi-opening proofs and public inputs.
* (Currently only 2 public inputs)
*/
struct ZkEvmProof {
PublicInputProof publicInputProof;
uint256[] proof;
uint256[] pair;
}
/**
* @notice Struct representing zkVM public input and proof.
*
* @param zkVmProgramVKey The verification key for the zkVM program.
* @param publicValues The public values concatenated.
* (Currently 3 public inputs: bytes32 srcOutputRoot, bytes32 dstOutputRoot, bytes32 l1Head)
* @param proofBytes The proof of the program execution the SP1 zkVM encoded as bytes.
*/
struct ZkVmProof {
bytes32 zkVmProgramVKey;
bytes publicValues;
bytes proofBytes;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title ISemver
/// @notice ISemver is a simple contract for ensuring that contracts are
/// versioned using semantic versioning.
interface ISemver {
/// @notice Getter for the semantic version of the contract. This is not
/// meant to be used onchain but instead meant to be used by offchain
/// tooling.
/// @return Semver contract version as a string.
function version() external view returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
/// @title SP1 Verifier Interface
/// @author Succinct Labs
/// @notice This contract is the interface for the SP1 Verifier.
/// See https://github.com/succinctlabs/sp1-contracts/blob/main-0.8.15/contracts/src/ISP1Verifier.sol
interface ISP1Verifier {
/// @notice Verifies a proof with given public values and vkey.
/// @dev It is expected that the first 4 bytes of proofBytes must match the first 4 bytes of
/// target verifier's VERIFIER_HASH.
/// @param programVKey The verification key for the RISC-V program.
/// @param publicValues The public values encoded as bytes.
/// @param proofBytes The proof of the program execution the SP1 zkVM encoded as bytes.
function verifyProof(
bytes32 programVKey,
bytes calldata publicValues,
bytes calldata proofBytes
) external view;
}
interface ISP1VerifierWithHash is ISP1Verifier {
/// @notice Returns the hash of the verifier.
function VERIFIER_HASH() external pure returns (bytes32);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
/**
* @title IZKMerkleTrie
*/
interface IZKMerkleTrie {
/**
* @notice Verifies a proof that a given key/value pair is present in the trie.
*
* @param _key Key of the node to search for, as a hex string.
* @param _value Value of the node to search for, as a hex string.
* @param _proofs Merkle trie inclusion proof for the desired node.
* @param _root Known root of the Merkle trie. Used to verify that the included proof is
* correctly constructed.
*
* @return Whether or not the proof is valid.
*/
function verifyInclusionProof(
bytes32 _key,
bytes memory _value,
bytes[] memory _proofs,
bytes32 _root
) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Hashing } from "./Hashing.sol";
import { Types } from "./Types.sol";
import { RLPWriter } from "./rlp/RLPWriter.sol";
/// @title Encoding
/// @notice Encoding handles Kroma's various different encoding schemes.
library Encoding {
/// @notice RLP encodes the L2 transaction that would be generated when a given deposit is sent
/// to the L2 system. Useful for searching for a deposit in the L2 system. The
/// transaction is prefixed with 0x7e to identify its EIP-2718 type.
/// @param _tx User deposit transaction to encode.
/// @param _isKromaDepTx Whether the given transaction is a KromaDepositTx.
/// @return RLP encoded L2 deposit transaction.
function encodeDepositTransaction(
Types.UserDepositTransaction memory _tx,
bool _isKromaDepTx
) internal pure returns (bytes memory) {
bytes32 source = Hashing.hashDepositSource(_tx.l1BlockHash, _tx.logIndex);
bytes[] memory raw;
if (_isKromaDepTx) {
raw = new bytes[](7);
raw[0] = RLPWriter.writeBytes(abi.encodePacked(source));
raw[1] = RLPWriter.writeAddress(_tx.from);
raw[2] = _tx.isCreation ? RLPWriter.writeBytes("") : RLPWriter.writeAddress(_tx.to);
raw[3] = RLPWriter.writeUint(_tx.mint);
raw[4] = RLPWriter.writeUint(_tx.value);
raw[5] = RLPWriter.writeUint(uint256(_tx.gasLimit));
raw[6] = RLPWriter.writeBytes(_tx.data);
} else {
raw = new bytes[](8);
raw[0] = RLPWriter.writeBytes(abi.encodePacked(source));
raw[1] = RLPWriter.writeAddress(_tx.from);
raw[2] = _tx.isCreation ? RLPWriter.writeBytes("") : RLPWriter.writeAddress(_tx.to);
raw[3] = RLPWriter.writeUint(_tx.mint);
raw[4] = RLPWriter.writeUint(_tx.value);
raw[5] = RLPWriter.writeUint(uint256(_tx.gasLimit));
raw[6] = RLPWriter.writeBool(false);
raw[7] = RLPWriter.writeBytes(_tx.data);
}
return abi.encodePacked(uint8(0x7e), RLPWriter.writeList(raw));
}
/// @notice Encodes the cross domain message based on the version that is encoded into the
/// message nonce.
/// @param _nonce Message nonce with version encoded into the first two bytes.
/// @param _sender Address of the sender of the message.
/// @param _target Address of the target of the message.
/// @param _value ETH value to send to the target.
/// @param _gasLimit Gas limit to use for the message.
/// @param _data Data to send with the message.
/// @return Encoded cross domain message.
function encodeCrossDomainMessage(
uint256 _nonce,
address _sender,
address _target,
uint256 _value,
uint256 _gasLimit,
bytes memory _data
) internal pure returns (bytes memory) {
(, uint16 version) = decodeVersionedNonce(_nonce);
if (version == 0) {
return encodeCrossDomainMessageV0(_nonce, _sender, _target, _value, _gasLimit, _data);
} else {
revert("Encoding: unknown cross domain message version");
}
}
/// @notice Encodes a cross domain message based on the V0 (current) encoding.
/// @param _nonce Message nonce.
/// @param _sender Address of the sender of the message.
/// @param _target Address of the target of the message.
/// @param _value ETH value to send to the target.
/// @param _gasLimit Gas limit to use for the message.
/// @param _data Data to send with the message.
/// @return Encoded cross domain message.
function encodeCrossDomainMessageV0(
uint256 _nonce,
address _sender,
address _target,
uint256 _value,
uint256 _gasLimit,
bytes memory _data
) internal pure returns (bytes memory) {
return
abi.encodeWithSignature(
"relayMessage(uint256,address,address,uint256,uint256,bytes)",
_nonce,
_sender,
_target,
_value,
_gasLimit,
_data
);
}
/// @notice Adds a version number into the first two bytes of a message nonce.
/// @param _nonce Message nonce to encode into.
/// @param _version Version number to encode into the message nonce.
/// @return Message nonce with version encoded into the first two bytes.
function encodeVersionedNonce(uint240 _nonce, uint16 _version) internal pure returns (uint256) {
uint256 nonce;
assembly {
nonce := or(shl(240, _version), _nonce)
}
return nonce;
}
/// @notice Pulls the version out of a version-encoded nonce.
/// @param _nonce Message nonce with version encoded into the first two bytes.
/// @return Nonce without encoded version.
/// @return Version of the message.
function decodeVersionedNonce(uint256 _nonce) internal pure returns (uint240, uint16) {
uint240 nonce;
uint16 version;
assembly {
nonce := and(_nonce, 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
version := shr(240, _nonce)
}
return (nonce, version);
}
/// @notice Returns an appropriately encoded call to KromaL1Block.setL1BlockValuesEcotone
/// @param baseFeeScalar L1 base fee Scalar
/// @param blobBaseFeeScalar L1 blob base fee Scalar
/// @param sequenceNumber Number of L2 blocks since epoch start.
/// @param timestamp L1 timestamp.
/// @param number L1 blocknumber.
/// @param baseFee L1 base fee.
/// @param blobBaseFee L1 blob base fee.
/// @param hash L1 blockhash.
/// @param batcherHash Versioned hash to authenticate batcher by.
/// @param validatorRewardScalar Validator reward scalar.
function encodeSetL1BlockValuesEcotone(
uint32 baseFeeScalar,
uint32 blobBaseFeeScalar,
uint64 sequenceNumber,
uint64 timestamp,
uint64 number,
uint256 baseFee,
uint256 blobBaseFee,
bytes32 hash,
bytes32 batcherHash,
uint256 validatorRewardScalar
) internal pure returns (bytes memory) {
bytes4 functionSignature = bytes4(keccak256("setL1BlockValuesEcotone()"));
return
abi.encodePacked(
functionSignature,
baseFeeScalar,
blobBaseFeeScalar,
sequenceNumber,
timestamp,
number,
baseFee,
blobBaseFee,
hash,
batcherHash,
validatorRewardScalar
);
}
/// @notice Returns an appropriately encoded call to L1Block.setL1BlockValuesEcotone without validatorRewardScalar.
/// @param baseFeeScalar L1 base fee Scalar
/// @param blobBaseFeeScalar L1 blob base fee Scalar
/// @param sequenceNumber Number of L2 blocks since epoch start.
/// @param timestamp L1 timestamp.
/// @param number L1 blocknumber.
/// @param baseFee L1 base fee.
/// @param blobBaseFee L1 blob base fee.
/// @param hash L1 blockhash.
/// @param batcherHash Versioned hash to authenticate batcher by.
function encodeSetL1BlockValuesKromaMPT(
uint32 baseFeeScalar,
uint32 blobBaseFeeScalar,
uint64 sequenceNumber,
uint64 timestamp,
uint64 number,
uint256 baseFee,
uint256 blobBaseFee,
bytes32 hash,
bytes32 batcherHash
) internal pure returns (bytes memory) {
bytes4 functionSignature = bytes4(keccak256("setL1BlockValuesEcotone()"));
return
abi.encodePacked(
functionSignature,
baseFeeScalar,
blobBaseFeeScalar,
sequenceNumber,
timestamp,
number,
baseFee,
blobBaseFee,
hash,
batcherHash
);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @custom:attribution https://github.com/bakaoh/solidity-rlp-encode
/// @title RLPWriter
/// @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's
/// RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor
/// modifications to improve legibility.
library RLPWriter {
/// @notice RLP encodes a byte string.
/// @param _in The byte string to encode.
/// @return out_ The RLP encoded string in bytes.
function writeBytes(bytes memory _in) internal pure returns (bytes memory out_) {
if (_in.length == 1 && uint8(_in[0]) < 128) {
out_ = _in;
} else {
out_ = abi.encodePacked(_writeLength(_in.length, 128), _in);
}
}
/// @notice RLP encodes a list of RLP encoded byte byte strings.
/// @param _in The list of RLP encoded byte strings.
/// @return list_ The RLP encoded list of items in bytes.
function writeList(bytes[] memory _in) internal pure returns (bytes memory list_) {
list_ = _flatten(_in);
list_ = abi.encodePacked(_writeLength(list_.length, 192), list_);
}
/// @notice RLP encodes a string.
/// @param _in The string to encode.
/// @return out_ The RLP encoded string in bytes.
function writeString(string memory _in) internal pure returns (bytes memory out_) {
out_ = writeBytes(bytes(_in));
}
/// @notice RLP encodes an address.
/// @param _in The address to encode.
/// @return out_ The RLP encoded address in bytes.
function writeAddress(address _in) internal pure returns (bytes memory out_) {
out_ = writeBytes(abi.encodePacked(_in));
}
/// @notice RLP encodes a uint.
/// @param _in The uint256 to encode.
/// @return out_ The RLP encoded uint256 in bytes.
function writeUint(uint256 _in) internal pure returns (bytes memory out_) {
out_ = writeBytes(_toBinary(_in));
}
/// @notice RLP encodes a bool.
/// @param _in The bool to encode.
/// @return out_ The RLP encoded bool in bytes.
function writeBool(bool _in) internal pure returns (bytes memory out_) {
out_ = new bytes(1);
out_[0] = (_in ? bytes1(0x01) : bytes1(0x80));
}
/// @notice Encode the first byte and then the `len` in binary form if `length` is more than 55.
/// @param _len The length of the string or the payload.
/// @param _offset 128 if item is string, 192 if item is list.
/// @return out_ RLP encoded bytes.
function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory out_) {
if (_len < 56) {
out_ = new bytes(1);
out_[0] = bytes1(uint8(_len) + uint8(_offset));
} else {
uint256 lenLen;
uint256 i = 1;
while (_len / i != 0) {
lenLen++;
i *= 256;
}
out_ = new bytes(lenLen + 1);
out_[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55);
for (i = 1; i <= lenLen; i++) {
out_[i] = bytes1(uint8((_len / (256 ** (lenLen - i))) % 256));
}
}
}
/// @notice Encode integer in big endian binary form with no leading zeroes.
/// @param _x The integer to encode.
/// @return out_ RLP encoded bytes.
function _toBinary(uint256 _x) private pure returns (bytes memory out_) {
bytes memory b = abi.encodePacked(_x);
uint256 i = 0;
for (; i < 32; i++) {
if (b[i] != 0) {
break;
}
}
out_ = new bytes(32 - i);
for (uint256 j = 0; j < out_.length; j++) {
out_[j] = b[i++];
}
}
/// @custom:attribution https://github.com/Arachnid/solidity-stringutils
/// @notice Copies a piece of memory to another location.
/// @param _dest Destination location.
/// @param _src Source location.
/// @param _len Length of memory to copy.
function _memcpy(uint256 _dest, uint256 _src, uint256 _len) private pure {
uint256 dest = _dest;
uint256 src = _src;
uint256 len = _len;
for (; len >= 32; len -= 32) {
assembly {
mstore(dest, mload(src))
}
dest += 32;
src += 32;
}
uint256 mask;
unchecked {
mask = 256 ** (32 - len) - 1;
}
assembly {
let srcpart := and(mload(src), not(mask))
let destpart := and(mload(dest), mask)
mstore(dest, or(destpart, srcpart))
}
}
/// @custom:attribution https://github.com/sammayo/solidity-rlp-encoder
/// @notice Flattens a list of byte strings into one byte string.
/// @param _list List of byte strings to flatten.
/// @return out_ The flattened byte string.
function _flatten(bytes[] memory _list) private pure returns (bytes memory out_) {
if (_list.length == 0) {
return new bytes(0);
}
uint256 len;
uint256 i = 0;
for (; i < _list.length; i++) {
len += _list[i].length;
}
out_ = new bytes(len);
uint256 flattenedPtr;
assembly {
flattenedPtr := add(out_, 0x20)
}
for (i = 0; i < _list.length; i++) {
bytes memory item = _list[i];
uint256 listPtr;
assembly {
listPtr := add(item, 0x20)
}
_memcpy(flattenedPtr, listPtr, item.length);
flattenedPtr += _list[i].length;
}
}
}{
"remappings": [
"@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/",
"@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/",
"@rari-capital/solmate/=node_modules/@rari-capital/solmate/",
"forge-std/=node_modules/forge-std/src/",
"ds-test/=node_modules/ds-test/src/",
"hardhat-deploy/=node_modules/hardhat-deploy/",
"hardhat/=node_modules/hardhat/"
],
"optimizer": {
"enabled": true,
"runs": 10000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract ZKVerifier","name":"_zkVerifier","type":"address"},{"internalType":"bytes32","name":"_dummyHash","type":"bytes32"},{"internalType":"uint256","name":"_maxTxs","type":"uint256"},{"internalType":"address","name":"_zkMerkleTrie","type":"address"},{"internalType":"contract ISP1Verifier","name":"_sp1Verifier","type":"address"},{"internalType":"bytes32","name":"_zkVmProgramVKey","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BlockHashMismatched","type":"error"},{"inputs":[],"name":"BlockHashMismatchedBtwSrcAndDst","type":"error"},{"inputs":[],"name":"DstOutputMatched","type":"error"},{"inputs":[],"name":"InvalidInclusionProof","type":"error"},{"inputs":[],"name":"InvalidPublicInput","type":"error"},{"inputs":[],"name":"InvalidZkProof","type":"error"},{"inputs":[],"name":"InvalidZkVmVKey","type":"error"},{"inputs":[],"name":"SrcOutputMismatched","type":"error"},{"inputs":[],"name":"StateRootMismatched","type":"error"},{"inputs":[],"name":"dummyHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTxs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sp1Verifier","outputs":[{"internalType":"contract ISP1Verifier","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"components":[{"internalType":"bytes32","name":"version","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"internalType":"bytes32","name":"messagePasserStorageRoot","type":"bytes32"},{"internalType":"bytes32","name":"latestBlockhash","type":"bytes32"},{"internalType":"bytes32","name":"nextBlockHash","type":"bytes32"}],"internalType":"struct Types.OutputRootProof","name":"srcOutputRootProof","type":"tuple"},{"components":[{"internalType":"bytes32","name":"version","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"internalType":"bytes32","name":"messagePasserStorageRoot","type":"bytes32"},{"internalType":"bytes32","name":"latestBlockhash","type":"bytes32"},{"internalType":"bytes32","name":"nextBlockHash","type":"bytes32"}],"internalType":"struct Types.OutputRootProof","name":"dstOutputRootProof","type":"tuple"},{"components":[{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"bytes32","name":"parentHash","type":"bytes32"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"uint64","name":"number","type":"uint64"},{"internalType":"uint64","name":"gasLimit","type":"uint64"},{"internalType":"uint256","name":"baseFee","type":"uint256"},{"internalType":"bytes32","name":"transactionsRoot","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"internalType":"bytes32","name":"withdrawalsRoot","type":"bytes32"},{"internalType":"bytes32[]","name":"txHashes","type":"bytes32[]"},{"internalType":"uint64","name":"blobGasUsed","type":"uint64"},{"internalType":"uint64","name":"excessBlobGas","type":"uint64"},{"internalType":"bytes32","name":"parentBeaconRoot","type":"bytes32"}],"internalType":"struct Types.PublicInput","name":"publicInput","type":"tuple"},{"components":[{"internalType":"bytes","name":"uncleHash","type":"bytes"},{"internalType":"bytes","name":"coinbase","type":"bytes"},{"internalType":"bytes","name":"receiptsRoot","type":"bytes"},{"internalType":"bytes","name":"logsBloom","type":"bytes"},{"internalType":"bytes","name":"difficulty","type":"bytes"},{"internalType":"bytes","name":"gasUsed","type":"bytes"},{"internalType":"bytes","name":"extraData","type":"bytes"},{"internalType":"bytes","name":"mixHash","type":"bytes"},{"internalType":"bytes","name":"nonce","type":"bytes"}],"internalType":"struct Types.BlockHeaderRLP","name":"rlps","type":"tuple"},{"internalType":"bytes32","name":"l2ToL1MessagePasserBalance","type":"bytes32"},{"internalType":"bytes32","name":"l2ToL1MessagePasserCodeHash","type":"bytes32"},{"internalType":"bytes[]","name":"merkleProof","type":"bytes[]"}],"internalType":"struct Types.PublicInputProof","name":"publicInputProof","type":"tuple"},{"internalType":"uint256[]","name":"proof","type":"uint256[]"},{"internalType":"uint256[]","name":"pair","type":"uint256[]"}],"internalType":"struct Types.ZkEvmProof","name":"_zkEvmProof","type":"tuple"},{"internalType":"bytes32","name":"_storedSrcOutput","type":"bytes32"},{"internalType":"bytes32","name":"_storedDstOutput","type":"bytes32"}],"name":"verifyZkEvmProof","outputs":[{"internalType":"bytes32","name":"publicInputHash_","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"zkVmProgramVKey","type":"bytes32"},{"internalType":"bytes","name":"publicValues","type":"bytes"},{"internalType":"bytes","name":"proofBytes","type":"bytes"}],"internalType":"struct Types.ZkVmProof","name":"_zkVmProof","type":"tuple"},{"internalType":"bytes32","name":"_storedSrcOutput","type":"bytes32"},{"internalType":"bytes32","name":"_storedDstOutput","type":"bytes32"},{"internalType":"bytes32","name":"_storedL1Head","type":"bytes32"}],"name":"verifyZkVmProof","outputs":[{"internalType":"bytes32","name":"publicInputHash_","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"zkMerkleTrie","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"zkVerifier","outputs":[{"internalType":"contract ZKVerifier","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"zkVmProgramVKey","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"}]Contract Creation Code
6101406040523480156200001257600080fd5b50604051620023bf380380620023bf83398101604081905262000035916200007e565b6001600160a01b0395861660805260a09490945260c092909252831660e0529091166101005261012052620000ef565b6001600160a01b03811681146200007b57600080fd5b50565b60008060008060008060c087890312156200009857600080fd5b8651620000a58162000065565b8096505060208701519450604087015193506060870151620000c78162000065565b6080880151909350620000da8162000065565b8092505060a087015190509295509295509295565b60805160a05160c05160e051610100516101205161224a620001756000396000818160aa0152818161041f015261055f01526000818160f2015261053801526000818161018201526108530152600081816101a80152818161094b01526109b90152600081816101e10152610985015260008181610207015261033a015261224a6000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c80635747274b116100765780639a7ec1361161005b5780639a7ec136146101cc5780639aea2572146101df578063d6df096d1461020557600080fd5b80635747274b14610180578063816bf26d146101a657600080fd5b8063222ce122146100a85780633955d7a1146100dd57806352a07fa3146100f057806354fd4d5014610137575b600080fd5b7f00000000000000000000000000000000000000000000000000000000000000005b6040519081526020015b60405180910390f35b6100ca6100eb366004611504565b61022b565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100d4565b6101736040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100d491906115c8565b7f0000000000000000000000000000000000000000000000000000000000000000610112565b7f00000000000000000000000000000000000000000000000000000000000000006100ca565b6100ca6101da3660046115e2565b610419565b7f00000000000000000000000000000000000000000000000000000000000000006100ca565b7f0000000000000000000000000000000000000000000000000000000000000000610112565b6000366102388580611636565b905060808101356101008201351461027c576040517f3f126fab00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6102b2848461029861029336869003860186611740565b610616565b6102ad61029336879003870160a08801611740565b6106b8565b6102da60a082016102c76101408401846117b0565b6102d56101608501856117e4565b610736565b6103066102eb6101c0830183611818565b6101808401356101a085013560e086013560c08701356107fb565b610321602082013561031c6101408401846117b0565b610945565b915073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016634292dc3e61036c6020880188611818565b61037960408a018a611818565b876040518663ffffffff1660e01b815260040161039a9594939291906118d6565b602060405180830381865afa1580156103b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103db9190611910565b610411576040517fe1ac453100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b509392505050565b600084357f000000000000000000000000000000000000000000000000000000000000000014610475576040517f2166766900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104c484846104876020890189611932565b61049691602891600891611997565b61049f916119c1565b6104ac60208a018a611932565b6104bb91605091603091611997565b6102ad916119c1565b816104d26020870187611932565b6104e191607891605891611997565b6104ea916119c1565b14610521576040517f7458ca2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166341493c607f000000000000000000000000000000000000000000000000000000000000000061058b6020890189611932565b61059860408b018b611932565b6040518663ffffffff1660e01b81526004016105b8959493929190611a28565b60006040518083038186803b1580156105d057600080fd5b505afa1580156105e4573d6000803e3d6000fd5b506105f6925050506020860186611932565b604051610604929190611a61565b60405180910390209050949350505050565b60808101516000906106785781516020808401516040808601516060870151915161065b95949192910193845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b81516020808401516040808601516060808801516080808a01518551978801989098529386019490945284015282015260a081019190915260c00161065b565b8184146106f1576040517f8b10302800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b821561073057808303610730576040517f4e15341500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b82602001358260e0013514610777576040517f4d9e774000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006101808301356107a25761079d61078f84611b09565b61079884611c81565b610a02565b6107bc565b6107bc6107ae84611b09565b6107b784611c81565b610aa6565b905080846060013514610730576040517fb033950600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051600060208201528082018690526060810185905260808082018590528251808303909101815260a08201928390527f12e64a72000000000000000000000000000000000000000000000000000000009092527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906312e64a72906108c5907f42000000000000000000000000000000000000030000000000000000000000009085908c908c90899060a401611df7565b602060405180830381865afa1580156108e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190611910565b61093c576040517ff35959c000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050565b600060607f0000000000000000000000000000000000000000000000000000000000000000610978610120850185611818565b905010156109e5576109e27f00000000000000000000000000000000000000000000000000000000000000006109b2610120860186611818565b6109dd91507f0000000000000000000000000000000000000000000000000000000000000000611f1f565b610bb7565b90505b6109f8846109f285611b09565b83610c3b565b9150505b92915050565b6040805160118082526102408201909252600091829190816020015b6060815260200190600190039081610a1e579050509050610a40848483610cad565b610a6f846101000151604051602001610a5b91815260200190565b604051602081830303815290604052610f60565b81601081518110610a8257610a82611f36565b6020026020010181905250610a9681610fcb565b8051906020012091505092915050565b6040805160148082526102a08201909252600091829190816020015b6060815260200190600190039081610ac2579050509050610ae4848483610cad565b610aff846101000151604051602001610a5b91815260200190565b81601081518110610b1257610b12611f36565b6020026020010181905250610b3584610140015167ffffffffffffffff16610ff6565b81601181518110610b4857610b48611f36565b6020026020010181905250610b6b84610160015167ffffffffffffffff16610ff6565b81601281518110610b7e57610b7e611f36565b6020026020010181905250610ba4846101800151604051602001610a5b91815260200190565b81601381518110610a8257610a82611f36565b606060008267ffffffffffffffff811115610bd457610bd4611674565b604051908082528060200260200182016040528015610bfd578160200160208202803683370190505b50905060005b838110156104115784828281518110610c1e57610c1e611f36565b602090810291909101015280610c3381611f65565b915050610c03565b6000838360e001516000801b85600001518660200151876060015188604001518960a001518a608001518b6101200151518c61012001518c604051602001610c8e9c9b9a99989796959493929190611fb2565b6040516020818303038152906040528051906020012090509392505050565b610cc78360200151604051602001610a5b91815260200190565b81600081518110610cda57610cda611f36565b6020026020010181905250816000015181600181518110610cfd57610cfd611f36565b6020026020010181905250816020015181600281518110610d2057610d20611f36565b6020026020010181905250610d458360e00151604051602001610a5b91815260200190565b81600381518110610d5857610d58611f36565b6020026020010181905250610d7d8360c00151604051602001610a5b91815260200190565b81600481518110610d9057610d90611f36565b6020026020010181905250816040015181600581518110610db357610db3611f36565b6020026020010181905250816060015181600681518110610dd657610dd6611f36565b6020026020010181905250816080015181600781518110610df957610df9611f36565b6020026020010181905250610e1b836060015167ffffffffffffffff16610ff6565b81600881518110610e2e57610e2e611f36565b6020026020010181905250610e50836080015167ffffffffffffffff16610ff6565b81600981518110610e6357610e63611f36565b60200260200101819052508160a0015181600a81518110610e8657610e86611f36565b6020026020010181905250610ea8836040015167ffffffffffffffff16610ff6565b81600b81518110610ebb57610ebb611f36565b60200260200101819052508160c0015181600c81518110610ede57610ede611f36565b60200260200101819052508160e0015181600d81518110610f0157610f01611f36565b602002602001018190525081610100015181600e81518110610f2557610f25611f36565b6020026020010181905250610f3d8360a00151610ff6565b81600f81518110610f5057610f50611f36565b6020026020010181905250505050565b606081516001148015610f8d5750608082600081518110610f8357610f83611f36565b016020015160f81c105b15610f96575090565b610fa282516080611009565b82604051602001610fb492919061206b565b60405160208183030381529060405290505b919050565b6060610fd6826111fd565b9050610fe4815160c0611009565b81604051602001610fb492919061206b565b60606109fc61100483611332565b610f60565b60606038831015611087576040805160018082528183019092529060208201818036833701905050905061103d828461209a565b60f81b8160008151811061105357611053611f36565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506109fc565b600060015b61109681866120ee565b156110bc57816110a581611f65565b92506110b5905061010082612102565b905061108c565b6110c7826001612121565b67ffffffffffffffff8111156110df576110df611674565b6040519080825280601f01601f191660200182016040528015611109576020820181803683370190505b509250611116848361209a565b61112190603761209a565b60f81b8360008151811061113757611137611f36565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600190505b8181116111f55761010061117f8284611f1f565b61118b9061010061221d565b61119590876120ee565b61119f9190612229565b60f81b8382815181106111b4576111b4611f36565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806111ed81611f65565b91505061116b565b505092915050565b6060815160000361121c57505060408051600081526020810190915290565b6000805b83518110156112635783818151811061123b5761123b611f36565b6020026020010151518261124f9190612121565b91508061125b81611f65565b915050611220565b8167ffffffffffffffff81111561127c5761127c611674565b6040519080825280601f01601f1916602001820160405280156112a6576020820181803683370190505b50925060009050602083015b845182101561132a5760008583815181106112cf576112cf611f36565b6020026020010151905060006020820190506112ed8382845161148f565b8684815181106112ff576112ff611f36565b602002602001015151836113139190612121565b92505050818061132290611f65565b9250506112b2565b505050919050565b606060008260405160200161134991815260200190565b604051602081830303815290604052905060005b60208110156113b85781818151811061137857611378611f36565b01602001517fff00000000000000000000000000000000000000000000000000000000000000166000036113b857806113b081611f65565b91505061135d565b6113c3816020611f1f565b67ffffffffffffffff8111156113db576113db611674565b6040519080825280601f01601f191660200182016040528015611405576020820181803683370190505b50925060005b835181101561132a57828261141f81611f65565b93508151811061143157611431611f36565b602001015160f81c60f81b84828151811061144e5761144e611f36565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508061148781611f65565b91505061140b565b8282825b602081106114cb57815183526114aa602084612121565b92506114b7602083612121565b91506114c4602082611f1f565b9050611493565b905182516020929092036101000a6000190180199091169116179052505050565b6000606082840312156114fe57600080fd5b50919050565b60008060006060848603121561151957600080fd5b833567ffffffffffffffff81111561153057600080fd5b61153c868287016114ec565b9660208601359650604090950135949350505050565b60005b8381101561156d578181015183820152602001611555565b838111156107305750506000910152565b60008151808452611596816020860160208601611552565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006115db602083018461157e565b9392505050565b600080600080608085870312156115f857600080fd5b843567ffffffffffffffff81111561160f57600080fd5b61161b878288016114ec565b97602087013597506040870135966060013595509350505050565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe2183360301811261166a57600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516101a0810167ffffffffffffffff811182821017156116c7576116c7611674565b60405290565b604051610120810167ffffffffffffffff811182821017156116c7576116c7611674565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561173857611738611674565b604052919050565b600060a0828403121561175257600080fd5b60405160a0810181811067ffffffffffffffff8211171561177557611775611674565b806040525082358152602083013560208201526040830135604082015260608301356060820152608083013560808201528091505092915050565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe6183360301811261166a57600080fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee183360301811261166a57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261184d57600080fd5b83018035915067ffffffffffffffff82111561186857600080fd5b6020019150600581901b360382131561188057600080fd5b9250929050565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156118b957600080fd5b8260051b8083602087013760009401602001938452509192915050565b6060815260006118ea606083018789611887565b82810360208401526118fd818688611887565b9150508260408301529695505050505050565b60006020828403121561192257600080fd5b815180151581146115db57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261196757600080fd5b83018035915067ffffffffffffffff82111561198257600080fd5b60200191503681900382131561188057600080fd5b600080858511156119a757600080fd5b838611156119b457600080fd5b5050820193919092039150565b803560208310156109fc57600019602084900360031b1b1692915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b858152606060208201526000611a426060830186886119df565b8281036040840152611a558185876119df565b98975050505050505050565b8183823760009101908152919050565b803567ffffffffffffffff81168114610fc657600080fd5b600082601f830112611a9a57600080fd5b8135602067ffffffffffffffff821115611ab657611ab6611674565b8160051b611ac58282016116f1565b9283528481018201928281019087851115611adf57600080fd5b83870192505b84831015611afe57823582529183019190830190611ae5565b979650505050505050565b60006101a08236031215611b1c57600080fd5b611b246116a3565b8235815260208301356020820152611b3e60408401611a71565b6040820152611b4f60608401611a71565b6060820152611b6060808401611a71565b608082015260a083013560a082015260c083013560c082015260e083013560e08201526101008084013581830152506101208084013567ffffffffffffffff811115611bab57600080fd5b611bb736828701611a89565b828401525050610140611bcb818501611a71565b90820152610160611bdd848201611a71565b9082015261018092830135928101929092525090565b600082601f830112611c0457600080fd5b813567ffffffffffffffff811115611c1e57611c1e611674565b611c4f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016116f1565b818152846020838601011115611c6457600080fd5b816020850160208301376000918101602001919091529392505050565b60006101208236031215611c9457600080fd5b611c9c6116cd565b823567ffffffffffffffff80821115611cb457600080fd5b611cc036838701611bf3565b83526020850135915080821115611cd657600080fd5b611ce236838701611bf3565b60208401526040850135915080821115611cfb57600080fd5b611d0736838701611bf3565b60408401526060850135915080821115611d2057600080fd5b611d2c36838701611bf3565b60608401526080850135915080821115611d4557600080fd5b611d5136838701611bf3565b608084015260a0850135915080821115611d6a57600080fd5b611d7636838701611bf3565b60a084015260c0850135915080821115611d8f57600080fd5b611d9b36838701611bf3565b60c084015260e0850135915080821115611db457600080fd5b611dc036838701611bf3565b60e084015261010091508185013581811115611ddb57600080fd5b611de736828801611bf3565b8385015250505080915050919050565b85815260006020608081840152611e11608084018861157e565b8381036040850152858152818101600587901b820183018860005b89811015611ed7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085840301845281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18c3603018112611e8d57600080fd5b8b01868101903567ffffffffffffffff811115611ea957600080fd5b803603821315611eb857600080fd5b611ec38582846119df565b958801959450505090850190600101611e2c565b5050809450505050508260608301529695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611f3157611f31611ef0565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006000198203611f7857611f78611ef0565b5060010190565b60008151602080840160005b83811015611fa757815187529582019590820190600101611f8b565b509495945050505050565b8c81528b60208201528a604082015289606082015288608082015260007fffffffffffffffff000000000000000000000000000000000000000000000000808a60c01b1660a0840152808960c01b1660a88401528760b0840152808760c01b1660d0840152507fffff0000000000000000000000000000000000000000000000000000000000008560f01b1660d883015261205961205360da840186611f7f565b84611f7f565b9e9d5050505050505050505050505050565b6000835161207d818460208801611552565b835190830190612091818360208801611552565b01949350505050565b600060ff821660ff84168060ff038211156120b7576120b7611ef0565b019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826120fd576120fd6120bf565b500490565b600081600019048311821515161561211c5761211c611ef0565b500290565b6000821982111561213457612134611ef0565b500190565b600181815b8085111561217457816000190482111561215a5761215a611ef0565b8085161561216757918102915b93841c939080029061213e565b509250929050565b60008261218b575060016109fc565b81612198575060006109fc565b81600181146121ae57600281146121b8576121d4565b60019150506109fc565b60ff8411156121c9576121c9611ef0565b50506001821b6109fc565b5060208310610133831016604e8410600b84101617156121f7575081810a6109fc565b6122018383612139565b806000190482111561221557612215611ef0565b029392505050565b60006115db838361217c565b600082612238576122386120bf565b50069056fea164736f6c634300080f000a0000000000000000000000006deb6a630d7b486c1c08d4016aee3835a2f52fa7edf1ae3da135c124658e215a9bf53477facb442a1dcd5a92388332cb6193237f0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000339208824010425cbe73201ced4372308acd610b000000000000000000000000d2832cf1fc8ba210ffabf62db9a8781153131d160082f10b794f55a90a98566913e7639ffeca0b7fcba30bdb1b3faed9c5534b75
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100a35760003560e01c80635747274b116100765780639a7ec1361161005b5780639a7ec136146101cc5780639aea2572146101df578063d6df096d1461020557600080fd5b80635747274b14610180578063816bf26d146101a657600080fd5b8063222ce122146100a85780633955d7a1146100dd57806352a07fa3146100f057806354fd4d5014610137575b600080fd5b7f0082f10b794f55a90a98566913e7639ffeca0b7fcba30bdb1b3faed9c5534b755b6040519081526020015b60405180910390f35b6100ca6100eb366004611504565b61022b565b7f000000000000000000000000d2832cf1fc8ba210ffabf62db9a8781153131d165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100d4565b6101736040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100d491906115c8565b7f000000000000000000000000339208824010425cbe73201ced4372308acd610b610112565b7f00000000000000000000000000000000000000000000000000000000000000646100ca565b6100ca6101da3660046115e2565b610419565b7fedf1ae3da135c124658e215a9bf53477facb442a1dcd5a92388332cb6193237f6100ca565b7f0000000000000000000000006deb6a630d7b486c1c08d4016aee3835a2f52fa7610112565b6000366102388580611636565b905060808101356101008201351461027c576040517f3f126fab00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6102b2848461029861029336869003860186611740565b610616565b6102ad61029336879003870160a08801611740565b6106b8565b6102da60a082016102c76101408401846117b0565b6102d56101608501856117e4565b610736565b6103066102eb6101c0830183611818565b6101808401356101a085013560e086013560c08701356107fb565b610321602082013561031c6101408401846117b0565b610945565b915073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006deb6a630d7b486c1c08d4016aee3835a2f52fa716634292dc3e61036c6020880188611818565b61037960408a018a611818565b876040518663ffffffff1660e01b815260040161039a9594939291906118d6565b602060405180830381865afa1580156103b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103db9190611910565b610411576040517fe1ac453100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b509392505050565b600084357f0082f10b794f55a90a98566913e7639ffeca0b7fcba30bdb1b3faed9c5534b7514610475576040517f2166766900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104c484846104876020890189611932565b61049691602891600891611997565b61049f916119c1565b6104ac60208a018a611932565b6104bb91605091603091611997565b6102ad916119c1565b816104d26020870187611932565b6104e191607891605891611997565b6104ea916119c1565b14610521576040517f7458ca2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d2832cf1fc8ba210ffabf62db9a8781153131d16166341493c607f0082f10b794f55a90a98566913e7639ffeca0b7fcba30bdb1b3faed9c5534b7561058b6020890189611932565b61059860408b018b611932565b6040518663ffffffff1660e01b81526004016105b8959493929190611a28565b60006040518083038186803b1580156105d057600080fd5b505afa1580156105e4573d6000803e3d6000fd5b506105f6925050506020860186611932565b604051610604929190611a61565b60405180910390209050949350505050565b60808101516000906106785781516020808401516040808601516060870151915161065b95949192910193845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b81516020808401516040808601516060808801516080808a01518551978801989098529386019490945284015282015260a081019190915260c00161065b565b8184146106f1576040517f8b10302800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b821561073057808303610730576040517f4e15341500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b82602001358260e0013514610777576040517f4d9e774000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006101808301356107a25761079d61078f84611b09565b61079884611c81565b610a02565b6107bc565b6107bc6107ae84611b09565b6107b784611c81565b610aa6565b905080846060013514610730576040517fb033950600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051600060208201528082018690526060810185905260808082018590528251808303909101815260a08201928390527f12e64a72000000000000000000000000000000000000000000000000000000009092527f000000000000000000000000339208824010425cbe73201ced4372308acd610b73ffffffffffffffffffffffffffffffffffffffff16906312e64a72906108c5907f42000000000000000000000000000000000000030000000000000000000000009085908c908c90899060a401611df7565b602060405180830381865afa1580156108e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190611910565b61093c576040517ff35959c000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050565b600060607f0000000000000000000000000000000000000000000000000000000000000064610978610120850185611818565b905010156109e5576109e27fedf1ae3da135c124658e215a9bf53477facb442a1dcd5a92388332cb6193237f6109b2610120860186611818565b6109dd91507f0000000000000000000000000000000000000000000000000000000000000064611f1f565b610bb7565b90505b6109f8846109f285611b09565b83610c3b565b9150505b92915050565b6040805160118082526102408201909252600091829190816020015b6060815260200190600190039081610a1e579050509050610a40848483610cad565b610a6f846101000151604051602001610a5b91815260200190565b604051602081830303815290604052610f60565b81601081518110610a8257610a82611f36565b6020026020010181905250610a9681610fcb565b8051906020012091505092915050565b6040805160148082526102a08201909252600091829190816020015b6060815260200190600190039081610ac2579050509050610ae4848483610cad565b610aff846101000151604051602001610a5b91815260200190565b81601081518110610b1257610b12611f36565b6020026020010181905250610b3584610140015167ffffffffffffffff16610ff6565b81601181518110610b4857610b48611f36565b6020026020010181905250610b6b84610160015167ffffffffffffffff16610ff6565b81601281518110610b7e57610b7e611f36565b6020026020010181905250610ba4846101800151604051602001610a5b91815260200190565b81601381518110610a8257610a82611f36565b606060008267ffffffffffffffff811115610bd457610bd4611674565b604051908082528060200260200182016040528015610bfd578160200160208202803683370190505b50905060005b838110156104115784828281518110610c1e57610c1e611f36565b602090810291909101015280610c3381611f65565b915050610c03565b6000838360e001516000801b85600001518660200151876060015188604001518960a001518a608001518b6101200151518c61012001518c604051602001610c8e9c9b9a99989796959493929190611fb2565b6040516020818303038152906040528051906020012090509392505050565b610cc78360200151604051602001610a5b91815260200190565b81600081518110610cda57610cda611f36565b6020026020010181905250816000015181600181518110610cfd57610cfd611f36565b6020026020010181905250816020015181600281518110610d2057610d20611f36565b6020026020010181905250610d458360e00151604051602001610a5b91815260200190565b81600381518110610d5857610d58611f36565b6020026020010181905250610d7d8360c00151604051602001610a5b91815260200190565b81600481518110610d9057610d90611f36565b6020026020010181905250816040015181600581518110610db357610db3611f36565b6020026020010181905250816060015181600681518110610dd657610dd6611f36565b6020026020010181905250816080015181600781518110610df957610df9611f36565b6020026020010181905250610e1b836060015167ffffffffffffffff16610ff6565b81600881518110610e2e57610e2e611f36565b6020026020010181905250610e50836080015167ffffffffffffffff16610ff6565b81600981518110610e6357610e63611f36565b60200260200101819052508160a0015181600a81518110610e8657610e86611f36565b6020026020010181905250610ea8836040015167ffffffffffffffff16610ff6565b81600b81518110610ebb57610ebb611f36565b60200260200101819052508160c0015181600c81518110610ede57610ede611f36565b60200260200101819052508160e0015181600d81518110610f0157610f01611f36565b602002602001018190525081610100015181600e81518110610f2557610f25611f36565b6020026020010181905250610f3d8360a00151610ff6565b81600f81518110610f5057610f50611f36565b6020026020010181905250505050565b606081516001148015610f8d5750608082600081518110610f8357610f83611f36565b016020015160f81c105b15610f96575090565b610fa282516080611009565b82604051602001610fb492919061206b565b60405160208183030381529060405290505b919050565b6060610fd6826111fd565b9050610fe4815160c0611009565b81604051602001610fb492919061206b565b60606109fc61100483611332565b610f60565b60606038831015611087576040805160018082528183019092529060208201818036833701905050905061103d828461209a565b60f81b8160008151811061105357611053611f36565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506109fc565b600060015b61109681866120ee565b156110bc57816110a581611f65565b92506110b5905061010082612102565b905061108c565b6110c7826001612121565b67ffffffffffffffff8111156110df576110df611674565b6040519080825280601f01601f191660200182016040528015611109576020820181803683370190505b509250611116848361209a565b61112190603761209a565b60f81b8360008151811061113757611137611f36565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600190505b8181116111f55761010061117f8284611f1f565b61118b9061010061221d565b61119590876120ee565b61119f9190612229565b60f81b8382815181106111b4576111b4611f36565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806111ed81611f65565b91505061116b565b505092915050565b6060815160000361121c57505060408051600081526020810190915290565b6000805b83518110156112635783818151811061123b5761123b611f36565b6020026020010151518261124f9190612121565b91508061125b81611f65565b915050611220565b8167ffffffffffffffff81111561127c5761127c611674565b6040519080825280601f01601f1916602001820160405280156112a6576020820181803683370190505b50925060009050602083015b845182101561132a5760008583815181106112cf576112cf611f36565b6020026020010151905060006020820190506112ed8382845161148f565b8684815181106112ff576112ff611f36565b602002602001015151836113139190612121565b92505050818061132290611f65565b9250506112b2565b505050919050565b606060008260405160200161134991815260200190565b604051602081830303815290604052905060005b60208110156113b85781818151811061137857611378611f36565b01602001517fff00000000000000000000000000000000000000000000000000000000000000166000036113b857806113b081611f65565b91505061135d565b6113c3816020611f1f565b67ffffffffffffffff8111156113db576113db611674565b6040519080825280601f01601f191660200182016040528015611405576020820181803683370190505b50925060005b835181101561132a57828261141f81611f65565b93508151811061143157611431611f36565b602001015160f81c60f81b84828151811061144e5761144e611f36565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508061148781611f65565b91505061140b565b8282825b602081106114cb57815183526114aa602084612121565b92506114b7602083612121565b91506114c4602082611f1f565b9050611493565b905182516020929092036101000a6000190180199091169116179052505050565b6000606082840312156114fe57600080fd5b50919050565b60008060006060848603121561151957600080fd5b833567ffffffffffffffff81111561153057600080fd5b61153c868287016114ec565b9660208601359650604090950135949350505050565b60005b8381101561156d578181015183820152602001611555565b838111156107305750506000910152565b60008151808452611596816020860160208601611552565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006115db602083018461157e565b9392505050565b600080600080608085870312156115f857600080fd5b843567ffffffffffffffff81111561160f57600080fd5b61161b878288016114ec565b97602087013597506040870135966060013595509350505050565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe2183360301811261166a57600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516101a0810167ffffffffffffffff811182821017156116c7576116c7611674565b60405290565b604051610120810167ffffffffffffffff811182821017156116c7576116c7611674565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561173857611738611674565b604052919050565b600060a0828403121561175257600080fd5b60405160a0810181811067ffffffffffffffff8211171561177557611775611674565b806040525082358152602083013560208201526040830135604082015260608301356060820152608083013560808201528091505092915050565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe6183360301811261166a57600080fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee183360301811261166a57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261184d57600080fd5b83018035915067ffffffffffffffff82111561186857600080fd5b6020019150600581901b360382131561188057600080fd5b9250929050565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156118b957600080fd5b8260051b8083602087013760009401602001938452509192915050565b6060815260006118ea606083018789611887565b82810360208401526118fd818688611887565b9150508260408301529695505050505050565b60006020828403121561192257600080fd5b815180151581146115db57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261196757600080fd5b83018035915067ffffffffffffffff82111561198257600080fd5b60200191503681900382131561188057600080fd5b600080858511156119a757600080fd5b838611156119b457600080fd5b5050820193919092039150565b803560208310156109fc57600019602084900360031b1b1692915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b858152606060208201526000611a426060830186886119df565b8281036040840152611a558185876119df565b98975050505050505050565b8183823760009101908152919050565b803567ffffffffffffffff81168114610fc657600080fd5b600082601f830112611a9a57600080fd5b8135602067ffffffffffffffff821115611ab657611ab6611674565b8160051b611ac58282016116f1565b9283528481018201928281019087851115611adf57600080fd5b83870192505b84831015611afe57823582529183019190830190611ae5565b979650505050505050565b60006101a08236031215611b1c57600080fd5b611b246116a3565b8235815260208301356020820152611b3e60408401611a71565b6040820152611b4f60608401611a71565b6060820152611b6060808401611a71565b608082015260a083013560a082015260c083013560c082015260e083013560e08201526101008084013581830152506101208084013567ffffffffffffffff811115611bab57600080fd5b611bb736828701611a89565b828401525050610140611bcb818501611a71565b90820152610160611bdd848201611a71565b9082015261018092830135928101929092525090565b600082601f830112611c0457600080fd5b813567ffffffffffffffff811115611c1e57611c1e611674565b611c4f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016116f1565b818152846020838601011115611c6457600080fd5b816020850160208301376000918101602001919091529392505050565b60006101208236031215611c9457600080fd5b611c9c6116cd565b823567ffffffffffffffff80821115611cb457600080fd5b611cc036838701611bf3565b83526020850135915080821115611cd657600080fd5b611ce236838701611bf3565b60208401526040850135915080821115611cfb57600080fd5b611d0736838701611bf3565b60408401526060850135915080821115611d2057600080fd5b611d2c36838701611bf3565b60608401526080850135915080821115611d4557600080fd5b611d5136838701611bf3565b608084015260a0850135915080821115611d6a57600080fd5b611d7636838701611bf3565b60a084015260c0850135915080821115611d8f57600080fd5b611d9b36838701611bf3565b60c084015260e0850135915080821115611db457600080fd5b611dc036838701611bf3565b60e084015261010091508185013581811115611ddb57600080fd5b611de736828801611bf3565b8385015250505080915050919050565b85815260006020608081840152611e11608084018861157e565b8381036040850152858152818101600587901b820183018860005b89811015611ed7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085840301845281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18c3603018112611e8d57600080fd5b8b01868101903567ffffffffffffffff811115611ea957600080fd5b803603821315611eb857600080fd5b611ec38582846119df565b958801959450505090850190600101611e2c565b5050809450505050508260608301529695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611f3157611f31611ef0565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006000198203611f7857611f78611ef0565b5060010190565b60008151602080840160005b83811015611fa757815187529582019590820190600101611f8b565b509495945050505050565b8c81528b60208201528a604082015289606082015288608082015260007fffffffffffffffff000000000000000000000000000000000000000000000000808a60c01b1660a0840152808960c01b1660a88401528760b0840152808760c01b1660d0840152507fffff0000000000000000000000000000000000000000000000000000000000008560f01b1660d883015261205961205360da840186611f7f565b84611f7f565b9e9d5050505050505050505050505050565b6000835161207d818460208801611552565b835190830190612091818360208801611552565b01949350505050565b600060ff821660ff84168060ff038211156120b7576120b7611ef0565b019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826120fd576120fd6120bf565b500490565b600081600019048311821515161561211c5761211c611ef0565b500290565b6000821982111561213457612134611ef0565b500190565b600181815b8085111561217457816000190482111561215a5761215a611ef0565b8085161561216757918102915b93841c939080029061213e565b509250929050565b60008261218b575060016109fc565b81612198575060006109fc565b81600181146121ae57600281146121b8576121d4565b60019150506109fc565b60ff8411156121c9576121c9611ef0565b50506001821b6109fc565b5060208310610133831016604e8410600b84101617156121f7575081810a6109fc565b6122018383612139565b806000190482111561221557612215611ef0565b029392505050565b60006115db838361217c565b600082612238576122386120bf565b50069056fea164736f6c634300080f000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000006deb6a630d7b486c1c08d4016aee3835a2f52fa7edf1ae3da135c124658e215a9bf53477facb442a1dcd5a92388332cb6193237f0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000339208824010425cbe73201ced4372308acd610b000000000000000000000000d2832cf1fc8ba210ffabf62db9a8781153131d160082f10b794f55a90a98566913e7639ffeca0b7fcba30bdb1b3faed9c5534b75
-----Decoded View---------------
Arg [0] : _zkVerifier (address): 0x6deb6a630D7b486c1C08d4016AEe3835a2F52Fa7
Arg [1] : _dummyHash (bytes32): 0xedf1ae3da135c124658e215a9bf53477facb442a1dcd5a92388332cb6193237f
Arg [2] : _maxTxs (uint256): 100
Arg [3] : _zkMerkleTrie (address): 0x339208824010425cBE73201ceD4372308ACD610B
Arg [4] : _sp1Verifier (address): 0xd2832Cf1fC8bA210FfABF62Db9A8781153131d16
Arg [5] : _zkVmProgramVKey (bytes32): 0x0082f10b794f55a90a98566913e7639ffeca0b7fcba30bdb1b3faed9c5534b75
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000006deb6a630d7b486c1c08d4016aee3835a2f52fa7
Arg [1] : edf1ae3da135c124658e215a9bf53477facb442a1dcd5a92388332cb6193237f
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000064
Arg [3] : 000000000000000000000000339208824010425cbe73201ced4372308acd610b
Arg [4] : 000000000000000000000000d2832cf1fc8ba210ffabf62db9a8781153131d16
Arg [5] : 0082f10b794f55a90a98566913e7639ffeca0b7fcba30bdb1b3faed9c5534b75
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.