Contratto
0xa2e71fc2fb02d1ce93aa958e56cab83d26f3bfa6
- Indirizzo
- 0xa2e71fc2fb02d1ce93aa958e56cab83d26f3bfa6
- Tipo
- contratto verificato FinalIdentityRegistry
- Saldo
- 0 vETH
- Nonce
- 1
- Codice
- 24,120 byte codehash 0xc7fc0a1d2c10a7246f5f4455f89c75fc5dedf707edb37a1182c8e5a5a572946d
albero dei conti
- Albero
- 1 · conti
- Presente
- nessuna foglia
- Chiave
- 0x8ed7379e1912b74da297b1921c3fd6e9bd3568453b2bb6ffaacf4e79d0fffa88
- Radice live
- 0xe7eb646dfe4cfe9c975fd970c7c565c8d96e5c1edae4440e5f6a2560325fb328
Questo indirizzo non ha una foglia nell'albero dei conti. Ogni Final Wallet — identità di servizio incluse — ne ha una, quindi una foglia assente significa un account ordinario, non una wallet.
sorgente verificato
- Contratto
- FinalIdentityRegistry corrispondenza esatta
- Compilatore
- v0.8.33+commit.64118f21
- Ottimizzatore
- attivo · 200 passaggi
- Versione EVM
- prague
- Verificato
- 2026-09-07T05:08:56.460Z
- Provenienza
- preverify-final-chain (forge artifact, bytecode compared against live code)
contracts/finalchain/FinalCertificate.sol
// SPDX-License-Identifier: BUSL-1.1
// Copyright (c) 2024-2026 Final DeFi
// Licensed under the Business Source License 1.1 (the "License")
//
// Change Date: 2029-01-01
// Change License: GPL-2.0-or-later
//
// @author Final DeFi
// @version 1.0.0
pragma solidity ^0.8.20;
import {FinalChainPrecompiles} from "./FinalChainPrecompiles.sol";
import {FinalChainTime} from "./FinalChainTime.sol";
/**
* @title FinalCertificate
* @notice Reads a Final Certificate (`.fcert`, schema v3) on chain.
*
* @dev Final Chain only — it needs the SHA3-256 precompile, because the schema
* hashes with FIPS-202 SHA3 and the EVM has `keccak256`, which is a different
* function.
*
* ## Why the chain parses this at all
*
* `FinalIdentityRegistry.registerWithCertificate` used to take the TBS bytes
* AND the public keys as separate arguments. It derived `certHash` from the
* bytes, which sounds like verification and is not: nothing compared the keys
* to the certificate, so a registrar could bind any certificate to any keypair.
* The registry would then hold a key the certificate does not contain, and every
* signature that key produced would verify against a certificate that never
* authorised it.
*
* So the keys are read OUT of the certificate. There is one input and no way for
* two arguments to disagree.
*
* ## The SubjectKeyId check
*
* The schema defines `SubjectKeyId` as SHA3-256 of the `PublicKeyBlock`. Having
* parsed the block, this recomputes that digest and compares. The field is
* inside the TBS, so it is covered by the CA's signatures — which makes the
* check a statement about what the CA attested, not merely about internal
* consistency of bytes the caller supplied.
*
* ## What this does NOT do
*
* It does not verify the CA's signatures over the TBS, and it does not walk the
* chain to the root. Both are possible here — the precompiles verify ML-DSA-87
* and SLH-DSA-SHAKE-256s — and both are deliberately out of scope for the
* registry's bootstrap path, where the registrar is the party that issued the
* certificate in the first place. `verifyIssuerSignatures` below is provided for
* callers that need it, and the identity registry uses it once a CA is itself
* registered.
*/
library FinalCertificate {
/// `"PQCF"`.
uint32 internal constant MAGIC = 0x50514346;
/// The current wire generation — v5's `Version = 2` (chain-attested
/// issuance; ruled 2026-09-01). The v4 wire (`Version = 1`) stays
/// PARSEABLE so pre-cutover artifacts still read; encoders write 2.
/// fails to parse rather than being reinterpreted: `pqKeysHash` and every
/// wallet address derive from this exact layout.
uint32 internal constant VERSION = 2;
/// The v4 generation, accepted on parse for pre-cutover artifacts.
uint32 internal constant VERSION_V4 = 1;
/// @notice The 0x0102 Institution identity extension (issuer profile).
uint16 internal constant EXT_INSTITUTION = 0x0102;
/// Algorithm ids ARE the FIPS numbers, in one space for signatures and KEMs
/// — the same ids the quorum wire format and the backend registry use, and
/// the numbers the precompile addresses end in.
/// ML-KEM-1024 (FIPS 203), the lattice half of the encapsulation pair.
uint16 internal constant ALG_ML_KEM_1024 = 0x0003;
/// ML-DSA-87 (FIPS 204). Transaction class.
uint16 internal constant ALG_ML_DSA_87 = 0x0004;
/// SLH-DSA-SHAKE-256s (FIPS 205). Access class, and the seal.
uint16 internal constant ALG_SLH_DSA_SHAKE_256S = 0x0005;
/// FN-DSA (FIPS 206). Reserved: no implementation, never accepted.
uint16 internal constant ALG_FN_DSA = 0x0006;
/// HQC-5 (FIPS 207), the code-based half of the encapsulation pair.
uint16 internal constant ALG_HQC_5 = 0x0007;
/// Certificate signing. Says which key to verify WITH; it grants nothing —
/// that comes from `Depth` and `MaxDelegationDepth`.
uint16 internal constant PURPOSE_CERT_SIGNING = 0x0004;
/// The wallet's four slots, in two stages of two.
///
/// A certificate carries ONE stage, never all four. The stage is what gets
/// issued, rotated and revoked as a unit, and a holder presenting a live
/// certificate presents both of that stage's keys or neither — splitting
/// them per slot would let half a stage be presented as if it were whole.
///
/// This applies to services exactly as it applies to a user's wallet.
/// A co-signer is a Final Wallet: same four slots, same split, same
/// algorithms. There is no second kind of identity in this system.
uint16 internal constant PURPOSE_ACTIVE_TX = 0x0010;
uint16 internal constant PURPOSE_ACTIVE_ACCESS = 0x0011;
uint16 internal constant PURPOSE_RECOVERY_TX = 0x0012;
uint16 internal constant PURPOSE_RECOVERY_ACCESS = 0x0013;
/// @dev v4's encapsulation purposes. Parsed, and each stage's pair is
/// resolved alongside its signing pair — `FinalIdentityRegistry` then
/// stores them so a sender can encapsulate to a registered party
/// without a second lookup somewhere less authoritative.
///
/// They were declared and skipped for one release, which is how the
/// registry's four encapsulation-key mappings ended up read in three
/// places and written in none: `kemCommitments` hashed the empty
/// string for every account and `kemKeysOf` returned nothing.
uint16 internal constant PURPOSE_ACTIVE_KEM = 0x0014;
uint16 internal constant PURPOSE_RECOVERY_KEM = 0x0015;
/// @dev The seal: a second SLH-DSA-SHAKE-256s key, distinct from the access
/// key, that co-signs execution-class quorum decisions. Carried by
/// SERVICE certificates only — a user's wallet never seals — and
/// optional in the schema, so a certificate without it parses
/// unchanged. Outside `keysHash`: a seal is operational, rotated by
/// issuing a new live certificate, and it must not move a wallet
/// address it plays no part in.
uint16 internal constant PURPOSE_ACTIVE_SEAL = 0x0016;
/// @dev A purpose no certificate can carry, so `parse` can be told "this
/// stage has no encapsulation slot" without a second boolean. `0xffff`
/// is outside the registry and reserved by being used here.
uint16 internal constant NO_KEM_PURPOSE = 0xffff;
/// Nanoseconds per second. The schema's validity fields are nanoseconds and
/// `block.timestamp` is seconds; a comparison across the two units is a bug
/// waiting for the first certificate anybody actually checks.
/// @dev The schema stamps validity in NANOseconds and this chain's clock is
/// MILLIseconds, so a certificate converts down by 1e6 rather than by
/// 1e9. It was 1e9 — seconds — which made every `notBefore` look 1000x
/// too small against `block.timestamp` and every certificate
/// permanently "already valid", including one issued for the future.
uint64 internal constant NS_PER_MILLISECOND = FinalChainTime.NS_PER_MILLISECOND;
/// @notice What the chain keeps out of one certificate.
struct Parsed {
bytes32 certHash;
bytes32 serial;
/// keccak256 of the IssuerDN bytes, for the chain-issuer pin: a
/// chain-attested certificate carries the ruled constant DN and the
/// registry compares hashes rather than strings.
bytes32 issuerDnHash;
/// The SubjectDN bytes verbatim — the jurisdiction rule reads its
/// `C=` component at issuer registration.
bytes subjectDn;
/// The 0x0102 Institution extension VALUE, when present; empty
/// otherwise. Issuer registration parses jurisdiction out of it.
bytes institutionExt;
/// SHA3-256 of the ISSUER's public key block. Zero-length — and so
/// `bytes32(0)` here — for exactly one certificate in the hierarchy,
/// which is what terminates chain validation.
bytes32 authorityKeyId;
/// SHA3-256 of this certificate's own public key block. The child's
/// `authorityKeyId` must equal it, which is what links the two.
bytes32 subjectKeyId;
uint8 depth;
uint8 maxDelegationDepth;
/// MILLISECONDS, converted from the schema's nanoseconds — this chain's clock.
uint64 notBefore;
/// Milliseconds. Zero means never expires, which the schema allows.
uint64 notAfter;
/// The stage's transaction-class key. ML-DSA-87 — spending, and every
/// high-cadence protocol action.
bytes transactionKey;
/// The stage's access-class key. SLH-DSA-SHAKE-256s — identity,
/// rotation, recovery-pair promotion. A different hardness assumption,
/// so a lattice break leaves the key that governs identity standing.
bytes accessKey;
/// The stage's ML-KEM-1024 encapsulation key. Empty on a CA, which has
/// no encapsulation stage, and on any v4 certificate issued without
/// one — see `parse` for why that is tolerated rather than refused.
bytes kemMlKem;
/// The stage's HQC-5 encapsulation key. Carried under the SAME purpose
/// as the lattice half and distinguished only by algorithm, which is
/// why the parser matches on the `(purpose, algorithm)` pair.
bytes kemHqc;
/// The service's seal key (`PURPOSE_ACTIVE_SEAL`, SLH-DSA-SHAKE-256s).
/// Empty on every certificate that does not carry one — a user wallet,
/// a recovery stage, a CA.
bytes sealKey;
/// Where the TBS ends, so a caller holding the whole certificate can
/// find the `SignatureBlock` without parsing forward again.
uint256 tbsLength;
}
error BadMagic(uint32 got);
error BadVersion(uint32 got);
error Truncated(uint256 needed, uint256 got);
error SubjectKeyIdMismatch(bytes32 derived, bytes32 declared);
error MissingSlot(uint16 purpose);
error WrongAlgorithmForSlot(uint16 purpose, uint16 algorithm);
error DuplicateKey(uint16 purpose, uint16 algorithm);
error KeysNotSorted();
error BadKeyLength(uint16 algorithm, uint256 length);
error InvalidDepth(uint8 depth, uint8 maxDelegationDepth);
error ValidityInverted(uint64 notBefore, uint64 notAfter);
/**
* @notice Parse and self-check a `TBSCertificate`.
* @param tbs the TBS bytes, verbatim. Not the whole certificate.
* @param txPurpose the transaction-class purpose this stage should carry.
* @param accessPurpose the access-class purpose for the same stage.
*
* @dev Checking for a CAPABILITY rather than a type is the schema's own
* rule, and the reason there is no type field to check instead. Passing the
* LIVE purposes to a recovery certificate finds neither key and reverts —
* which is what stops a recovery certificate being registered as a live one
* and handing the recovery pair everyday authority.
*/
function parse(bytes calldata tbs, uint16 txPurpose, uint16 accessPurpose, uint16 kemPurpose)
internal
view
returns (Parsed memory out)
{
_need(tbs, 58);
if (uint32(bytes4(tbs[0:4])) != MAGIC) revert BadMagic(uint32(bytes4(tbs[0:4])));
// Both live generations. v4 artifacts predate chain-attested issuance
// and still parse — supersession is handled at admission (PoP and the
// chain-issuer pins), not by refusing to read history.
uint32 wireVersion = uint32(bytes4(tbs[4:8]));
if (wireVersion != VERSION && wireVersion != VERSION_V4) revert BadVersion(wireVersion);
out.certHash = FinalChainPrecompiles.sha3_256(tbs);
out.serial = bytes32(tbs[8:40]);
out.depth = uint8(tbs[40]);
out.maxDelegationDepth = uint8(tbs[41]);
uint64 notBeforeNs = uint64(bytes8(tbs[42:50]));
uint64 notAfterNs = uint64(bytes8(tbs[50:58]));
if (out.maxDelegationDepth < out.depth) {
revert InvalidDepth(out.depth, out.maxDelegationDepth);
}
if (notAfterNs != 0 && notAfterNs <= notBeforeNs) {
revert ValidityInverted(notBeforeNs, notAfterNs);
}
out.notBefore = notBeforeNs / NS_PER_MILLISECOND;
out.notAfter = notAfterNs == 0 ? 0 : notAfterNs / NS_PER_MILLISECOND;
// Four length-prefixed fields: IssuerDN, SubjectDN, AuthorityKeyId,
// SubjectKeyId. Every field before them is fixed width, which is the
// whole reason the schema orders them this way.
uint256 p = 58;
uint256 issuerDnLen;
(p, issuerDnLen) = _skipLengthPrefixed(tbs, p);
out.issuerDnHash = keccak256(tbs[p - issuerDnLen:p]);
uint256 subjectDnLen;
(p, subjectDnLen) = _skipLengthPrefixed(tbs, p);
out.subjectDn = tbs[p - subjectDnLen:p];
uint256 akidLen;
(p, akidLen) = _skipLengthPrefixed(tbs, p);
out.authorityKeyId = _bytes32At(tbs, p - akidLen, akidLen);
uint256 skidLen;
(p, skidLen) = _skipLengthPrefixed(tbs, p);
uint256 skidStart = p - skidLen;
_need(tbs, p + 2);
uint16 keyCount = uint16(bytes2(tbs[p:p + 2]));
p += 2;
// AFTER the count word. `SubjectKeyId` is SHA3-256 of the KeyEntry
// array alone — `encodeTbs` writes `PublicKeyCount` as its own field and
// `encodePublicKeyBlock` returns only the entries. Hashing the count in
// produces a digest that is self-consistent and matches no certificate
// any issuer ever wrote.
uint256 blockStart = p;
uint32 previousSort = 0;
for (uint256 i = 0; i < keyCount; i++) {
_need(tbs, p + 8);
uint16 alg = uint16(bytes2(tbs[p:p + 2]));
uint16 purpose = uint16(bytes2(tbs[p + 2:p + 4]));
uint32 keyLen = uint32(bytes4(tbs[p + 4:p + 8]));
p += 8;
_need(tbs, p + keyLen);
// Ascending by (purpose, algorithm), duplicates invalid. The schema
// requires the order so `certHash` is reproducible across
// implementations; enforcing it here also means a second entry for
// one slot cannot quietly shadow the first.
uint32 sortKey = (uint32(purpose) << 16) | uint32(alg);
if (i > 0) {
if (sortKey == previousSort) revert DuplicateKey(purpose, alg);
if (sortKey < previousSort) revert KeysNotSorted();
}
previousSort = sortKey;
// The algorithm is pinned per CLASS, not merely recorded. A
// transaction slot carrying an access-class key would verify
// cryptographically and mean something entirely different — an
// identity key must never authorize a transaction, or splitting the
// classes buys nothing.
// Matched on the PAIR, not on the purpose alone. A CA carries two
// keys under one purpose (`0x0004`) distinguished only by
// algorithm, so matching on purpose first would find the first of
// them twice and the second never.
if (purpose == txPurpose && alg == ALG_ML_DSA_87) {
if (keyLen != FinalChainPrecompiles.ML_DSA_87_PUBLIC_KEY_LEN) {
revert BadKeyLength(alg, keyLen);
}
out.transactionKey = tbs[p:p + keyLen];
} else if (purpose == accessPurpose && alg == ALG_SLH_DSA_SHAKE_256S) {
if (keyLen != FinalChainPrecompiles.SLH_DSA_SHAKE_256S_PUBLIC_KEY_LEN) {
revert BadKeyLength(alg, keyLen);
}
out.accessKey = tbs[p:p + keyLen];
} else if (purpose == kemPurpose && alg == ALG_ML_KEM_1024) {
out.kemMlKem = tbs[p:p + keyLen];
} else if (purpose == kemPurpose && alg == ALG_HQC_5) {
out.kemHqc = tbs[p:p + keyLen];
} else if (purpose == PURPOSE_ACTIVE_SEAL && alg == ALG_SLH_DSA_SHAKE_256S) {
if (keyLen != FinalChainPrecompiles.SLH_DSA_SHAKE_256S_PUBLIC_KEY_LEN) {
revert BadKeyLength(alg, keyLen);
}
out.sealKey = tbs[p:p + keyLen];
} else if (purpose == PURPOSE_ACTIVE_SEAL) {
// The seal is hash-based by definition — it exists to stand on
// the OTHER assumption from the transaction key it co-signs
// with. A lattice seal would be two signatures on one bet.
revert WrongAlgorithmForSlot(purpose, alg);
} else if (purpose == txPurpose || purpose == accessPurpose) {
// A slot the caller asked for, carrying the wrong scheme. It
// would verify cryptographically and mean something else
// entirely — an identity key must never authorize a
// transaction, or splitting the classes buys nothing.
revert WrongAlgorithmForSlot(purpose, alg);
} else if (purpose == kemPurpose) {
// Same rule for the encapsulation slot. A third KEM appearing
// under this purpose is a hybrid whose second family nobody
// agreed on, and admitting it silently is how a pair becomes a
// trio that one reader honours and another ignores.
revert WrongAlgorithmForSlot(purpose, alg);
}
// NO length check on the KEM keys here, and that is deliberate.
// The signing slots are checked against a constant because the
// parser's own callers depend on the length; an encapsulation key
// is checked by `0x0203` / `0x0207` at the moment it is REGISTERED,
// where the answer is a well-formedness verdict rather than a
// parse failure. Two checks of the same thing in two shapes is how
// one of them ends up weaker and nobody notices which.
p += keyLen;
}
// `SubjectKeyId` is SHA3-256 of the KeyEntry array, count word
// EXCLUDED — `blockStart` is taken after the count is consumed, for the
// reason given where it is set. Recomputing it is what turns "these
// bytes decode" into "the CA signed these exact keys"; the field is
// inside the TBS, so it is covered by the signatures.
out.subjectKeyId = FinalChainPrecompiles.sha3_256(tbs[blockStart:p]);
bytes32 declared = _bytes32At(tbs, skidStart, skidLen);
if (out.subjectKeyId != declared) revert SubjectKeyIdMismatch(out.subjectKeyId, declared);
// Both or neither. A stage is issued as a unit, so a certificate
// carrying one of its two keys is not a partial certificate — it is a
// certificate for a stage that does not exist.
if (out.transactionKey.length == 0) revert MissingSlot(txPurpose);
if (out.accessKey.length == 0) revert MissingSlot(accessPurpose);
// The encapsulation pair is both-or-neither for the same reason, and
// the reason is louder here: a hybrid quietly reduced to one family is
// identical on the wire, so a certificate carrying only the lattice
// half would seal successfully and silently drop the code-based hedge.
// Neither is the CA case and the pre-v4 case, both legitimate.
if ((out.kemMlKem.length == 0) != (out.kemHqc.length == 0)) {
revert MissingSlot(kemPurpose);
}
_need(tbs, p + 2);
uint16 extCount = uint16(bytes2(tbs[p:p + 2]));
p += 2;
for (uint256 i = 0; i < extCount; i++) {
_need(tbs, p + 7);
uint16 extType = uint16(bytes2(tbs[p:p + 2]));
uint32 valueLen = uint32(bytes4(tbs[p + 3:p + 7]));
p += 7;
_need(tbs, p + valueLen);
// The Institution extension's VALUE, kept for the issuer
// profile's jurisdiction rule. Everything else is skipped as
// before — extensions are structural to certHash, semantic to
// whichever consumer knows them.
if (extType == EXT_INSTITUTION) out.institutionExt = tbs[p:p + valueLen];
p += valueLen;
}
out.tbsLength = p;
}
/// @notice Parse a LIVE-stage certificate: `activeTransaction` + `activeAccess`.
/// @dev `external`, like the other three entry points below: the registry
/// sits against the EIP-170 ceiling and the TBS parser is its single
/// largest inlined dependency, so the four doors it actually calls are
/// DEPLOY-LINKED — the library is one more contract in the plane's fixed
/// nonce-0 deploy order (doctrine §2 of `arch/final-chain-regenesis.md`),
/// its address baked immutably into the registry's bytecode. A linked
/// library is code, not a key: nothing can repoint it after deployment.
function parseLive(bytes calldata tbs) external view returns (Parsed memory) {
return parse(tbs, PURPOSE_ACTIVE_TX, PURPOSE_ACTIVE_ACCESS, PURPOSE_ACTIVE_KEM);
}
/// @notice Parse a RECOVERY-stage certificate.
/// @dev The recovery pair authorizes rotating the wallet's own credentials
/// and NOTHING else — acting as a guardian, an ordinary action for that
/// account, uses the live access key. Keeping the two stages in separate
/// certificates is what makes that boundary something a verifier can see.
function parseRecovery(bytes calldata tbs) external view returns (Parsed memory) {
return parse(tbs, PURPOSE_RECOVERY_TX, PURPOSE_RECOVERY_ACCESS, PURPOSE_RECOVERY_KEM);
}
/// @notice Parse a CA certificate, whose two keys are both cert-signing.
/// @dev No encapsulation purpose: a CA signs and is never sealed to, so
/// `PURPOSE_ACTIVE_KEM` is passed as a value the loop can never match. A
/// CA certificate carrying encapsulation keys would parse them into slots
/// `_write` then discards, which is a shape worth refusing to have.
function parseCa(bytes calldata tbs) external view returns (Parsed memory) {
return parse(tbs, PURPOSE_CERT_SIGNING, PURPOSE_CERT_SIGNING, NO_KEM_PURPOSE);
}
/**
* @notice Verify a CA's dual signature over `tbs`.
* @dev Both must verify, not either. Two signatures under two different
* hardness assumptions is the entire reason the schema carries two, and
* accepting one would collapse that to whichever family breaks first.
*/
function verifyIssuerSignatures(
bytes memory tbs,
bytes memory issuerMlDsaKey,
bytes memory issuerSlhDsaKey,
bytes memory mlDsaSignature,
bytes memory slhDsaSignature
) external view returns (bool) {
return FinalChainPrecompiles.verifyMlDsa87(issuerMlDsaKey, tbs, mlDsaSignature)
&& FinalChainPrecompiles.verifySlhDsa(issuerSlhDsaKey, tbs, slhDsaSignature);
}
function _need(bytes calldata tbs, uint256 upto) private pure {
if (tbs.length < upto) revert Truncated(upto, tbs.length);
}
function _skipLengthPrefixed(bytes calldata tbs, uint256 p)
private
pure
returns (uint256 next, uint256 length)
{
_need(tbs, p + 4);
length = uint32(bytes4(tbs[p:p + 4]));
next = p + 4 + length;
_need(tbs, next);
}
function _bytes32At(bytes calldata tbs, uint256 start, uint256 length)
private
pure
returns (bytes32)
{
// A SubjectKeyId that is not 32 bytes is not a SHA3-256 digest, so it
// cannot match and the comparison will fail — which is the correct
// outcome and needs no separate error.
if (length != 32) return bytes32(0);
return bytes32(tbs[start:start + 32]);
}
}
contracts/finalchain/FinalChainPrecompiles.sol
// SPDX-License-Identifier: BUSL-1.1
// Copyright (c) 2024-2026 Final DeFi
// Licensed under the Business Source License 1.1 (the "License")
//
// Change Date: 2029-01-01
// Change License: GPL-2.0-or-later
//
// @author Final DeFi
// @version 1.0.0
pragma solidity ^0.8.20;
/**
* @title FinalChainPrecompiles
* @notice The three primitives Final Chain adds to the EVM, and the only
* supported way to reach them.
*
* @dev **These exist ONLY on Final Chain (chain id 48359).** They are provided
* by `final-reth`, the node binary in `FinalBackend/vendor/reth/final/`, and
* nothing at these addresses on Ethereum, Optimism or any other chain will
* answer. A contract that calls them must be one that only ever runs here;
* `assertAvailable` below is the cheap way to fail loudly rather than treat an
* empty return as a verified signature.
*
* The addresses are the FIPS numbers, which is the whole allocation rule —
* there is no local registry to consult and no way for two implementations to
* disagree about where a primitive lives:
*
* | address | primitive | FIPS |
* |---|---|---|
* | `0x…0202` | SHA3-256 | 202 |
* | `0x…0203` | ML-KEM-1024 key validation | 203 |
* | `0x…0204` | ML-DSA-87 verify | 204 |
* | `0x…0205` | SLH-DSA-SHAKE-256s verify | 205 |
* | `0x…0207` | HQC-5 key validation | 207 |
*
* The two KEM addresses VALIDATE keys and do nothing else, for one reason:
* encapsulation is a SENDER operation and decapsulation needs the secret key,
* so neither belongs on a chain at all. Checking that a registered public key
* is well-formed is hardening rather than a dependency, and nothing in this
* system waits on it.
*
* HQC's number is 207. It had none when the KEM pair was chosen, which was the
* one thing separating it from ML-KEM here — a primitive with no standard
* number has no address under this rule, and inventing one would have been a
* local convention masquerading as the global one.
*
* **No AEAD precompile, at any number.** The chain must never be able to
* decrypt an intent, and checking a revealed body against its commitment is a
* hash compare that `0x0202` already serves.
*
* ## Why this library refuses to take a public key from its caller
*
* It does take one — the primitives are pure functions and cannot do otherwise.
* The rule lives one level up, in `FinalPqQuorum`: a key passed as an argument
* proves nothing, because anyone holding a keypair can produce a valid
* signature under it. Only a key read from `FinalIdentityRegistry` is evidence
* about WHO signed. Every call site here must be able to answer "where did this
* key come from" with "storage", never "calldata".
*
* ## `success` is not the answer
*
* A `staticcall` to a verifier returns two things and both matter. `success`
* false means the call was malformed — usually a length bug in the caller — and
* `success` true with a zero word means the signature did not verify. The
* helpers below collapse both to `false` for the caller's convenience, which is
* safe in that direction and only in that direction: treating a failed call as
* a valid signature would be the whole security of the system.
*/
library FinalChainPrecompiles {
/// @notice SHA3-256 (FIPS 202). NOT `keccak256`, which is the
/// pre-standardisation padding and produces a different digest.
address internal constant SHA3_256 = address(0x0202);
/// @notice ML-DSA-87 verification (FIPS 204). Transaction-class keys.
address internal constant ML_DSA_87 = address(0x0204);
/// @notice SLH-DSA-SHAKE-256s verification (FIPS 205). Access-class keys.
address internal constant SLH_DSA_SHAKE_256S = address(0x0205);
/// @notice ML-KEM-1024 encapsulation-key validation (FIPS 203).
/// @dev VALIDATES; it does not encapsulate. Runs FIPS 203 §7.2's own
/// encapsulation-key check — the type check and the modulus check — and
/// nothing else. Encapsulation is a sender operation and decapsulation
/// needs the secret key, so neither belongs on a chain.
address internal constant ML_KEM_1024 = address(0x0203);
/// @notice HQC-5 public-key validation (FIPS 207).
/// @dev Structural only: the length, and the three padding bits the
/// encoding leaves beyond `n = 57637`. HQC has no cheap key-validity
/// predicate and this does not pretend to one.
address internal constant HQC_5 = address(0x0207);
/// @notice ML-DSA-87 public key length. Round-3 Dilithium5 shares it.
uint256 internal constant ML_DSA_87_PUBLIC_KEY_LEN = 2592;
/// @notice ML-DSA-87 signature length. Round-3 Dilithium5 is 4595.
uint256 internal constant ML_DSA_87_SIGNATURE_LEN = 4627;
/// @notice SLH-DSA-SHAKE-256s public key length (`PK.seed ‖ PK.root`).
uint256 internal constant SLH_DSA_SHAKE_256S_PUBLIC_KEY_LEN = 64;
/// @notice SLH-DSA-SHAKE-256s signature length. The `f` set is 49,856.
uint256 internal constant SLH_DSA_SHAKE_256S_SIGNATURE_LEN = 29792;
/// @notice Thrown when a precompile is absent, i.e. this is not Final Chain
/// or the node is stock reth rather than `final-reth`.
error PrecompileUnavailable(address precompile);
/**
* @notice Reverts unless all five precompiles answer.
* @dev Call this from a constructor. A contract whose security rests on PQ
* verification must not deploy onto a chain that cannot perform it — the
* failure mode otherwise is a quorum that reaches threshold with zero valid
* signatures, discovered at the worst possible moment.
*
* The probe is SHA3-256 of the empty string, whose value is a published
* FIPS 202 constant. It cannot be produced by an address with no code
* (which returns empty) nor by `keccak256` (which gives a different digest
* for the same input), so it distinguishes "the right precompile" from both
* "nothing here" and "the wrong hash function".
*/
function assertAvailable() internal view {
bytes32 expected = 0xa7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a;
(bool ok, bytes memory out) = SHA3_256.staticcall("");
if (!ok || out.length != 32 || bytes32(out) != expected) {
revert PrecompileUnavailable(SHA3_256);
}
// The two signature verifiers are probed by shape rather than by a
// known-answer vector: a KAT here would put a 29,792-byte signature in
// this contract's bytecode. A deliberately short input is a
// *precompile error* by contract, so a FAILED call is the pass and a
// silent success would mean something else is answering at the address.
_probeRejectsShortInput(ML_DSA_87);
_probeRejectsShortInput(SLH_DSA_SHAKE_256S);
// The two KEM validators are probed the other way round, because they
// are total by contract: a wrong length is a malformed KEY, which is
// the question being asked, so they ANSWER rather than error. A
// one-byte input must therefore come back as a well-formed `false`, and
// a failed call means nothing is there.
_probeAnswersFalse(ML_KEM_1024);
_probeAnswersFalse(HQC_5);
}
/**
* @dev A short input must make the precompile ERROR. The gas budget is the
* whole subtlety.
*
* A reverting CONTRACT refunds the gas it did not use. A precompile that
* returns an error consumes **everything forwarded to it** — and Solidity
* forwards 63/64 of what is left by default. Two such probes in a
* constructor therefore burn all but 1/4096 of the deployment's gas, and
* the deploy fails with no revert data at all.
*
* That is not hypothetical: it is what happened the first time this ran
* against a real `final-reth`, and no Foundry test could have caught it.
* A mocked precompile is a contract, and a contract's `require` hands the
* gas back.
*
* 5,000 is generous for a call that fails on a length check before any
* cryptography runs, and small enough that both probes together are noise
* against a deployment.
*/
function _probeRejectsShortInput(address precompile) private view {
bool ok;
assembly ("memory-safe") {
let ptr := mload(0x40)
mstore8(ptr, 0x00)
ok := staticcall(5000, precompile, ptr, 0x01, 0x00, 0x00)
}
if (ok) revert PrecompileUnavailable(precompile);
}
/**
* @dev A one-byte input must come back as a well-formed zero word.
*
* The inverse of `_probeRejectsShortInput`, and the inversion is the point:
* these two precompiles are TOTAL. Every byte string has an answer to "is
* this a well-formed key", and for one byte the answer is no. A precompile
* that errored here would be one that treats a malformed key as a caller
* bug, which is the opposite of what a registry wants.
*
* Gas is bounded for the same reason as the other probe — an erroring
* precompile consumes everything forwarded — even though the pass case
* returns normally and refunds.
*/
function _probeAnswersFalse(address precompile) private view {
bool ok;
bytes32 answer;
assembly ("memory-safe") {
let ptr := mload(0x40)
mstore8(ptr, 0x00)
ok := staticcall(5000, precompile, ptr, 0x01, ptr, 0x20)
answer := mload(ptr)
}
if (!ok || answer != bytes32(0)) revert PrecompileUnavailable(precompile);
}
/**
* @notice Is `encapsulationKey` a well-formed ML-KEM-1024 key?
*
* @dev The check a registry owes a sender. A malformed encapsulation key
* stored on chain is an account whose intents cannot be sealed, and the
* discovery happens at the first attempt to seal one — on the hybrid path,
* as a pair silently reduced to one family, which is the failure with no
* error attached.
*
* False rather than reverting on any shape, including the wrong length,
* because the caller is asking a question and every input has an answer.
*/
function isWellFormedMlKem1024(bytes memory encapsulationKey) internal view returns (bool) {
return _validatesKey(ML_KEM_1024, encapsulationKey);
}
/// @notice Is `publicKey` a well-formed HQC-5 key?
/// @dev Structural, and honestly partial — see the precompile. It catches a
/// truncated key, a key from the wrong parameter set, and a tail carrying
/// smuggled bytes, which are the three ways this goes wrong in practice.
function isWellFormedHqc5(bytes memory publicKey) internal view returns (bool) {
return _validatesKey(HQC_5, publicKey);
}
/// @dev A failed CALL is not a false answer. It means nothing is at the
/// address — this is not Final Chain, or the node is stock reth — and
/// reading it as "the key is malformed" would silently disable the check on
/// exactly the deployment where it cannot run.
function _validatesKey(address precompile, bytes memory key) private view returns (bool) {
(bool ok, bytes memory out) = precompile.staticcall(key);
if (!ok || out.length != 32) revert PrecompileUnavailable(precompile);
return bytes32(out) != bytes32(0);
}
/// @notice FIPS 202 SHA3-256 over `data`.
/// @dev The certificate schema hashes `TBSCertificate`, `SubjectKeyId` and
/// `AuthorityKeyId` with this, so it is the only function that can check a
/// `certHash` against the bytes it claims to summarise.
function sha3_256(bytes memory data) internal view returns (bytes32 digest) {
(bool ok, bytes memory out) = SHA3_256.staticcall(data);
if (!ok || out.length != 32) revert PrecompileUnavailable(SHA3_256);
digest = bytes32(out);
}
/// @notice Verify an ML-DSA-87 signature. False on any failure, including
/// a malformed call.
function verifyMlDsa87(bytes memory publicKey, bytes memory message, bytes memory signature)
internal
view
returns (bool)
{
if (
publicKey.length != ML_DSA_87_PUBLIC_KEY_LEN
|| signature.length != ML_DSA_87_SIGNATURE_LEN
) return false;
return _verify(ML_DSA_87, publicKey, signature, message);
}
/// @notice Verify an SLH-DSA-SHAKE-256s signature. False on any failure.
function verifySlhDsa(bytes memory publicKey, bytes memory message, bytes memory signature)
internal
view
returns (bool)
{
if (
publicKey.length != SLH_DSA_SHAKE_256S_PUBLIC_KEY_LEN
|| signature.length != SLH_DSA_SHAKE_256S_SIGNATURE_LEN
) return false;
return _verify(SLH_DSA_SHAKE_256S, publicKey, signature, message);
}
/// @dev `publicKey ‖ signature ‖ message`, in that order. Both fixed-length
/// fields come first so the message is unambiguously the remainder — the
/// same reason the precompile takes no length prefix.
function _verify(
address precompile,
bytes memory publicKey,
bytes memory signature,
bytes memory message
) private view returns (bool) {
(bool ok, bytes memory out) =
precompile.staticcall(abi.encodePacked(publicKey, signature, message));
return ok && out.length == 32 && bytes32(out) != bytes32(0);
}
}
contracts/finalchain/FinalChainTime.sol
// SPDX-License-Identifier: BUSL-1.1
// Copyright (c) 2024-2026 Final DeFi
pragma solidity ^0.8.20;
/**
* @title FinalChainTime
* @notice **On Final Chain, `block.timestamp` is MILLISECONDS.**
*
* @dev Every other EVM chain stamps seconds. This one cannot: it mints a block
* every 100 ms and Ethereum requires block timestamps to strictly increase, so
* a second-denominated clock would run out of distinct values ten times over
* per second. Milliseconds is the deliberate choice, and it is a property of
* the CHAIN — `final-reth` — not of any contract here.
*
* Every duration on this chain is therefore in milliseconds, and this library
* exists so that is stated in one place instead of assumed in fifteen.
*
* ## How this was found, which is the reason for the naming rules below
*
* It was not found by the test suite. Foundry's `block.timestamp` is seconds,
* so all 1249 tests agreed with the contracts and every one of them was wrong
* about the chain they deploy to. It was found the first time anything
* exercised a deadline against the real chain — a posted intent, which reverted
* `DeadlinePassed` against a header whose deadline had been computed from wall
* time.
*
* What was actually broken was worse than a posting. `rotationInitiatedAt` is
* written from `block.timestamp` and compared against `rotationInitiatedAt +
* delaySeconds`: a millisecond clock plus a second-denominated delay. The
* 24-hour default recovery delay elapsed in **86 seconds**, and the two-year
* dormancy threshold in about seventeen hours. That delay is the thing standing
* between a stolen recovery key and an account.
*
* Nothing had noticed because nothing time-dependent had ever run: `walletCount`
* is 0, `FinalBundleLog.size` is 0, and no intent had been posted.
*
* ## The naming rule
*
* A field or constant carrying a duration or an instant on this chain ends in
* `Ms`. Not decoration — the bug was a field named `delaySeconds` that held
* milliseconds, and a name that lies is how the next reader reintroduces it.
* `SECONDS` names are gone from `contracts/finalchain/` and must not come back.
*
* Solidity's `hours` / `days` suffixes are still the clearest way to write a
* duration, so they are written as `24 hours * MS_PER_SECOND` rather than as a
* literal: the intent stays readable and the unit stays explicit.
*/
library FinalChainTime {
/// @notice Milliseconds per second. The whole conversion, named once.
uint64 internal constant MS_PER_SECOND = 1_000;
/// @notice Milliseconds per nanosecond divisor — the certificate schema
/// stamps validity in NANOseconds, so a certificate converts down to this
/// chain's clock rather than up.
uint64 internal constant NS_PER_MILLISECOND = 1_000_000;
/// @notice This chain's clock, stated as a function so a caller reads the
/// unit rather than remembering it.
/// @dev No arithmetic. It exists to make `FinalChainTime.nowMs()` the thing
/// people write, which is self-describing where `block.timestamp` is not.
function nowMs() internal view returns (uint64) {
return uint64(block.timestamp);
}
}
contracts/finalchain/FinalIdentityRegistry.sol
// SPDX-License-Identifier: BUSL-1.1
// Copyright (c) 2024-2026 Final DeFi
// Licensed under the Business Source License 1.1 (the "License")
//
// Change Date: 2029-01-01
// Change License: GPL-2.0-or-later
//
// @author Final DeFi
// @version 1.0.0
pragma solidity ^0.8.20;
import {FinalCertificate} from "./FinalCertificate.sol";
import {FinalChainTime} from "./FinalChainTime.sol";
import {FinalChainPrecompiles} from "./FinalChainPrecompiles.sol";
import {FinalPqQuorum} from "./FinalPqQuorum.sol";
/**
* @title FinalIdentityRegistry
* @notice Who every party in the system IS, on chain, with its certificate.
*
* @dev Final Chain only. Every service, every co-signer, every certificate
* authority and every operator has one record here, and that record carries the
* party's actual public keys — not commitments to them.
*
* ## Why the full key and not a hash
*
* A commitment would be a quarter of the storage and would be enough to *check*
* a key someone hands you. It is not enough to VERIFY A SIGNATURE, because
* verification needs the key itself, and a key that arrives in calldata proves
* nothing: anyone holding a keypair can produce a valid signature under it. A
* quorum built on caller-supplied keys is a quorum of one — whoever built the
* calldata.
*
* So the keys live here in full, `FinalPqQuorum` reads them from storage, and
* "which key is co-signer 3" has exactly one answer. That question previously
* had three: an environment variable, an on-chain roster, and a Secret Manager
* entry, with nothing comparing them. Every configuration failure in this
* program has been those three disagreeing.
*
* ## The certificate is the record, not a pointer to one
*
* `certHash` is `SHA3-256(TBSCertificate)` — the certificate's own identity per
* the v3 schema, and the handle revocation is keyed on. The schema says
* revocation exists "on Final Chain only"; this is that place.
*
`registerWithCertificate` takes the TBS bytes and **reads everything out of
* them**: the digest, the serial, the key identifiers, the depth pair, the
* validity window and both public keys. It takes no key arguments at all.
*
* That is a correction, and the version it replaces is worth naming because it
* looked right. It took the TBS *and* the keys, derived `certHash` from the
* TBS, and never compared the two — so a registrar could bind any certificate
* to any keypair, and the registry would hold a key the certificate does not
* contain. Every signature that key produced would then verify against a
* certificate that never authorised it.
*
* ## The root is the first record on this chain, not a file somewhere
*
* The schema says Final Chain is the only root CA and that "the root is pinned,
* not distributed" — chain validation terminates at Final Chain **by identity**,
* never by finding a self-signed certificate in a local store.
*
* `registerRoot` is that pin, and it is the only entry point that accepts a
* certificate without checking an issuer's signature. It takes a depth-0,
* self-issued certificate from the bootstrap admin, once. Everything after it
* is `registerWithCertificate`, which **verifies the issuer's ML-DSA and
* SLH-DSA signatures on chain, through the precompiles**, against the issuer's
* own registered keys, and checks that the child's `AuthorityKeyId` is the
* issuer's `SubjectKeyId` and that the issuer's depth admits it.
*
* So there is no path by which a key enters this registry unattested. Not
* "a registrar should only register certified keys" — a registrar *cannot*
* register anything else.
*
* ## Roles are a bitmask
*
* One party is legitimately several things — a co-signer that is also a
* publisher, an operator that is also a guardian. A single enum would force
* either duplicate records for one key (two sources of truth about one party)
* or a role hierarchy nobody agrees on. A mask has neither problem, and a
* quorum asks "does this account carry ROLE_X" rather than "is this account an
* X", which is the same distinction the certificate schema draws when it says
* verifiers check for capabilities and never for types.
*
* ## Membership is hybrid-gated
*
* Who is in this registry, and with which roles, is the root of every quorum on
* the chain — so it is the one thing no single key may decide. Once bootstrap
* is sealed, every membership mutation (register, roles, revoke, an LMS key,
* the registrar threshold itself) and every state-plane configuration change
* that routes through {requireRegistrarQuorum} takes a `ROLE_REGISTRAR` quorum
* whose approvals carry BOTH families: the ML-DSA-87 vote and the SLH-DSA
* seal. A lattice break cannot then rewrite the roster, and neither can a
* hash-function break; only both at once.
*
* The bootstrap window is the exception, and it is the only one: while it is
* open the bootstrap admin writes alone, because every roster has to be
* installed by someone before it can install itself.
*
* ## The sender is not the account
*
* Final Chain transactions are type 0x46, signed by ML-DSA-87, and the node
* derives `msg.sender` from the key: `keccak256(0x04 ‖ publicKey)[12:]`. That
* address pays gas and holds no authority. {accountOfSender} binds it to the
* identity whose `activeTransaction` key it derives from, so a `msg.sender`
* gate anywhere on this chain asks {senderHasRole} and resolves to the
* identity — and a key rotation moves the binding rather than the roster.
*/
/// @dev Domain for a stage's encapsulation commitment. Byte-equal to
/// `FinalWalletFactory.DOMAIN_KEM_BUNDLE` and to `DOMAIN_KEM_BUNDLE_PREIMAGE` in
/// the issuer; three derivations of one word, and a mismatch in any of them is a
/// certificate that verifies nowhere.
bytes32 constant DOMAIN_KEM_BUNDLE = keccak256("FINAL_KEM_BUNDLE_v01");
/// @dev Tree 8's leaf domain — byte-equal to
/// `IdentityRootModule.DOMAIN_IDENTITY_LEAF` on every execution chain.
/// Restated rather than imported because the module lives on other chains and
/// there is no import that would make them one value; the cross-contract
/// parity test pins the pair. The `_PQ_` spelling is historical and FROZEN:
/// the premined vanity certificates were mined against this exact constant,
/// and the leaf it derives is the `certHash` inside every wallet's CREATE2
/// derivation.
bytes32 constant DOMAIN_IDENTITY_LEAF = keccak256("FINAL_IDENTITY_LEAF_PQ_v01");
/// @dev D7 (ruled 2026-09-01): ISSUER records project into tree 8 under their
/// own domain — `DOMAIN_ISSUER_LEAF ‖ certHash ‖ version ‖ issuerTreeRoot` —
/// so an issuer is stapleable for offline licence verification while the
/// distinct domain keeps its leaf out of wallet admission (the gateway folds
/// with the wallet domain, so an issuer leaf can never satisfy
/// `verifyIdentityCert`). `issuerTreeRoot` is a RESERVED word, zero until an
/// issuer's own certificate-tree anchor is wired — the only clean path to
/// offline licence revocation, since the fixed-depth insertion-ordered state
/// trees cannot prove non-inclusion.
bytes32 constant DOMAIN_ISSUER_LEAF = keccak256("FINAL_ISSUER_LEAF_v01");
/// @dev Chain-issuer constants (ruled 2026-09-01, amended same day: C-less).
/// The chain is the issuer but holds no keypair, so every chain-attested
/// certificate carries these two NAMED values in its issuer fields — required
/// by the wire format, verifying nothing, covered by `certHash`. The DN is
/// deliberately env-agnostic AND jurisdiction-silent: the issuer is the
/// worldwide network, not a legal entity, and an env-specific DN would fork
/// `certHash` per environment. Reference implementation:
/// `dashboard/public/fcert.js` (`CHAIN_ISSUER_DN`, `CHAIN_AUTHORITY_KEY_ID`);
/// `docs/developers/certificate-schema.md` § Chain-issuer constants.
bytes32 constant CHAIN_ISSUER_DN_HASH = keccak256("CN=Final Chain,O=Final DeFi");
/// @dev `SHA3-256(utf8("FINAL_CHAIN_AUTHORITY_v01"))` — a DOMAIN constant, not
/// a key digest (the chain has no PublicKeyBlock). Precomputed because the
/// mock SHA3 precompile under Foundry is deliberately not the real function;
/// pinned against `hashlib.sha3_256` and the dashboard's value by test.
/// Zero-length AuthorityKeyId stays reserved for the retired genesis root
/// alone and is admitted nowhere.
bytes32 constant CHAIN_AUTHORITY_KEY_ID =
0x9a6a5d8139ad2d28957698330aaa691017dba7dc80eb7cbec585239fb680bbab;
/// @notice The identity tree's projection door on `FinalStateTrees`. A narrow
/// interface rather than an import, because the trees contract imports this
/// file — the dependency runs that way and this is the one call that runs the
/// other. Same pattern as `IChainSource` on the trees side.
interface IIdentityLeafSink {
function syncIdentityLeaves(address[] calldata accounts) external;
}
/// @notice `FinalRevocationLog`'s recording door, same narrow-interface
/// reasoning. `recorded` is read first so a fingerprint someone already
/// recorded permissionlessly cannot revert the registry mutation feeding it.
interface IRevocationRecorder {
function record(bytes32 signerId) external;
function recorded(bytes32 signerId) external view returns (bool);
}
contract FinalIdentityRegistry {
// ---------------------------------------------------------------- roles
/// @notice May co-sign account-state rounds (tree 1).
uint256 public constant ROLE_ACCOUNT_COSIGNER = 1 << 0;
/// @notice May co-sign MMR / bundle-log advances.
uint256 public constant ROLE_MMR_COSIGNER = 1 << 1;
/// @notice May publish PHI ledger state (tree 2).
uint256 public constant ROLE_PHI_PUBLISHER = 1 << 2;
/// @notice May publish vAsset state (tree 3).
uint256 public constant ROLE_VASSET_PUBLISHER = 1 << 3;
/// @notice May publish oracle data (tree 4).
uint256 public constant ROLE_ORACLE_PUBLISHER = 1 << 4;
/// @notice May publish settlement / asset registry roots (trees 5 and 6).
uint256 public constant ROLE_REGISTRY_PUBLISHER = 1 << 5;
/// @notice May act as a wallet guardian.
uint256 public constant ROLE_GUARDIAN = 1 << 6;
/// @notice May submit transactions on behalf of the protocol.
uint256 public constant ROLE_RELAYER = 1 << 7;
/// @notice May register and revoke identities once bootstrap is sealed.
uint256 public constant ROLE_REGISTRAR = 1 << 8;
/// @notice A certificate authority — the root, or an intermediate under it.
uint256 public constant ROLE_CERTIFICATE_AUTHORITY = 1 << 9;
/// @notice May co-sign `FinalSettlementLog` appends — the cross-chain
/// settlement quorum, the same members whose LMS keys satisfy the
/// execution chains' settlement set. A role of its own rather than a
/// second use of `ROLE_REGISTRY_PUBLISHER`: the registries (trees 5/6)
/// change on listing cadence and settlement leaves release custody, and
/// one role for both would put the value plane behind the listing roster.
uint256 public constant ROLE_SETTLEMENT_COSIGNER = 1 << 10;
// ----------------------------------------------------- action domains
/// @dev One per membership mutation, so an approval to grant a role can
/// never be replayed as one to revoke. The registry is its own verifying
/// contract for these.
bytes32 public constant DOMAIN_REGISTER_WALLET = keccak256("FINAL_REGISTRY_REGISTER_WALLET_v01");
bytes32 public constant DOMAIN_REGISTER_ISSUER = keccak256("FINAL_REGISTRY_REGISTER_ISSUER_v01");
/// @notice The admission proof-of-possession digest domain (schema §v5).
/// The HOLDER signs `keccak256(abi.encode(domain, chainid, registry,
/// certHash, recoveryCertHash, gateNonce))` with the live transaction key
/// (ML-DSA-87) AND the live access key (SLH-DSA-SHAKE-256s) — both
/// families, in the admission transaction, verified by the precompiles.
/// Possession lives in the TRANSACTION, never in the artifact.
bytes32 public constant DOMAIN_IDENTITY_ADMISSION = keccak256("FINAL_IDENTITY_ADMISSION_v01");
/// @notice Root-plane global certificate revocation (D5).
bytes32 public constant DOMAIN_REVOKE_CERTIFICATE =
keccak256("FINAL_REGISTRY_REVOKE_CERTIFICATE_v01");
/// @notice The ISSUING identity's certificate-revocation digest domain.
bytes32 public constant DOMAIN_ISSUER_CERT_REVOCATION =
keccak256("FINAL_ISSUER_CERT_REVOCATION_v01");
bytes32 public constant DOMAIN_REGISTER_LMS_KEY = keccak256("FINAL_REGISTRY_REGISTER_LMS_KEY_v01");
bytes32 public constant DOMAIN_SET_ROLES = keccak256("FINAL_REGISTRY_SET_ROLES_v01");
bytes32 public constant DOMAIN_REVOKE = keccak256("FINAL_REGISTRY_REVOKE_v01");
bytes32 public constant DOMAIN_SET_REGISTRAR_THRESHOLD =
keccak256("FINAL_REGISTRY_SET_REGISTRAR_THRESHOLD_v01");
/// @dev The algorithm id the sender derivation is domain-separated by:
/// ML-DSA-87, FIPS 204, the only algorithm the transaction envelope admits.
uint8 private constant ENVELOPE_ALG_ML_DSA_87 = 4;
// ------------------------------------------------------------- storage
/**
* @notice One party's on-chain identity.
* @dev `version` increments on every mutation and is what a rotation is:
* the record is replaced, not appended to, and the version is how a reader
* on another chain knows which of two copies it saw is newer.
*/
struct Identity {
/// SHA3-256 of the LIVE certificate's TBS bytes. The revocation handle.
bytes32 certHash;
/// SHA3-256 of the RECOVERY certificate's TBS bytes.
bytes32 recoveryCertHash;
/// The certificate's 32-byte serial, `16 B entropy ‖ 16 B counter`.
bytes32 serial;
/// SHA3-256 of this certificate's public key block. A child names it in
/// its own `AuthorityKeyId`, which is how the chain links the two.
bytes32 subjectKeyId;
/// Capability bitmask. Zero for a registered-but-idle party.
uint256 roles;
/// Position on the delegation axis; 0 is the Final Chain root.
uint8 depth;
/// Deepest level this key may issue to. `== depth` means it signs no
/// certificates at all, which is every end entity.
uint8 maxDelegationDepth;
/// Seconds since epoch. The schema's TBS is nanoseconds; the conversion
/// happens off chain because block timestamps are seconds and a
/// comparison across units is a bug waiting for a leap.
/// @dev MILLISECONDS — this chain's clock. See `FinalChainTime`.
uint64 notBefore;
/// Seconds since epoch, or 0 for "never expires" — which the schema
/// allows and personal identity certificates use.
uint64 notAfter;
/// Monotonic. A rotation that does not advance it is refused.
uint64 version;
/// Set by `revoke`. Never unset: a revoked certificate is finished, and
/// an un-revoke would make every past verification re-openable.
bool revoked;
/// Distinguishes "no record" from "a record whose fields are all zero".
bool registered;
}
/**
* @notice A hash-based (LMS) signing key held by a registered account.
*
* The protocol plane's quorums verify LMS, not ML-DSA: an execution chain
* has no PQ precompiles, so `FinalRootAuthority` checks a keccak hash loop
* instead (`arch/hash-based-authority.md`). Those keys are the authority
* over `masterRoot`, and therefore over PQ execution — which makes "who
* holds signer 0x39bb…?" a question the state plane has to be able to
* answer, exactly as it answers it for every other key.
*
* Recorded against an account that is ALREADY registered, so an LMS key is
* a capability of a known identity rather than a standalone credential. It
* inherits that identity's revocation: a revoked account's signer is a
* revoked signer, with nothing extra to remember to do.
*/
struct LmsKey {
/// `I`, hashed into every step of the signature.
bytes16 keyId;
/// Merkle tree height. Bound into the fingerprint, because the leaf
/// commits to node `2^h + q` and a signer who could vary it could vary
/// the numbering.
uint8 height;
/// `T[1]`, the LMS public key.
bytes32 root;
/// Monotonic. A rotation that does not advance it is refused, so a
/// replayed registration cannot reinstate a superseded key.
uint64 version;
/// Distinguishes "no key" from "a key whose fields are all zero".
bool registered;
}
/// @notice The LMS signing key for an account, if it holds one.
/// @dev One slot per (account, chain) — LMS-01. `nextLeaf` on an
/// authority is a complete single-use counter only while the key it names
/// signs for ONE chain, so the roster is stored the way it is armed:
/// the same operator is a different signer on every chain.
mapping(address account => mapping(uint64 chainId => LmsKey)) private _lmsKey;
/// @notice Which account a signer fingerprint belongs to. This is the
/// lookup the whole record exists for: a gateway roster names fingerprints
/// and nothing else, so without it the keys are unattributable.
/// @dev What a fingerprint is bound to: the account that holds it and the
/// chain it signs for — one slot, written once at registration and left in
/// place when superseded (attribution is history). The chain names the
/// (account, chain) slot `lmsSignerIsLive` resolves against.
// NOTE: this contract sits ~13 bytes under EIP-170 (24,563 of 24,576 at
// the pinned optimizer settings). The next feature here pays for itself
// in bytecode first — see the LMS-binding merge and the off-chain
// zero-chain check for what that looks like.
struct LmsBinding {
address account;
uint64 chainId;
}
mapping(bytes32 signerId => LmsBinding) private _lmsBinding;
/// @notice The identity record for an account.
mapping(address account => Identity) private _identity;
/// The four slots, verbatim. All four are stored in full because the
/// precompiles verify against a KEY, not a commitment — and a key that
/// arrived in calldata proves nothing about who signed.
///
/// A CA has two keys, not four, and they live in the two ACTIVE slots. One
/// storage shape rather than two, because every reader would otherwise have
/// to know which kind of party it was looking at before it could look.
mapping(address account => bytes) private _activeTransactionKey;
mapping(address account => bytes) private _activeAccessKey;
mapping(address account => bytes) private _recoveryTransactionKey;
mapping(address account => bytes) private _recoveryAccessKey;
/// @notice The seal key — a service's second SLH-DSA-SHAKE-256s key, which
/// co-signs execution-class quorum decisions. Empty for every identity
/// whose certificate carries no `PURPOSE_ACTIVE_SEAL` entry: users, CAs.
mapping(address account => bytes) private _activeSealKey;
/// @notice Encapsulation keys, per stage. Two algorithms each — ML-KEM-1024
/// (lattice) and HQC-5 (code-based) — so a break in either family leaves the
/// other standing, the same reasoning that pairs ML-DSA with SLH-DSA above.
/// @dev Stored as the RAW keys, like the signing keys, because a registry
/// that held only commitments could not answer "encapsulate to this party"
/// without a second lookup somewhere less authoritative.
mapping(address account => bytes) private _activeKemMlKem;
mapping(address account => bytes) private _activeKemHqc;
mapping(address account => bytes) private _recoveryKemMlKem;
mapping(address account => bytes) private _recoveryKemHqc;
/// @notice Reverse index. A certificate identifies exactly one account, so
/// presenting a `certHash` is enough to find who it belongs to.
mapping(bytes32 certHash => address account) public accountOfCertificate;
/// @notice Revocation by certificate, independent of the account record.
/// A certificate stays revoked even if its account is later re-registered
/// under a new one.
mapping(bytes32 certHash => bool) public certificateRevoked;
/// @notice Who revoked a certificate through the ISSUER half of the lane.
/// Scoped by the verifier: the entry binds only when the recorded revoker
/// is the certificate's own issuer. Never gates registration.
mapping(bytes32 certHash => address) public certificateRevokedBy;
/// @notice Every registered account, in registration order. Small by
/// construction — this is services and co-signers, not wallets.
address[] private _accounts;
/// @notice Bootstrap authority. Zero once `sealBootstrap` has run.
address public bootstrapAdmin;
/// @notice Whether registration still accepts the bootstrap admin.
bool public bootstrapSealed;
/// @notice Where identity mutations project the tree-8 leaf, same-tx.
/// Zero only before {wireStatePlane} — the deploy tooling wires it before
/// the first registration, and the projection is skipped while unset so
/// the wiring transaction itself can be ordered freely in the bootstrap
/// window.
address public stateTrees;
/// @notice Where the PERMANENT standing losses — revocation and LMS-key
/// supersession — are recorded, same-tx. Zero only before {wireStatePlane}.
address public revocationLog;
/// @notice Sealed `ROLE_REGISTRAR` approvals a membership mutation needs.
/// @dev Zero until set, and bootstrap cannot be sealed while it is zero or
/// unreachable: a registry sealed behind a threshold nobody can meet is a
/// registry nobody can ever write to again.
uint256 public registrarThreshold;
/// @notice Replay counter per verifying contract — this registry for its
/// own mutations, each state-plane contract for its configuration. Bound
/// into every registrar digest, so an approval is for exactly one action.
mapping(address caller => uint64) private _gateNonce;
/// @notice The identity a Final Chain sender belongs to. See the contract
/// notes: a sender is derived from the `activeTransaction` key and is not
/// the account.
mapping(address sender => address account) public accountOfSender;
// -------------------------------------------------------------- events
event IdentityRegistered(
address indexed account, bytes32 indexed certHash, uint256 roles, uint64 version
);
event IdentityRolesChanged(address indexed account, uint256 previousRoles, uint256 newRoles);
event LmsKeyRegistered(
address indexed account,
bytes32 indexed signerId,
uint64 indexed chainId,
bytes16 keyId,
uint8 height,
bytes32 root,
uint64 version
);
event IdentityRevoked(address indexed account, bytes32 indexed certHash);
/// @notice One revocation-lane entry: `revoker` is `address(0)` for the
/// root plane, the issuing identity otherwise.
event CertificateRevoked(bytes32 indexed certHash, address indexed revoker);
event BootstrapSealed(address indexed sealedBy);
/// @notice The one-shot state-plane wiring landed.
event StatePlaneWired(address stateTrees, address revocationLog);
event RegistrarThresholdSet(uint256 threshold);
/// @notice A registrar quorum authorized an action. `nonce` is the value
/// the approvals were made over; the next action needs the next one.
event RegistrarQuorumApproved(
address indexed verifyingContract, bytes32 indexed actionDomain, uint64 nonce, uint256 valid
);
// -------------------------------------------------------------- errors
error NotAuthorized(address caller);
error BootstrapAlreadySealed();
error UnknownAccount(address account);
/// @notice A certificate's encapsulation key failed the chain's own
/// well-formedness check. Names the algorithm, because the pair is stored
/// together and "one of these two" is not an actionable answer.
error MalformedEncapsulationKey(address account, uint16 algorithmId);
error CertificateAlreadyBound(bytes32 certHash, address boundTo);
error CertificateIsRevoked(bytes32 certHash);
error VersionNotNewer(uint64 current, uint64 offered);
error IssuerNotACertificateAuthority(address issuer);
error IssuerMayNotSign(address issuer, uint8 depth, uint8 maxDelegationDepth);
error WrongDepth(uint8 got, uint8 want);
error DelegationWidened(uint8 child, uint8 issuer);
error AuthorityKeyIdMismatch(bytes32 got, bytes32 want);
error StagesDisagree(bytes32 liveSerial, bytes32 recoverySerial);
/// @notice `height` outside 1..24. See `FinalLms.MAX_HEIGHT`.
error LmsHeightOutOfRange(uint8 height);
/// @notice A zero root commits to no tree.
error LmsRootIsZero();
/// @notice This fingerprint already belongs to a different account.
error LmsKeyAlreadyBound(bytes32 signerId, address boundTo);
/// @notice Two identities cannot share a transaction key: the sender it
/// derives would be attributable to both.
error SenderAlreadyBound(address sender, address boundTo);
/// @notice Fewer registrars able to seal than the threshold asks for.
error RegistrarThresholdUnreachable(uint256 sealable, uint256 threshold);
error RegistrarThresholdIsZero();
/// @notice {wireStatePlane} ran already, or was handed a zero address.
error StatePlaneAlreadyWired();
error ZeroStatePlane();
/// @notice The holder's admission proof of possession did not verify —
/// one family failed, or the digest was built over the wrong nonce.
error AdmissionProofInvalid(address account);
/// @notice The certificate does not carry the ruled chain-issuer
/// AuthorityKeyId — it is not a chain-attested certificate.
error NotChainAttested(bytes32 authorityKeyId);
/// @notice The certificate's IssuerDN is not the ruled constant.
error WrongIssuerDn(bytes32 issuerDnHash);
/// @notice A chain-attested end entity sits at depth 1 with
/// `maxDelegationDepth == depth`; anything else is not an end entity.
error NotAnEndEntity(uint8 depth, uint8 maxDelegationDepth);
/// @notice An issuer that cannot sign is an end entity wearing a profile.
error IssuerCannotSign(uint8 depth, uint8 maxDelegationDepth);
/// @notice Third-party issuers carry a real `NotAfter` (ruling 3) —
/// expiry is the passive half of their lifecycle.
error IssuerMustExpire();
/// @notice An issuer validity window past the ~2-year ceiling (ruling 3).
error IssuerValidityTooLong(uint64 notBefore, uint64 notAfter);
/// @notice An institution registration without a real ISO 3166 `C=` in
/// its subject DN, or with a jurisdiction that does not match its
/// Institution extension. Only the trust root is jurisdiction-silent.
error JurisdictionMissing();
error JurisdictionMismatch();
// --------------------------------------------------------- constructor
/**
* @param admin The bootstrap registrar. Genesis names the chain deployer.
* @dev The precompile probe is the point of the constructor. This contract
* is meaningless on a chain that cannot verify PQ signatures, and deploying
* it there would produce a registry full of keys nothing can check.
*/
constructor(address admin) {
FinalChainPrecompiles.assertAvailable();
bootstrapAdmin = admin;
}
// ----------------------------------------------------------- authority
/**
* @dev Bootstrap is a real window, not a formality: every roster in this
* system has to be installed by someone before it can install itself, and
* pretending otherwise produced the one roster that could not be
* bootstrapped in `FinalRootAuthority`. It is closed by
* `sealBootstrap`, which is irreversible.
*
* While it is open the admin writes alone. Once it is closed there is no
* single-caller path left — not for a registrar, not for anyone — and
* every mutation goes through the sealed registrar quorum.
*/
function _requireMembershipAuthority(
bytes32 actionDomain,
bytes32 payloadDigest,
uint64 anchorBlock,
FinalPqQuorum.Approval[] calldata approvals
) private {
if (!bootstrapSealed && msg.sender == bootstrapAdmin) return;
_requireRegistrarQuorum(address(this), actionDomain, payloadDigest, anchorBlock, approvals);
}
/**
* @notice The sealed registrar quorum, for the other state-plane contracts.
* @dev `msg.sender` — the calling contract — is the verifying contract the
* digest binds and the counter it burns, so an approval collected for the
* trees' configuration cannot be spent on the bundle log's. The caller
* decides its own bootstrap exemption before calling; this function knows
* no caller's admin and applies none.
*
* Anyone may SUBMIT such a transaction. Authority is the approvals, not the
* sender, which is the whole point of the quorum.
*/
function requireRegistrarQuorum(
bytes32 actionDomain,
bytes32 payloadDigest,
uint64 anchorBlock,
FinalPqQuorum.Approval[] calldata approvals
) external {
_requireRegistrarQuorum(msg.sender, actionDomain, payloadDigest, anchorBlock, approvals);
}
/// @dev The digest is `FinalPqQuorum.digest(verifyingContract, actionDomain,
/// anchorBlock, keccak256(abi.encode(nonce, payloadDigest)))`; the seal is
/// required — membership is the hybrid class.
function _requireRegistrarQuorum(
address verifyingContract,
bytes32 actionDomain,
bytes32 payloadDigest,
uint64 anchorBlock,
FinalPqQuorum.Approval[] calldata approvals
) private {
if (registrarThreshold == 0) revert RegistrarThresholdIsZero();
uint64 nonce = _gateNonce[verifyingContract];
_gateNonce[verifyingContract] = nonce + 1;
bytes32 quorumDigest = FinalPqQuorum.digest(
verifyingContract, actionDomain, anchorBlock, keccak256(abi.encode(nonce, payloadDigest))
);
uint256 valid = FinalPqQuorum.require_(
this,
approvals,
quorumDigest,
ROLE_REGISTRAR,
registrarThreshold,
FinalPqQuorum.ALG_ML_DSA_87,
anchorBlock,
true
);
emit RegistrarQuorumApproved(verifyingContract, actionDomain, nonce, valid);
}
/**
* @notice Set how many sealed registrar approvals a membership mutation needs.
* @dev Bootstrap admin while the window is open; the current registrar
* quorum afterwards, so a registrar set that grows or shrinks can move it.
* Refuses a threshold the sealable registrars cannot meet, and refuses zero:
* both are a registry that can never be written to again.
*/
function setRegistrarThreshold(
uint256 threshold,
uint64 anchorBlock,
FinalPqQuorum.Approval[] calldata approvals
) external {
_requireMembershipAuthority(
DOMAIN_SET_REGISTRAR_THRESHOLD, keccak256(abi.encode(threshold)), anchorBlock, approvals
);
if (threshold == 0) revert RegistrarThresholdIsZero();
uint256 sealable = sealableMemberCount(ROLE_REGISTRAR);
if (sealable < threshold) revert RegistrarThresholdUnreachable(sealable, threshold);
registrarThreshold = threshold;
emit RegistrarThresholdSet(threshold);
}
/// @notice The replay counter the next registrar approval for `caller`
/// must be made over.
function gateNonceOf(address caller) external view returns (uint64) {
return _gateNonce[caller];
}
// -------------------------------------------------------- LMS signers
/**
* @notice The roster identity of an LMS public key.
* @dev Byte-identical to `FinalRootAuthority.signerId`. Restated rather
* than imported because the two live on different chains and there is no
* import that would make them one value — which is precisely why a test
* pins them together. A drift here would make every lookup miss while
* looking perfectly well-formed.
*/
function lmsSignerId(bytes16 keyId, uint8 height, bytes32 root) public pure returns (bytes32) {
return keccak256(abi.encode(keyId, height, root));
}
/**
* @notice Record the LMS signing key an already-registered account holds.
* @dev Membership-gated, same as every other write here.
*
* Deliberately NOT a certificate: an LMS key is a capability of an existing
* identity, not an identity of its own. Binding it to an account means it
* inherits that account's revocation, so retiring a compromised operator is
* one action rather than one-per-key-they-hold.
*
* @param account Must already be registered and not revoked.
* @param version Strictly increasing. A rotation that does not advance it
* is refused, so a replayed registration cannot reinstate a key the
* operator has moved off.
* @param anchorBlock The block the registrars read the roster at; see
* `FinalPqQuorum`. Ignored while bootstrap is open.
* @param approvals The sealed registrar quorum. Empty while bootstrap is open.
*/
function registerLmsKey(
address account,
uint64 chainId,
bytes16 keyId,
uint8 height,
bytes32 root,
uint64 version,
uint64 anchorBlock,
FinalPqQuorum.Approval[] calldata approvals
) external {
_requireMembershipAuthority(
DOMAIN_REGISTER_LMS_KEY,
keccak256(abi.encode(account, chainId, keyId, height, root, version)),
anchorBlock,
approvals
);
Identity storage id = _identity[account];
if (!id.registered) revert UnknownAccount(account);
if (id.revoked) revert CertificateIsRevoked(id.certHash);
// A zero chain id is a tooling mistake, not an attack: the slot it
// would occupy is self-consistent and no authority consults it. The
// publisher refuses it; EIP-170 pressure keeps the check off-chain.
if (height == 0 || height > 24) revert LmsHeightOutOfRange(height);
if (root == bytes32(0)) revert LmsRootIsZero();
// Version lineage is PER (account, chain) — LMS-01 made the same
// operator a different signer on every chain, so chain B starting at
// version 1 says nothing about chain A being at version 3.
LmsKey storage existing = _lmsKey[account][chainId];
// An empty slot holds version 0, so this alone also refuses a version-0
// registration — versions start at 1.
if (version <= existing.version) {
revert VersionNotNewer(existing.version, version);
}
bytes32 signerId = lmsSignerId(keyId, height, root);
address boundTo = _lmsBinding[signerId].account;
if (boundTo != address(0) && boundTo != account) {
revert LmsKeyAlreadyBound(signerId, boundTo);
}
// The fingerprint being superseded, captured before the slot moves —
// `existing` is a storage pointer and reads the NEW key afterwards.
bytes32 superseded = existing.registered
? lmsSignerId(existing.keyId, existing.height, existing.root)
: bytes32(0);
// The superseded fingerprint is left bound to this account rather than
// cleared. It is history: a signature made under the old key was made
// by this operator, and a lookup that stopped resolving would make that
// unprovable after the fact.
_lmsKey[account][chainId] = LmsKey(keyId, height, root, version, true);
_lmsBinding[signerId] = LmsBinding(account, chainId);
emit LmsKeyRegistered(account, signerId, chainId, keyId, height, root, version);
// Supersession is a PERMANENT transition — the old fingerprint stops
// being this slot's current key and nothing re-registers it (a
// re-registration of the same material is the same fingerprint, which
// the guard below leaves alone). Recorded same-tx so the execution
// chains' suspension lane never depends on someone noticing.
if (superseded != bytes32(0) && superseded != signerId) {
_recordRevokedSigner(superseded);
}
_projectIdentity(account);
}
/// @notice The LMS key an account holds for one chain, if any.
function lmsKeyOf(address account, uint64 chainId) external view returns (LmsKey memory) {
return _lmsKey[account][chainId];
}
/// @notice What a fingerprint is bound to: the account that registered it
/// and the chain it signs for. Zeroes for a fingerprint never registered.
/// @dev The revocation log's permanence gate reads this to find the
/// (account, chain) SLOT a fingerprint belongs to — the slot's current key
/// is what separates a superseded fingerprint (permanent, recordable) from
/// a merely lapsed one (expiry, temporary, refused). Attribution is
/// history: the binding survives supersession, exactly as the mapping
/// behind {lmsSignerIsLive} does, because it IS that mapping.
function lmsBindingOf(bytes32 signerId) external view returns (address account, uint64 chainId) {
LmsBinding storage binding = _lmsBinding[signerId];
return (binding.account, binding.chainId);
}
/**
* @notice Is this signer fingerprint held by a live, unrevoked account?
* @dev The question a verifier actually has. A gateway roster names
* fingerprints and nothing else, so "is 0x39bb… still good?" is otherwise
* unanswerable from the state plane.
*/
function lmsSignerIsLive(bytes32 signerId) external view returns (bool live, address account) {
LmsBinding storage binding = _lmsBinding[signerId];
account = binding.account;
if (account == address(0)) return (false, address(0));
// `isActive`, not a registered/revoked pair spelled out here. The
// certificate validity window is part of standing: an expired identity
// already holds no role, and a signer lookup that disagreed would leave
// a roster satisfiable by an operator the rest of the registry has
// stopped honouring. Spelling the condition out a second time is how
// the two drift apart.
if (!isActive(account)) return (false, account);
// The CURRENT key of the fingerprint's own (account, chain) slot, not
// merely one this account ever held: a superseded fingerprint stays
// attributable but stops being live, and a rotation on one chain says
// nothing about the same operator's key on another.
LmsKey storage k = _lmsKey[account][binding.chainId];
live = k.registered && lmsSignerId(k.keyId, k.height, k.root) == signerId;
}
/// @notice Close the bootstrap window. Irreversible.
/// @dev Refuses while the registrar quorum is unset or unreachable, because
/// sealing then would leave a registry nobody can ever write to again. The
/// count is of registrars that can SEAL — a certificate authority carrying
/// the role has no seal key and can never contribute an approval.
function sealBootstrap() external {
if (msg.sender != bootstrapAdmin) revert NotAuthorized(msg.sender);
if (bootstrapSealed) revert BootstrapAlreadySealed();
if (registrarThreshold == 0) revert RegistrarThresholdIsZero();
uint256 sealable = sealableMemberCount(ROLE_REGISTRAR);
if (sealable < registrarThreshold) {
revert RegistrarThresholdUnreachable(sealable, registrarThreshold);
}
bootstrapSealed = true;
bootstrapAdmin = address(0);
emit BootstrapSealed(msg.sender);
}
// ------------------------------------------------- state-plane wiring
/**
* @notice Wire the trees and the revocation log, once, inside the
* bootstrap window.
* @dev One-shot because both pointers are TRUST TOPOLOGY: the trees
* pointer decides where the wallet-creation admission set is written, and
* the log pointer decides where permanent standing losses are recorded. A
* re-wireable pointer would be a key over both. It cannot be a constructor
* argument — both contracts take THIS registry as one — so the deploy
* tooling calls it in the same nonce-fixed block that deploys them, before
* any identity is registered.
*/
function wireStatePlane(address stateTrees_, address revocationLog_) external {
if (bootstrapSealed || msg.sender != bootstrapAdmin) revert NotAuthorized(msg.sender);
if (stateTrees != address(0) || revocationLog != address(0)) revert StatePlaneAlreadyWired();
if (stateTrees_ == address(0) || revocationLog_ == address(0)) revert ZeroStatePlane();
stateTrees = stateTrees_;
revocationLog = revocationLog_;
emit StatePlaneWired(stateTrees_, revocationLog_);
}
/// @dev Project `account`'s tree-8 leaf, same-tx. Skipped while the plane
/// is unwired — the bootstrap-window state the deploy tooling closes
/// before the first registration — and never otherwise: the leaf value is
/// derived by the trees contract from THIS registry's post-mutation state,
/// so there is nothing here to get wrong besides forgetting to call it.
function _projectIdentity(address account) private {
address trees = stateTrees;
if (trees == address(0)) return;
address[] memory one = new address[](1);
one[0] = account;
IIdentityLeafSink(trees).syncIdentityLeaves(one);
}
/// @dev Record a PERMANENTLY retired fingerprint, same-tx, unless the log
/// is unwired or someone already recorded it permissionlessly.
function _recordRevokedSigner(bytes32 signerId) private {
address log = revocationLog;
if (log == address(0)) return;
if (IRevocationRecorder(log).recorded(signerId)) return;
IRevocationRecorder(log).record(signerId);
}
// -------------------------------------------------------- registration
/// @notice The holder's admission proof of possession: both live-stage
/// families over the admission digest (schema §v5). There is no root
/// keypair and no CA signature any more — the chain admits, and the
/// "2 signatures at creation" are the HOLDER's, verified by the
/// precompiles inside this very transaction.
struct AdmissionProof {
bytes mlDsaSignature;
bytes slhDsaSignature;
}
/**
* @notice Register or rotate a Final Wallet identity from its two public
* certificates — CHAIN-ATTESTED (schema §v5, ruled 2026-09-01).
*
* @param account The wallet address the certificate set derives.
* @param liveTbs `live.pub.fcert` TBS — `activeTransaction` + `activeAccess`.
* @param recoveryTbs `recovery.pub.fcert` TBS — the pre-committed recovery pair.
* @param proof The HOLDER's two signatures over the admission digest —
* the live transaction key (ML-DSA-87) and the live access key
* (SLH-DSA-SHAKE-256s), verified in the precompiles inside this
* transaction. This replaced the CA signature: issuance authority
* is the registrar quorum, possession is this proof, and there is
* no root keypair anywhere.
* @param roles Capability bitmask. The one thing the certificates do not
* say, because capability is this system's decision.
* @param version Monotonic. A rotation that does not advance it is refused.
* @param anchorBlock The block the registrars read the roster at. Ignored
* while bootstrap is open.
* @param approvals The sealed registrar quorum. Empty while bootstrap is
* open. The digest binds the account, both certificates' bytes,
* the roles and the version.
*
* @dev **Both stages, together.** A wallet has four keys in two stages and
* the recovery pair is PRE-COMMITTED — written at `initialize` from the same
* certificate set that determined the address, which is why PQ migration
* takes no key arguments. The two must share a `SerialNumber`: a serial is
* per certificate SET, so two stages disagreeing are two different wallets.
*
* **Chain-attested means pinned, per stage:** the ruled IssuerDN and
* AuthorityKeyId constants, depth exactly 1 (directly under the chain),
* and `maxDelegationDepth == depth` (an end entity signs nothing — the
* same immutable pair `identityTreeLeafOf` discriminates records by).
*/
function registerWallet(
address account,
bytes calldata liveTbs,
bytes calldata recoveryTbs,
AdmissionProof calldata proof,
uint256 roles,
uint64 version,
uint64 anchorBlock,
FinalPqQuorum.Approval[] calldata approvals
) external returns (bytes32 certHash) {
// Read BEFORE the authority check: the quorum path burns this counter
// inside `_requireRegistrarQuorum`, and the proof must bind the value
// the round was built over. The bootstrap path burns it explicitly in
// `_requireAdmissionProof`, so an admission is one-shot in both regimes.
uint64 admissionNonce = _gateNonce[address(this)];
_requireMembershipAuthority(
DOMAIN_REGISTER_WALLET,
keccak256(
abi.encode(account, keccak256(liveTbs), keccak256(recoveryTbs), roles, version)
),
anchorBlock,
approvals
);
FinalCertificate.Parsed memory l = FinalCertificate.parseLive(liveTbs);
FinalCertificate.Parsed memory r = FinalCertificate.parseRecovery(recoveryTbs);
if (l.serial != r.serial) revert StagesDisagree(l.serial, r.serial);
_requireChainAttestedEndEntity(l);
_requireChainAttestedEndEntity(r);
_requireAdmissionProof(account, l, r.certHash, proof, admissionNonce);
certHash = l.certHash;
_write(account, l, r, roles, version, false);
}
/**
* @notice Register or rotate an ISSUER — a third party (or our own
* intermediate) that signs certificates OFF-chain with the keys
* registered here (D2: the superCA).
*
* @param account The issuer's account on this chain.
* @param tbs The single issuer certificate's TBS: two CERT_SIGNING keys
* (ML-DSA-87 + SLH-DSA-SHAKE-256s), no recovery stage — renewing an
* issuer is re-issuing, a governance act rather than a key rotation.
* @param parent The registered parent issuer for a nested intermediate;
* `address(0)` for an issuer hanging directly under the chain.
* @param proof The issuer's OWN two cert-signing keys over the admission
* digest (`recoveryCertHash` slot is zero — there is no recovery
* stage to bind).
*
* @dev Admission is chain-native like any identity: registrar quorum plus
* the holder's PoP. What the v4 delegation rules said survives verbatim as
* LINEAGE — a nested issuer's depth, delegation bound and AuthorityKeyId
* must chain to its registered parent — but no parent SIGNS anything; the
* chain's admission is the issuance.
*
* Ruling 3: a registered issuer always expires (`NotAfter` real, window
* bounded ~2 years) — the passive liveness touchpoint; renewal re-issues
* under the same registered keys with a version bump.
*
* The jurisdiction rule (ruled 2026-09-01, amended): only the trust root
* is jurisdiction-silent. An institution MUST carry its real ISO 3166
* `C=` in its subject DN, matching the `jurisdiction` field of its
* `0x0102` Institution extension — CA/Browser-Forum practice, enforced at
* the door because a verifier's legal recourse starts with knowing where
* an issuer answers for itself.
*/
function registerIssuer(
address account,
bytes calldata tbs,
address parent,
AdmissionProof calldata proof,
uint256 roles,
uint64 version,
uint64 anchorBlock,
FinalPqQuorum.Approval[] calldata approvals
) external returns (bytes32 certHash) {
uint64 admissionNonce = _gateNonce[address(this)];
_requireMembershipAuthority(
DOMAIN_REGISTER_ISSUER,
keccak256(abi.encode(account, keccak256(tbs), parent, roles, version)),
anchorBlock,
approvals
);
FinalCertificate.Parsed memory c = FinalCertificate.parseCa(tbs);
// An issuer that cannot sign is an end entity wearing a profile —
// and an end entity belongs in `registerWallet`.
if (c.depth == 0 || c.maxDelegationDepth <= c.depth) {
revert IssuerCannotSign(c.depth, c.maxDelegationDepth);
}
if (c.notAfter == 0) revert IssuerMustExpire();
if (c.notAfter - c.notBefore > MAX_ISSUER_VALIDITY_MS) {
revert IssuerValidityTooLong(c.notBefore, c.notAfter);
}
if (c.issuerDnHash != CHAIN_ISSUER_DN_HASH) revert WrongIssuerDn(c.issuerDnHash);
_requireLineage(parent, c);
_requireJurisdiction(c);
_requireAdmissionProof(account, c, bytes32(0), proof, admissionNonce);
certHash = c.certHash;
_write(account, c, c, roles | ROLE_CERTIFICATE_AUTHORITY, version, true);
}
/// @notice Ruling 3's validity ceiling for registered issuers, in this
/// chain's milliseconds: two 366-day years.
uint64 public constant MAX_ISSUER_VALIDITY_MS = 2 * 366 days * 1000;
/// @dev The chain-attested end-entity pins, run once per stage.
function _requireChainAttestedEndEntity(FinalCertificate.Parsed memory c) private pure {
if (c.authorityKeyId != CHAIN_AUTHORITY_KEY_ID) revert NotChainAttested(c.authorityKeyId);
if (c.issuerDnHash != CHAIN_ISSUER_DN_HASH) revert WrongIssuerDn(c.issuerDnHash);
if (c.depth != 1 || c.maxDelegationDepth != c.depth) {
revert NotAnEndEntity(c.depth, c.maxDelegationDepth);
}
}
/// @dev The v4 delegation rules, surviving as lineage: a nested issuer
/// chains to a registered, signing-capable parent one level up; a direct
/// issuer hangs under the chain at depth 1.
function _requireLineage(address parent, FinalCertificate.Parsed memory c) private view {
if (parent == address(0)) {
if (c.authorityKeyId != CHAIN_AUTHORITY_KEY_ID) {
revert NotChainAttested(c.authorityKeyId);
}
if (c.depth != 1) revert WrongDepth(c.depth, 1);
return;
}
Identity storage ca = _identity[parent];
if (!hasRole(parent, ROLE_CERTIFICATE_AUTHORITY)) {
revert IssuerNotACertificateAuthority(parent);
}
// Delegation is governed by depth, not by a boolean. `Depth <
// MaxDelegationDepth` permits signing, and a child sits exactly one
// level down — an issuer cannot skip levels to escape its own bound.
if (ca.depth >= ca.maxDelegationDepth) {
revert IssuerMayNotSign(parent, ca.depth, ca.maxDelegationDepth);
}
if (c.depth != ca.depth + 1) revert WrongDepth(c.depth, ca.depth + 1);
if (c.maxDelegationDepth > ca.maxDelegationDepth) {
revert DelegationWidened(c.maxDelegationDepth, ca.maxDelegationDepth);
}
if (c.authorityKeyId != ca.subjectKeyId) {
revert AuthorityKeyIdMismatch(c.authorityKeyId, ca.subjectKeyId);
}
}
/// @dev The jurisdiction rule: a real ISO 3166 alpha-2 `C=` in the subject
/// DN, equal to the Institution extension's `jurisdiction` field. The DN
/// is canonical comma-separated form, so `C=` matches at the start or
/// right after a comma; the component value is exactly two bytes.
function _requireJurisdiction(FinalCertificate.Parsed memory c) private pure {
bytes memory dn = c.subjectDn;
bytes2 country;
bool found = false;
for (uint256 i = 0; i + 4 <= dn.length; i++) {
if ((i == 0 || dn[i - 1] == ",") && dn[i] == "C" && dn[i + 1] == "=") {
// Exactly two bytes, then end-of-DN or the next component.
if (i + 4 < dn.length && dn[i + 4] != ",") revert JurisdictionMissing();
country = bytes2(bytes.concat(dn[i + 2], dn[i + 3]));
found = true;
break;
}
}
if (!found) revert JurisdictionMissing();
// Institution extension: legalNameLength ‖ legalName ‖
// registrationNoLength ‖ registrationNo ‖ jurisdictionLength ‖
// jurisdiction. The jurisdiction must EQUAL the DN's country.
bytes memory ext = c.institutionExt;
if (ext.length < 6) revert JurisdictionMissing();
uint256 q = 2 + (uint256(uint8(ext[0])) << 8 | uint256(uint8(ext[1])));
if (ext.length < q + 2) revert JurisdictionMissing();
q += 2 + (uint256(uint8(ext[q])) << 8 | uint256(uint8(ext[q + 1])));
if (ext.length < q + 2) revert JurisdictionMissing();
uint256 jLen = uint256(uint8(ext[q])) << 8 | uint256(uint8(ext[q + 1]));
q += 2;
if (jLen != 2 || ext.length < q + 2) revert JurisdictionMismatch();
if (bytes2(bytes.concat(ext[q], ext[q + 1])) != country) revert JurisdictionMismatch();
}
/// @dev Verify the holder's PoP: both live-stage families over the
/// admission digest, in the precompiles, inside this transaction. Burns
/// the gate nonce on the bootstrap path (the quorum path burned it in
/// `_requireRegistrarQuorum` already), so an admission is one-shot in
/// both regimes.
function _requireAdmissionProof(
address account,
FinalCertificate.Parsed memory live,
bytes32 recoveryCertHash,
AdmissionProof calldata proof,
uint64 admissionNonce
) private {
bytes memory message = abi.encodePacked(
keccak256(
abi.encode(
DOMAIN_IDENTITY_ADMISSION,
block.chainid,
address(this),
live.certHash,
recoveryCertHash,
admissionNonce
)
)
);
if (
!FinalChainPrecompiles.verifyMlDsa87(live.transactionKey, message, proof.mlDsaSignature)
|| !FinalChainPrecompiles.verifySlhDsa(live.accessKey, message, proof.slhDsaSignature)
) revert AdmissionProofInvalid(account);
if (_gateNonce[address(this)] == admissionNonce) {
_gateNonce[address(this)] = admissionNonce + 1;
}
}
function _write(
address account,
FinalCertificate.Parsed memory live,
FinalCertificate.Parsed memory recovery,
uint256 roles,
uint64 version,
bool isCa
) private {
if (account == address(0)) revert UnknownAccount(account);
if (certificateRevoked[live.certHash]) revert CertificateIsRevoked(live.certHash);
address boundTo = accountOfCertificate[live.certHash];
if (boundTo != address(0) && boundTo != account) {
revert CertificateAlreadyBound(live.certHash, boundTo);
}
Identity storage id = _identity[account];
if (!id.registered) {
_accounts.push(account);
id.registered = true;
} else {
if (version <= id.version) revert VersionNotNewer(id.version, version);
if (id.revoked) revert CertificateIsRevoked(id.certHash);
// A rotation releases the previous certificate's binding. It is NOT
// revoked — a superseded certificate and a compromised one are
// different facts and revocation is the louder of the two.
if (id.certHash != live.certHash) delete accountOfCertificate[id.certHash];
}
id.certHash = live.certHash;
id.recoveryCertHash = recovery.certHash;
id.serial = live.serial;
id.subjectKeyId = live.subjectKeyId;
id.roles = roles;
id.depth = live.depth;
id.maxDelegationDepth = live.maxDelegationDepth;
id.notBefore = live.notBefore;
id.notAfter = live.notAfter;
id.version = version;
// The sender binding moves with the transaction key. The old sender is
// released rather than kept: a rotation is the account disowning that
// key, and a gate that still resolved it would honour a retired key.
address sender = senderFor(live.transactionKey);
address senderBoundTo = accountOfSender[sender];
if (senderBoundTo != address(0) && senderBoundTo != account) {
revert SenderAlreadyBound(sender, senderBoundTo);
}
if (_activeTransactionKey[account].length != 0) {
address previousSender = senderFor(_activeTransactionKey[account]);
if (previousSender != sender) delete accountOfSender[previousSender];
}
accountOfSender[sender] = account;
_activeTransactionKey[account] = live.transactionKey;
_activeAccessKey[account] = live.accessKey;
// A CA has no recovery pair; the two active slots are all it has.
_recoveryTransactionKey[account] = isCa ? bytes("") : recovery.transactionKey;
_recoveryAccessKey[account] = isCa ? bytes("") : recovery.accessKey;
// Cleared on a rotation to a certificate without one, for the same
// reason the encapsulation pair is: a stale seal surviving a rotation
// would let a retired key keep co-signing execution.
_activeSealKey[account] = isCa ? bytes("") : live.sealKey;
// The encapsulation pair, validated before it is stored.
//
// **The registry is where a sender looks up "encapsulate to this
// party", so a malformed key here is not a bad record — it is an
// account nobody can seal an intent to.** The discovery would happen at
// the first attempt, and on the hybrid path it would happen as a pair
// silently reduced to one family, which is identical on the wire. The
// precompiles make it a refusal at registration instead.
//
// Neither is a re-implementation of the KEM: `0x0203` runs FIPS 203
// §7.2's own encapsulation-key check and `0x0207` runs the structural
// check HQC-5's encoding admits. Encapsulation is a sender operation
// and decapsulation needs the secret key, so nothing more belongs here.
//
// A CA is sealed to by nobody and carries no encapsulation stage, so
// its slots are cleared rather than checked.
_storeKemPair(account, isCa, live.kemMlKem, live.kemHqc, true);
_storeKemPair(account, isCa, recovery.kemMlKem, recovery.kemHqc, false);
accountOfCertificate[live.certHash] = account;
emit IdentityRegistered(account, live.certHash, roles, version);
// Same-tx: a registration or rotation is visible to every execution
// chain's admission set the moment it is visible here.
_projectIdentity(account);
}
/**
* @dev Store one stage's encapsulation pair, or clear it.
*
* Empty is legitimate and is not the same as absent-and-wrong: a CA has no
* encapsulation stage, and a certificate issued before v4 carries none.
* `FinalCertificate.parse` has already refused the half-populated case, so
* by here the pair is both or neither.
*
* Cleared rather than left alone on a rotation to an empty pair. A stale
* key surviving a rotation is a sender encapsulating to a credential the
* account has disowned, and the intent then never decrypts — the failure
* mode with no error attached, and the one this whole pairing exists to
* avoid.
*/
function _storeKemPair(address account, bool isCa, bytes memory mlKem, bytes memory hqc, bool isLive)
private
{
if (isCa || mlKem.length == 0) {
delete (isLive ? _activeKemMlKem : _recoveryKemMlKem)[account];
delete (isLive ? _activeKemHqc : _recoveryKemHqc)[account];
return;
}
if (!FinalChainPrecompiles.isWellFormedMlKem1024(mlKem)) {
revert MalformedEncapsulationKey(account, FinalCertificate.ALG_ML_KEM_1024);
}
if (!FinalChainPrecompiles.isWellFormedHqc5(hqc)) {
revert MalformedEncapsulationKey(account, FinalCertificate.ALG_HQC_5);
}
if (isLive) {
_activeKemMlKem[account] = mlKem;
_activeKemHqc[account] = hqc;
} else {
_recoveryKemMlKem[account] = mlKem;
_recoveryKemHqc[account] = hqc;
}
}
/// @notice Grant or withdraw capabilities without rotating keys.
/// @dev Separate from registration because the two have different
/// cadences: a role changes when a service's job changes, a key changes
/// when it is compromised or aged out. Folding them together would force a
/// key rotation to express a role change.
function setRoles(
address account,
uint256 roles,
uint64 anchorBlock,
FinalPqQuorum.Approval[] calldata approvals
) external {
_requireMembershipAuthority(
DOMAIN_SET_ROLES, keccak256(abi.encode(account, roles)), anchorBlock, approvals
);
Identity storage id = _identity[account];
if (!id.registered) revert UnknownAccount(account);
if (id.revoked) revert CertificateIsRevoked(id.certHash);
uint256 previous = id.roles;
id.roles = roles;
_requireRegistrarQuorumReachable();
emit IdentityRolesChanged(account, previous, roles);
// Roles are not in the tree-8 leaf, so this rewrites the same value —
// kept anyway so "every identity mutation projects" has no exceptions
// to remember.
_projectIdentity(account);
}
/// @dev Once sealed, no mutation may leave the registrar quorum unreachable
/// — that is the one change nothing could ever undo. Checked after the
/// write so the count reflects it.
function _requireRegistrarQuorumReachable() private view {
if (!bootstrapSealed) return;
uint256 sealable = sealableMemberCount(ROLE_REGISTRAR);
if (sealable < registrarThreshold) {
revert RegistrarThresholdUnreachable(sealable, registrarThreshold);
}
}
/// @notice Revoke an identity and its certificate. Irreversible.
/// @param chainIds The chains whose LMS-key slots this account holds — the
/// registrars supply the list (the digest binds it) because a mapping
/// cannot enumerate its own keys. Each named slot's current fingerprint is
/// recorded into the revocation log same-tx; a chain with no slot is
/// skipped, and a fingerprint missed by an incomplete list stays
/// permanently recordable through the log's permissionless door, since a
/// revoked account never regains standing.
/// @dev Clears the roles as well as setting the flag. Both are checked
/// everywhere, but leaving a revoked record carrying roles invites a future
/// reader that checks only one of them.
function revoke(
address account,
uint64[] calldata chainIds,
uint64 anchorBlock,
FinalPqQuorum.Approval[] calldata approvals
) external {
_requireMembershipAuthority(
DOMAIN_REVOKE, keccak256(abi.encode(account, chainIds)), anchorBlock, approvals
);
Identity storage id = _identity[account];
if (!id.registered) revert UnknownAccount(account);
id.revoked = true;
id.roles = 0;
certificateRevoked[id.certHash] = true;
_requireRegistrarQuorumReachable();
emit IdentityRevoked(account, id.certHash);
// AFTER the flag lands, so the log's own gate sees the permanent
// transition it requires.
for (uint256 i = 0; i < chainIds.length; i++) {
LmsKey storage k = _lmsKey[account][chainIds[i]];
if (k.registered) _recordRevokedSigner(lmsSignerId(k.keyId, k.height, k.root));
}
_projectIdentity(account);
}
/**
* @notice Root-plane GLOBAL certificate revocation, by `certHash` (D5).
*
* @dev The half of the one revocation lane that gates registration and
* covers break-glass: any certificate — registered, off-chain-issued, or
* never seen — can be killed by handle under the registrar quorum. When
* the handle is a registered identity's CURRENT certificate the identity
* falls with it (flag, roles, same-tx projection), so a break-glass by
* handle is never weaker than {revoke} — it only skips the LMS-slot
* enumeration, which stays permanently recordable through the revocation
* log's permissionless door.
*/
function revokeCertificate(
bytes32 certHash,
uint64 anchorBlock,
FinalPqQuorum.Approval[] calldata approvals
) external {
_requireMembershipAuthority(
DOMAIN_REVOKE_CERTIFICATE, keccak256(abi.encode(certHash)), anchorBlock, approvals
);
certificateRevoked[certHash] = true;
address bound = accountOfCertificate[certHash];
if (bound != address(0)) {
Identity storage id = _identity[bound];
if (!id.revoked) {
id.revoked = true;
id.roles = 0;
_requireRegistrarQuorumReachable();
emit IdentityRevoked(bound, certHash);
_projectIdentity(bound);
}
}
emit CertificateRevoked(certHash, address(0));
}
/**
* @notice The ISSUING identity's half of the revocation lane: a registered
* issuer revokes a certificate it signed OFF-chain, by `certHash`.
*
* @dev "Sub-issuer and us alike" (D5) — but SCOPED: this records WHO
* revoked, and a verifier honours the entry only when the revoker is the
* certificate's own issuer (which the verifier knows — it holds the
* cert). It deliberately does NOT set the global `certificateRevoked`
* flag: that flag gates registration, and letting any registered issuer
* set it for an arbitrary handle would be a griefing lane over other
* people's certificates.
*
* Anyone may SUBMIT; authority is the two signatures — the issuer's
* registered cert-signing keys over a digest binding this registry, the
* chain, the handle and the issuer's own gate nonce. One-way: the first
* revoker of a handle is recorded and a second write is refused, because
* "revoked twice by two parties" is two facts where the lane models one.
*/
function revokeIssuedCertificate(
address issuer,
bytes32 certHash,
AdmissionProof calldata proof
) external {
if (!hasRole(issuer, ROLE_CERTIFICATE_AUTHORITY)) {
revert IssuerNotACertificateAuthority(issuer);
}
if (certificateRevokedBy[certHash] != address(0)) revert CertificateIsRevoked(certHash);
uint64 nonce = _gateNonce[issuer];
_gateNonce[issuer] = nonce + 1;
bytes memory message = abi.encodePacked(
keccak256(
abi.encode(
DOMAIN_ISSUER_CERT_REVOCATION,
block.chainid,
address(this),
issuer,
certHash,
nonce
)
)
);
if (
!FinalChainPrecompiles.verifyMlDsa87(
_activeTransactionKey[issuer], message, proof.mlDsaSignature
)
|| !FinalChainPrecompiles.verifySlhDsa(
_activeAccessKey[issuer], message, proof.slhDsaSignature
)
) revert AdmissionProofInvalid(issuer);
certificateRevokedBy[certHash] = issuer;
emit CertificateRevoked(certHash, issuer);
}
// ---------------------------------------------------------------- views
/// @notice The full identity record. `registered` is the field to branch on.
function identityOf(address account) external view returns (Identity memory) {
return _identity[account];
}
/// @notice `activeTransaction` — ML-DSA-87. What a quorum verifies against.
function activeTransactionKeyOf(address account) external view returns (bytes memory) {
return _activeTransactionKey[account];
}
/// @notice `activeAccess` — SLH-DSA-SHAKE-256s. Identity, and guardianship.
function activeAccessKeyOf(address account) external view returns (bytes memory) {
return _activeAccessKey[account];
}
/// @notice `activeSeal` — SLH-DSA-SHAKE-256s. What `FinalPqQuorum` verifies
/// an execution-class approval's `seal` against. Empty when the identity
/// carries no seal, in which case it cannot take part in a sealed quorum.
function activeSealKeyOf(address account) external view returns (bytes memory) {
return _activeSealKey[account];
}
/// @notice `recoveryTransaction`. Authorizes rotating this account's own
/// credentials and nothing else. Empty for a CA.
function recoveryTransactionKeyOf(address account) external view returns (bytes memory) {
return _recoveryTransactionKey[account];
}
/// @notice `recoveryAccess`. Empty for a CA.
function recoveryAccessKeyOf(address account) external view returns (bytes memory) {
return _recoveryAccessKey[account];
}
/// @notice The four commitments, in the order tree 1's leaf wants them.
/// @dev keccak, not SHA3 — these feed `FinalWalletFactory.accountStateLeafHash`,
/// which every other chain verifies with, and that one hashes with keccak.
function keyCommitments(address account)
external
view
returns (
bytes32 liveAccess,
bytes32 liveTransaction,
bytes32 recoveryAccess,
bytes32 recoveryTransaction
)
{
liveAccess = keccak256(_activeAccessKey[account]);
liveTransaction = keccak256(_activeTransactionKey[account]);
recoveryAccess = keccak256(_recoveryAccessKey[account]);
recoveryTransaction = keccak256(_recoveryTransactionKey[account]);
}
/**
* @notice The tree-8 leaf `account` currently earns: the execution
* chains' identity leaf while the identity stands, zero once it
* does not.
*
* @dev The leaf VALUE is `keccak256(DOMAIN_IDENTITY_LEAF ‖ serial ‖
* keysHash)` — byte-identical to `IdentityRootModule.identityLeafHash`,
* which is also the `certHash` inside the wallet's CREATE2 derivation —
* with `keysHash` folded exactly as the certificate issuer folds it:
* `keccak256(activeAccess ‖ activeTransaction ‖ recoveryAccess ‖
* recoveryTransaction ‖ activeKem ‖ recoveryKem)`, six commitment words
* packed in slot order (`minePqVanityCerts.cjs` is the reference encoder;
* the parity test pins this function against the premined fixtures).
*
* Zero — the empty slot's own value, unprovable as a leaf because no
* certificate hashes to it — for anything that must not admit a wallet
* creation: a revoked identity, one outside its validity window, and any
* CA. The CA exclusion is structural, not a role read: an end entity has
* `depth == maxDelegationDepth` (it issues nothing), a CA never does, and
* the depth pair is immutable per version where roles are not.
*
* Lives HERE rather than on `FinalStateTrees` (whose tree 8 consumes it)
* because every input is this contract's storage and the trees contract
* sits against EIP-170.
*/
function identityTreeLeafOf(address account) external view returns (bytes32) {
Identity storage id = _identity[account];
if (!id.registered) revert UnknownAccount(account);
if (id.revoked || !_withinValidity(id)) return bytes32(0);
if (id.depth != id.maxDelegationDepth) {
// D7 (ruled 2026-09-01): an ISSUER exists in tree 8 under its own
// domain, so its record is stapleable for offline licence
// verification. `certHash` suffices (it covers the whole TBS and
// the verifier holds the cert), `version` makes supersession move
// the leaf, and the third word RESERVES the issuer's own
// certificate-tree anchor — zero until wired. The distinct domain
// does the wallet-admission exclusion the zero projection used to
// do; zero-on-revoke above is now load-bearing for both record
// kinds (a fresh staple is an unrevoked statement).
return keccak256(
abi.encodePacked(DOMAIN_ISSUER_LEAF, id.certHash, uint64(id.version), bytes32(0))
);
}
bytes32 liveKem = keccak256(
abi.encodePacked(DOMAIN_KEM_BUNDLE, _activeKemMlKem[account], _activeKemHqc[account]));
bytes32 recoveryKem = keccak256(
abi.encodePacked(DOMAIN_KEM_BUNDLE, _recoveryKemMlKem[account], _recoveryKemHqc[account]));
bytes32 keysHash = keccak256(
abi.encodePacked(
keccak256(_activeAccessKey[account]),
keccak256(_activeTransactionKey[account]),
keccak256(_recoveryAccessKey[account]),
keccak256(_recoveryTransactionKey[account]),
liveKem,
recoveryKem
)
);
return keccak256(abi.encodePacked(DOMAIN_IDENTITY_LEAF, id.serial, keysHash));
}
/// @notice Per-stage encapsulation commitments, in `AccountStateLeaf` order.
/// @dev One word per STAGE, over both of that stage's KEM public keys. The
/// pair is the unit — an account holds both or neither — so committing them
/// separately would model a state the protocol does not recognise, and every
/// downstream record would carry two words where one says the same thing.
///
/// An account registered before the encapsulation slots existed hashes the
/// empty string here rather than reverting: `syncIdentities` must keep
/// projecting it, and a leaf that cannot be built is a party that cannot be
/// revoked.
function kemCommitments(address account)
external
view
returns (bytes32 liveKem, bytes32 recoveryKem)
{
liveKem = keccak256(
abi.encodePacked(DOMAIN_KEM_BUNDLE, _activeKemMlKem[account], _activeKemHqc[account]));
recoveryKem = keccak256(
abi.encodePacked(DOMAIN_KEM_BUNDLE, _recoveryKemMlKem[account], _recoveryKemHqc[account]));
}
/// @notice The encapsulation keys themselves, for a party composing a message.
function kemKeysOf(address account)
external
view
returns (bytes memory activeMlKem, bytes memory activeHqc)
{
return (_activeKemMlKem[account], _activeKemHqc[account]);
}
// ------------------------------------------------------------- senders
/**
* @notice The Final Chain sender a transaction key produces.
* @dev `keccak256(uint8(4) ‖ publicKey)[12:]` — byte-identical to what the
* node derives from a type-0x46 envelope and to the backend's
* `pqTransaction.senderOf`. Pure, so a client can compute it from a
* certificate before the identity is registered.
*/
function senderFor(bytes memory transactionKey) public pure returns (address) {
return address(uint160(uint256(keccak256(abi.encodePacked(ENVELOPE_ALG_ML_DSA_87, transactionKey)))));
}
/// @notice The sender `account`'s transactions arrive from, or zero for an
/// account with no transaction key on record.
function senderOf(address account) external view returns (address) {
bytes storage key = _activeTransactionKey[account];
if (key.length == 0) return address(0);
return senderFor(key);
}
/// @notice `hasRole` for a `msg.sender`: resolves the sender to its identity
/// first. False for a sender no identity claims.
function senderHasRole(address sender, uint256 roleMask) external view returns (bool) {
address account = accountOfSender[sender];
return account != address(0) && hasRole(account, roleMask);
}
/// @notice How many accounts carrying `roleMask` also hold a seal key —
/// the members that can take part in a sealed quorum.
function sealableMemberCount(uint256 roleMask) public view returns (uint256 sealable) {
uint256 n = _accounts.length;
for (uint256 i = 0; i < n; i++) {
address a = _accounts[i];
if (hasRole(a, roleMask) && _activeSealKey[a].length != 0) sealable++;
}
}
/// @notice Number of registered accounts.
function accountCount() external view returns (uint256) {
return _accounts.length;
}
/// @notice Registered account by index, in registration order.
function accountAt(uint256 index) external view returns (address) {
return _accounts[index];
}
/// @notice Every account carrying every bit in `roleMask`.
/// @dev A view, so the O(n) scan costs nothing. Callers that need this in a
/// transaction should pass the member list explicitly instead — see
/// `FinalPqQuorum`, which takes signers rather than searching for them.
function accountsWithRole(uint256 roleMask) external view returns (address[] memory found) {
uint256 n = _accounts.length;
address[] memory buf = new address[](n);
uint256 count;
for (uint256 i = 0; i < n; i++) {
if (hasRole(_accounts[i], roleMask)) {
buf[count++] = _accounts[i];
}
}
found = new address[](count);
for (uint256 i = 0; i < count; i++) {
found[i] = buf[i];
}
}
/**
* @notice How many accounts could satisfy a quorum for `roleMask` right now.
* @dev The number a threshold has to be reachable against. A threshold above
* it is not a strict quorum, it is a quorum that cannot be met — and the way
* that presents is an operation that reverts forever with nothing naming the
* roster as the cause.
*/
function liveMemberCount(uint256 roleMask) public view returns (uint256 live) {
uint256 n = _accounts.length;
for (uint256 i = 0; i < n; i++) {
if (hasRole(_accounts[i], roleMask)) live++;
}
}
/**
* @notice Whether `account` currently carries every bit in `roleMask`.
* @dev Every gate in this system asks this one question, so every gate gets
* the same answer: registered, not revoked, inside its validity window, and
* holding the capability. A caller that checked only the role bit would
* accept an expired certificate.
*
* `roleMask == 0` is false. A zero mask asks nothing and must not read as
* "yes" — that is the shape of an uninitialised configuration variable, and
* the one reading it should not be a universal pass.
*/
function hasRole(address account, uint256 roleMask) public view returns (bool) {
if (roleMask == 0) return false;
Identity storage id = _identity[account];
if (!id.registered || id.revoked) return false;
if (id.roles & roleMask != roleMask) return false;
return _withinValidity(id);
}
/// @notice Whether `account` is registered, unrevoked and in date,
/// regardless of capability.
function isActive(address account) public view returns (bool) {
Identity storage id = _identity[account];
return id.registered && !id.revoked && _withinValidity(id);
}
function _withinValidity(Identity storage id) private view returns (bool) {
if (id.notBefore != 0 && FinalChainTime.nowMs() < id.notBefore) return false;
if (id.notAfter != 0 && FinalChainTime.nowMs() >= id.notAfter) return false;
return true;
}
}
contracts/finalchain/FinalPqQuorum.sol
// SPDX-License-Identifier: BUSL-1.1
// Copyright (c) 2024-2026 Final DeFi
// Licensed under the Business Source License 1.1 (the "License")
//
// Change Date: 2029-01-01
// Change License: GPL-2.0-or-later
//
// @author Final DeFi
// @version 1.0.0
pragma solidity ^0.8.20;
import {FinalChainPrecompiles} from "./FinalChainPrecompiles.sol";
import {FinalIdentityRegistry} from "./FinalIdentityRegistry.sol";
/**
* @title FinalPqQuorum
* @notice K-of-N approval where the signatures are post-quantum and the chain
* is what checks them.
*
* @dev This library is the reason Final Chain exists in this design.
*
* `FinalBackend/src/pq/credential.js` carries a rule it had to enforce in code
* because nothing else could: **a surface whose signature is verified on chain
* cannot be PQ.** A co-signer approval reaching `FinalRootAuthority` is checked
* by ECDSA/ERC-1271 in Solidity, so a PQ co-signer would produce approvals the
* contract cannot read, and the quorum would stop reaching threshold with
* nothing in any log naming the cause. `PQ_SURFACE` and `assertBackendVerified`
* exist to keep anyone from crossing that line by accident.
*
* Here the line is gone. The precompiles verify ML-DSA-87 and
* SLH-DSA-SHAKE-256s natively, so a quorum can be PQ *and* on chain, and
* "the backend says these four signatures verified" becomes "these four
* signatures verify, and any node re-derives that independently".
*
* ## Three rules, each closing a specific hole
*
* 1. **Keys come from the registry, never from calldata.** A key passed as an
* argument proves nothing — anyone with a keypair can sign under it. This is
* the difference between a 4-of-5 quorum and a 1-of-1 held by whoever built
* the transaction.
*
* 2. **Signers strictly ascending.** One comparison per entry rejects duplicates
* outright, so a single member cannot supply four approvals and satisfy a
* threshold of four. The alternative — an O(n²) seen-check — is the same
* guarantee with more ways to get it wrong.
*
* 3. **The digest binds chain id and verifying contract.** Without both, an
* approval collected for one contract is replayable against another with the
* same payload shape, and an approval from the test chain is replayable on
* the production one. These co-signers hold one key across environments.
*
* ## Which algorithm
*
* The stack splits its keys by hardness assumption, not by convenience:
* ML-DSA-87 (lattice) signs transactions, SLH-DSA-SHAKE-256s (hash-based) signs
* identity. Two families, so one cryptanalytic result cannot take both.
*
* So an action inherits the class of what it authorizes. Advancing a state root
* is operational and high-cadence: transaction class. Registering or revoking
* an identity is the thing the access class exists for. `ALG_ANY` is available
* and should be used sparingly — accepting either means a break in one family
* takes the quorum.
*
* An action that authorizes EXECUTION takes both: the ML-DSA-87 approval and a
* `seal`, an SLH-DSA-SHAKE-256s signature over the same digest by the member's
* `activeSeal` key. Neither family alone can then move funds, and the seal key
* is its own slot — never the access key — so the process that seals cannot
* also rotate the identity it seals for.
*
* Every digest binds an `anchorBlock`: the block at which the members read
* tree 1 to decide who is in the round. Binding it means every approval in a
* round was made against ONE roster view, and the window in `require_` means a
* view older than `ANCHOR_WINDOW` blocks is refused rather than honoured.
*
* The practical cost is worth stating: an SLH-DSA signature is 29,792 bytes, so
* a 4-of-5 access-class quorum is ~119 KB of calldata. That is affordable here
* only because this is our own chain. Do not carry this pattern to a chain
* where it is not.
*/
library FinalPqQuorum {
/// @notice ML-DSA-87 — FIPS 204. Algorithm ids are the FIPS numbers: the
/// same ids `FinalCertificate` and the backend registry use, and the numbers
/// the precompile addresses end in (`0x0204`).
uint8 internal constant ALG_ML_DSA_87 = 4;
/// @notice SLH-DSA-SHAKE-256s — FIPS 205 (`0x0205`).
uint8 internal constant ALG_SLH_DSA_SHAKE_256S = 5;
/// @notice Either scheme is acceptable for this action.
uint8 internal constant ALG_ANY = 0;
/// @notice How far behind the chain head an approval's anchor may sit.
/// @dev Members evaluate roster membership against tree 1 AT the anchor
/// block. 600 blocks is ten minutes at the chain's one-second cadence —
/// generous against a round that takes seconds, and short enough that a
/// roster rotated away is refused rather than counted.
uint64 internal constant ANCHOR_WINDOW = 600;
/// @dev Domain separator for every quorum digest. Distinct from any
/// EIP-712 domain in the stack: these are not typed-data signatures and
/// must not be confusable with one.
bytes32 internal constant DOMAIN_PQ_QUORUM = keccak256("FINAL_CHAIN_PQ_QUORUM_v01");
/// @notice One member's approval.
struct Approval {
/// The member's account, which is also the key it is looked up by.
address signer;
/// `ALG_ML_DSA_87` or `ALG_SLH_DSA_SHAKE_256S`.
uint8 algorithm;
/// Over the 32-byte digest from `digest()`, verbatim. Both schemes
/// hash internally, so the digest is not re-hashed before signing.
bytes signature;
/// SLH-DSA-SHAKE-256s over the same digest, by the member's `activeSeal`
/// key. Required where the action authorizes execution; empty otherwise.
bytes seal;
}
error ThresholdNotMet(uint256 valid, uint256 required);
error SignersNotAscending(address previous, address next);
error SignerLacksRole(address signer, uint256 roleMask);
error WrongAlgorithm(address signer, uint8 got, uint8 required);
error BadSignature(address signer, uint8 algorithm);
error BadSeal(address signer);
error AnchorAhead(uint64 anchorBlock, uint256 blockNumber);
error AnchorStale(uint64 anchorBlock, uint256 blockNumber);
error ThresholdIsZero();
/**
* @notice The message every member of this quorum signs.
* @param verifyingContract The contract consuming the approvals. Binding it
* stops an approval collected for one contract being replayed
* against another with the same payload shape.
* @param actionDomain What is being authorized — a per-action constant, so
* an approval for "advance the accounts tree" cannot be replayed as
* one for "revoke an identity".
* @param anchorBlock The Final Chain block the members read tree 1 at to
* decide the roster. Bound here so every approval in a round names
* the same view; checked against `ANCHOR_WINDOW` by `require_`.
* @param payloadDigest The action's own committed content. Callers MUST
* include a nonce or a monotonic counter in it; nothing here can
* tell a replay of round 7 from a fresh round 7.
*/
function digest(
address verifyingContract,
bytes32 actionDomain,
uint64 anchorBlock,
bytes32 payloadDigest
) internal view returns (bytes32) {
return keccak256(
abi.encode(
DOMAIN_PQ_QUORUM,
block.chainid,
verifyingContract,
actionDomain,
anchorBlock,
payloadDigest
)
);
}
/**
* @notice Reverts unless at least `threshold` distinct members holding
* `roleMask` have signed `quorumDigest`.
* @param registry Where public keys and roles come from. Not a parameter
* for flexibility — a parameter so the caller's own immutable
* registry address is what is used, rather than one from calldata.
* @param requiredAlgorithm `ALG_ANY` to accept either scheme.
* @param anchorBlock The anchor the digest was built over. Refused if it is
* ahead of this block or more than `ANCHOR_WINDOW` behind it.
* @param requireSeal Whether every approval must also carry a valid `seal`
* by the member's `activeSeal` key — the execution class.
* @return valid The number of approvals that verified, which is at least
* `threshold` if this returns at all.
*
* @dev Every failure reverts with the offending signer named. A quorum that
* silently skipped bad approvals and counted the rest would let a
* misconfigured co-signer sit broken indefinitely: the threshold would keep
* being met by the others and nothing would say one member had stopped
* contributing. That is exactly the failure this program has already had,
* in `fanOut`, where a per-chain advance failure was recorded and execution
* continued.
*/
function require_(
FinalIdentityRegistry registry,
Approval[] calldata approvals,
bytes32 quorumDigest,
uint256 roleMask,
uint256 threshold,
uint8 requiredAlgorithm,
uint64 anchorBlock,
bool requireSeal
) internal view returns (uint256 valid) {
if (threshold == 0) revert ThresholdIsZero();
if (anchorBlock > block.number) revert AnchorAhead(anchorBlock, block.number);
if (block.number - anchorBlock > ANCHOR_WINDOW) revert AnchorStale(anchorBlock, block.number);
bytes memory message = abi.encodePacked(quorumDigest);
address previous = address(0);
uint256 n = approvals.length;
for (uint256 i = 0; i < n; i++) {
Approval calldata a = approvals[i];
// Strictly ascending. `address(0)` as the initial value works
// because it can never be a registered signer.
if (a.signer <= previous) revert SignersNotAscending(previous, a.signer);
previous = a.signer;
if (!registry.hasRole(a.signer, roleMask)) revert SignerLacksRole(a.signer, roleMask);
if (requiredAlgorithm != ALG_ANY && a.algorithm != requiredAlgorithm) {
revert WrongAlgorithm(a.signer, a.algorithm, requiredAlgorithm);
}
if (!_verify(registry, a, message)) revert BadSignature(a.signer, a.algorithm);
if (requireSeal && !_verifySeal(registry, a, message)) revert BadSeal(a.signer);
valid++;
}
if (valid < threshold) revert ThresholdNotMet(valid, threshold);
}
/// @notice Non-reverting form, for views and for callers that want to
/// report rather than refuse.
function count(
FinalIdentityRegistry registry,
Approval[] calldata approvals,
bytes32 quorumDigest,
uint256 roleMask,
uint8 requiredAlgorithm,
uint64 anchorBlock,
bool requireSeal
) internal view returns (uint256 valid) {
if (anchorBlock > block.number || block.number - anchorBlock > ANCHOR_WINDOW) return 0;
bytes memory message = abi.encodePacked(quorumDigest);
address previous = address(0);
uint256 n = approvals.length;
for (uint256 i = 0; i < n; i++) {
Approval calldata a = approvals[i];
if (a.signer <= previous) return valid;
previous = a.signer;
if (!registry.hasRole(a.signer, roleMask)) continue;
if (requiredAlgorithm != ALG_ANY && a.algorithm != requiredAlgorithm) continue;
if (!_verify(registry, a, message)) continue;
if (requireSeal && !_verifySeal(registry, a, message)) continue;
valid++;
}
}
/// @dev The seal: SLH-DSA-SHAKE-256s by the member's `activeSeal` key over
/// the same digest. A member with no seal key on record cannot seal, and an
/// approval with no seal bytes is not one.
function _verifySeal(
FinalIdentityRegistry registry,
Approval calldata a,
bytes memory message
) private view returns (bool) {
bytes memory key = registry.activeSealKeyOf(a.signer);
if (key.length == 0 || a.seal.length == 0) return false;
return FinalChainPrecompiles.verifySlhDsa(key, message, a.seal);
}
function _verify(
FinalIdentityRegistry registry,
Approval calldata a,
bytes memory message
) private view returns (bool) {
// The LIVE pair, always. The recovery pair authorizes rotating this
// account's own credentials and NOTHING else — a quorum that accepted
// it would hand the recovery keys everyday authority, which is exactly
// the separation the two stages exist to draw.
if (a.algorithm == ALG_ML_DSA_87) {
return FinalChainPrecompiles.verifyMlDsa87(
registry.activeTransactionKeyOf(a.signer), message, a.signature
);
}
if (a.algorithm == ALG_SLH_DSA_SHAKE_256S) {
return FinalChainPrecompiles.verifySlhDsa(
registry.activeAccessKeyOf(a.signer), message, a.signature
);
}
// Any other id is a refusal, never a default — including the KEM ids
// (3, 7) and the reserved FN-DSA id (6), none of which is a signature
// scheme this quorum verifies.
return false;
}
}
abi
[
{
"type": "constructor",
"inputs": [
{
"name": "admin",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "DOMAIN_IDENTITY_ADMISSION",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "DOMAIN_ISSUER_CERT_REVOCATION",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "DOMAIN_REGISTER_ISSUER",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "DOMAIN_REGISTER_LMS_KEY",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "DOMAIN_REGISTER_WALLET",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "DOMAIN_REVOKE",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "DOMAIN_REVOKE_CERTIFICATE",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "DOMAIN_SET_REGISTRAR_THRESHOLD",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "DOMAIN_SET_ROLES",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "MAX_ISSUER_VALIDITY_MS",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint64",
"internalType": "uint64"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "ROLE_ACCOUNT_COSIGNER",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "ROLE_CERTIFICATE_AUTHORITY",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "ROLE_GUARDIAN",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "ROLE_MMR_COSIGNER",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "ROLE_ORACLE_PUBLISHER",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "ROLE_PHI_PUBLISHER",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "ROLE_REGISTRAR",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "ROLE_REGISTRY_PUBLISHER",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "ROLE_RELAYER",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "ROLE_SETTLEMENT_COSIGNER",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "ROLE_VASSET_PUBLISHER",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "accountAt",
"inputs": [
{
"name": "index",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "accountCount",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "accountOfCertificate",
"inputs": [
{
"name": "certHash",
"type": "bytes32",
"internalType": "bytes32"
}
],
"outputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "accountOfSender",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "accountsWithRole",
"inputs": [
{
"name": "roleMask",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "found",
"type": "address[]",
"internalType": "address[]"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "activeAccessKeyOf",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "bytes",
"internalType": "bytes"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "activeSealKeyOf",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "bytes",
"internalType": "bytes"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "activeTransactionKeyOf",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "bytes",
"internalType": "bytes"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "bootstrapAdmin",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "bootstrapSealed",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "certificateRevoked",
"inputs": [
{
"name": "certHash",
"type": "bytes32",
"internalType": "bytes32"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "certificateRevokedBy",
"inputs": [
{
"name": "certHash",
"type": "bytes32",
"internalType": "bytes32"
}
],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "gateNonceOf",
"inputs": [
{
"name": "caller",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "uint64",
"internalType": "uint64"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "hasRole",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
},
{
"name": "roleMask",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "identityOf",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "tuple",
"internalType": "struct FinalIdentityRegistry.Identity",
"components": [
{
"name": "certHash",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "recoveryCertHash",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "serial",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "subjectKeyId",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "roles",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "depth",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "maxDelegationDepth",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "notBefore",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "notAfter",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "version",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "revoked",
"type": "bool",
"internalType": "bool"
},
{
"name": "registered",
"type": "bool",
"internalType": "bool"
}
]
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "identityTreeLeafOf",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "isActive",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "kemCommitments",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "liveKem",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "recoveryKem",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "kemKeysOf",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "activeMlKem",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "activeHqc",
"type": "bytes",
"internalType": "bytes"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "keyCommitments",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "liveAccess",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "liveTransaction",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "recoveryAccess",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "recoveryTransaction",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "liveMemberCount",
"inputs": [
{
"name": "roleMask",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "live",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "lmsBindingOf",
"inputs": [
{
"name": "signerId",
"type": "bytes32",
"internalType": "bytes32"
}
],
"outputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
},
{
"name": "chainId",
"type": "uint64",
"internalType": "uint64"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "lmsKeyOf",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
},
{
"name": "chainId",
"type": "uint64",
"internalType": "uint64"
}
],
"outputs": [
{
"name": "",
"type": "tuple",
"internalType": "struct FinalIdentityRegistry.LmsKey",
"components": [
{
"name": "keyId",
"type": "bytes16",
"internalType": "bytes16"
},
{
"name": "height",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "root",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "version",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "registered",
"type": "bool",
"internalType": "bool"
}
]
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "lmsSignerId",
"inputs": [
{
"name": "keyId",
"type": "bytes16",
"internalType": "bytes16"
},
{
"name": "height",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "root",
"type": "bytes32",
"internalType": "bytes32"
}
],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "pure"
},
{
"type": "function",
"name": "lmsSignerIsLive",
"inputs": [
{
"name": "signerId",
"type": "bytes32",
"internalType": "bytes32"
}
],
"outputs": [
{
"name": "live",
"type": "bool",
"internalType": "bool"
},
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "recoveryAccessKeyOf",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "bytes",
"internalType": "bytes"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "recoveryTransactionKeyOf",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "bytes",
"internalType": "bytes"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "registerIssuer",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
},
{
"name": "tbs",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "parent",
"type": "address",
"internalType": "address"
},
{
"name": "proof",
"type": "tuple",
"internalType": "struct FinalIdentityRegistry.AdmissionProof",
"components": [
{
"name": "mlDsaSignature",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "slhDsaSignature",
"type": "bytes",
"internalType": "bytes"
}
]
},
{
"name": "roles",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "version",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "anchorBlock",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "approvals",
"type": "tuple[]",
"internalType": "struct FinalPqQuorum.Approval[]",
"components": [
{
"name": "signer",
"type": "address",
"internalType": "address"
},
{
"name": "algorithm",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "signature",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "seal",
"type": "bytes",
"internalType": "bytes"
}
]
}
],
"outputs": [
{
"name": "certHash",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "registerLmsKey",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
},
{
"name": "chainId",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "keyId",
"type": "bytes16",
"internalType": "bytes16"
},
{
"name": "height",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "root",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "version",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "anchorBlock",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "approvals",
"type": "tuple[]",
"internalType": "struct FinalPqQuorum.Approval[]",
"components": [
{
"name": "signer",
"type": "address",
"internalType": "address"
},
{
"name": "algorithm",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "signature",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "seal",
"type": "bytes",
"internalType": "bytes"
}
]
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "registerWallet",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
},
{
"name": "liveTbs",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "recoveryTbs",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "proof",
"type": "tuple",
"internalType": "struct FinalIdentityRegistry.AdmissionProof",
"components": [
{
"name": "mlDsaSignature",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "slhDsaSignature",
"type": "bytes",
"internalType": "bytes"
}
]
},
{
"name": "roles",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "version",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "anchorBlock",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "approvals",
"type": "tuple[]",
"internalType": "struct FinalPqQuorum.Approval[]",
"components": [
{
"name": "signer",
"type": "address",
"internalType": "address"
},
{
"name": "algorithm",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "signature",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "seal",
"type": "bytes",
"internalType": "bytes"
}
]
}
],
"outputs": [
{
"name": "certHash",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "registrarThreshold",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "requireRegistrarQuorum",
"inputs": [
{
"name": "actionDomain",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "payloadDigest",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "anchorBlock",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "approvals",
"type": "tuple[]",
"internalType": "struct FinalPqQuorum.Approval[]",
"components": [
{
"name": "signer",
"type": "address",
"internalType": "address"
},
{
"name": "algorithm",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "signature",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "seal",
"type": "bytes",
"internalType": "bytes"
}
]
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "revocationLog",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "revoke",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
},
{
"name": "chainIds",
"type": "uint64[]",
"internalType": "uint64[]"
},
{
"name": "anchorBlock",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "approvals",
"type": "tuple[]",
"internalType": "struct FinalPqQuorum.Approval[]",
"components": [
{
"name": "signer",
"type": "address",
"internalType": "address"
},
{
"name": "algorithm",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "signature",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "seal",
"type": "bytes",
"internalType": "bytes"
}
]
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "revokeCertificate",
"inputs": [
{
"name": "certHash",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "anchorBlock",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "approvals",
"type": "tuple[]",
"internalType": "struct FinalPqQuorum.Approval[]",
"components": [
{
"name": "signer",
"type": "address",
"internalType": "address"
},
{
"name": "algorithm",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "signature",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "seal",
"type": "bytes",
"internalType": "bytes"
}
]
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "revokeIssuedCertificate",
"inputs": [
{
"name": "issuer",
"type": "address",
"internalType": "address"
},
{
"name": "certHash",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "proof",
"type": "tuple",
"internalType": "struct FinalIdentityRegistry.AdmissionProof",
"components": [
{
"name": "mlDsaSignature",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "slhDsaSignature",
"type": "bytes",
"internalType": "bytes"
}
]
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "sealBootstrap",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "sealableMemberCount",
"inputs": [
{
"name": "roleMask",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "sealable",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "senderFor",
"inputs": [
{
"name": "transactionKey",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "pure"
},
{
"type": "function",
"name": "senderHasRole",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "roleMask",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "senderOf",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "setRegistrarThreshold",
"inputs": [
{
"name": "threshold",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "anchorBlock",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "approvals",
"type": "tuple[]",
"internalType": "struct FinalPqQuorum.Approval[]",
"components": [
{
"name": "signer",
"type": "address",
"internalType": "address"
},
{
"name": "algorithm",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "signature",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "seal",
"type": "bytes",
"internalType": "bytes"
}
]
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "setRoles",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
},
{
"name": "roles",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "anchorBlock",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "approvals",
"type": "tuple[]",
"internalType": "struct FinalPqQuorum.Approval[]",
"components": [
{
"name": "signer",
"type": "address",
"internalType": "address"
},
{
"name": "algorithm",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "signature",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "seal",
"type": "bytes",
"internalType": "bytes"
}
]
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "stateTrees",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "wireStatePlane",
"inputs": [
{
"name": "stateTrees_",
"type": "address",
"internalType": "address"
},
{
"name": "revocationLog_",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "event",
"name": "BootstrapSealed",
"inputs": [
{
"name": "sealedBy",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"type": "event",
"name": "CertificateRevoked",
"inputs": [
{
"name": "certHash",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "revoker",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"type": "event",
"name": "IdentityRegistered",
"inputs": [
{
"name": "account",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "certHash",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "roles",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "version",
"type": "uint64",
"indexed": false,
"internalType": "uint64"
}
],
"anonymous": false
},
{
"type": "event",
"name": "IdentityRevoked",
"inputs": [
{
"name": "account",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "certHash",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
}
],
"anonymous": false
},
{
"type": "event",
"name": "IdentityRolesChanged",
"inputs": [
{
"name": "account",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "previousRoles",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "newRoles",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"type": "event",
"name": "LmsKeyRegistered",
"inputs": [
{
"name": "account",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "signerId",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "chainId",
"type": "uint64",
"indexed": true,
"internalType": "uint64"
},
{
"name": "keyId",
"type": "bytes16",
"indexed": false,
"internalType": "bytes16"
},
{
"name": "height",
"type": "uint8",
"indexed": false,
"internalType": "uint8"
},
{
"name": "root",
"type": "bytes32",
"indexed": false,
"internalType": "bytes32"
},
{
"name": "version",
"type": "uint64",
"indexed": false,
"internalType": "uint64"
}
],
"anonymous": false
},
{
"type": "event",
"name": "RegistrarQuorumApproved",
"inputs": [
{
"name": "verifyingContract",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "actionDomain",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "nonce",
"type": "uint64",
"indexed": false,
"internalType": "uint64"
},
{
"name": "valid",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"type": "event",
"name": "RegistrarThresholdSet",
"inputs": [
{
"name": "threshold",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"type": "event",
"name": "StatePlaneWired",
"inputs": [
{
"name": "stateTrees",
"type": "address",
"indexed": false,
"internalType": "address"
},
{
"name": "revocationLog",
"type": "address",
"indexed": false,
"internalType": "address"
}
],
"anonymous": false
},
{
"type": "error",
"name": "AdmissionProofInvalid",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
]
},
{
"type": "error",
"name": "AnchorAhead",
"inputs": [
{
"name": "anchorBlock",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "blockNumber",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"type": "error",
"name": "AnchorStale",
"inputs": [
{
"name": "anchorBlock",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "blockNumber",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"type": "error",
"name": "AuthorityKeyIdMismatch",
"inputs": [
{
"name": "got",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "want",
"type": "bytes32",
"internalType": "bytes32"
}
]
},
{
"type": "error",
"name": "BadSeal",
"inputs": [
{
"name": "signer",
"type": "address",
"internalType": "address"
}
]
},
{
"type": "error",
"name": "BadSignature",
"inputs": [
{
"name": "signer",
"type": "address",
"internalType": "address"
},
{
"name": "algorithm",
"type": "uint8",
"internalType": "uint8"
}
]
},
{
"type": "error",
"name": "BootstrapAlreadySealed",
"inputs": []
},
{
"type": "error",
"name": "CertificateAlreadyBound",
"inputs": [
{
"name": "certHash",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "boundTo",
"type": "address",
"internalType": "address"
}
]
},
{
"type": "error",
"name": "CertificateIsRevoked",
"inputs": [
{
"name": "certHash",
"type": "bytes32",
"internalType": "bytes32"
}
]
},
{
"type": "error",
"name": "DelegationWidened",
"inputs": [
{
"name": "child",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "issuer",
"type": "uint8",
"internalType": "uint8"
}
]
},
{
"type": "error",
"name": "IssuerCannotSign",
"inputs": [
{
"name": "depth",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "maxDelegationDepth",
"type": "uint8",
"internalType": "uint8"
}
]
},
{
"type": "error",
"name": "IssuerMayNotSign",
"inputs": [
{
"name": "issuer",
"type": "address",
"internalType": "address"
},
{
"name": "depth",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "maxDelegationDepth",
"type": "uint8",
"internalType": "uint8"
}
]
},
{
"type": "error",
"name": "IssuerMustExpire",
"inputs": []
},
{
"type": "error",
"name": "IssuerNotACertificateAuthority",
"inputs": [
{
"name": "issuer",
"type": "address",
"internalType": "address"
}
]
},
{
"type": "error",
"name": "IssuerValidityTooLong",
"inputs": [
{
"name": "notBefore",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "notAfter",
"type": "uint64",
"internalType": "uint64"
}
]
},
{
"type": "error",
"name": "JurisdictionMismatch",
"inputs": []
},
{
"type": "error",
"name": "JurisdictionMissing",
"inputs": []
},
{
"type": "error",
"name": "LmsHeightOutOfRange",
"inputs": [
{
"name": "height",
"type": "uint8",
"internalType": "uint8"
}
]
},
{
"type": "error",
"name": "LmsKeyAlreadyBound",
"inputs": [
{
"name": "signerId",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "boundTo",
"type": "address",
"internalType": "address"
}
]
},
{
"type": "error",
"name": "LmsRootIsZero",
"inputs": []
},
{
"type": "error",
"name": "MalformedEncapsulationKey",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
},
{
"name": "algorithmId",
"type": "uint16",
"internalType": "uint16"
}
]
},
{
"type": "error",
"name": "NotAnEndEntity",
"inputs": [
{
"name": "depth",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "maxDelegationDepth",
"type": "uint8",
"internalType": "uint8"
}
]
},
{
"type": "error",
"name": "NotAuthorized",
"inputs": [
{
"name": "caller",
"type": "address",
"internalType": "address"
}
]
},
{
"type": "error",
"name": "NotChainAttested",
"inputs": [
{
"name": "authorityKeyId",
"type": "bytes32",
"internalType": "bytes32"
}
]
},
{
"type": "error",
"name": "PrecompileUnavailable",
"inputs": [
{
"name": "precompile",
"type": "address",
"internalType": "address"
}
]
},
{
"type": "error",
"name": "RegistrarThresholdIsZero",
"inputs": []
},
{
"type": "error",
"name": "RegistrarThresholdUnreachable",
"inputs": [
{
"name": "sealable",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "threshold",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"type": "error",
"name": "SenderAlreadyBound",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "boundTo",
"type": "address",
"internalType": "address"
}
]
},
{
"type": "error",
"name": "SignerLacksRole",
"inputs": [
{
"name": "signer",
"type": "address",
"internalType": "address"
},
{
"name": "roleMask",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"type": "error",
"name": "SignersNotAscending",
"inputs": [
{
"name": "previous",
"type": "address",
"internalType": "address"
},
{
"name": "next",
"type": "address",
"internalType": "address"
}
]
},
{
"type": "error",
"name": "StagesDisagree",
"inputs": [
{
"name": "liveSerial",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "recoverySerial",
"type": "bytes32",
"internalType": "bytes32"
}
]
},
{
"type": "error",
"name": "StatePlaneAlreadyWired",
"inputs": []
},
{
"type": "error",
"name": "ThresholdIsZero",
"inputs": []
},
{
"type": "error",
"name": "ThresholdNotMet",
"inputs": [
{
"name": "valid",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "required",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"type": "error",
"name": "UnknownAccount",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
]
},
{
"type": "error",
"name": "VersionNotNewer",
"inputs": [
{
"name": "current",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "offered",
"type": "uint64",
"internalType": "uint64"
}
]
},
{
"type": "error",
"name": "WrongAlgorithm",
"inputs": [
{
"name": "signer",
"type": "address",
"internalType": "address"
},
{
"name": "got",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "required",
"type": "uint8",
"internalType": "uint8"
}
]
},
{
"type": "error",
"name": "WrongDepth",
"inputs": [
{
"name": "got",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "want",
"type": "uint8",
"internalType": "uint8"
}
]
},
{
"type": "error",
"name": "WrongIssuerDn",
"inputs": [
{
"name": "issuerDnHash",
"type": "bytes32",
"internalType": "bytes32"
}
]
},
{
"type": "error",
"name": "ZeroStatePlane",
"inputs": []
}
]leggi contratto
bytecode · 24,120 byte
0x6080806040526004361015610012575f80fd5b5f905f3560e01c9081630408a87f14613af85750806304525da814613ad05780630d641df014613a045780631479bc3a1461392e57806315ba3c1d146139135780631d4f1077146137d55780631f394fb3146137a05780631f9dc0bb146135b8578063209f80441461359d578063222e6f0e1461356e578063228bf014146135535780632741cb021461332c5780632ca02983146132825780633222383e1461324a57806332596d711461322d578063342f6163146131bb57806345e7e88e14613172578063461de6c114613138578063488429d9146130fe5780634c4af1a414612d6d5780634ccf000514612cd45780634f8d321614612c605780635a232a3914612c265780635b88250114612af75780635c97f4a214612ad057806361dbd45214612a9657806364d2218d14612a7757806370f64f0a14612a2c57806377e223b014612a1157806386731755146129d75780638c6820a914611a745780638cfc6aa014611a4257806390ecddbf14611a01578063926590d61461193257806394338765146118f05780639aae87ad146118b65780639c11e31b1461189b5780639d07ae09146117875780639e5adaeb1461174f5780639f8a13d714611722578063a0c176c4146116fd578063a760c295146116cb578063a874eea5146116b0578063ad20445d14611696578063ad84ad131461165e578063b0538d5a14611643578063b16abc6c1461160b578063b3c26283146115aa578063b7af85d71461155a578063baadbb3214611520578063c071672914611504578063c177a97e146114e1578063c5768fe4146114b9578063c6345626146112f6578063cbe6ebb414610672578063ce092d1c14610655578063de043e951461061a578063e0cd096a146105ee578063e14c465b146105d1578063e4af29fc146105b3578063e51442e31461057b578063ec964baa146104b0578063ef23f9f81461046f578063f5778b0314610446578063fce072f8146103e95763ffd326f3146102f4575f80fd5b346103e65760403660031901126103e6576001600160401b036040610317613bfa565b92610320613b30565b93816080845161032f81613c61565b8281528260208201528286820152826060820152015260018060a01b03168152806020522091165f5260205260a060405f2060405161036d81613c61565b6001600160401b038254916001600160801b03198360801b169384825260ff602083019460801c16845260ff60026001830154926040850193845201549481608060608601958789168752019660401c161515865260405196875251166020860152516040850152511660608301525115156080820152f35b80fd5b50346103e65760203660031901126103e657600435906001600160401b0382116103e657366023830112156103e657602061043461042f36600486013560248701613cd4565b614701565b6040516001600160a01b039091168152f35b50346103e657806003193601126103e6576010546040516001600160a01b039091168152602090f35b50346103e65760203660031901126103e6576020906001600160a01b03610494613bfa565b16815260158252604060018060a01b0391205416604051908152f35b50346103e657806003193601126103e6576010546001600160a01b03811633036105685760ff8160a01c1661055957601354801561054a576104f0613f57565b8181106105345750506001600160a81b031916600160a01b17601055337fdd5280e26bdef754c085fd1fe40c0ab76df98368bb6014f85b49f8852a81be578280a280f35b6304951c2160e11b845260045260245250604490fd5b631de31ea560e11b8352600483fd5b630f80bc0560e31b8252600482fd5b634a0bfec160e01b825233600452602482fd5b50346103e65760203660031901126103e657602061059a600435613d53565b905460405160039290921b1c6001600160a01b03168152f35b50346103e657806003193601126103e6576020600f54604051908152f35b50346103e657806003193601126103e65760206040516101008152f35b50346103e65760203660031901126103e657602061061261060d613bfa565b6144a9565b604051908152f35b50346103e657806003193601126103e65760206040517f664b0e72d3e91e88f8d9d2c0d916d51aff408110b8760394f6d677a5e6b24a2e8152f35b50346103e657806003193601126103e65760206040516102008152f35b346112f2576101003660031901126112f25761068c613bfa565b6024356001600160401b0381116112f2576106ab903690600401613c34565b90916044356001600160401b0381116112f2576106cc903690600401613c34565b606492919235936001600160401b0385116112f2578460040193604060031987360301126112f25760843595610700613b5c565b95610709613b72565b9360e435956001600160401b0387116112f257899661072c903690600401613b88565b929096305f52601460205260405f20546001600160401b0316938d83369061075392613cd4565b80519060200120988b8d3661076990888d613cd4565b805190602001209c604051809e6020820194600160a01b60019003169e8f865260408301526060820152608001526001600160401b03169b8c60a082015260a081526107b660c082613c98565b519020926107c39361495e565b7383d50624b34718978a0f118a95f7c6b6c9008c478091604051809e81926325f1701d60e21b835260048301916107f992614303565b03815a935f94f49586156112c5576108339c5f976112d0575b50905f9291604051809e8194829363b389b84f60e01b845260048401614303565b03915af4998a156112c5575f9a6112a1575b506020840191825160208c01519081810361128c5750506108658561527f565b61086e8b61527f565b8a518551906040519060208201927f6e3591285df1e4e62815fc41f5a94072fc4e3ab79993ede42c87f8995a9f81688452466040840152306060840152608083015260a08201528360c082015260c081526108ca60e082613c98565b51902093604051946020860152602085526108e6604086613c98565b61016086019461090c8651826109066108ff8780613e4d565b3691613cd4565b91614b32565b15928315611261575b50505061124e57305f526014602052806001600160401b0360405f2054161461121a575b5082519684156112075783515f52600d60205260ff60405f2054166111f35783515f908152600c60205260409020546001600160a01b0316801515806111e9575b6111d35750845f52600260205260405f206005810192835460ff8160d81c16155f14611151575090600f5490600160401b821015610e50578b926109ee8b6109ca85600160049701600f55613d53565b81546001600160a01b0393841660039290921b91821b9390911b1916919091179055565b855460ff60d81b1916600160d81b1786555b875182558d51600183015551600282015560c08701516003820155015560e084015182546101008601516101208701516101408801516001600160d01b031990931660ff949094169390931760089190911b61ff00161760109290921b69ffffffffffffffff0000169190911760509190911b67ffffffffffffffff60501b161760909190911b67ffffffffffffffff60901b1617905580516001600160a01b0390610aab90614701565b165f818152601560205260409020546001600160a01b031680151580611147575b6111315750835f526003602052610ae660405f2054613e7f565b6110e3575b5f52601560205260405f20836001600160601b0360a01b82541617905551825f52600360205260405f20908051906001600160401b038211610e5057610b318354613e7f565b601f81116110a9575b50602090601f831160011461104657610b6a92915f9183610e64575b50508160011b915f199060031b1c19161790565b90555b610180810151825f52600460205260405f20908051906001600160401b038211610e5057610b9b8354613e7f565b601f811161100c575b50602090601f8311600114610fa957610bd392915f9183610e645750508160011b915f199060031b1c19161790565b90555b610160870151825f52600560205260405f20908051906001600160401b038211610e5057610c048354613e7f565b601f8111610f6f575b50602090601f8311600114610f0c57610c3c92915f9183610e645750508160011b915f199060031b1c19161790565b90555b610180870151825f52600660205260405f20908051906001600160401b038211610e5057610c6d8354613e7f565b601f8111610ed2575b50602090601f8311600114610e6f57610ca592915f9183610e645750508160011b915f199060031b1c19161790565b90555b6101e081015196825f52600760205260405f2088516001600160401b038111610e5057602099610cd88354613e7f565b601f8111610e0f575b508a90601f8311600114610d925793610612999a93610d2b845f516020615df85f395f51905f529895610d59956040995f92610d875750508160011b915f199060031b1c19161790565b90555b610d456101a08401516101c0850151905f8c6153e9565b6101c06101a0820151910151905f8a6156ad565b80515f52600c8a52825f20856001600160601b0360a01b8254161790555194825191825289820152a36149db565b015190505f80610b56565b90601f19831691845f52815f20925f5b818110610df8575084610d5994604098946106129e9f98945f516020615df85f395f51905f529b9860019510610de0575b505050811b019055610d2e565b01515f1960f88460031b161c191690558f8080610dd3565b92938e600181928786015181550195019301610da2565b82811115610ce157610e4290845f528c5f2090601f850160051c908e8610610e48575b601f82910160051c039101615264565b8b610ce1565b5f9150610e32565b634e487b7160e01b5f52604160045260245ffd5b015190508b80610b56565b90601f19831691845f52815f20925f5b818110610eba5750908460019594939210610ea2575b505050811b019055610ca8565b01515f1960f88460031b161c191690558a8080610e95565b92936020600181928786015181550195019301610e7f565b82811115610c7657610f0690845f5260205f2090601f850160051c9060208610610e4857601f82910160051c039101615264565b8a610c76565b90601f19831691845f52815f20925f5b818110610f575750908460019594939210610f3f575b505050811b019055610c3f565b01515f1960f88460031b161c191690558a8080610f32565b92936020600181928786015181550195019301610f1c565b82811115610c0d57610fa390845f5260205f2090601f850160051c9060208610610e4857601f82910160051c039101615264565b8a610c0d565b90601f19831691845f52815f20925f5b818110610ff45750908460019594939210610fdc575b505050811b019055610bd6565b01515f1960f88460031b161c191690558a8080610fcf565b92936020600181928786015181550195019301610fb9565b82811115610ba45761104090845f5260205f2090601f850160051c9060208610610e4857601f82910160051c039101615264565b8a610ba4565b90601f19831691845f52815f20925f5b8181106110915750908460019594939210611079575b505050811b019055610b6d565b01515f1960f88460031b161c191690558a808061106c565b92936020600181928786015181550195019301611056565b82811115610b3a576110dd90845f5260205f2090601f850160051c9060208610610e4857601f82910160051c039101615264565b8a610b3a565b835f52600360205260018060a01b0361110161042f60405f20613eb7565b16818103611110575b50610aeb565b5f52601560205260405f206001600160601b0360a01b81541690558961110a565b906313362de360e01b5f5260045260245260445ffd5b5084811415610acc565b6001600160401b038160901c16808a11156111bc575060d01c60ff166111a857816004918c935488518103611187575b50610a00565b5f52600c60205260405f206001600160601b0360a01b81541690558e611181565b505463e41b98f760e01b5f5260045260245ffd5b899063df5abcab60e01b5f5260045260245260445ffd5b8451623bdaab60e51b5f5260045260245260445ffd5b508581141561097a565b835163e41b98f760e01b5f5260045260245ffd5b84633131bf7960e21b5f5260045260245ffd5b61122390613e2f565b305f5260146020526001600160401b0360405f2091166001600160401b031982541617905589610939565b84639ae9f73b60e01b5f5260045260245ffd5b61128393506108ff61127d9160246101808b0151950190613e4d565b91614bd9565b158b8080610915565b6388e0872960e01b5f5260045260245260445ffd5b6112be919a503d805f833e6112b68183613c98565b810190614133565b988a610845565b6040513d5f823e3d90fd5b5f93929197506112e9903d8086833e6112b68183613c98565b96909192610812565b5f80fd5b346112f25760203660031901126112f25761130f613bfa565b60405161131b81613c7c565b5f8152602081015f9052604081015f9052606081015f9052608081015f905260a081015f905260c081015f905260e081015f905261010081015f905261012081015f905261014081015f9052610160015f9052600160a01b60019003165f52600260205260405f206040519061139082613c7c565b80549182815260018201546020820190815260028301546040830190815260038401546060840190815260048501549460808501958652600501549460a0850160ff8716815260c08601918760081c60ff16835260e08701938860101c6001600160401b031685526101008801958960501c6001600160401b031687526101208901978a60901c6001600160401b031689526101408a01998b60d01c60ff1615158b52610160019a60d81c60ff1615158b526040519b8c525160208c01525160408b01525160608a01525160808901525160ff1660a08801525160ff1660c0870152516001600160401b031660e0860152516001600160401b0316610100850152516001600160401b031661012084015251151561014083015251151561016082015261018090f35b346112f2575f3660031901126112f2576012546040516001600160a01b039091168152602090f35b346112f25760203660031901126112f25760206104346114ff613bfa565b6143e2565b346112f2575f3660031901126112f25760206040516104008152f35b346112f2575f3660031901126112f25760206040517f6e3591285df1e4e62815fc41f5a94072fc4e3ab79993ede42c87f8995a9f81688152f35b346112f25760203660031901126112f2576001600160a01b0361157b613bfa565b165f5260036020526115a661159260405f20613eb7565b604051918291602083526020830190613c10565b0390f35b346112f25760403660031901126112f2576001600160a01b036115cb613bfa565b165f526015602052602060018060a01b0360405f20541680151590816115f7575b506040519015158152f35b611605915060243590614036565b826115ec565b346112f25760203660031901126112f2576001600160a01b0361162c613bfa565b165f5260056020526115a661159260405f20613eb7565b346112f2575f3660031901126112f257602060405160108152f35b346112f25760203660031901126112f2576001600160a01b0361167f613bfa565b165f5260076020526115a661159260405f20613eb7565b346112f2575f3660031901126112f2576020604051818152f35b346112f2575f3660031901126112f257602060405160028152f35b346112f25760203660031901126112f2576004355f52600c602052602060018060a01b0360405f205416604051908152f35b346112f2575f3660031901126112f257602060ff60105460a01c166040519015158152f35b346112f25760203660031901126112f2576020611745611740613bfa565b614394565b6040519015158152f35b346112f25760203660031901126112f2576001600160a01b03611770613bfa565b165f5260046020526115a661159260405f20613eb7565b346112f25760803660031901126112f2576117a0613bfa565b602435906117ac613b46565b6064356001600160401b0381116112f2576117ce611801913690600401613b88565b90604051936020850160018060a01b03871695868252886040820152604081526117f9606082613c98565b519020614906565b805f52600260205260405f2092600584015460ff8160d81c16156118885760d01c60ff166118745760407ffea1c9b6eea77fb9c209307935fb32ed2f3299cb9c639571480c67b17929807f91600461187296019080825492556118626149b6565b82519182526020820152a26149db565b005b835463e41b98f760e01b5f5260045260245ffd5b82633131bf7960e21b5f5260045260245ffd5b346112f2575f3660031901126112f257602060405160088152f35b346112f2575f3660031901126112f25760206040517fc1f01606bfc0d9242f3def839a8589d5b92fe65d09df4befd80f0439f60344cc8152f35b346112f25760203660031901126112f2576004355f5260016020526040805f20546001600160401b0382519160018060a01b038116835260a01c166020820152f35b346112f25760203660031901126112f25760406001600160a01b03611955613bfa565b16805f526008602052815f20815f52600960205261199e6119ac845f20855192839161199860208401965f516020615e185f395f51905f5288528985019061432a565b9061432a565b03601f198101835282613c98565b51902090805f52600a602052825f20905f52600b60205261199e6119f2845f20855192839161199860208401965f516020615e185f395f51905f5288528985019061432a565b51902082519182526020820152f35b346112f25760203660031901126112f2576001600160a01b03611a22613bfa565b165f52601460205260206001600160401b0360405f205416604051908152f35b346112f25760203660031901126112f2576004355f52600e602052602060018060a01b0360405f205416604051908152f35b346112f2576101003660031901126112f257611a8e613bfa565b6024356001600160401b0381116112f257611aad903690600401613c34565b90916044356001600160a01b03811692918382036112f257606435936001600160401b0385116112f2578460040192604060031987360301126112f25760843593611af6613b5c565b611afe613b72565b9260e4356001600160401b0381116112f257611b1e903690600401613b88565b989094305f52601460205260405f20546001600160401b0316998c833690611b4592613cd4565b80519060200120966040519860208a0190600160a01b600190038c16998a835260408c015260608b01528b60808b01526001600160401b038716998a60a082015260a08152611b9560c082613c98565b51902092611ba2936148ae565b604051633ba294e360e01b81529a8b91611bbf9160048401614303565b038a7383d50624b34718978a0f118a95f7c6b6c9008c4791815a935f94f4998a156112c5575f9a6129bb575b5060e08a019160ff8351168015818d82156129a8575b505061298957506101408b01986001600160401b038a51161561297a576001600160401b038a5116926101208d01936001600160401b0385511690036001600160401b03811161283e576001600160401b03640eb9af10009116116129545760408d01517fa5f1406585e87ef6c3645d6270cf45d62ae1c5d1abf447614cd94657a3f429a0810361294257508c611c979161507d565b60608c01519a5f9b5f5f5b6004810180821161283e578351811161292c57811580156128fe575b806128dd575b806128af575b611cdd5750611cd890613d6b565b611ca2565b91509192939495969798999a9b9c9d5082518110908161288a575b50612867576002810180821161283e576001600160f81b031990611d1c90846151eb565b51166003820180921161283e57611d4c92611d3f611d479360ff60f81b926151eb565b5116906151fc565b615227565b60015b156128675760808d01516006815110612867578051156128765761ff0080602083015160f01c161681516001101561287657602182015160f81c1780600201908160021161283e578251600482019081841161283e57106128675761ff0080611db884866151eb565b5160f01c16166003820180841161283e57611dd390856151eb565b5160f81c17908160020160021161283e570160040190811061283e57815190600281019182821161283e5782116128675761ff0080611e1283866151eb565b5160f01c1616600182019081831161283e57611e30600292866151eb565b5160f81c1714801590612852575b61282f5760036001600160f81b0319611e5784866151eb565b5116910180921161283e57611e7892611d3f611d479360ff60f81b926151eb565b6001600160f01b031991821691160361282f578b90815160405160208101917f6e3591285df1e4e62815fc41f5a94072fc4e3ab79993ede42c87f8995a9f8168835246604083015230606083015260808201525f60a08201528460c082015260c08152611ee660e082613c98565b51902060405190602082015260208152611f01604082613c98565b610160830197611f1a8951836109066108ff8580613e4d565b15938415612809575b505050506127f657305f526014602052806001600160401b0360405f205416146127c2575b506102008a5198179885156127af578a515f52600d60205260ff60405f20541661279b578a515f908152600c60205260409020546001600160a01b031680151580612791575b61277b5750855f52600260205260405f20926005840194855460ff8160d81c16155f146126ef5750600f5490600160401b821015610e50578c60048f97611fe18e6109ca87600160ff9901600f55613d53565b895460d886901b1916600160d81b178a555b88518155885160018201556020890151600282015560c08901516003820155015551169069ffffffffffffffff000061ff00610100885497015160081b16915160101b16926001600160401b0360501b905160501b16936001600160401b0360901b9060901b16946001600160401b0360901b19926001600160401b0360501b199169ffffffffffffffffffff191617161716171717905560018060a01b0361209c8251614701565b165f818152601560205260409020546001600160a01b0316801515806126e5575b6111315750825f5260036020526120d760405f2054613e7f565b612697575b5f52601560205260405f20826001600160601b0360a01b82541617905551815f52600360205260405f20908051906001600160401b038211610e50576121228354613e7f565b601f811161265d575b50602090601f83116001146125fa5761215a92915f91836125525750508160011b915f199060031b1c19161790565b90555b610180860151815f52600460205260405f20908051906001600160401b038211610e505761218b8354613e7f565b601f81116125c0575b50602090601f831160011461255d576121c392915f91836125525750508160011b915f199060031b1c19161790565b90555b6020956040516121d68882613c98565b5f8152825f526005885260405f20908051906001600160401b038211610e50576122008354613e7f565b601f811161251a575b508990601f83116001146124b75761223792915f9183610e645750508160011b915f199060031b1c19161790565b90555b6040516122478882613c98565b5f8152825f526006885260405f20908051906001600160401b038211610e50576122718354613e7f565b601f811161247f575b508990601f831160011461241c576122a892915f9183610e645750508160011b915f199060031b1c19161790565b90555b6040516122b88882613c98565b5f8152825f526007885260405f20908051906001600160401b038211610e50576122e28354613e7f565b601f81116123e4575b508990601f831160011461236a5792612331836106129a9b945f516020615df85f395f51905f5297946040975f9261235f5750508160011b915f199060031b1c19161790565b90555b610d596101a082018051906123536101c085019283519060018d6153e9565b5190519060018a6156ad565b015190508e80610b56565b90601f19831691845f528b5f20925f5b8d8282106123ce575050935f516020615df85f395f51905f52969360409693600193836106129e9f98106123b6575b505050811b019055612334565b01515f1960f88460031b161c191690558d80806123a9565b600185968293968601518155019501930161237a565b828111156122eb5761241690845f528b5f2090601f850160051c908d8610610e4857601f82910160051c039101615264565b8a6122eb565b90601f19831691845f528b5f20925f5b8d828210612469575050908460019594939210612451575b505050811b0190556122ab565b01515f1960f88460031b161c191690558a8080612444565b600185968293968601518155019501930161242c565b8281111561227a576124b190845f528b5f2090601f850160051c908d8610610e4857601f82910160051c039101615264565b8a61227a565b90601f19831691845f528b5f20925f5b8d8282106125045750509084600195949392106124ec575b505050811b01905561223a565b01515f1960f88460031b161c191690558a80806124df565b60018596829396860151815501950193016124c7565b828111156122095761254c90845f528b5f2090601f850160051c908d8610610e4857601f82910160051c039101615264565b8a612209565b015190508a80610b56565b90601f19831691845f52815f20925f5b8181106125a85750908460019594939210612590575b505050811b0190556121c6565b01515f1960f88460031b161c19169055898080612583565b9293602060018192878601518155019501930161256d565b82811115612194576125f490845f5260205f2090601f850160051c9060208610610e4857601f82910160051c039101615264565b89612194565b90601f19831691845f52815f20925f5b818110612645575090846001959493921061262d575b505050811b01905561215d565b01515f1960f88460031b161c19169055898080612620565b9293602060018192878601518155019501930161260a565b8281111561212b5761269190845f5260205f2090601f850160051c9060208610610e4857601f82910160051c039101615264565b8961212b565b825f52600360205260018060a01b036126b561042f60405f20613eb7565b168181036126c4575b506120dc565b5f52601560205260405f206001600160601b0360a01b8154169055886126be565b50838114156120bd565b6001600160401b038160909793949596971c16808b1115612764575060d01c60ff16612751578c949392918c60048360ff945489518103612731575b50611ff3565b5f908152600c6020526040812080546001600160a01b031916905561272b565b5463e41b98f760e01b5f5260045260245ffd5b8a9063df5abcab60e01b5f5260045260245260445ffd5b8b51623bdaab60e51b5f5260045260245260445ffd5b5086811415611f8e565b8a5163e41b98f760e01b5f5260045260245ffd5b85633131bf7960e21b5f5260045260245ffd5b6127cb90613e2f565b305f5260146020526001600160401b0360405f2091166001600160401b03198254161790558a611f48565b85639ae9f73b60e01b5f5260045260245ffd5b612825945061127d9160246101806108ff930151950190613e4d565b158c80808e611f23565b63261ab3b160e21b5f5260045ffd5b634e487b7160e01b5f52601160045260245ffd5b508251600482019081841161283e5710611e3e565b6301c8a09760e41b5f5260045ffd5b634e487b7160e01b5f52603260045260245ffd5b600b60fa1b91506001600160f81b0319906128a590856151eb565b511614158f611cf8565b506001820180831161283e57603d60f81b906001600160f81b0319906128d590876151eb565b511614611cca565b50604360f81b6001600160f81b03196128f684876151eb565b511614611cc4565b505f19820182811161283e57600b60fa1b906001600160f81b03199061292490876151eb565b511614611cbe565b505090509b909192939495969798999a9b611d4f565b63914a64c360e01b5f5260045260245ffd5b8a6001600160401b03808651169151169063950cff1d60e01b5f5260045260245260445ffd5b63ea0930b960e01b5f5260045ffd5b60ff6101008d01511690634f67a11560e01b5f5260045260245260445ffd5b610100015160ff1611159050818d611c01565b6129d0919a503d805f833e6112b68183613c98565b988a611beb565b346112f2575f3660031901126112f25760206040517f617214620b6c0e190ece7e2c8e3b97354e56dc3501b8a6811dd7e742dc6637c08152f35b346112f2575f3660031901126112f257602060405160408152f35b346112f25760603660031901126112f2576004356fffffffffffffffffffffffffffffffff19811681036112f25760243560ff811681036112f2576020916106129160443591614093565b346112f2575f3660031901126112f2576020604051640eb9af10008152f35b346112f2575f3660031901126112f25760206040517f9e01a06a8e87fa34b0b3b7f97e4f2ba5e105d644fac817f11f688ac916421fa28152f35b346112f25760403660031901126112f2576020611745612aee613bfa565b60243590614036565b346112f25760403660031901126112f257612b10613bfa565b6024356001600160a01b03811691908290036112f25760105460ff8160a01c16908115612c12575b50612bff57601154906001600160a01b03821615801590612beb575b612bdc576001600160a01b031680158015612bd4575b612bc5577f518f647756fa8c0e3a5d52ac2a56a5c3d0d4296b6f72486107a91a8cc8d9a8cd92816040936001600160601b0360a01b1617601155806001600160601b0360a01b601254161760125582519182526020820152a1005b632bd300bd60e21b5f5260045ffd5b508215612b6a565b63586ccc6160e11b5f5260045ffd5b506012546001600160a01b03161515612b54565b634a0bfec160e01b5f523360045260245ffd5b6001600160a01b0316331415905083612b38565b346112f2575f3660031901126112f25760206040517f3dbb5a17e2dda6a97acc2c59c4b3d3368b94b07f1b32afec7987d57e37e4fd078152f35b346112f25760203660031901126112f257612cc66001600160a01b03612c84613bfa565b16805f52600860205260405f20905f5260096020526115a6612cb2612cac60405f2093613eb7565b92613eb7565b604051938493604085526040850190613c10565b908382036020850152613c10565b346112f25760203660031901126112f257600f545f90600435825b828110612d0157602084604051908152f35b612d0a81613d53565b905460039190911b1c6001600160a01b0316612d268382614036565b9081612d4f575b50612d3b575b600101612cef565b92612d47600191613d6b565b939050612d33565b90505f526007602052612d6560405f2054613e7f565b151585612d2d565b346112f2576101003660031901126112f257612d87613bfa565b612d8f613b30565b906044356001600160801b03198116908181036112f2576064359160ff83168084036112f25760843595612dc1613b5c565b92612dca613b72565b9560e4356001600160401b0381116112f257612dea903690600401613b88565b6040989198519860208a01600160a01b600190038c16968782526001600160401b0316988960408d01528660608d01528860808d01528d60a08d01526001600160401b03169a8b60c082015260c08152612e4560e082613c98565b51902092612e5293614856565b825f52600260205260405f2060058101548060d81c60ff16156112075760d01c60ff166127515750831580156130f4575b6130e15788156130d257825f525f60205260405f20855f5260205260405f20906002820154966001600160401b038816808a11156111bc5750612ec7918b91614093565b5f818152600160205260409020549096906001600160a01b0316801515806130c8575b6130b2575060401c60ff16156130aa57806001612f1692549101549060ff8160801c169060801b614093565b955b88604051612f2581613c61565b8381526001600160401b0380600260208401938985526040810195865260608101958787526080820195600187528a5f525f60205260405f208d5f5260205260405f20925160801c83549160ff60801b905160801b169170ffffffffffffffffffffffffffffffffff19161717825551600182015501935116166001600160401b031983541617825551151560ff60401b82549160401b169060ff60401b19161790556040519160408301918383106001600160401b03841117610e5057604092835284845260208085018881525f8a8152600183528590209551865491516001600160e01b03199092166001600160a01b03919091161760a09190911b67ffffffffffffffff60a01b161790945582519182529281019490945283019790975260608201969096526118729583917f6ad0a6fc4d05a6986296bd82532c1c289660c306537630a1da2b80727d33a44f90608090a4811515908161309f575b50613090575b506149db565b61309990614a8d565b8261308a565b905081141584613084565b505f95612f18565b87633e9d9ea960e11b5f5260045260245260445ffd5b5084811415612eea565b630211d2d560e21b5f5260045ffd5b836385f6e97760e01b5f5260045260245ffd5b5060188411612e83565b346112f2575f3660031901126112f25760206040517ff6cc552646468a7983c31df0f953b1703ccadc1760ee2c78464c51e7c443171c8152f35b346112f2575f3660031901126112f25760206040517fcf993e293750106c3db70c784002b78c8fba024f618e4e3bb2748ef6a46321c28152f35b346112f25760803660031901126112f25761318b613b46565b606435906001600160401b0382116112f2576131ae611872923690600401613b88565b9160243560043533614c55565b346112f25760203660031901126112f257600f545f90600435825b8281106131e857602084604051908152f35b61320c826131f583613d53565b905460039190911b1c6001600160a01b0316614036565b613219575b6001016131d6565b92613225600191613d6b565b939050613211565b346112f2575f3660031901126112f2576020601354604051908152f35b346112f25760203660031901126112f2576001600160a01b0361326b613bfa565b165f5260066020526115a661159260405f20613eb7565b346112f25760203660031901126112f25760806001600160a01b036132a5613bfa565b16805f5260046020526132ba60405f20613eb7565b6020815191012090805f5260036020526132d660405f20613eb7565b6020815191012090805f5260066020526132f260405f20613eb7565b60208151910120905f52600560205261330d60405f20613eb7565b6020815191012091604051938452602084015260408301526060820152f35b346112f25760603660031901126112f257613345613bfa565b602435604435916001600160401b0383116112f2578260040190604060031985360301126112f25761337681613fd7565b15613533575f838152600e60205260409020546001600160a01b0316613520576001600160a01b03165f818152601460205260409020549093906001600160401b03166133c281613e2f565b855f5260146020526001600160401b0360405f2091166001600160401b031982541617905560405160208101917f3dbb5a17e2dda6a97acc2c59c4b3d3368b94b07f1b32afec7987d57e37e4fd0783524660408301523060608301528660808301528560a083015260c082015260c0815261343e60e082613c98565b519020906040519160208301526020825261345a604083613c98565b845f52600360205261348a6134828361090660405f2061347a8880613e4d565b949091613eb7565b933691613cd4565b159283156134f0575b5050506134dd575f818152600e6020526040812080546001600160a01b031916841790557f1dbd7f0554a6447214abb6405781d5ee119037a7024fcb7fffd542c3c12cd7769080a3005b50639ae9f73b60e01b5f5260045260245ffd5b6135179350613482929161347a61127d92885f526004602052602460405f20930190613e4d565b15838080613493565b8263e41b98f760e01b5f5260045260245ffd5b633210722560e21b5f9081526001600160a01b0391909116600452602490fd5b346112f2575f3660031901126112f257602060405160048152f35b346112f25760203660031901126112f2576004355f52600d602052602060ff60405f2054166040519015158152f35b346112f2575f3660031901126112f257602060405160808152f35b346112f25760803660031901126112f2576135d1613bfa565b6024356001600160401b0381116112f2576135f0903690600401613b88565b6135f8613b46565b6064356001600160401b0381116112f257613617903690600401613b88565b60409591955195602087019360608801948660018060a01b038616968783526040808c0152526080890198885f5b898110613777575050613668816136709798999a9b03601f198101835282613c98565b5190206147fe565b815f52600260205260405f2060058101805460ff8160d81c16156112075760ff60d01b1916600160d01b1790555f6004820181905581548152600d60205260409020805460ff191660011790556136c56149b6565b54827f898185a9e0933bcd25b9f43bc589ab95570a5c4b75d013955435eaf290380d4c5f80a35f5b8381101561376e57825f525f60205260405f20908060051b860135916001600160401b03831683036112f2576001600160401b03600193165f5260205260405f2060ff600282015460401c16613745575b50016136ed565b613763818461376893549101549060ff8160801c169060801b614093565b614a8d565b8661373e565b611872826149db565b909a8b35906001600160401b0382168092036112f257602081600193829352019c019101613645565b346112f25760203660031901126112f25760406137be600435613d8d565b825191151582526001600160a01b03166020820152f35b346112f25760603660031901126112f2576004356137f1613b30565b906044356001600160401b0381116112f2575f92613816613839923690600401613b88565b91604051602081019086825260208152613831604082613c98565b5190206147a6565b808252600d60209081526040808420805460ff19166001179055828452600c9091528220546001600160a01b031680613894575b507f1dbd7f0554a6447214abb6405781d5ee119037a7024fcb7fffd542c3c12cd7768280a3005b8083526002602052604083209060058201805460ff8160d01c16156138bc575b50505061386d565b60ff60d01b1916600160d01b179055600490910183905561390a906138df6149b6565b82817f898185a9e0933bcd25b9f43bc589ab95570a5c4b75d013955435eaf290380d4c8680a36149db565b828080806138b4565b346112f2575f3660031901126112f257602060405160018152f35b346112f25760203660031901126112f257600f5460043561394e82613d21565b915f915f5b8281106139a65750505061396681613d21565b915f5b82811061397e57604051806115a68682613bb8565b6001906001600160a01b036139938285613d79565b511661399f8287613d79565b5201613969565b806139c9836139b6600194613d53565b858060a01b0391549060031b1c16614036565b6139d4575b01613953565b6139dd81613d53565b838060a01b0391549060031b1c166139fe6139f787613d6b565b9688613d79565b526139ce565b346112f25760603660031901126112f257600435613a20613b30565b604435906001600160401b0382116112f257613a43613a66923690600401613b88565b91604051602081019086825260208152613a5e604082613c98565b519020614748565b8015613ac157613a74613f57565b818110613aac577f08808b872c36595369a5004f16ab8777648833a654e6b43a1a7e36b081f2b32460208380601355604051908152a1005b6304951c2160e11b5f5260045260245260445ffd5b631de31ea560e11b5f5260045ffd5b346112f2575f3660031901126112f2576011546040516001600160a01b039091168152602090f35b346112f2575f3660031901126112f257807f6c9c22b535529e02295bb8861d935a916462e2e1bb844c50ef1dd822975a61f060209252f35b602435906001600160401b03821682036112f257565b604435906001600160401b03821682036112f257565b60a435906001600160401b03821682036112f257565b60c435906001600160401b03821682036112f257565b9181601f840112156112f2578235916001600160401b0383116112f2576020808501948460051b0101116112f257565b60206040818301928281528451809452019201905f5b818110613bdb5750505090565b82516001600160a01b0316845260209384019390920191600101613bce565b600435906001600160a01b03821682036112f257565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b9181601f840112156112f2578235916001600160401b0383116112f257602083818601950101116112f257565b60a081019081106001600160401b03821117610e5057604052565b61018081019081106001600160401b03821117610e5057604052565b90601f801991011681019081106001600160401b03821117610e5057604052565b6001600160401b038111610e5057601f01601f191660200190565b929192613ce082613cb9565b91613cee6040519384613c98565b8294818452818301116112f2578281602093845f960137010152565b6001600160401b038111610e505760051b60200190565b90613d2b82613d0a565b613d386040519182613c98565b8281528092613d49601f1991613d0a565b0190602036910137565b600f5481101561287657600f5f5260205f2001905f90565b5f19811461283e5760010190565b80518210156128765760209160051b010190565b5f818152600160205260409020546001600160a01b03811691908215613e2657613db683614394565b15613e1f5760018060a01b0383165f525f6020526001600160401b038060405f209260a01c16165f5260205260405f209060ff600283015460401c169182613dfd57505091565b613e1b919250600181549101549060ff8160801c169060801b614093565b1491565b505f929050565b5050505f905f90565b6001600160401b036001911601906001600160401b03821161283e57565b903590601e19813603018212156112f257018035906001600160401b0382116112f2576020019181360383136112f257565b90600182811c92168015613ead575b6020831014613e9957565b634e487b7160e01b5f52602260045260245ffd5b91607f1691613e8e565b9060405191825f825492613eca84613e7f565b8084529360018116908115613f355750600114613ef1575b50613eef92500383613c98565b565b90505f9291925260205f20905f915b818310613f19575050906020613eef928201015f613ee2565b6020919350806001915483858901015201910190918492613f00565b905060209250613eef94915060ff191682840152151560051b8201015f613ee2565b5f90600f545f5b818110613f69575050565b613f7281613d53565b905460039190911b1c6001600160a01b0316613f9061010082614036565b9081613fb9575b50613fa5575b600101613f5e565b92613fb1600191613d6b565b939050613f9d565b90505f526007602052613fcf60405f2054613e7f565b15155f613f97565b6001600160a01b03165f908152600260205260409020600581015460d881901c60ff1615908115614028575b506140235761020080600483015416036140235761402090615000565b90565b505f90565b60ff915060d01c165f614003565b811561407f5760018060a01b03165f52600260205260405f2090600582015460ff8160d81c1615908115614085575b5061407f5780600483015416036140235761402090615000565b50505f90565b60ff915060d01c165f614065565b9160ff6040519260208401946001600160801b03191685521660408301526060820152606081526140c5608082613c98565b51902090565b81601f820112156112f2578051906140e282613cb9565b926140f06040519485613c98565b828452602083830101116112f257815f9260208093018386015e8301015290565b519060ff821682036112f257565b51906001600160401b03821682036112f257565b6020818303126112f2578051906001600160401b0382116112f2570190610220828203126112f2576040519161022083018381106001600160401b03821117610e505760405280518352602081015160208401526040810151604084015260608101516001600160401b0381116112f257826141b09183016140cb565b606084015260808101516001600160401b0381116112f257826141d49183016140cb565b608084015260a081015160a084015260c081015160c08401526141f960e08201614111565b60e084015261420b6101008201614111565b61010084015261421e610120820161411f565b610120840152614231610140820161411f565b6101408401526101608101516001600160401b0381116112f257826142579183016140cb565b6101608401526101808101516001600160401b0381116112f2578261427d9183016140cb565b6101808401526101a08101516001600160401b0381116112f257826142a39183016140cb565b6101a08401526101c08101516001600160401b0381116112f257826142c99183016140cb565b6101c08401526101e08101516001600160401b0381116112f257610200926142f29183016140cb565b6101e0840152015161020082015290565b90918060409360208452816020850152848401375f828201840152601f01601f1916010190565b5f929181549161433983613e7f565b9260018116908115614381575060011461435257505050565b90919293505f5260205f205f905b83821061436d5750500190565b600181602092548486015201910190614360565b60ff191683525050811515909102019150565b6001600160a01b03165f908152600260205260409020600581015460d881901c60ff169190826143d3575b50816143c9575090565b6140209150615000565b60d01c60ff161591505f6143bf565b6001600160a01b03165f90815260036020526040902080549061440482613e7f565b1561407f57604051915f9161441882613e7f565b80855291600181169081156144825750600114614442575b50509061042f81614020930382613c98565b5f90815260208120939250905b8082106144685750909150810160200161042f82614430565b91926001816020925483858801015201910190929161444f565b60ff191660208087019190915292151560051b8501909201925061042f9150839050614430565b6001600160a01b03165f81815260026020526040902060058101549160d883901c60ff16156146ef5760ff8360d01c1680156146df575b6146d85760ff8360081c1660ff84160361467a576002919250805f52600860205260405f20815f52600960205261199e61453f60405f2060405192839161199860208401965f516020615e185f395f51905f528852604085019061432a565b51902090805f52600a60205260405f20815f52600b60205261199e61458960405f2060405192839161199860208401965f516020615e185f395f51905f528852604085019061432a565b519020815f5260046020526145a060405f20613eb7565b6020815191012092825f5260036020526145bc60405f20613eb7565b6020815191012092805f5260066020526145d860405f20613eb7565b60208151910120905f5260056020526145f360405f20613eb7565b6020815191012090604051946020860196875260408601526060850152608084015260a083015260c082015260c0815261462e60e082613c98565b519020910154906040519060208201927fcc25d3fea88291f95ddfb5590a6b760f02245a0e4ca7c0b69285c6cd26543afd845260408301526060820152606081526140c5608082613c98565b5054906040519060208201927fa654ea8b191780d915fe370e2900652d600c179f2abeb8967e1b06ba97fe7094845260408301526001600160401b0360c01b9060301b1660608201525f6068820152606881526140c5608882613c98565b5050505f90565b506146e982615000565b156144e0565b633131bf7960e21b5f5260045260245ffd5b60405190614738602183602080820194600160fa1b86528051918291018484015e81015f838201520301601f198101845283613c98565b905190206001600160a01b031690565b92919060105460ff8160a01c16159081614793575b5061478d57613eef937f6c9c22b535529e02295bb8861d935a916462e2e1bb844c50ef1dd822975a61f030614c55565b50505050565b6001600160a01b0316331490505f61475d565b92919060105460ff8160a01c161590816147eb575b5061478d57613eef937f617214620b6c0e190ece7e2c8e3b97354e56dc3501b8a6811dd7e742dc6637c030614c55565b6001600160a01b0316331490505f6147bb565b92919060105460ff8160a01c16159081614843575b5061478d57613eef937fc1f01606bfc0d9242f3def839a8589d5b92fe65d09df4befd80f0439f60344cc30614c55565b6001600160a01b0316331490505f614813565b92919060105460ff8160a01c1615908161489b575b5061478d57613eef937ff6cc552646468a7983c31df0f953b1703ccadc1760ee2c78464c51e7c443171c30614c55565b6001600160a01b0316331490505f61486b565b92919060105460ff8160a01c161590816148f3575b5061478d57613eef937fcf993e293750106c3db70c784002b78c8fba024f618e4e3bb2748ef6a46321c230614c55565b6001600160a01b0316331490505f6148c3565b92919060105460ff8160a01c1615908161494b575b5061478d57613eef937f9e01a06a8e87fa34b0b3b7f97e4f2ba5e105d644fac817f11f688ac916421fa230614c55565b6001600160a01b0316331490505f61491b565b92919060105460ff8160a01c161590816149a3575b5061478d57613eef937f664b0e72d3e91e88f8d9d2c0d916d51aff408110b8760394f6d677a5e6b24a2e30614c55565b6001600160a01b0316331490505f614973565b60ff60105460a01c1615613eef576149cc613f57565b60135490818110613aac575050565b6011546001600160a01b03168015614a71576040908151926149fd8385613c98565b600184526020840190601f198401368337845115612876576001600160a01b03169052803b156112f25781516301e8a3a760e01b8152925f918491829084908290614a4b9060048301613bb8565b03925af1908115614a685750614a5e5750565b5f613eef91613c98565b513d5f823e3d90fd5b5050565b908160209103126112f2575180151581036112f25790565b6012546001600160a01b0316908115614a7157604051630d63997960e41b815260048101829052602081602481865afa9081156112c5575f91614b03575b50614a7157813b156112f2575f9160248392604051948593849263b5c645bd60e01b845260048401525af180156112c557614a5e5750565b614b25915060203d602011614b2b575b614b1d8183613c98565b810190614a75565b5f614acb565b503d614b13565b610a20815114801590614bcc575b6146d8576020614b935f948286958160405195869481808701998051918291018b5e8601908282018b8152815193849201905e010190878252805192839101825e0185815203601f198101835282613c98565b51906102045afa614ba2615327565b81614bc0575b81614bb1575090565b614bbb9150615356565b151590565b80516020149150614ba8565b5061121383511415614b40565b6040815114801590614c48575b6146d8576020614c395f948286958160405195869481808701998051918291018b5e8601908282018b8152815193849201905e010190878252805192839101825e0185815203601f198101835282613c98565b51906102055afa614ba2615327565b5061746083511415614be6565b9594919390929560135415613ac15760018060a01b031694855f5260146020526001600160401b0360405f20541694614c8d86613e2f565b875f5260146020526001600160401b0360405f2091166001600160401b03198254161790556040516020810191878352604082015260408152614cd1606082613c98565b519020966040516001600160401b0360208201927fd850f5df47b124511e8e6ec99cf1a0beaf7c6237eff0a31305ce53d85f312675845246604084015289606084015287608084015216988960a083015260c082015260c08152614d3660e082613c98565b51902093601354965f988815614ff157438111614fdb5780430343811161283e5761025810614fc557506040989497985195602087015260208652614d7c604087613c98565b5f965f99607e1986360301965b8a8c1015614f69578b60051b870135888112156112f257870199614dac8b615378565b6001600160a01b039182169116811015614f3d5750614dca8a615378565b99614dd481615378565b604051632e4bfa5160e11b81526001600160a01b0390911660048201526101006024820152602081604481305afa9081156112c5575f91614f1f575b5015614ef05760208101600460ff614e278361538c565b1603614ebe57614e388b8330615b97565b15614e8b5750614e498a8230615cc6565b15614e625750614e5a600191613d6b565b9b019a614d89565b614e6b90615378565b63c082266360e01b5f9081526001600160a01b0391909116600452602490fd5b614e9f614e9960ff93615378565b9161538c565b9063bbf82ba360e01b5f5260018060a01b03166004521660245260445ffd5b614ecc614e9960ff93615378565b9063587548c360e11b5f5260018060a01b031660045216602452600460445260645ffd5b614ef990615378565b63ae8bb03960e01b5f9081526001600160a01b0391909116600452610100602452604490fd5b614f37915060203d8111614b2b57614b1d8183613c98565b5f614e10565b614f468b615378565b6311641feb60e21b5f9081526004929092526001600160a01b0316602452604490fd5b965094509550955095509550808210614faf57507fd0ab8cbd6c510239be8b7cbd29e233d090728605764b8a4149ead15ae98677b49160409182519182526020820152a3565b906305bc216760e51b5f5260045260245260445ffd5b630ed38fd160e41b5f526004524360245260445ffd5b637b51505560e01b5f526004524360245260445ffd5b631fc460bf60e11b5f5260045ffd5b600501546001600160401b038160101c168015159081615058575b506140235760501c6001600160401b03168015159081615044575b5061504057600190565b5f90565b90506001600160401b03421610155f615036565b90506001600160401b034216105f61501b565b60ff60019116019060ff821161283e57565b906001600160a01b038216801561518057805f5260026020526150a360405f2093613fd7565b1561516e57600583015460ff8082169160081c169182821015615156575060e0830160ff81511660ff6150d58461506b565b160361512f57505060ff6101008301511681811161511a57505060a0600391015191015490818103615105575050565b635a6d501b60e11b5f5260045260245260445ffd5b63a96ac3e360e01b5f5260045260245260445ffd5b9061513f60ff809351169161506b565b9063239acc5160e21b5f526004521660245260445ffd5b632026243960e01b5f5260045260245260445260645ffd5b633210722560e21b5f5260045260245ffd5b50905060a08101517f9a6a5d8139ad2d28957698330aaa691017dba7dc80eb7cbec585239fb680bbab81036151d9575060e0015160ff165f1981016151c25750565b63239acc5160e21b5f52600452600160245260445ffd5b637557fe2160e11b5f5260045260245ffd5b908151811015612876570160200190565b6040516001600160f81b03199182166020820152911660218201526002815290613eef602283613c98565b80516020909101516001600160f01b0319811692919060028210615249575050565b6001600160f01b031960029290920360031b82901b16169150565b5f5b82811061527257505050565b5f82820155600101615266565b60a08101517f9a6a5d8139ad2d28957698330aaa691017dba7dc80eb7cbec585239fb680bbab81036151d9575060408101517fa5f1406585e87ef6c3645d6270cf45d62ae1c5d1abf447614cd94657a3f429a08103612942575060ff60e0820151169060018214801590615315575b6152f6575050565b61010060ff9101511690631a25415160e21b5f5260045260245260445ffd5b508160ff6101008301511614156152ee565b3d15615351573d9061533882613cb9565b916153466040519384613c98565b82523d5f602084013e565b606090565b60208151910151906020811061536a575090565b5f199060200360031b1b1690565b356001600160a01b03811681036112f25790565b3560ff811681036112f25790565b6153a48154613e7f565b90816153ae575050565b81601f5f93116001146153bf575055565b818352602083206153dc91601f0160051c84190190600101615264565b8082528160208120915555565b9093929380156156a4575b6156655761540182615d5d565b156156405761540f84615daa565b1561561b576001600160a01b03165f818152600860205260409020825191929091906001600160401b038211610e50576154498354613e7f565b601f81116155e1575b50602090601f831160011461557e5761548192915f9183610d875750508160011b915f199060031b1c19161790565b90555b5f52600960205260405f2082516001600160401b038111610e50576154a98254613e7f565b601f8111615544575b506020601f82116001146154e65781906154e29394955f92610d875750508160011b915f199060031b1c19161790565b9055565b601f19821690835f52805f20915f5b81811061552c57509583600195969710615514575b505050811b019055565b01515f1960f88460031b161c191690555f808061550a565b9192602060018192868b0151815501940192016154f5565b818111156154b25761557890835f5260205f2090601f840160051c9060208510610e4857601f82910160051c039101615264565b5f6154b2565b90601f19831691845f52815f20925f5b8181106155c957509084600195949392106155b1575b505050811b019055615484565b01515f1960f88460031b161c191690555f80806155a4565b9293602060018192878601518155019501930161558e565b828111156154525761561590845f5260205f2090601f850160051c9060208610610e4857601f82910160051c039101615264565b5f615452565b63c4facfbf60e01b5f9081526001600160a01b03919091166004526007602452604490fd5b63c4facfbf60e01b5f9081526001600160a01b03919091166004526003602452604490fd5b9192505060018060a01b0381165f52600860205261568560405f2061539a565b6001600160a01b03165f908152600960205260409020613eef9061539a565b508151156153f4565b9293925f92918015615b69575b615b29576156c782615d5d565b15615b09576156d585615daa565b15615ae9578215615900576001600160a01b0316808352600860205260408320825191929091906001600160401b0382116158ec576157148354613e7f565b601f81116158aa575b50602090601f83116001146158485761574c9291869183610d875750508160011b915f199060031b1c19161790565b90555b8152600960205260408120908351906001600160401b038211615834576157768354613e7f565b601f81116157f2575b50602090601f83116001146157ae57906154e293949583610d875750508160011b915f199060031b1c19161790565b90601f198316848352818320925b8181106157da5750958360019596971061551457505050811b019055565b9192602060018192868b0151815501940192016157bc565b8281111561577f57615826908483526020832090601f850160051c906020861061582c57601f82910160051c039101615264565b5f61577f565b849150610e32565b634e487b7160e01b81526041600452602490fd5b8386528186209190601f198416875b818110615892575090846001959493921061587a575b505050811b01905561574f565b01515f1960f88460031b161c191690555f808061586d565b92936020600181928786015181550195019301615857565b8281111561571d576158de908487526020872090601f850160051c90602086106158e457601f82910160051c039101615264565b5f61571d565b889150610e32565b634e487b7160e01b85526041600452602485fd5b6001600160a01b03165f818152600a602052604090208251919350916001600160401b038211610e50576159348354613e7f565b601f8111615aaf575b50602090601f8311600114615a4c5761596c92915f9183610d875750508160011b915f199060031b1c19161790565b90555b5f52600b60205260405f2082516001600160401b038111610e50576159948254613e7f565b601f8111615a12575b506020601f82116001146159cd5781906154e29394955f92610d875750508160011b915f199060031b1c19161790565b601f19821690835f52805f20915f5b8181106159fa5750958360019596971061551457505050811b019055565b9192602060018192868b0151815501940192016159dc565b8181111561599d57615a4690835f5260205f2090601f840160051c9060208510610e4857601f82910160051c039101615264565b5f61599d565b90601f19831691845f52815f20925f5b818110615a975750908460019594939210615a7f575b505050811b01905561596f565b01515f1960f88460031b161c191690555f8080615a72565b92936020600181928786015181550195019301615a5c565b8281111561593d57615ae390845f5260205f2090601f850160051c9060208610610e4857601f82910160051c039101615264565b5f61593d565b63c4facfbf60e01b83526001600160a01b03166004526007602452604482fd5b63c4facfbf60e01b83526001600160a01b03166004526003602452604482fd5b929350505060018060a01b0381165f52600a602052615b4a60405f2061539a565b6001600160a01b03165f908152600b60205260409020613eef9061539a565b508151156156ba565b906020828203126112f25781516001600160401b0381116112f25761402092016140cb565b9160208201600460ff615ba98361538c565b1614615c4b5760ff615bbc60059261538c565b1614615bc9575050505f90565b5f615bd383615378565b604051639e5adaeb60e01b81526001600160a01b0391821660048201529485916024918391165afa9182156112c557614020935f93615c1f575b506108ff81604061127d930190613e4d565b61127d919350615c436108ff913d805f833e615c3b8183613c98565b810190615b72565b939150615c0d565b505f615c5683615378565b60405163b7af85d760e01b81526001600160a01b0391821660048201529485916024918391165afa9182156112c557614020935f93615ca2575b506108ff816040610906930190613e4d565b610906919350615cbe6108ff913d805f833e615c3b8183613c98565b939150615c90565b90915f615cd284615378565b60405163ad84ad1360e01b81526001600160a01b0391821660048201529384916024918391165afa9182156112c5575f92615d41575b508151158015615d2b575b6146d85761127d6108ff846060614020960190613e4d565b50615d396060840184613e4d565b905015615d13565b615d569192503d805f833e615c3b8183613c98565b905f615d08565b5f80916020815191016102035afa615d73615327565b90158015615d9e575b615d8957614bbb90615356565b634e6f9bdf60e11b5f5261020360045260245ffd5b50602081511415615d7c565b5f80916020815191016102075afa615dc0615327565b90158015615deb575b615dd657614bbb90615356565b634e6f9bdf60e11b5f5261020760045260245ffd5b50602081511415615dc956fecd32e76e8e1fee2c6f45e0ccbed91002a21c754eaaa76564a10aa391f628a2b5374d5630a5adaa53fb387074872486662e4eff70f8ef438306c8697c24e7016c
Nessuna coda di metadati CBOR — questo bytecode è stato compilato con cbor_metadata disattivato, l'impostazione che i nostri contratti fissano per l'invarianza degli indirizzi CREATE2.
disassemblato (prime 4,000 op)
| pc | op | operando |
|---|---|---|
| 0000 | PUSH1 | 0x80 |
| 0002 | DUP1 | |
| 0003 | PUSH1 | 0x40 |
| 0005 | MSTORE | |
| 0006 | PUSH1 | 0x04 |
| 0008 | CALLDATASIZE | |
| 0009 | LT | |
| 000a | ISZERO | |
| 000b | PUSH2 | 0x0012 |
| 000e | JUMPI | |
| 000f | PUSH0 | |
| 0010 | DUP1 | |
| 0011 | REVERT | |
| 0012 | JUMPDEST | |
| 0013 | PUSH0 | |
| 0014 | SWAP1 | |
| 0015 | PUSH0 | |
| 0016 | CALLDATALOAD | |
| 0017 | PUSH1 | 0xe0 |
| 0019 | SHR | |
| 001a | SWAP1 | |
| 001b | DUP2 | |
| 001c | PUSH4 | 0x0408a87f |
| 0021 | EQ | |
| 0022 | PUSH2 | 0x3af8 |
| 0025 | JUMPI | |
| 0026 | POP | |
| 0027 | DUP1 | |
| 0028 | PUSH4 | 0x04525da8 |
| 002d | EQ | |
| 002e | PUSH2 | 0x3ad0 |
| 0031 | JUMPI | |
| 0032 | DUP1 | |
| 0033 | PUSH4 | 0x0d641df0 |
| 0038 | EQ | |
| 0039 | PUSH2 | 0x3a04 |
| 003c | JUMPI | |
| 003d | DUP1 | |
| 003e | PUSH4 | 0x1479bc3a |
| 0043 | EQ | |
| 0044 | PUSH2 | 0x392e |
| 0047 | JUMPI | |
| 0048 | DUP1 | |
| 0049 | PUSH4 | 0x15ba3c1d |
| 004e | EQ | |
| 004f | PUSH2 | 0x3913 |
| 0052 | JUMPI | |
| 0053 | DUP1 | |
| 0054 | PUSH4 | 0x1d4f1077 |
| 0059 | EQ | |
| 005a | PUSH2 | 0x37d5 |
| 005d | JUMPI | |
| 005e | DUP1 | |
| 005f | PUSH4 | 0x1f394fb3 |
| 0064 | EQ | |
| 0065 | PUSH2 | 0x37a0 |
| 0068 | JUMPI | |
| 0069 | DUP1 | |
| 006a | PUSH4 | 0x1f9dc0bb |
| 006f | EQ | |
| 0070 | PUSH2 | 0x35b8 |
| 0073 | JUMPI | |
| 0074 | DUP1 | |
| 0075 | PUSH4 | 0x209f8044 |
| 007a | EQ | |
| 007b | PUSH2 | 0x359d |
| 007e | JUMPI | |
| 007f | DUP1 | |
| 0080 | PUSH4 | 0x222e6f0e |
| 0085 | EQ | |
| 0086 | PUSH2 | 0x356e |
| 0089 | JUMPI | |
| 008a | DUP1 | |
| 008b | PUSH4 | 0x228bf014 |
| 0090 | EQ | |
| 0091 | PUSH2 | 0x3553 |
| 0094 | JUMPI | |
| 0095 | DUP1 | |
| 0096 | PUSH4 | 0x2741cb02 |
| 009b | EQ | |
| 009c | PUSH2 | 0x332c |
| 009f | JUMPI | |
| 00a0 | DUP1 | |
| 00a1 | PUSH4 | 0x2ca02983 |
| 00a6 | EQ | |
| 00a7 | PUSH2 | 0x3282 |
| 00aa | JUMPI | |
| 00ab | DUP1 | |
| 00ac | PUSH4 | 0x3222383e |
| 00b1 | EQ | |
| 00b2 | PUSH2 | 0x324a |
| 00b5 | JUMPI | |
| 00b6 | DUP1 | |
| 00b7 | PUSH4 | 0x32596d71 |
| 00bc | EQ | |
| 00bd | PUSH2 | 0x322d |
| 00c0 | JUMPI | |
| 00c1 | DUP1 | |
| 00c2 | PUSH4 | 0x342f6163 |
| 00c7 | EQ | |
| 00c8 | PUSH2 | 0x31bb |
| 00cb | JUMPI | |
| 00cc | DUP1 | |
| 00cd | PUSH4 | 0x45e7e88e |
| 00d2 | EQ | |
| 00d3 | PUSH2 | 0x3172 |
| 00d6 | JUMPI | |
| 00d7 | DUP1 | |
| 00d8 | PUSH4 | 0x461de6c1 |
| 00dd | EQ | |
| 00de | PUSH2 | 0x3138 |
| 00e1 | JUMPI | |
| 00e2 | DUP1 | |
| 00e3 | PUSH4 | 0x488429d9 |
| 00e8 | EQ | |
| 00e9 | PUSH2 | 0x30fe |
| 00ec | JUMPI | |
| 00ed | DUP1 | |
| 00ee | PUSH4 | 0x4c4af1a4 |
| 00f3 | EQ | |
| 00f4 | PUSH2 | 0x2d6d |
| 00f7 | JUMPI | |
| 00f8 | DUP1 | |
| 00f9 | PUSH4 | 0x4ccf0005 |
| 00fe | EQ | |
| 00ff | PUSH2 | 0x2cd4 |
| 0102 | JUMPI | |
| 0103 | DUP1 | |
| 0104 | PUSH4 | 0x4f8d3216 |
| 0109 | EQ | |
| 010a | PUSH2 | 0x2c60 |
| 010d | JUMPI | |
| 010e | DUP1 | |
| 010f | PUSH4 | 0x5a232a39 |
| 0114 | EQ | |
| 0115 | PUSH2 | 0x2c26 |
| 0118 | JUMPI | |
| 0119 | DUP1 | |
| 011a | PUSH4 | 0x5b882501 |
| 011f | EQ | |
| 0120 | PUSH2 | 0x2af7 |
| 0123 | JUMPI | |
| 0124 | DUP1 | |
| 0125 | PUSH4 | 0x5c97f4a2 |
| 012a | EQ | |
| 012b | PUSH2 | 0x2ad0 |
| 012e | JUMPI | |
| 012f | DUP1 | |
| 0130 | PUSH4 | 0x61dbd452 |
| 0135 | EQ | |
| 0136 | PUSH2 | 0x2a96 |
| 0139 | JUMPI | |
| 013a | DUP1 | |
| 013b | PUSH4 | 0x64d2218d |
| 0140 | EQ | |
| 0141 | PUSH2 | 0x2a77 |
| 0144 | JUMPI | |
| 0145 | DUP1 | |
| 0146 | PUSH4 | 0x70f64f0a |
| 014b | EQ | |
| 014c | PUSH2 | 0x2a2c |
| 014f | JUMPI | |
| 0150 | DUP1 | |
| 0151 | PUSH4 | 0x77e223b0 |
| 0156 | EQ | |
| 0157 | PUSH2 | 0x2a11 |
| 015a | JUMPI | |
| 015b | DUP1 | |
| 015c | PUSH4 | 0x86731755 |
| 0161 | EQ | |
| 0162 | PUSH2 | 0x29d7 |
| 0165 | JUMPI | |
| 0166 | DUP1 | |
| 0167 | PUSH4 | 0x8c6820a9 |
| 016c | EQ | |
| 016d | PUSH2 | 0x1a74 |
| 0170 | JUMPI | |
| 0171 | DUP1 | |
| 0172 | PUSH4 | 0x8cfc6aa0 |
| 0177 | EQ | |
| 0178 | PUSH2 | 0x1a42 |
| 017b | JUMPI | |
| 017c | DUP1 | |
| 017d | PUSH4 | 0x90ecddbf |
| 0182 | EQ | |
| 0183 | PUSH2 | 0x1a01 |
| 0186 | JUMPI | |
| 0187 | DUP1 | |
| 0188 | PUSH4 | 0x926590d6 |
| 018d | EQ | |
| 018e | PUSH2 | 0x1932 |
| 0191 | JUMPI | |
| 0192 | DUP1 | |
| 0193 | PUSH4 | 0x94338765 |
| 0198 | EQ | |
| 0199 | PUSH2 | 0x18f0 |
| 019c | JUMPI | |
| 019d | DUP1 | |
| 019e | PUSH4 | 0x9aae87ad |
| 01a3 | EQ | |
| 01a4 | PUSH2 | 0x18b6 |
| 01a7 | JUMPI | |
| 01a8 | DUP1 | |
| 01a9 | PUSH4 | 0x9c11e31b |
| 01ae | EQ | |
| 01af | PUSH2 | 0x189b |
| 01b2 | JUMPI | |
| 01b3 | DUP1 | |
| 01b4 | PUSH4 | 0x9d07ae09 |
| 01b9 | EQ | |
| 01ba | PUSH2 | 0x1787 |
| 01bd | JUMPI | |
| 01be | DUP1 | |
| 01bf | PUSH4 | 0x9e5adaeb |
| 01c4 | EQ | |
| 01c5 | PUSH2 | 0x174f |
| 01c8 | JUMPI | |
| 01c9 | DUP1 | |
| 01ca | PUSH4 | 0x9f8a13d7 |
| 01cf | EQ | |
| 01d0 | PUSH2 | 0x1722 |
| 01d3 | JUMPI | |
| 01d4 | DUP1 | |
| 01d5 | PUSH4 | 0xa0c176c4 |
| 01da | EQ | |
| 01db | PUSH2 | 0x16fd |
| 01de | JUMPI | |
| 01df | DUP1 | |
| 01e0 | PUSH4 | 0xa760c295 |
| 01e5 | EQ | |
| 01e6 | PUSH2 | 0x16cb |
| 01e9 | JUMPI | |
| 01ea | DUP1 | |
| 01eb | PUSH4 | 0xa874eea5 |
| 01f0 | EQ | |
| 01f1 | PUSH2 | 0x16b0 |
| 01f4 | JUMPI | |
| 01f5 | DUP1 | |
| 01f6 | PUSH4 | 0xad20445d |
| 01fb | EQ | |
| 01fc | PUSH2 | 0x1696 |
| 01ff | JUMPI | |
| 0200 | DUP1 | |
| 0201 | PUSH4 | 0xad84ad13 |
| 0206 | EQ | |
| 0207 | PUSH2 | 0x165e |
| 020a | JUMPI | |
| 020b | DUP1 | |
| 020c | PUSH4 | 0xb0538d5a |
| 0211 | EQ | |
| 0212 | PUSH2 | 0x1643 |
| 0215 | JUMPI | |
| 0216 | DUP1 | |
| 0217 | PUSH4 | 0xb16abc6c |
| 021c | EQ | |
| 021d | PUSH2 | 0x160b |
| 0220 | JUMPI | |
| 0221 | DUP1 | |
| 0222 | PUSH4 | 0xb3c26283 |
| 0227 | EQ | |
| 0228 | PUSH2 | 0x15aa |
| 022b | JUMPI | |
| 022c | DUP1 | |
| 022d | PUSH4 | 0xb7af85d7 |
| 0232 | EQ | |
| 0233 | PUSH2 | 0x155a |
| 0236 | JUMPI | |
| 0237 | DUP1 | |
| 0238 | PUSH4 | 0xbaadbb32 |
| 023d | EQ | |
| 023e | PUSH2 | 0x1520 |
| 0241 | JUMPI | |
| 0242 | DUP1 | |
| 0243 | PUSH4 | 0xc0716729 |
| 0248 | EQ | |
| 0249 | PUSH2 | 0x1504 |
| 024c | JUMPI | |
| 024d | DUP1 | |
| 024e | PUSH4 | 0xc177a97e |
| 0253 | EQ | |
| 0254 | PUSH2 | 0x14e1 |
| 0257 | JUMPI | |
| 0258 | DUP1 | |
| 0259 | PUSH4 | 0xc5768fe4 |
| 025e | EQ | |
| 025f | PUSH2 | 0x14b9 |
| 0262 | JUMPI | |
| 0263 | DUP1 | |
| 0264 | PUSH4 | 0xc6345626 |
| 0269 | EQ | |
| 026a | PUSH2 | 0x12f6 |
| 026d | JUMPI | |
| 026e | DUP1 | |
| 026f | PUSH4 | 0xcbe6ebb4 |
| 0274 | EQ | |
| 0275 | PUSH2 | 0x0672 |
| 0278 | JUMPI | |
| 0279 | DUP1 | |
| 027a | PUSH4 | 0xce092d1c |
| 027f | EQ | |
| 0280 | PUSH2 | 0x0655 |
| 0283 | JUMPI | |
| 0284 | DUP1 | |
| 0285 | PUSH4 | 0xde043e95 |
| 028a | EQ | |
| 028b | PUSH2 | 0x061a |
| 028e | JUMPI | |
| 028f | DUP1 | |
| 0290 | PUSH4 | 0xe0cd096a |
| 0295 | EQ | |
| 0296 | PUSH2 | 0x05ee |
| 0299 | JUMPI | |
| 029a | DUP1 | |
| 029b | PUSH4 | 0xe14c465b |
| 02a0 | EQ | |
| 02a1 | PUSH2 | 0x05d1 |
| 02a4 | JUMPI | |
| 02a5 | DUP1 | |
| 02a6 | PUSH4 | 0xe4af29fc |
| 02ab | EQ | |
| 02ac | PUSH2 | 0x05b3 |
| 02af | JUMPI | |
| 02b0 | DUP1 | |
| 02b1 | PUSH4 | 0xe51442e3 |
| 02b6 | EQ | |
| 02b7 | PUSH2 | 0x057b |
| 02ba | JUMPI | |
| 02bb | DUP1 | |
| 02bc | PUSH4 | 0xec964baa |
| 02c1 | EQ | |
| 02c2 | PUSH2 | 0x04b0 |
| 02c5 | JUMPI | |
| 02c6 | DUP1 | |
| 02c7 | PUSH4 | 0xef23f9f8 |
| 02cc | EQ | |
| 02cd | PUSH2 | 0x046f |
| 02d0 | JUMPI | |
| 02d1 | DUP1 | |
| 02d2 | PUSH4 | 0xf5778b03 |
| 02d7 | EQ | |
| 02d8 | PUSH2 | 0x0446 |
| 02db | JUMPI | |
| 02dc | DUP1 | |
| 02dd | PUSH4 | 0xfce072f8 |
| 02e2 | EQ | |
| 02e3 | PUSH2 | 0x03e9 |
| 02e6 | JUMPI | |
| 02e7 | PUSH4 | 0xffd326f3 |
| 02ec | EQ | |
| 02ed | PUSH2 | 0x02f4 |
| 02f0 | JUMPI | |
| 02f1 | PUSH0 | |
| 02f2 | DUP1 | |
| 02f3 | REVERT | |
| 02f4 | JUMPDEST | |
| 02f5 | CALLVALUE | |
| 02f6 | PUSH2 | 0x03e6 |
| 02f9 | JUMPI | |
| 02fa | PUSH1 | 0x40 |
| 02fc | CALLDATASIZE | |
| 02fd | PUSH1 | 0x03 |
| 02ff | NOT | |
| 0300 | ADD | |
| 0301 | SLT | |
| 0302 | PUSH2 | 0x03e6 |
| 0305 | JUMPI | |
| 0306 | PUSH1 | 0x01 |
| 0308 | PUSH1 | 0x01 |
| 030a | PUSH1 | 0x40 |
| 030c | SHL | |
| 030d | SUB | |
| 030e | PUSH1 | 0x40 |
| 0310 | PUSH2 | 0x0317 |
| 0313 | PUSH2 | 0x3bfa |
| 0316 | JUMP | |
| 0317 | JUMPDEST | |
| 0318 | SWAP3 | |
| 0319 | PUSH2 | 0x0320 |
| 031c | PUSH2 | 0x3b30 |
| 031f | JUMP | |
| 0320 | JUMPDEST | |
| 0321 | SWAP4 | |
| 0322 | DUP2 | |
| 0323 | PUSH1 | 0x80 |
| 0325 | DUP5 | |
| 0326 | MLOAD | |
| 0327 | PUSH2 | 0x032f |
| 032a | DUP2 | |
| 032b | PUSH2 | 0x3c61 |
| 032e | JUMP | |
| 032f | JUMPDEST | |
| 0330 | DUP3 | |
| 0331 | DUP2 | |
| 0332 | MSTORE | |
| 0333 | DUP3 | |
| 0334 | PUSH1 | 0x20 |
| 0336 | DUP3 | |
| 0337 | ADD | |
| 0338 | MSTORE | |
| 0339 | DUP3 | |
| 033a | DUP7 | |
| 033b | DUP3 | |
| 033c | ADD | |
| 033d | MSTORE | |
| 033e | DUP3 | |
| 033f | PUSH1 | 0x60 |
| 0341 | DUP3 | |
| 0342 | ADD | |
| 0343 | MSTORE | |
| 0344 | ADD | |
| 0345 | MSTORE | |
| 0346 | PUSH1 | 0x01 |
| 0348 | DUP1 | |
| 0349 | PUSH1 | 0xa0 |
| 034b | SHL | |
| 034c | SUB | |
| 034d | AND | |
| 034e | DUP2 | |
| 034f | MSTORE | |
| 0350 | DUP1 | |
| 0351 | PUSH1 | 0x20 |
| 0353 | MSTORE | |
| 0354 | KECCAK256 | |
| 0355 | SWAP2 | |
| 0356 | AND | |
| 0357 | PUSH0 | |
| 0358 | MSTORE | |
| 0359 | PUSH1 | 0x20 |
| 035b | MSTORE | |
| 035c | PUSH1 | 0xa0 |
| 035e | PUSH1 | 0x40 |
| 0360 | PUSH0 | |
| 0361 | KECCAK256 | |
| 0362 | PUSH1 | 0x40 |
| 0364 | MLOAD | |
| 0365 | PUSH2 | 0x036d |
| 0368 | DUP2 | |
| 0369 | PUSH2 | 0x3c61 |
| 036c | JUMP | |
| 036d | JUMPDEST | |
| 036e | PUSH1 | 0x01 |
| 0370 | PUSH1 | 0x01 |
| 0372 | PUSH1 | 0x40 |
| 0374 | SHL | |
| 0375 | SUB | |
| 0376 | DUP3 | |
| 0377 | SLOAD | |
| 0378 | SWAP2 | |
| 0379 | PUSH1 | 0x01 |
| 037b | PUSH1 | 0x01 |
| 037d | PUSH1 | 0x80 |
| 037f | SHL | |
| 0380 | SUB | |
| 0381 | NOT | |
| 0382 | DUP4 | |
| 0383 | PUSH1 | 0x80 |
| 0385 | SHL | |
| 0386 | AND | |
| 0387 | SWAP4 | |
| 0388 | DUP5 | |
| 0389 | DUP3 | |
| 038a | MSTORE | |
| 038b | PUSH1 | 0xff |
| 038d | PUSH1 | 0x20 |
| 038f | DUP4 | |
| 0390 | ADD | |
| 0391 | SWAP5 | |
| 0392 | PUSH1 | 0x80 |
| 0394 | SHR | |
| 0395 | AND | |
| 0396 | DUP5 | |
| 0397 | MSTORE | |
| 0398 | PUSH1 | 0xff |
| 039a | PUSH1 | 0x02 |
| 039c | PUSH1 | 0x01 |
| 039e | DUP4 | |
| 039f | ADD | |
| 03a0 | SLOAD | |
| 03a1 | SWAP3 | |
| 03a2 | PUSH1 | 0x40 |
| 03a4 | DUP6 | |
| 03a5 | ADD | |
| 03a6 | SWAP4 | |
| 03a7 | DUP5 | |
| 03a8 | MSTORE | |
| 03a9 | ADD | |
| 03aa | SLOAD | |
| 03ab | SWAP5 | |
| 03ac | DUP2 | |
| 03ad | PUSH1 | 0x80 |
| 03af | PUSH1 | 0x60 |
| 03b1 | DUP7 | |
| 03b2 | ADD | |
| 03b3 | SWAP6 | |
| 03b4 | DUP8 | |
| 03b5 | DUP10 | |
| 03b6 | AND | |
| 03b7 | DUP8 | |
| 03b8 | MSTORE | |
| 03b9 | ADD | |
| 03ba | SWAP7 | |
| 03bb | PUSH1 | 0x40 |
| 03bd | SHR | |
| 03be | AND | |
| 03bf | ISZERO | |
| 03c0 | ISZERO | |
| 03c1 | DUP7 | |
| 03c2 | MSTORE | |
| 03c3 | PUSH1 | 0x40 |
| 03c5 | MLOAD | |
| 03c6 | SWAP7 | |
| 03c7 | DUP8 | |
| 03c8 | MSTORE | |
| 03c9 | MLOAD | |
| 03ca | AND | |
| 03cb | PUSH1 | 0x20 |
| 03cd | DUP7 | |
| 03ce | ADD | |
| 03cf | MSTORE | |
| 03d0 | MLOAD | |
| 03d1 | PUSH1 | 0x40 |
| 03d3 | DUP6 | |
| 03d4 | ADD | |
| 03d5 | MSTORE | |
| 03d6 | MLOAD | |
| 03d7 | AND | |
| 03d8 | PUSH1 | 0x60 |
| 03da | DUP4 | |
| 03db | ADD | |
| 03dc | MSTORE | |
| 03dd | MLOAD | |
| 03de | ISZERO | |
| 03df | ISZERO | |
| 03e0 | PUSH1 | 0x80 |
| 03e2 | DUP3 | |
| 03e3 | ADD | |
| 03e4 | MSTORE | |
| 03e5 | RETURN | |
| 03e6 | JUMPDEST | |
| 03e7 | DUP1 | |
| 03e8 | REVERT | |
| 03e9 | JUMPDEST | |
| 03ea | POP | |
| 03eb | CALLVALUE | |
| 03ec | PUSH2 | 0x03e6 |
| 03ef | JUMPI | |
| 03f0 | PUSH1 | 0x20 |
| 03f2 | CALLDATASIZE | |
| 03f3 | PUSH1 | 0x03 |
| 03f5 | NOT | |
| 03f6 | ADD | |
| 03f7 | SLT | |
| 03f8 | PUSH2 | 0x03e6 |
| 03fb | JUMPI | |
| 03fc | PUSH1 | 0x04 |
| 03fe | CALLDATALOAD | |
| 03ff | SWAP1 | |
| 0400 | PUSH1 | 0x01 |
| 0402 | PUSH1 | 0x01 |
| 0404 | PUSH1 | 0x40 |
| 0406 | SHL | |
| 0407 | SUB | |
| 0408 | DUP3 | |
| 0409 | GT | |
| 040a | PUSH2 | 0x03e6 |
| 040d | JUMPI | |
| 040e | CALLDATASIZE | |
| 040f | PUSH1 | 0x23 |
| 0411 | DUP4 | |
| 0412 | ADD | |
| 0413 | SLT | |
| 0414 | ISZERO | |
| 0415 | PUSH2 | 0x03e6 |
| 0418 | JUMPI | |
| 0419 | PUSH1 | 0x20 |
| 041b | PUSH2 | 0x0434 |
| 041e | PUSH2 | 0x042f |
| 0421 | CALLDATASIZE | |
| 0422 | PUSH1 | 0x04 |
| 0424 | DUP7 | |
| 0425 | ADD | |
| 0426 | CALLDATALOAD | |
| 0427 | PUSH1 | 0x24 |
| 0429 | DUP8 | |
| 042a | ADD | |
| 042b | PUSH2 | 0x3cd4 |
| 042e | JUMP | |
| 042f | JUMPDEST | |
| 0430 | PUSH2 | 0x4701 |
| 0433 | JUMP | |
| 0434 | JUMPDEST | |
| 0435 | PUSH1 | 0x40 |
| 0437 | MLOAD | |
| 0438 | PUSH1 | 0x01 |
| 043a | PUSH1 | 0x01 |
| 043c | PUSH1 | 0xa0 |
| 043e | SHL | |
| 043f | SUB | |
| 0440 | SWAP1 | |
| 0441 | SWAP2 | |
| 0442 | AND | |
| 0443 | DUP2 | |
| 0444 | MSTORE | |
| 0445 | RETURN | |
| 0446 | JUMPDEST | |
| 0447 | POP | |
| 0448 | CALLVALUE | |
| 0449 | PUSH2 | 0x03e6 |
| 044c | JUMPI | |
| 044d | DUP1 | |
| 044e | PUSH1 | 0x03 |
| 0450 | NOT | |
| 0451 | CALLDATASIZE | |
| 0452 | ADD | |
| 0453 | SLT | |
| 0454 | PUSH2 | 0x03e6 |
| 0457 | JUMPI | |
| 0458 | PUSH1 | 0x10 |
| 045a | SLOAD | |
| 045b | PUSH1 | 0x40 |
| 045d | MLOAD | |
| 045e | PUSH1 | 0x01 |
| 0460 | PUSH1 | 0x01 |
| 0462 | PUSH1 | 0xa0 |
| 0464 | SHL | |
| 0465 | SUB | |
| 0466 | SWAP1 | |
| 0467 | SWAP2 | |
| 0468 | AND | |
| 0469 | DUP2 | |
| 046a | MSTORE | |
| 046b | PUSH1 | 0x20 |
| 046d | SWAP1 | |
| 046e | RETURN | |
| 046f | JUMPDEST | |
| 0470 | POP | |
| 0471 | CALLVALUE | |
| 0472 | PUSH2 | 0x03e6 |
| 0475 | JUMPI | |
| 0476 | PUSH1 | 0x20 |
| 0478 | CALLDATASIZE | |
| 0479 | PUSH1 | 0x03 |
| 047b | NOT | |
| 047c | ADD | |
| 047d | SLT | |
| 047e | PUSH2 | 0x03e6 |
| 0481 | JUMPI | |
| 0482 | PUSH1 | 0x20 |
| 0484 | SWAP1 | |
| 0485 | PUSH1 | 0x01 |
| 0487 | PUSH1 | 0x01 |
| 0489 | PUSH1 | 0xa0 |
| 048b | SHL | |
| 048c | SUB | |
| 048d | PUSH2 | 0x0494 |
| 0490 | PUSH2 | 0x3bfa |
| 0493 | JUMP | |
| 0494 | JUMPDEST | |
| 0495 | AND | |
| 0496 | DUP2 | |
| 0497 | MSTORE | |
| 0498 | PUSH1 | 0x15 |
| 049a | DUP3 | |
| 049b | MSTORE | |
| 049c | PUSH1 | 0x40 |
| 049e | PUSH1 | 0x01 |
| 04a0 | DUP1 | |
| 04a1 | PUSH1 | 0xa0 |
| 04a3 | SHL | |
| 04a4 | SUB | |
| 04a5 | SWAP2 | |
| 04a6 | KECCAK256 | |
| 04a7 | SLOAD | |
| 04a8 | AND | |
| 04a9 | PUSH1 | 0x40 |
| 04ab | MLOAD | |
| 04ac | SWAP1 | |
| 04ad | DUP2 | |
| 04ae | MSTORE | |
| 04af | RETURN | |
| 04b0 | JUMPDEST | |
| 04b1 | POP | |
| 04b2 | CALLVALUE | |
| 04b3 | PUSH2 | 0x03e6 |
| 04b6 | JUMPI | |
| 04b7 | DUP1 | |
| 04b8 | PUSH1 | 0x03 |
| 04ba | NOT | |
| 04bb | CALLDATASIZE | |
| 04bc | ADD | |
| 04bd | SLT | |
| 04be | PUSH2 | 0x03e6 |
| 04c1 | JUMPI | |
| 04c2 | PUSH1 | 0x10 |
| 04c4 | SLOAD | |
| 04c5 | PUSH1 | 0x01 |
| 04c7 | PUSH1 | 0x01 |
| 04c9 | PUSH1 | 0xa0 |
| 04cb | SHL | |
| 04cc | SUB | |
| 04cd | DUP2 | |
| 04ce | AND | |
| 04cf | CALLER | |
| 04d0 | SUB | |
| 04d1 | PUSH2 | 0x0568 |
| 04d4 | JUMPI | |
| 04d5 | PUSH1 | 0xff |
| 04d7 | DUP2 | |
| 04d8 | PUSH1 | 0xa0 |
| 04da | SHR | |
| 04db | AND | |
| 04dc | PUSH2 | 0x0559 |
| 04df | JUMPI | |
| 04e0 | PUSH1 | 0x13 |
| 04e2 | SLOAD | |
| 04e3 | DUP1 | |
| 04e4 | ISZERO | |
| 04e5 | PUSH2 | 0x054a |
| 04e8 | JUMPI | |
| 04e9 | PUSH2 | 0x04f0 |
| 04ec | PUSH2 | 0x3f57 |
| 04ef | JUMP | |
| 04f0 | JUMPDEST | |
| 04f1 | DUP2 | |
| 04f2 | DUP2 | |
| 04f3 | LT | |
| 04f4 | PUSH2 | 0x0534 |
| 04f7 | JUMPI | |
| 04f8 | POP | |
| 04f9 | POP | |
| 04fa | PUSH1 | 0x01 |
| 04fc | PUSH1 | 0x01 |
| 04fe | PUSH1 | 0xa8 |
| 0500 | SHL | |
| 0501 | SUB | |
| 0502 | NOT | |
| 0503 | AND | |
| 0504 | PUSH1 | 0x01 |
| 0506 | PUSH1 | 0xa0 |
| 0508 | SHL | |
| 0509 | OR | |
| 050a | PUSH1 | 0x10 |
| 050c | SSTORE | |
| 050d | CALLER | |
| 050e | PUSH32 | 0xdd5280e26bdef754c085fd1fe40c0ab76df98368bb6014f85b49f8852a81be57 |
| 052f | DUP3 | |
| 0530 | DUP1 | |
| 0531 | LOG2 | |
| 0532 | DUP1 | |
| 0533 | RETURN | |
| 0534 | JUMPDEST | |
| 0535 | PUSH4 | 0x04951c21 |
| 053a | PUSH1 | 0xe1 |
| 053c | SHL | |
| 053d | DUP5 | |
| 053e | MSTORE | |
| 053f | PUSH1 | 0x04 |
| 0541 | MSTORE | |
| 0542 | PUSH1 | 0x24 |
| 0544 | MSTORE | |
| 0545 | POP | |
| 0546 | PUSH1 | 0x44 |
| 0548 | SWAP1 | |
| 0549 | REVERT | |
| 054a | JUMPDEST | |
| 054b | PUSH4 | 0x1de31ea5 |
| 0550 | PUSH1 | 0xe1 |
| 0552 | SHL | |
| 0553 | DUP4 | |
| 0554 | MSTORE | |
| 0555 | PUSH1 | 0x04 |
| 0557 | DUP4 | |
| 0558 | REVERT | |
| 0559 | JUMPDEST | |
| 055a | PUSH4 | 0x0f80bc05 |
| 055f | PUSH1 | 0xe3 |
| 0561 | SHL | |
| 0562 | DUP3 | |
| 0563 | MSTORE | |
| 0564 | PUSH1 | 0x04 |
| 0566 | DUP3 | |
| 0567 | REVERT | |
| 0568 | JUMPDEST | |
| 0569 | PUSH4 | 0x4a0bfec1 |
| 056e | PUSH1 | 0xe0 |
| 0570 | SHL | |
| 0571 | DUP3 | |
| 0572 | MSTORE | |
| 0573 | CALLER | |
| 0574 | PUSH1 | 0x04 |
| 0576 | MSTORE | |
| 0577 | PUSH1 | 0x24 |
| 0579 | DUP3 | |
| 057a | REVERT | |
| 057b | JUMPDEST | |
| 057c | POP | |
| 057d | CALLVALUE | |
| 057e | PUSH2 | 0x03e6 |
| 0581 | JUMPI | |
| 0582 | PUSH1 | 0x20 |
| 0584 | CALLDATASIZE | |
| 0585 | PUSH1 | 0x03 |
| 0587 | NOT | |
| 0588 | ADD | |
| 0589 | SLT | |
| 058a | PUSH2 | 0x03e6 |
| 058d | JUMPI | |
| 058e | PUSH1 | 0x20 |
| 0590 | PUSH2 | 0x059a |
| 0593 | PUSH1 | 0x04 |
| 0595 | CALLDATALOAD | |
| 0596 | PUSH2 | 0x3d53 |
| 0599 | JUMP | |
| 059a | JUMPDEST | |
| 059b | SWAP1 | |
| 059c | SLOAD | |
| 059d | PUSH1 | 0x40 |
| 059f | MLOAD | |
| 05a0 | PUSH1 | 0x03 |
| 05a2 | SWAP3 | |
| 05a3 | SWAP1 | |
| 05a4 | SWAP3 | |
| 05a5 | SHL | |
| 05a6 | SHR | |
| 05a7 | PUSH1 | 0x01 |
| 05a9 | PUSH1 | 0x01 |
| 05ab | PUSH1 | 0xa0 |
| 05ad | SHL | |
| 05ae | SUB | |
| 05af | AND | |
| 05b0 | DUP2 | |
| 05b1 | MSTORE | |
| 05b2 | RETURN | |
| 05b3 | JUMPDEST | |
| 05b4 | POP | |
| 05b5 | CALLVALUE | |
| 05b6 | PUSH2 | 0x03e6 |
| 05b9 | JUMPI | |
| 05ba | DUP1 | |
| 05bb | PUSH1 | 0x03 |
| 05bd | NOT | |
| 05be | CALLDATASIZE | |
| 05bf | ADD | |
| 05c0 | SLT | |
| 05c1 | PUSH2 | 0x03e6 |
| 05c4 | JUMPI | |
| 05c5 | PUSH1 | 0x20 |
| 05c7 | PUSH1 | 0x0f |
| 05c9 | SLOAD | |
| 05ca | PUSH1 | 0x40 |
| 05cc | MLOAD | |
| 05cd | SWAP1 | |
| 05ce | DUP2 | |
| 05cf | MSTORE | |
| 05d0 | RETURN | |
| 05d1 | JUMPDEST | |
| 05d2 | POP | |
| 05d3 | CALLVALUE | |
| 05d4 | PUSH2 | 0x03e6 |
| 05d7 | JUMPI | |
| 05d8 | DUP1 | |
| 05d9 | PUSH1 | 0x03 |
| 05db | NOT | |
| 05dc | CALLDATASIZE | |
| 05dd | ADD | |
| 05de | SLT | |
| 05df | PUSH2 | 0x03e6 |
| 05e2 | JUMPI | |
| 05e3 | PUSH1 | 0x20 |
| 05e5 | PUSH1 | 0x40 |
| 05e7 | MLOAD | |
| 05e8 | PUSH2 | 0x0100 |
| 05eb | DUP2 | |
| 05ec | MSTORE | |
| 05ed | RETURN | |
| 05ee | JUMPDEST | |
| 05ef | POP | |
| 05f0 | CALLVALUE | |
| 05f1 | PUSH2 | 0x03e6 |
| 05f4 | JUMPI | |
| 05f5 | PUSH1 | 0x20 |
| 05f7 | CALLDATASIZE | |
| 05f8 | PUSH1 | 0x03 |
| 05fa | NOT | |
| 05fb | ADD | |
| 05fc | SLT | |
| 05fd | PUSH2 | 0x03e6 |
| 0600 | JUMPI | |
| 0601 | PUSH1 | 0x20 |
| 0603 | PUSH2 | 0x0612 |
| 0606 | PUSH2 | 0x060d |
| 0609 | PUSH2 | 0x3bfa |
| 060c | JUMP | |
| 060d | JUMPDEST | |
| 060e | PUSH2 | 0x44a9 |
| 0611 | JUMP | |
| 0612 | JUMPDEST | |
| 0613 | PUSH1 | 0x40 |
| 0615 | MLOAD | |
| 0616 | SWAP1 | |
| 0617 | DUP2 | |
| 0618 | MSTORE | |
| 0619 | RETURN | |
| 061a | JUMPDEST | |
| 061b | POP | |
| 061c | CALLVALUE | |
| 061d | PUSH2 | 0x03e6 |
| 0620 | JUMPI | |
| 0621 | DUP1 | |
| 0622 | PUSH1 | 0x03 |
| 0624 | NOT | |
| 0625 | CALLDATASIZE | |
| 0626 | ADD | |
| 0627 | SLT | |
| 0628 | PUSH2 | 0x03e6 |
| 062b | JUMPI | |
| 062c | PUSH1 | 0x20 |
| 062e | PUSH1 | 0x40 |
| 0630 | MLOAD | |
| 0631 | PUSH32 | 0x664b0e72d3e91e88f8d9d2c0d916d51aff408110b8760394f6d677a5e6b24a2e |
| 0652 | DUP2 | |
| 0653 | MSTORE | |
| 0654 | RETURN | |
| 0655 | JUMPDEST | |
| 0656 | POP | |
| 0657 | CALLVALUE | |
| 0658 | PUSH2 | 0x03e6 |
| 065b | JUMPI | |
| 065c | DUP1 | |
| 065d | PUSH1 | 0x03 |
| 065f | NOT | |
| 0660 | CALLDATASIZE | |
| 0661 | ADD | |
| 0662 | SLT | |
| 0663 | PUSH2 | 0x03e6 |
| 0666 | JUMPI | |
| 0667 | PUSH1 | 0x20 |
| 0669 | PUSH1 | 0x40 |
| 066b | MLOAD | |
| 066c | PUSH2 | 0x0200 |
| 066f | DUP2 | |
| 0670 | MSTORE | |
| 0671 | RETURN | |
| 0672 | JUMPDEST | |
| 0673 | CALLVALUE | |
| 0674 | PUSH2 | 0x12f2 |
| 0677 | JUMPI | |
| 0678 | PUSH2 | 0x0100 |
| 067b | CALLDATASIZE | |
| 067c | PUSH1 | 0x03 |
| 067e | NOT | |
| 067f | ADD | |
| 0680 | SLT | |
| 0681 | PUSH2 | 0x12f2 |
| 0684 | JUMPI | |
| 0685 | PUSH2 | 0x068c |
| 0688 | PUSH2 | 0x3bfa |
| 068b | JUMP | |
| 068c | JUMPDEST | |
| 068d | PUSH1 | 0x24 |
| 068f | CALLDATALOAD | |
| 0690 | PUSH1 | 0x01 |
| 0692 | PUSH1 | 0x01 |
| 0694 | PUSH1 | 0x40 |
| 0696 | SHL | |
| 0697 | SUB | |
| 0698 | DUP2 | |
| 0699 | GT | |
| 069a | PUSH2 | 0x12f2 |
| 069d | JUMPI | |
| 069e | PUSH2 | 0x06ab |
| 06a1 | SWAP1 | |
| 06a2 | CALLDATASIZE | |
| 06a3 | SWAP1 | |
| 06a4 | PUSH1 | 0x04 |
| 06a6 | ADD | |
| 06a7 | PUSH2 | 0x3c34 |
| 06aa | JUMP | |
| 06ab | JUMPDEST | |
| 06ac | SWAP1 | |
| 06ad | SWAP2 | |
| 06ae | PUSH1 | 0x44 |
| 06b0 | CALLDATALOAD | |
| 06b1 | PUSH1 | 0x01 |
| 06b3 | PUSH1 | 0x01 |
| 06b5 | PUSH1 | 0x40 |
| 06b7 | SHL | |
| 06b8 | SUB | |
| 06b9 | DUP2 | |
| 06ba | GT | |
| 06bb | PUSH2 | 0x12f2 |
| 06be | JUMPI | |
| 06bf | PUSH2 | 0x06cc |
| 06c2 | SWAP1 | |
| 06c3 | CALLDATASIZE | |
| 06c4 | SWAP1 | |
| 06c5 | PUSH1 | 0x04 |
| 06c7 | ADD | |
| 06c8 | PUSH2 | 0x3c34 |
| 06cb | JUMP | |
| 06cc | JUMPDEST | |
| 06cd | PUSH1 | 0x64 |
| 06cf | SWAP3 | |
| 06d0 | SWAP2 | |
| 06d1 | SWAP3 | |
| 06d2 | CALLDATALOAD | |
| 06d3 | SWAP4 | |
| 06d4 | PUSH1 | 0x01 |
| 06d6 | PUSH1 | 0x01 |
| 06d8 | PUSH1 | 0x40 |
| 06da | SHL | |
| 06db | SUB | |
| 06dc | DUP6 | |
| 06dd | GT | |
| 06de | PUSH2 | 0x12f2 |
| 06e1 | JUMPI | |
| 06e2 | DUP5 | |
| 06e3 | PUSH1 | 0x04 |
| 06e5 | ADD | |
| 06e6 | SWAP4 | |
| 06e7 | PUSH1 | 0x40 |
| 06e9 | PUSH1 | 0x03 |
| 06eb | NOT | |
| 06ec | DUP8 | |
| 06ed | CALLDATASIZE | |
| 06ee | SUB | |
| 06ef | ADD | |
| 06f0 | SLT | |
| 06f1 | PUSH2 | 0x12f2 |
| 06f4 | JUMPI | |
| 06f5 | PUSH1 | 0x84 |
| 06f7 | CALLDATALOAD | |
| 06f8 | SWAP6 | |
| 06f9 | PUSH2 | 0x0700 |
| 06fc | PUSH2 | 0x3b5c |
| 06ff | JUMP | |
| 0700 | JUMPDEST | |
| 0701 | SWAP6 | |
| 0702 | PUSH2 | 0x0709 |
| 0705 | PUSH2 | 0x3b72 |
| 0708 | JUMP | |
| 0709 | JUMPDEST | |
| 070a | SWAP4 | |
| 070b | PUSH1 | 0xe4 |
| 070d | CALLDATALOAD | |
| 070e | SWAP6 | |
| 070f | PUSH1 | 0x01 |
| 0711 | PUSH1 | 0x01 |
| 0713 | PUSH1 | 0x40 |
| 0715 | SHL | |
| 0716 | SUB | |
| 0717 | DUP8 | |
| 0718 | GT | |
| 0719 | PUSH2 | 0x12f2 |
| 071c | JUMPI | |
| 071d | DUP10 | |
| 071e | SWAP7 | |
| 071f | PUSH2 | 0x072c |
| 0722 | SWAP1 | |
| 0723 | CALLDATASIZE | |
| 0724 | SWAP1 | |
| 0725 | PUSH1 | 0x04 |
| 0727 | ADD | |
| 0728 | PUSH2 | 0x3b88 |
| 072b | JUMP | |
| 072c | JUMPDEST | |
| 072d | SWAP3 | |
| 072e | SWAP1 | |
| 072f | SWAP7 | |
| 0730 | ADDRESS | |
| 0731 | PUSH0 | |
| 0732 | MSTORE | |
| 0733 | PUSH1 | 0x14 |
| 0735 | PUSH1 | 0x20 |
| 0737 | MSTORE | |
| 0738 | PUSH1 | 0x40 |
| 073a | PUSH0 | |
| 073b | KECCAK256 | |
| 073c | SLOAD | |
| 073d | PUSH1 | 0x01 |
| 073f | PUSH1 | 0x01 |
| 0741 | PUSH1 | 0x40 |
| 0743 | SHL | |
| 0744 | SUB | |
| 0745 | AND | |
| 0746 | SWAP4 | |
| 0747 | DUP14 | |
| 0748 | DUP4 | |
| 0749 | CALLDATASIZE | |
| 074a | SWAP1 | |
| 074b | PUSH2 | 0x0753 |
| 074e | SWAP3 | |
| 074f | PUSH2 | 0x3cd4 |
| 0752 | JUMP | |
| 0753 | JUMPDEST | |
| 0754 | DUP1 | |
| 0755 | MLOAD | |
| 0756 | SWAP1 | |
| 0757 | PUSH1 | 0x20 |
| 0759 | ADD | |
| 075a | KECCAK256 | |
| 075b | SWAP9 | |
| 075c | DUP12 | |
| 075d | DUP14 | |
| 075e | CALLDATASIZE | |
| 075f | PUSH2 | 0x0769 |
| 0762 | SWAP1 | |
| 0763 | DUP9 | |
| 0764 | DUP14 | |
| 0765 | PUSH2 | 0x3cd4 |
| 0768 | JUMP | |
| 0769 | JUMPDEST | |
| 076a | DUP1 | |
| 076b | MLOAD | |
| 076c | SWAP1 | |
| 076d | PUSH1 | 0x20 |
| 076f | ADD | |
| 0770 | KECCAK256 | |
| 0771 | SWAP13 | |
| 0772 | PUSH1 | 0x40 |
| 0774 | MLOAD | |
| 0775 | DUP1 | |
| 0776 | SWAP15 | |
| 0777 | PUSH1 | 0x20 |
| 0779 | DUP3 | |
| 077a | ADD | |
| 077b | SWAP5 | |
| 077c | PUSH1 | 0x01 |
| 077e | PUSH1 | 0xa0 |
| 0780 | SHL | |
| 0781 | PUSH1 | 0x01 |
| 0783 | SWAP1 | |
| 0784 | SUB | |
| 0785 | AND | |
| 0786 | SWAP15 | |
| 0787 | DUP16 | |
| 0788 | DUP7 | |
| 0789 | MSTORE | |
| 078a | PUSH1 | 0x40 |
| 078c | DUP4 | |
| 078d | ADD | |
| 078e | MSTORE | |
| 078f | PUSH1 | 0x60 |
| 0791 | DUP3 | |
| 0792 | ADD | |
| 0793 | MSTORE | |
| 0794 | PUSH1 | 0x80 |
| 0796 | ADD | |
| 0797 | MSTORE | |
| 0798 | PUSH1 | 0x01 |
| 079a | PUSH1 | 0x01 |
| 079c | PUSH1 | 0x40 |
| 079e | SHL | |
| 079f | SUB | |
| 07a0 | AND | |
| 07a1 | SWAP12 | |
| 07a2 | DUP13 | |
| 07a3 | PUSH1 | 0xa0 |
| 07a5 | DUP3 | |
| 07a6 | ADD | |
| 07a7 | MSTORE | |
| 07a8 | PUSH1 | 0xa0 |
| 07aa | DUP2 | |
| 07ab | MSTORE | |
| 07ac | PUSH2 | 0x07b6 |
| 07af | PUSH1 | 0xc0 |
| 07b1 | DUP3 | |
| 07b2 | PUSH2 | 0x3c98 |
| 07b5 | JUMP | |
| 07b6 | JUMPDEST | |
| 07b7 | MLOAD | |
| 07b8 | SWAP1 | |
| 07b9 | KECCAK256 | |
| 07ba | SWAP3 | |
| 07bb | PUSH2 | 0x07c3 |
| 07be | SWAP4 | |
| 07bf | PUSH2 | 0x495e |
| 07c2 | JUMP | |
| 07c3 | JUMPDEST | |
| 07c4 | PUSH20 | 0x83d50624b34718978a0f118a95f7c6b6c9008c47 |
| 07d9 | DUP1 | |
| 07da | SWAP2 | |
| 07db | PUSH1 | 0x40 |
| 07dd | MLOAD | |
| 07de | DUP1 | |
| 07df | SWAP15 | |
| 07e0 | DUP2 | |
| 07e1 | SWAP3 | |
| 07e2 | PUSH4 | 0x25f1701d |
| 07e7 | PUSH1 | 0xe2 |
| 07e9 | SHL | |
| 07ea | DUP4 | |
| 07eb | MSTORE | |
| 07ec | PUSH1 | 0x04 |
| 07ee | DUP4 | |
| 07ef | ADD | |
| 07f0 | SWAP2 | |
| 07f1 | PUSH2 | 0x07f9 |
| 07f4 | SWAP3 | |
| 07f5 | PUSH2 | 0x4303 |
| 07f8 | JUMP | |
| 07f9 | JUMPDEST | |
| 07fa | SUB | |
| 07fb | DUP2 | |
| 07fc | GAS | |
| 07fd | SWAP4 | |
| 07fe | PUSH0 | |
| 07ff | SWAP5 | |
| 0800 | DELEGATECALL | |
| 0801 | SWAP6 | |
| 0802 | DUP7 | |
| 0803 | ISZERO | |
| 0804 | PUSH2 | 0x12c5 |
| 0807 | JUMPI | |
| 0808 | PUSH2 | 0x0833 |
| 080b | SWAP13 | |
| 080c | PUSH0 | |
| 080d | SWAP8 | |
| 080e | PUSH2 | 0x12d0 |
| 0811 | JUMPI | |
| 0812 | JUMPDEST | |
| 0813 | POP | |
| 0814 | SWAP1 | |
| 0815 | PUSH0 | |
| 0816 | SWAP3 | |
| 0817 | SWAP2 | |
| 0818 | PUSH1 | 0x40 |
| 081a | MLOAD | |
| 081b | DUP1 | |
| 081c | SWAP15 | |
| 081d | DUP2 | |
| 081e | SWAP5 | |
| 081f | DUP3 | |
| 0820 | SWAP4 | |
| 0821 | PUSH4 | 0xb389b84f |
| 0826 | PUSH1 | 0xe0 |
| 0828 | SHL | |
| 0829 | DUP5 | |
| 082a | MSTORE | |
| 082b | PUSH1 | 0x04 |
| 082d | DUP5 | |
| 082e | ADD | |
| 082f | PUSH2 | 0x4303 |
| 0832 | JUMP | |
| 0833 | JUMPDEST | |
| 0834 | SUB | |
| 0835 | SWAP2 | |
| 0836 | GAS | |
| 0837 | DELEGATECALL | |
| 0838 | SWAP10 | |
| 0839 | DUP11 | |
| 083a | ISZERO | |
| 083b | PUSH2 | 0x12c5 |
| 083e | JUMPI | |
| 083f | PUSH0 | |
| 0840 | SWAP11 | |
| 0841 | PUSH2 | 0x12a1 |
| 0844 | JUMPI | |
| 0845 | JUMPDEST | |
| 0846 | POP | |
| 0847 | PUSH1 | 0x20 |
| 0849 | DUP5 | |
| 084a | ADD | |
| 084b | SWAP2 | |
| 084c | DUP3 | |
| 084d | MLOAD | |
| 084e | PUSH1 | 0x20 |
| 0850 | DUP13 | |
| 0851 | ADD | |
| 0852 | MLOAD | |
| 0853 | SWAP1 | |
| 0854 | DUP2 | |
| 0855 | DUP2 | |
| 0856 | SUB | |
| 0857 | PUSH2 | 0x128c |
| 085a | JUMPI | |
| 085b | POP | |
| 085c | POP | |
| 085d | PUSH2 | 0x0865 |
| 0860 | DUP6 | |
| 0861 | PUSH2 | 0x527f |
| 0864 | JUMP | |
| 0865 | JUMPDEST | |
| 0866 | PUSH2 | 0x086e |
| 0869 | DUP12 | |
| 086a | PUSH2 | 0x527f |
| 086d | JUMP | |
| 086e | JUMPDEST | |
| 086f | DUP11 | |
| 0870 | MLOAD | |
| 0871 | DUP6 | |
| 0872 | MLOAD | |
| 0873 | SWAP1 | |
| 0874 | PUSH1 | 0x40 |
| 0876 | MLOAD | |
| 0877 | SWAP1 | |
| 0878 | PUSH1 | 0x20 |
| 087a | DUP3 | |
| 087b | ADD | |
| 087c | SWAP3 | |
| 087d | PUSH32 | 0x6e3591285df1e4e62815fc41f5a94072fc4e3ab79993ede42c87f8995a9f8168 |
| 089e | DUP5 | |
| 089f | MSTORE | |
| 08a0 | CHAINID | |
| 08a1 | PUSH1 | 0x40 |
| 08a3 | DUP5 | |
| 08a4 | ADD | |
| 08a5 | MSTORE | |
| 08a6 | ADDRESS | |
| 08a7 | PUSH1 | 0x60 |
| 08a9 | DUP5 | |
| 08aa | ADD | |
| 08ab | MSTORE | |
| 08ac | PUSH1 | 0x80 |
| 08ae | DUP4 | |
| 08af | ADD | |
| 08b0 | MSTORE | |
| 08b1 | PUSH1 | 0xa0 |
| 08b3 | DUP3 | |
| 08b4 | ADD | |
| 08b5 | MSTORE | |
| 08b6 | DUP4 | |
| 08b7 | PUSH1 | 0xc0 |
| 08b9 | DUP3 | |
| 08ba | ADD | |
| 08bb | MSTORE | |
| 08bc | PUSH1 | 0xc0 |
| 08be | DUP2 | |
| 08bf | MSTORE | |
| 08c0 | PUSH2 | 0x08ca |
| 08c3 | PUSH1 | 0xe0 |
| 08c5 | DUP3 | |
| 08c6 | PUSH2 | 0x3c98 |
| 08c9 | JUMP | |
| 08ca | JUMPDEST | |
| 08cb | MLOAD | |
| 08cc | SWAP1 | |
| 08cd | KECCAK256 | |
| 08ce | SWAP4 | |
| 08cf | PUSH1 | 0x40 |
| 08d1 | MLOAD | |
| 08d2 | SWAP5 | |
| 08d3 | PUSH1 | 0x20 |
| 08d5 | DUP7 | |
| 08d6 | ADD | |
| 08d7 | MSTORE | |
| 08d8 | PUSH1 | 0x20 |
| 08da | DUP6 | |
| 08db | MSTORE | |
| 08dc | PUSH2 | 0x08e6 |
| 08df | PUSH1 | 0x40 |
| 08e1 | DUP7 | |
| 08e2 | PUSH2 | 0x3c98 |
| 08e5 | JUMP | |
| 08e6 | JUMPDEST | |
| 08e7 | PUSH2 | 0x0160 |
| 08ea | DUP7 | |
| 08eb | ADD | |
| 08ec | SWAP5 | |
| 08ed | PUSH2 | 0x090c |
| 08f0 | DUP7 | |
| 08f1 | MLOAD | |
| 08f2 | DUP3 | |
| 08f3 | PUSH2 | 0x0906 |
| 08f6 | PUSH2 | 0x08ff |
| 08f9 | DUP8 | |
| 08fa | DUP1 | |
| 08fb | PUSH2 | 0x3e4d |
| 08fe | JUMP | |
| 08ff | JUMPDEST | |
| 0900 | CALLDATASIZE | |
| 0901 | SWAP2 | |
| 0902 | PUSH2 | 0x3cd4 |
| 0905 | JUMP | |
| 0906 | JUMPDEST | |
| 0907 | SWAP2 | |
| 0908 | PUSH2 | 0x4b32 |
| 090b | JUMP | |
| 090c | JUMPDEST | |
| 090d | ISZERO | |
| 090e | SWAP3 | |
| 090f | DUP4 | |
| 0910 | ISZERO | |
| 0911 | PUSH2 | 0x1261 |
| 0914 | JUMPI | |
| 0915 | JUMPDEST | |
| 0916 | POP | |
| 0917 | POP | |
| 0918 | POP | |
| 0919 | PUSH2 | 0x124e |
| 091c | JUMPI | |
| 091d | ADDRESS | |
| 091e | PUSH0 | |
| 091f | MSTORE | |
| 0920 | PUSH1 | 0x14 |
| 0922 | PUSH1 | 0x20 |
| 0924 | MSTORE | |
| 0925 | DUP1 | |
| 0926 | PUSH1 | 0x01 |
| 0928 | PUSH1 | 0x01 |
| 092a | PUSH1 | 0x40 |
| 092c | SHL | |
| 092d | SUB | |
| 092e | PUSH1 | 0x40 |
| 0930 | PUSH0 | |
| 0931 | KECCAK256 | |
| 0932 | SLOAD | |
| 0933 | AND | |
| 0934 | EQ | |
| 0935 | PUSH2 | 0x121a |
| 0938 | JUMPI | |
| 0939 | JUMPDEST | |
| 093a | POP | |
| 093b | DUP3 | |
| 093c | MLOAD | |
| 093d | SWAP7 | |
| 093e | DUP5 | |
| 093f | ISZERO | |
| 0940 | PUSH2 | 0x1207 |
| 0943 | JUMPI | |
| 0944 | DUP4 | |
| 0945 | MLOAD | |
| 0946 | PUSH0 | |
| 0947 | MSTORE | |
| 0948 | PUSH1 | 0x0d |
| 094a | PUSH1 | 0x20 |
| 094c | MSTORE | |
| 094d | PUSH1 | 0xff |
| 094f | PUSH1 | 0x40 |
| 0951 | PUSH0 | |
| 0952 | KECCAK256 | |
| 0953 | SLOAD | |
| 0954 | AND | |
| 0955 | PUSH2 | 0x11f3 |
| 0958 | JUMPI | |
| 0959 | DUP4 | |
| 095a | MLOAD | |
| 095b | PUSH0 | |
| 095c | SWAP1 | |
| 095d | DUP2 | |
| 095e | MSTORE | |
| 095f | PUSH1 | 0x0c |
| 0961 | PUSH1 | 0x20 |
| 0963 | MSTORE | |
| 0964 | PUSH1 | 0x40 |
| 0966 | SWAP1 | |
| 0967 | KECCAK256 | |
| 0968 | SLOAD | |
| 0969 | PUSH1 | 0x01 |
| 096b | PUSH1 | 0x01 |
| 096d | PUSH1 | 0xa0 |
| 096f | SHL | |
| 0970 | SUB | |
| 0971 | AND | |
| 0972 | DUP1 | |
| 0973 | ISZERO | |
| 0974 | ISZERO | |
| 0975 | DUP1 | |
| 0976 | PUSH2 | 0x11e9 |
| 0979 | JUMPI | |
| 097a | JUMPDEST | |
| 097b | PUSH2 | 0x11d3 |
| 097e | JUMPI | |
| 097f | POP | |
| 0980 | DUP5 | |
| 0981 | PUSH0 | |
| 0982 | MSTORE | |
| 0983 | PUSH1 | 0x02 |
| 0985 | PUSH1 | 0x20 |
| 0987 | MSTORE | |
| 0988 | PUSH1 | 0x40 |
| 098a | PUSH0 | |
| 098b | KECCAK256 | |
| 098c | PUSH1 | 0x05 |
| 098e | DUP2 | |
| 098f | ADD | |
| 0990 | SWAP3 | |
| 0991 | DUP4 | |
| 0992 | SLOAD | |
| 0993 | PUSH1 | 0xff |
| 0995 | DUP2 | |
| 0996 | PUSH1 | 0xd8 |
| 0998 | SHR | |
| 0999 | AND | |
| 099a | ISZERO | |
| 099b | PUSH0 | |
| 099c | EQ | |
| 099d | PUSH2 | 0x1151 |
| 09a0 | JUMPI | |
| 09a1 | POP | |
| 09a2 | SWAP1 | |
| 09a3 | PUSH1 | 0x0f |
| 09a5 | SLOAD | |
| 09a6 | SWAP1 | |
| 09a7 | PUSH1 | 0x01 |
| 09a9 | PUSH1 | 0x40 |
| 09ab | SHL | |
| 09ac | DUP3 | |
| 09ad | LT | |
| 09ae | ISZERO | |
| 09af | PUSH2 | 0x0e50 |
| 09b2 | JUMPI | |
| 09b3 | DUP12 | |
| 09b4 | SWAP3 | |
| 09b5 | PUSH2 | 0x09ee |
| 09b8 | DUP12 | |
| 09b9 | PUSH2 | 0x09ca |
| 09bc | DUP6 | |
| 09bd | PUSH1 | 0x01 |
| 09bf | PUSH1 | 0x04 |
| 09c1 | SWAP8 | |
| 09c2 | ADD | |
| 09c3 | PUSH1 | 0x0f |
| 09c5 | SSTORE | |
| 09c6 | PUSH2 | 0x3d53 |
| 09c9 | JUMP | |
| 09ca | JUMPDEST | |
| 09cb | DUP2 | |
| 09cc | SLOAD | |
| 09cd | PUSH1 | 0x01 |
| 09cf | PUSH1 | 0x01 |
| 09d1 | PUSH1 | 0xa0 |
| 09d3 | SHL | |
| 09d4 | SUB | |
| 09d5 | SWAP4 | |
| 09d6 | DUP5 | |
| 09d7 | AND | |
| 09d8 | PUSH1 | 0x03 |
| 09da | SWAP3 | |
| 09db | SWAP1 | |
| 09dc | SWAP3 | |
| 09dd | SHL | |
| 09de | SWAP2 | |
| 09df | DUP3 | |
| 09e0 | SHL | |
| 09e1 | SWAP4 | |
| 09e2 | SWAP1 | |
| 09e3 | SWAP2 | |
| 09e4 | SHL | |
| 09e5 | NOT | |
| 09e6 | AND | |
| 09e7 | SWAP2 | |
| 09e8 | SWAP1 | |
| 09e9 | SWAP2 | |
| 09ea | OR | |
| 09eb | SWAP1 | |
| 09ec | SSTORE | |
| 09ed | JUMP | |
| 09ee | JUMPDEST | |
| 09ef | DUP6 | |
| 09f0 | SLOAD | |
| 09f1 | PUSH1 | 0xff |
| 09f3 | PUSH1 | 0xd8 |
| 09f5 | SHL | |
| 09f6 | NOT | |
| 09f7 | AND | |
| 09f8 | PUSH1 | 0x01 |
| 09fa | PUSH1 | 0xd8 |
| 09fc | SHL | |
| 09fd | OR | |
| 09fe | DUP7 | |
| 09ff | SSTORE | |
| 0a00 | JUMPDEST | |
| 0a01 | DUP8 | |
| 0a02 | MLOAD | |
| 0a03 | DUP3 | |
| 0a04 | SSTORE | |
| 0a05 | DUP14 | |
| 0a06 | MLOAD | |
| 0a07 | PUSH1 | 0x01 |
| 0a09 | DUP4 | |
| 0a0a | ADD | |
| 0a0b | SSTORE | |
| 0a0c | MLOAD | |
| 0a0d | PUSH1 | 0x02 |
| 0a0f | DUP3 | |
| 0a10 | ADD | |
| 0a11 | SSTORE | |
| 0a12 | PUSH1 | 0xc0 |
| 0a14 | DUP8 | |
| 0a15 | ADD | |
| 0a16 | MLOAD | |
| 0a17 | PUSH1 | 0x03 |
| 0a19 | DUP3 | |
| 0a1a | ADD | |
| 0a1b | SSTORE | |
| 0a1c | ADD | |
| 0a1d | SSTORE | |
| 0a1e | PUSH1 | 0xe0 |
| 0a20 | DUP5 | |
| 0a21 | ADD | |
| 0a22 | MLOAD | |
| 0a23 | DUP3 | |
| 0a24 | SLOAD | |
| 0a25 | PUSH2 | 0x0100 |
| 0a28 | DUP7 | |
| 0a29 | ADD | |
| 0a2a | MLOAD | |
| 0a2b | PUSH2 | 0x0120 |
| 0a2e | DUP8 | |
| 0a2f | ADD | |
| 0a30 | MLOAD | |
| 0a31 | PUSH2 | 0x0140 |
| 0a34 | DUP9 | |
| 0a35 | ADD | |
| 0a36 | MLOAD | |
| 0a37 | PUSH1 | 0x01 |
| 0a39 | PUSH1 | 0x01 |
| 0a3b | PUSH1 | 0xd0 |
| 0a3d | SHL | |
| 0a3e | SUB | |
| 0a3f | NOT | |
| 0a40 | SWAP1 | |
| 0a41 | SWAP4 | |
| 0a42 | AND | |
| 0a43 | PUSH1 | 0xff |
| 0a45 | SWAP5 | |
| 0a46 | SWAP1 | |
| 0a47 | SWAP5 | |
| 0a48 | AND | |
| 0a49 | SWAP4 | |
| 0a4a | SWAP1 | |
| 0a4b | SWAP4 | |
| 0a4c | OR | |
| 0a4d | PUSH1 | 0x08 |
| 0a4f | SWAP2 | |
| 0a50 | SWAP1 | |
| 0a51 | SWAP2 | |
| 0a52 | SHL | |
| 0a53 | PUSH2 | 0xff00 |
| 0a56 | AND | |
| 0a57 | OR | |
| 0a58 | PUSH1 | 0x10 |
| 0a5a | SWAP3 | |
| 0a5b | SWAP1 | |
| 0a5c | SWAP3 | |
| 0a5d | SHL | |
| 0a5e | PUSH10 | 0xffffffffffffffff0000 |
| 0a69 | AND | |
| 0a6a | SWAP2 | |
| 0a6b | SWAP1 | |
| 0a6c | SWAP2 | |
| 0a6d | OR | |
| 0a6e | PUSH1 | 0x50 |
| 0a70 | SWAP2 | |
| 0a71 | SWAP1 | |
| 0a72 | SWAP2 | |
| 0a73 | SHL | |
| 0a74 | PUSH8 | 0xffffffffffffffff |
| 0a7d | PUSH1 | 0x50 |
| 0a7f | SHL | |
| 0a80 | AND | |
| 0a81 | OR | |
| 0a82 | PUSH1 | 0x90 |
| 0a84 | SWAP2 | |
| 0a85 | SWAP1 | |
| 0a86 | SWAP2 | |
| 0a87 | SHL | |
| 0a88 | PUSH8 | 0xffffffffffffffff |
| 0a91 | PUSH1 | 0x90 |
| 0a93 | SHL | |
| 0a94 | AND | |
| 0a95 | OR | |
| 0a96 | SWAP1 | |
| 0a97 | SSTORE | |
| 0a98 | DUP1 | |
| 0a99 | MLOAD | |
| 0a9a | PUSH1 | 0x01 |
| 0a9c | PUSH1 | 0x01 |
| 0a9e | PUSH1 | 0xa0 |
| 0aa0 | SHL | |
| 0aa1 | SUB | |
| 0aa2 | SWAP1 | |
| 0aa3 | PUSH2 | 0x0aab |
| 0aa6 | SWAP1 | |
| 0aa7 | PUSH2 | 0x4701 |
| 0aaa | JUMP | |
| 0aab | JUMPDEST | |
| 0aac | AND | |
| 0aad | PUSH0 | |
| 0aae | DUP2 | |
| 0aaf | DUP2 | |
| 0ab0 | MSTORE | |
| 0ab1 | PUSH1 | 0x15 |
| 0ab3 | PUSH1 | 0x20 |
| 0ab5 | MSTORE | |
| 0ab6 | PUSH1 | 0x40 |
| 0ab8 | SWAP1 | |
| 0ab9 | KECCAK256 | |
| 0aba | SLOAD | |
| 0abb | PUSH1 | 0x01 |
| 0abd | PUSH1 | 0x01 |
| 0abf | PUSH1 | 0xa0 |
| 0ac1 | SHL | |
| 0ac2 | SUB | |
| 0ac3 | AND | |
| 0ac4 | DUP1 | |
| 0ac5 | ISZERO | |
| 0ac6 | ISZERO | |
| 0ac7 | DUP1 | |
| 0ac8 | PUSH2 | 0x1147 |
| 0acb | JUMPI | |
| 0acc | JUMPDEST | |
| 0acd | PUSH2 | 0x1131 |
| 0ad0 | JUMPI | |
| 0ad1 | POP | |
| 0ad2 | DUP4 | |
| 0ad3 | PUSH0 | |
| 0ad4 | MSTORE | |
| 0ad5 | PUSH1 | 0x03 |
| 0ad7 | PUSH1 | 0x20 |
| 0ad9 | MSTORE | |
| 0ada | PUSH2 | 0x0ae6 |
| 0add | PUSH1 | 0x40 |
| 0adf | PUSH0 | |
| 0ae0 | KECCAK256 | |
| 0ae1 | SLOAD | |
| 0ae2 | PUSH2 | 0x3e7f |
| 0ae5 | JUMP | |
| 0ae6 | JUMPDEST | |
| 0ae7 | PUSH2 | 0x10e3 |
| 0aea | JUMPI | |
| 0aeb | JUMPDEST | |
| 0aec | PUSH0 | |
| 0aed | MSTORE | |
| 0aee | PUSH1 | 0x15 |
| 0af0 | PUSH1 | 0x20 |
| 0af2 | MSTORE | |
| 0af3 | PUSH1 | 0x40 |
| 0af5 | PUSH0 | |
| 0af6 | KECCAK256 | |
| 0af7 | DUP4 | |
| 0af8 | PUSH1 | 0x01 |
| 0afa | PUSH1 | 0x01 |
| 0afc | PUSH1 | 0x60 |
| 0afe | SHL | |
| 0aff | SUB | |
| 0b00 | PUSH1 | 0xa0 |
| 0b02 | SHL | |
| 0b03 | DUP3 | |
| 0b04 | SLOAD | |
| 0b05 | AND | |
| 0b06 | OR | |
| 0b07 | SWAP1 | |
| 0b08 | SSTORE | |
| 0b09 | MLOAD | |
| 0b0a | DUP3 | |
| 0b0b | PUSH0 | |
| 0b0c | MSTORE | |
| 0b0d | PUSH1 | 0x03 |
| 0b0f | PUSH1 | 0x20 |
| 0b11 | MSTORE | |
| 0b12 | PUSH1 | 0x40 |
| 0b14 | PUSH0 | |
| 0b15 | KECCAK256 | |
| 0b16 | SWAP1 | |
| 0b17 | DUP1 | |
| 0b18 | MLOAD | |
| 0b19 | SWAP1 | |
| 0b1a | PUSH1 | 0x01 |
| 0b1c | PUSH1 | 0x01 |
| 0b1e | PUSH1 | 0x40 |
| 0b20 | SHL | |
| 0b21 | SUB | |
| 0b22 | DUP3 | |
| 0b23 | GT | |
| 0b24 | PUSH2 | 0x0e50 |
| 0b27 | JUMPI | |
| 0b28 | PUSH2 | 0x0b31 |
| 0b2b | DUP4 | |
| 0b2c | SLOAD | |
| 0b2d | PUSH2 | 0x3e7f |
| 0b30 | JUMP | |
| 0b31 | JUMPDEST | |
| 0b32 | PUSH1 | 0x1f |
| 0b34 | DUP2 | |
| 0b35 | GT | |
| 0b36 | PUSH2 | 0x10a9 |
| 0b39 | JUMPI | |
| 0b3a | JUMPDEST | |
| 0b3b | POP | |
| 0b3c | PUSH1 | 0x20 |
| 0b3e | SWAP1 | |
| 0b3f | PUSH1 | 0x1f |
| 0b41 | DUP4 | |
| 0b42 | GT | |
| 0b43 | PUSH1 | 0x01 |
| 0b45 | EQ | |
| 0b46 | PUSH2 | 0x1046 |
| 0b49 | JUMPI | |
| 0b4a | PUSH2 | 0x0b6a |
| 0b4d | SWAP3 | |
| 0b4e | SWAP2 | |
| 0b4f | PUSH0 | |
| 0b50 | SWAP2 | |
| 0b51 | DUP4 | |
| 0b52 | PUSH2 | 0x0e64 |
| 0b55 | JUMPI | |
| 0b56 | JUMPDEST | |
| 0b57 | POP | |
| 0b58 | POP | |
| 0b59 | DUP2 | |
| 0b5a | PUSH1 | 0x01 |
| 0b5c | SHL | |
| 0b5d | SWAP2 | |
| 0b5e | PUSH0 | |
| 0b5f | NOT | |
| 0b60 | SWAP1 | |
| 0b61 | PUSH1 | 0x03 |
| 0b63 | SHL | |
| 0b64 | SHR | |
| 0b65 | NOT | |
| 0b66 | AND | |
| 0b67 | OR | |
| 0b68 | SWAP1 | |
| 0b69 | JUMP | |
| 0b6a | JUMPDEST | |
| 0b6b | SWAP1 | |
| 0b6c | SSTORE | |
| 0b6d | JUMPDEST | |
| 0b6e | PUSH2 | 0x0180 |
| 0b71 | DUP2 | |
| 0b72 | ADD | |
| 0b73 | MLOAD | |
| 0b74 | DUP3 | |
| 0b75 | PUSH0 | |
| 0b76 | MSTORE | |
| 0b77 | PUSH1 | 0x04 |
| 0b79 | PUSH1 | 0x20 |
| 0b7b | MSTORE | |
| 0b7c | PUSH1 | 0x40 |
| 0b7e | PUSH0 | |
| 0b7f | KECCAK256 | |
| 0b80 | SWAP1 | |
| 0b81 | DUP1 | |
| 0b82 | MLOAD | |
| 0b83 | SWAP1 | |
| 0b84 | PUSH1 | 0x01 |
| 0b86 | PUSH1 | 0x01 |
| 0b88 | PUSH1 | 0x40 |
| 0b8a | SHL | |
| 0b8b | SUB | |
| 0b8c | DUP3 | |
| 0b8d | GT | |
| 0b8e | PUSH2 | 0x0e50 |
| 0b91 | JUMPI | |
| 0b92 | PUSH2 | 0x0b9b |
| 0b95 | DUP4 | |
| 0b96 | SLOAD | |
| 0b97 | PUSH2 | 0x3e7f |
| 0b9a | JUMP | |
| 0b9b | JUMPDEST | |
| 0b9c | PUSH1 | 0x1f |
| 0b9e | DUP2 | |
| 0b9f | GT | |
| 0ba0 | PUSH2 | 0x100c |
| 0ba3 | JUMPI | |
| 0ba4 | JUMPDEST | |
| 0ba5 | POP | |
| 0ba6 | PUSH1 | 0x20 |
| 0ba8 | SWAP1 | |
| 0ba9 | PUSH1 | 0x1f |
| 0bab | DUP4 | |
| 0bac | GT | |
| 0bad | PUSH1 | 0x01 |
| 0baf | EQ | |
| 0bb0 | PUSH2 | 0x0fa9 |
| 0bb3 | JUMPI | |
| 0bb4 | PUSH2 | 0x0bd3 |
| 0bb7 | SWAP3 | |
| 0bb8 | SWAP2 | |
| 0bb9 | PUSH0 | |
| 0bba | SWAP2 | |
| 0bbb | DUP4 | |
| 0bbc | PUSH2 | 0x0e64 |
| 0bbf | JUMPI | |
| 0bc0 | POP | |
| 0bc1 | POP | |
| 0bc2 | DUP2 | |
| 0bc3 | PUSH1 | 0x01 |
| 0bc5 | SHL | |
| 0bc6 | SWAP2 | |
| 0bc7 | PUSH0 | |
| 0bc8 | NOT | |
| 0bc9 | SWAP1 | |
| 0bca | PUSH1 | 0x03 |
| 0bcc | SHL | |
| 0bcd | SHR | |
| 0bce | NOT | |
| 0bcf | AND | |
| 0bd0 | OR | |
| 0bd1 | SWAP1 | |
| 0bd2 | JUMP | |
| 0bd3 | JUMPDEST | |
| 0bd4 | SWAP1 | |
| 0bd5 | SSTORE | |
| 0bd6 | JUMPDEST | |
| 0bd7 | PUSH2 | 0x0160 |
| 0bda | DUP8 | |
| 0bdb | ADD | |
| 0bdc | MLOAD | |
| 0bdd | DUP3 | |
| 0bde | PUSH0 | |
| 0bdf | MSTORE | |
| 0be0 | PUSH1 | 0x05 |
| 0be2 | PUSH1 | 0x20 |
| 0be4 | MSTORE | |
| 0be5 | PUSH1 | 0x40 |
| 0be7 | PUSH0 | |
| 0be8 | KECCAK256 | |
| 0be9 | SWAP1 | |
| 0bea | DUP1 | |
| 0beb | MLOAD | |
| 0bec | SWAP1 | |
| 0bed | PUSH1 | 0x01 |
| 0bef | PUSH1 | 0x01 |
| 0bf1 | PUSH1 | 0x40 |
| 0bf3 | SHL | |
| 0bf4 | SUB | |
| 0bf5 | DUP3 | |
| 0bf6 | GT | |
| 0bf7 | PUSH2 | 0x0e50 |
| 0bfa | JUMPI | |
| 0bfb | PUSH2 | 0x0c04 |
| 0bfe | DUP4 | |
| 0bff | SLOAD | |
| 0c00 | PUSH2 | 0x3e7f |
| 0c03 | JUMP | |
| 0c04 | JUMPDEST | |
| 0c05 | PUSH1 | 0x1f |
| 0c07 | DUP2 | |
| 0c08 | GT | |
| 0c09 | PUSH2 | 0x0f6f |
| 0c0c | JUMPI | |
| 0c0d | JUMPDEST | |
| 0c0e | POP | |
| 0c0f | PUSH1 | 0x20 |
| 0c11 | SWAP1 | |
| 0c12 | PUSH1 | 0x1f |
| 0c14 | DUP4 | |
| 0c15 | GT | |
| 0c16 | PUSH1 | 0x01 |
| 0c18 | EQ | |
| 0c19 | PUSH2 | 0x0f0c |
| 0c1c | JUMPI | |
| 0c1d | PUSH2 | 0x0c3c |
| 0c20 | SWAP3 | |
| 0c21 | SWAP2 | |
| 0c22 | PUSH0 | |
| 0c23 | SWAP2 | |
| 0c24 | DUP4 | |
| 0c25 | PUSH2 | 0x0e64 |
| 0c28 | JUMPI | |
| 0c29 | POP | |
| 0c2a | POP | |
| 0c2b | DUP2 | |
| 0c2c | PUSH1 | 0x01 |
| 0c2e | SHL | |
| 0c2f | SWAP2 | |
| 0c30 | PUSH0 | |
| 0c31 | NOT | |
| 0c32 | SWAP1 | |
| 0c33 | PUSH1 | 0x03 |
| 0c35 | SHL | |
| 0c36 | SHR | |
| 0c37 | NOT | |
| 0c38 | AND | |
| 0c39 | OR | |
| 0c3a | SWAP1 | |
| 0c3b | JUMP | |
| 0c3c | JUMPDEST | |
| 0c3d | SWAP1 | |
| 0c3e | SSTORE | |
| 0c3f | JUMPDEST | |
| 0c40 | PUSH2 | 0x0180 |
| 0c43 | DUP8 | |
| 0c44 | ADD | |
| 0c45 | MLOAD | |
| 0c46 | DUP3 | |
| 0c47 | PUSH0 | |
| 0c48 | MSTORE | |
| 0c49 | PUSH1 | 0x06 |
| 0c4b | PUSH1 | 0x20 |
| 0c4d | MSTORE | |
| 0c4e | PUSH1 | 0x40 |
| 0c50 | PUSH0 | |
| 0c51 | KECCAK256 | |
| 0c52 | SWAP1 | |
| 0c53 | DUP1 | |
| 0c54 | MLOAD | |
| 0c55 | SWAP1 | |
| 0c56 | PUSH1 | 0x01 |
| 0c58 | PUSH1 | 0x01 |
| 0c5a | PUSH1 | 0x40 |
| 0c5c | SHL | |
| 0c5d | SUB | |
| 0c5e | DUP3 | |
| 0c5f | GT | |
| 0c60 | PUSH2 | 0x0e50 |
| 0c63 | JUMPI | |
| 0c64 | PUSH2 | 0x0c6d |
| 0c67 | DUP4 | |
| 0c68 | SLOAD | |
| 0c69 | PUSH2 | 0x3e7f |
| 0c6c | JUMP | |
| 0c6d | JUMPDEST | |
| 0c6e | PUSH1 | 0x1f |
| 0c70 | DUP2 | |
| 0c71 | GT | |
| 0c72 | PUSH2 | 0x0ed2 |
| 0c75 | JUMPI | |
| 0c76 | JUMPDEST | |
| 0c77 | POP | |
| 0c78 | PUSH1 | 0x20 |
| 0c7a | SWAP1 | |
| 0c7b | PUSH1 | 0x1f |
| 0c7d | DUP4 | |
| 0c7e | GT | |
| 0c7f | PUSH1 | 0x01 |
| 0c81 | EQ | |
| 0c82 | PUSH2 | 0x0e6f |
| 0c85 | JUMPI | |
| 0c86 | PUSH2 | 0x0ca5 |
| 0c89 | SWAP3 | |
| 0c8a | SWAP2 | |
| 0c8b | PUSH0 | |
| 0c8c | SWAP2 | |
| 0c8d | DUP4 | |
| 0c8e | PUSH2 | 0x0e64 |
| 0c91 | JUMPI | |
| 0c92 | POP | |
| 0c93 | POP | |
| 0c94 | DUP2 | |
| 0c95 | PUSH1 | 0x01 |
| 0c97 | SHL | |
| 0c98 | SWAP2 | |
| 0c99 | PUSH0 | |
| 0c9a | NOT | |
| 0c9b | SWAP1 | |
| 0c9c | PUSH1 | 0x03 |
| 0c9e | SHL | |
| 0c9f | SHR | |
| 0ca0 | NOT | |
| 0ca1 | AND | |
| 0ca2 | OR | |
| 0ca3 | SWAP1 | |
| 0ca4 | JUMP | |
| 0ca5 | JUMPDEST | |
| 0ca6 | SWAP1 | |
| 0ca7 | SSTORE | |
| 0ca8 | JUMPDEST | |
| 0ca9 | PUSH2 | 0x01e0 |
| 0cac | DUP2 | |
| 0cad | ADD | |
| 0cae | MLOAD | |
| 0caf | SWAP7 | |
| 0cb0 | DUP3 | |
| 0cb1 | PUSH0 | |
| 0cb2 | MSTORE | |
| 0cb3 | PUSH1 | 0x07 |
| 0cb5 | PUSH1 | 0x20 |
| 0cb7 | MSTORE | |
| 0cb8 | PUSH1 | 0x40 |
| 0cba | PUSH0 | |
| 0cbb | KECCAK256 | |
| 0cbc | DUP9 | |
| 0cbd | MLOAD | |
| 0cbe | PUSH1 | 0x01 |
| 0cc0 | PUSH1 | 0x01 |
| 0cc2 | PUSH1 | 0x40 |
| 0cc4 | SHL | |
| 0cc5 | SUB | |
| 0cc6 | DUP2 | |
| 0cc7 | GT | |
| 0cc8 | PUSH2 | 0x0e50 |
| 0ccb | JUMPI | |
| 0ccc | PUSH1 | 0x20 |
| 0cce | SWAP10 | |
| 0ccf | PUSH2 | 0x0cd8 |
| 0cd2 | DUP4 | |
| 0cd3 | SLOAD | |
| 0cd4 | PUSH2 | 0x3e7f |
| 0cd7 | JUMP | |
| 0cd8 | JUMPDEST | |
| 0cd9 | PUSH1 | 0x1f |
| 0cdb | DUP2 | |
| 0cdc | GT | |
| 0cdd | PUSH2 | 0x0e0f |
| 0ce0 | JUMPI | |
| 0ce1 | JUMPDEST | |
| 0ce2 | POP | |
| 0ce3 | DUP11 | |
| 0ce4 | SWAP1 | |
| 0ce5 | PUSH1 | 0x1f |
| 0ce7 | DUP4 | |
| 0ce8 | GT | |
| 0ce9 | PUSH1 | 0x01 |
| 0ceb | EQ | |
| 0cec | PUSH2 | 0x0d92 |
| 0cef | JUMPI | |
| 0cf0 | SWAP4 | |
| 0cf1 | PUSH2 | 0x0612 |
| 0cf4 | SWAP10 | |
| 0cf5 | SWAP11 | |
| 0cf6 | SWAP4 | |
| 0cf7 | PUSH2 | 0x0d2b |
| 0cfa | DUP5 | |
| 0cfb | PUSH0 | |
| 0cfc | MLOAD | |
| 0cfd | PUSH1 | 0x20 |
| 0cff | PUSH2 | 0x5df8 |
| 0d02 | PUSH0 | |
| 0d03 | CODECOPY | |
| 0d04 | PUSH0 | |
| 0d05 | MLOAD | |
| 0d06 | SWAP1 | |
| 0d07 | PUSH0 | |
| 0d08 | MSTORE | |
| 0d09 | SWAP9 | |
| 0d0a | SWAP6 | |
| 0d0b | PUSH2 | 0x0d59 |
| 0d0e | SWAP6 | |
| 0d0f | PUSH1 | 0x40 |
| 0d11 | SWAP10 | |
| 0d12 | PUSH0 | |
| 0d13 | SWAP3 | |
| 0d14 | PUSH2 | 0x0d87 |
| 0d17 | JUMPI | |
| 0d18 | POP | |
| 0d19 | POP | |
| 0d1a | DUP2 | |
| 0d1b | PUSH1 | 0x01 |
| 0d1d | SHL | |
| 0d1e | SWAP2 | |
| 0d1f | PUSH0 | |
| 0d20 | NOT | |
| 0d21 | SWAP1 | |
| 0d22 | PUSH1 | 0x03 |
| 0d24 | SHL | |
| 0d25 | SHR | |
| 0d26 | NOT | |
| 0d27 | AND | |
| 0d28 | OR | |
| 0d29 | SWAP1 | |
| 0d2a | JUMP | |
| 0d2b | JUMPDEST | |
| 0d2c | SWAP1 | |
| 0d2d | SSTORE | |
| 0d2e | JUMPDEST | |
| 0d2f | PUSH2 | 0x0d45 |
| 0d32 | PUSH2 | 0x01a0 |
| 0d35 | DUP5 | |
| 0d36 | ADD | |
| 0d37 | MLOAD | |
| 0d38 | PUSH2 | 0x01c0 |
| 0d3b | DUP6 | |
| 0d3c | ADD | |
| 0d3d | MLOAD | |
| 0d3e | SWAP1 | |
| 0d3f | PUSH0 | |
| 0d40 | DUP13 | |
| 0d41 | PUSH2 | 0x53e9 |
| 0d44 | JUMP | |
| 0d45 | JUMPDEST | |
| 0d46 | PUSH2 | 0x01c0 |
| 0d49 | PUSH2 | 0x01a0 |
| 0d4c | DUP3 | |
| 0d4d | ADD | |
| 0d4e | MLOAD | |
| 0d4f | SWAP2 | |
| 0d50 | ADD | |
| 0d51 | MLOAD | |
| 0d52 | SWAP1 | |
| 0d53 | PUSH0 | |
| 0d54 | DUP11 | |
| 0d55 | PUSH2 | 0x56ad |
| 0d58 | JUMP | |
| 0d59 | JUMPDEST | |
| 0d5a | DUP1 | |
| 0d5b | MLOAD | |
| 0d5c | PUSH0 | |
| 0d5d | MSTORE | |
| 0d5e | PUSH1 | 0x0c |
| 0d60 | DUP11 | |
| 0d61 | MSTORE | |
| 0d62 | DUP3 | |
| 0d63 | PUSH0 | |
| 0d64 | KECCAK256 | |
| 0d65 | DUP6 | |
| 0d66 | PUSH1 | 0x01 |
| 0d68 | PUSH1 | 0x01 |
| 0d6a | PUSH1 | 0x60 |
| 0d6c | SHL | |
| 0d6d | SUB | |
| 0d6e | PUSH1 | 0xa0 |
| 0d70 | SHL | |
| 0d71 | DUP3 | |
| 0d72 | SLOAD | |
| 0d73 | AND | |
| 0d74 | OR | |
| 0d75 | SWAP1 | |
| 0d76 | SSTORE | |
| 0d77 | MLOAD | |
| 0d78 | SWAP5 | |
| 0d79 | DUP3 | |
| 0d7a | MLOAD | |
| 0d7b | SWAP2 | |
| 0d7c | DUP3 | |
| 0d7d | MSTORE | |
| 0d7e | DUP10 | |
| 0d7f | DUP3 | |
| 0d80 | ADD | |
| 0d81 | MSTORE | |
| 0d82 | LOG3 | |
| 0d83 | PUSH2 | 0x49db |
| 0d86 | JUMP | |
| 0d87 | JUMPDEST | |
| 0d88 | ADD | |
| 0d89 | MLOAD | |
| 0d8a | SWAP1 | |
| 0d8b | POP | |
| 0d8c | PUSH0 | |
| 0d8d | DUP1 | |
| 0d8e | PUSH2 | 0x0b56 |
| 0d91 | JUMP | |
| 0d92 | JUMPDEST | |
| 0d93 | SWAP1 | |
| 0d94 | PUSH1 | 0x1f |
| 0d96 | NOT | |
| 0d97 | DUP4 | |
| 0d98 | AND | |
| 0d99 | SWAP2 | |
| 0d9a | DUP5 | |
| 0d9b | PUSH0 | |
| 0d9c | MSTORE | |
| 0d9d | DUP2 | |
| 0d9e | PUSH0 | |
| 0d9f | KECCAK256 | |
| 0da0 | SWAP3 | |
| 0da1 | PUSH0 | |
| 0da2 | JUMPDEST | |
| 0da3 | DUP2 | |
| 0da4 | DUP2 | |
| 0da5 | LT | |
| 0da6 | PUSH2 | 0x0df8 |
| 0da9 | JUMPI | |
| 0daa | POP | |
| 0dab | DUP5 | |
| 0dac | PUSH2 | 0x0d59 |
| 0daf | SWAP5 | |
| 0db0 | PUSH1 | 0x40 |
| 0db2 | SWAP9 | |
| 0db3 | SWAP5 | |
| 0db4 | PUSH2 | 0x0612 |
| 0db7 | SWAP15 | |
| 0db8 | SWAP16 | |
| 0db9 | SWAP9 | |
| 0dba | SWAP5 | |
| 0dbb | PUSH0 | |
| 0dbc | MLOAD | |
| 0dbd | PUSH1 | 0x20 |
| 0dbf | PUSH2 | 0x5df8 |
| 0dc2 | PUSH0 | |
| 0dc3 | CODECOPY | |
| 0dc4 | PUSH0 | |
| 0dc5 | MLOAD | |
| 0dc6 | SWAP1 | |
| 0dc7 | PUSH0 | |
| 0dc8 | MSTORE | |
| 0dc9 | SWAP12 | |
| 0dca | SWAP9 | |
| 0dcb | PUSH1 | 0x01 |
| 0dcd | SWAP6 | |
| 0dce | LT | |
| 0dcf | PUSH2 | 0x0de0 |
| 0dd2 | JUMPI | |
| 0dd3 | JUMPDEST | |
| 0dd4 | POP | |
| 0dd5 | POP | |
| 0dd6 | POP | |
| 0dd7 | DUP2 | |
| 0dd8 | SHL | |
| 0dd9 | ADD | |
| 0dda | SWAP1 | |
| 0ddb | SSTORE | |
| 0ddc | PUSH2 | 0x0d2e |
| 0ddf | JUMP | |
| 0de0 | JUMPDEST | |
| 0de1 | ADD | |
| 0de2 | MLOAD | |
| 0de3 | PUSH0 | |
| 0de4 | NOT | |
| 0de5 | PUSH1 | 0xf8 |
| 0de7 | DUP5 | |
| 0de8 | PUSH1 | 0x03 |
| 0dea | SHL | |
| 0deb | AND | |
| 0dec | SHR | |
| 0ded | NOT | |
| 0dee | AND | |
| 0def | SWAP1 | |
| 0df0 | SSTORE | |
| 0df1 | DUP16 | |
| 0df2 | DUP1 | |
| 0df3 | DUP1 | |
| 0df4 | PUSH2 | 0x0dd3 |
| 0df7 | JUMP | |
| 0df8 | JUMPDEST | |
| 0df9 | SWAP3 | |
| 0dfa | SWAP4 | |
| 0dfb | DUP15 | |
| 0dfc | PUSH1 | 0x01 |
| 0dfe | DUP2 | |
| 0dff | SWAP3 | |
| 0e00 | DUP8 | |
| 0e01 | DUP7 | |
| 0e02 | ADD | |
| 0e03 | MLOAD | |
| 0e04 | DUP2 | |
| 0e05 | SSTORE | |
| 0e06 | ADD | |
| 0e07 | SWAP6 | |
| 0e08 | ADD | |
| 0e09 | SWAP4 | |
| 0e0a | ADD | |
| 0e0b | PUSH2 | 0x0da2 |
| 0e0e | JUMP | |
| 0e0f | JUMPDEST | |
| 0e10 | DUP3 | |
| 0e11 | DUP2 | |
| 0e12 | GT | |
| 0e13 | ISZERO | |
| 0e14 | PUSH2 | 0x0ce1 |
| 0e17 | JUMPI | |
| 0e18 | PUSH2 | 0x0e42 |
| 0e1b | SWAP1 | |
| 0e1c | DUP5 | |
| 0e1d | PUSH0 | |
| 0e1e | MSTORE | |
| 0e1f | DUP13 | |
| 0e20 | PUSH0 | |
| 0e21 | KECCAK256 | |
| 0e22 | SWAP1 | |
| 0e23 | PUSH1 | 0x1f |
| 0e25 | DUP6 | |
| 0e26 | ADD | |
| 0e27 | PUSH1 | 0x05 |
| 0e29 | SHR | |
| 0e2a | SWAP1 | |
| 0e2b | DUP15 | |
| 0e2c | DUP7 | |
| 0e2d | LT | |
| 0e2e | PUSH2 | 0x0e48 |
| 0e31 | JUMPI | |
| 0e32 | JUMPDEST | |
| 0e33 | PUSH1 | 0x1f |
| 0e35 | DUP3 | |
| 0e36 | SWAP2 | |
| 0e37 | ADD | |
| 0e38 | PUSH1 | 0x05 |
| 0e3a | SHR | |
| 0e3b | SUB | |
| 0e3c | SWAP2 | |
| 0e3d | ADD | |
| 0e3e | PUSH2 | 0x5264 |
| 0e41 | JUMP | |
| 0e42 | JUMPDEST | |
| 0e43 | DUP12 | |
| 0e44 | PUSH2 | 0x0ce1 |
| 0e47 | JUMP | |
| 0e48 | JUMPDEST | |
| 0e49 | PUSH0 | |
| 0e4a | SWAP2 | |
| 0e4b | POP | |
| 0e4c | PUSH2 | 0x0e32 |
| 0e4f | JUMP | |
| 0e50 | JUMPDEST | |
| 0e51 | PUSH4 | 0x4e487b71 |
| 0e56 | PUSH1 | 0xe0 |
| 0e58 | SHL | |
| 0e59 | PUSH0 | |
| 0e5a | MSTORE | |
| 0e5b | PUSH1 | 0x41 |
| 0e5d | PUSH1 | 0x04 |
| 0e5f | MSTORE | |
| 0e60 | PUSH1 | 0x24 |
| 0e62 | PUSH0 | |
| 0e63 | REVERT | |
| 0e64 | JUMPDEST | |
| 0e65 | ADD | |
| 0e66 | MLOAD | |
| 0e67 | SWAP1 | |
| 0e68 | POP | |
| 0e69 | DUP12 | |
| 0e6a | DUP1 | |
| 0e6b | PUSH2 | 0x0b56 |
| 0e6e | JUMP | |
| 0e6f | JUMPDEST | |
| 0e70 | SWAP1 | |
| 0e71 | PUSH1 | 0x1f |
| 0e73 | NOT | |
| 0e74 | DUP4 | |
| 0e75 | AND | |
| 0e76 | SWAP2 | |
| 0e77 | DUP5 | |
| 0e78 | PUSH0 | |
| 0e79 | MSTORE | |
| 0e7a | DUP2 | |
| 0e7b | PUSH0 | |
| 0e7c | KECCAK256 | |
| 0e7d | SWAP3 | |
| 0e7e | PUSH0 | |
| 0e7f | JUMPDEST | |
| 0e80 | DUP2 | |
| 0e81 | DUP2 | |
| 0e82 | LT | |
| 0e83 | PUSH2 | 0x0eba |
| 0e86 | JUMPI | |
| 0e87 | POP | |
| 0e88 | SWAP1 | |
| 0e89 | DUP5 | |
| 0e8a | PUSH1 | 0x01 |
| 0e8c | SWAP6 | |
| 0e8d | SWAP5 | |
| 0e8e | SWAP4 | |
| 0e8f | SWAP3 | |
| 0e90 | LT | |
| 0e91 | PUSH2 | 0x0ea2 |
| 0e94 | JUMPI | |
| 0e95 | JUMPDEST | |
| 0e96 | POP | |
| 0e97 | POP | |
| 0e98 | POP | |
| 0e99 | DUP2 | |
| 0e9a | SHL | |
| 0e9b | ADD | |
| 0e9c | SWAP1 | |
| 0e9d | SSTORE | |
| 0e9e | PUSH2 | 0x0ca8 |
| 0ea1 | JUMP | |
| 0ea2 | JUMPDEST | |
| 0ea3 | ADD | |
| 0ea4 | MLOAD | |
| 0ea5 | PUSH0 | |
| 0ea6 | NOT | |
| 0ea7 | PUSH1 | 0xf8 |
| 0ea9 | DUP5 | |
| 0eaa | PUSH1 | 0x03 |
| 0eac | SHL | |
| 0ead | AND | |
| 0eae | SHR | |
| 0eaf | NOT | |
| 0eb0 | AND | |
| 0eb1 | SWAP1 | |
| 0eb2 | SSTORE | |
| 0eb3 | DUP11 | |
| 0eb4 | DUP1 | |
| 0eb5 | DUP1 | |
| 0eb6 | PUSH2 | 0x0e95 |
| 0eb9 | JUMP | |
| 0eba | JUMPDEST | |
| 0ebb | SWAP3 | |
| 0ebc | SWAP4 | |
| 0ebd | PUSH1 | 0x20 |
| 0ebf | PUSH1 | 0x01 |
| 0ec1 | DUP2 | |
| 0ec2 | SWAP3 | |
| 0ec3 | DUP8 | |
| 0ec4 | DUP7 | |
| 0ec5 | ADD | |
| 0ec6 | MLOAD | |
| 0ec7 | DUP2 | |
| 0ec8 | SSTORE | |
| 0ec9 | ADD | |
| 0eca | SWAP6 | |
| 0ecb | ADD | |
| 0ecc | SWAP4 | |
| 0ecd | ADD | |
| 0ece | PUSH2 | 0x0e7f |
| 0ed1 | JUMP | |
| 0ed2 | JUMPDEST | |
| 0ed3 | DUP3 | |
| 0ed4 | DUP2 | |
| 0ed5 | GT | |
| 0ed6 | ISZERO | |
| 0ed7 | PUSH2 | 0x0c76 |
| 0eda | JUMPI | |
| 0edb | PUSH2 | 0x0f06 |
| 0ede | SWAP1 | |
| 0edf | DUP5 | |
| 0ee0 | PUSH0 | |
| 0ee1 | MSTORE | |
| 0ee2 | PUSH1 | 0x20 |
| 0ee4 | PUSH0 | |
| 0ee5 | KECCAK256 | |
| 0ee6 | SWAP1 | |
| 0ee7 | PUSH1 | 0x1f |
| 0ee9 | DUP6 | |
| 0eea | ADD | |
| 0eeb | PUSH1 | 0x05 |
| 0eed | SHR | |
| 0eee | SWAP1 | |
| 0eef | PUSH1 | 0x20 |
| 0ef1 | DUP7 | |
| 0ef2 | LT | |
| 0ef3 | PUSH2 | 0x0e48 |
| 0ef6 | JUMPI | |
| 0ef7 | PUSH1 | 0x1f |
| 0ef9 | DUP3 | |
| 0efa | SWAP2 | |
| 0efb | ADD | |
| 0efc | PUSH1 | 0x05 |
| 0efe | SHR | |
| 0eff | SUB | |
| 0f00 | SWAP2 | |
| 0f01 | ADD | |
| 0f02 | PUSH2 | 0x5264 |
| 0f05 | JUMP | |
| 0f06 | JUMPDEST | |
| 0f07 | DUP11 | |
| 0f08 | PUSH2 | 0x0c76 |
| 0f0b | JUMP | |
| 0f0c | JUMPDEST | |
| 0f0d | SWAP1 | |
| 0f0e | PUSH1 | 0x1f |
| 0f10 | NOT | |
| 0f11 | DUP4 | |
| 0f12 | AND | |
| 0f13 | SWAP2 | |
| 0f14 | DUP5 | |
| 0f15 | PUSH0 | |
| 0f16 | MSTORE | |
| 0f17 | DUP2 | |
| 0f18 | PUSH0 | |
| 0f19 | KECCAK256 | |
| 0f1a | SWAP3 | |
| 0f1b | PUSH0 | |
| 0f1c | JUMPDEST | |
| 0f1d | DUP2 | |
| 0f1e | DUP2 | |
| 0f1f | LT | |
| 0f20 | PUSH2 | 0x0f57 |
| 0f23 | JUMPI | |
| 0f24 | POP | |
| 0f25 | SWAP1 | |
| 0f26 | DUP5 | |
| 0f27 | PUSH1 | 0x01 |
| 0f29 | SWAP6 | |
| 0f2a | SWAP5 | |
| 0f2b | SWAP4 | |
| 0f2c | SWAP3 | |
| 0f2d | LT | |
| 0f2e | PUSH2 | 0x0f3f |
| 0f31 | JUMPI | |
| 0f32 | JUMPDEST | |
| 0f33 | POP | |
| 0f34 | POP | |
| 0f35 | POP | |
| 0f36 | DUP2 | |
| 0f37 | SHL | |
| 0f38 | ADD | |
| 0f39 | SWAP1 | |
| 0f3a | SSTORE | |
| 0f3b | PUSH2 | 0x0c3f |
| 0f3e | JUMP | |
| 0f3f | JUMPDEST | |
| 0f40 | ADD | |
| 0f41 | MLOAD | |
| 0f42 | PUSH0 | |
| 0f43 | NOT | |
| 0f44 | PUSH1 | 0xf8 |
| 0f46 | DUP5 | |
| 0f47 | PUSH1 | 0x03 |
| 0f49 | SHL | |
| 0f4a | AND | |
| 0f4b | SHR | |
| 0f4c | NOT | |
| 0f4d | AND | |
| 0f4e | SWAP1 | |
| 0f4f | SSTORE | |
| 0f50 | DUP11 | |
| 0f51 | DUP1 | |
| 0f52 | DUP1 | |
| 0f53 | PUSH2 | 0x0f32 |
| 0f56 | JUMP | |
| 0f57 | JUMPDEST | |
| 0f58 | SWAP3 | |
| 0f59 | SWAP4 | |
| 0f5a | PUSH1 | 0x20 |
| 0f5c | PUSH1 | 0x01 |
| 0f5e | DUP2 | |
| 0f5f | SWAP3 | |
| 0f60 | DUP8 | |
| 0f61 | DUP7 | |
| 0f62 | ADD | |
| 0f63 | MLOAD | |
| 0f64 | DUP2 | |
| 0f65 | SSTORE | |
| 0f66 | ADD | |
| 0f67 | SWAP6 | |
| 0f68 | ADD | |
| 0f69 | SWAP4 | |
| 0f6a | ADD | |
| 0f6b | PUSH2 | 0x0f1c |
| 0f6e | JUMP | |
| 0f6f | JUMPDEST | |
| 0f70 | DUP3 | |
| 0f71 | DUP2 | |
| 0f72 | GT | |
| 0f73 | ISZERO | |
| 0f74 | PUSH2 | 0x0c0d |
| 0f77 | JUMPI | |
| 0f78 | PUSH2 | 0x0fa3 |
| 0f7b | SWAP1 | |
| 0f7c | DUP5 | |
| 0f7d | PUSH0 | |
| 0f7e | MSTORE | |
| 0f7f | PUSH1 | 0x20 |
| 0f81 | PUSH0 | |
| 0f82 | KECCAK256 | |
| 0f83 | SWAP1 | |
| 0f84 | PUSH1 | 0x1f |
| 0f86 | DUP6 | |
| 0f87 | ADD | |
| 0f88 | PUSH1 | 0x05 |
| 0f8a | SHR | |
| 0f8b | SWAP1 | |
| 0f8c | PUSH1 | 0x20 |
| 0f8e | DUP7 | |
| 0f8f | LT | |
| 0f90 | PUSH2 | 0x0e48 |
| 0f93 | JUMPI | |
| 0f94 | PUSH1 | 0x1f |
| 0f96 | DUP3 | |
| 0f97 | SWAP2 | |
| 0f98 | ADD | |
| 0f99 | PUSH1 | 0x05 |
| 0f9b | SHR | |
| 0f9c | SUB | |
| 0f9d | SWAP2 | |
| 0f9e | ADD | |
| 0f9f | PUSH2 | 0x5264 |
| 0fa2 | JUMP | |
| 0fa3 | JUMPDEST | |
| 0fa4 | DUP11 | |
| 0fa5 | PUSH2 | 0x0c0d |
| 0fa8 | JUMP | |
| 0fa9 | JUMPDEST | |
| 0faa | SWAP1 | |
| 0fab | PUSH1 | 0x1f |
| 0fad | NOT | |
| 0fae | DUP4 | |
| 0faf | AND | |
| 0fb0 | SWAP2 | |
| 0fb1 | DUP5 | |
| 0fb2 | PUSH0 | |
| 0fb3 | MSTORE | |
| 0fb4 | DUP2 | |
| 0fb5 | PUSH0 | |
| 0fb6 | KECCAK256 | |
| 0fb7 | SWAP3 | |
| 0fb8 | PUSH0 | |
| 0fb9 | JUMPDEST | |
| 0fba | DUP2 | |
| 0fbb | DUP2 | |
| 0fbc | LT | |
| 0fbd | PUSH2 | 0x0ff4 |
| 0fc0 | JUMPI | |
| 0fc1 | POP | |
| 0fc2 | SWAP1 | |
| 0fc3 | DUP5 | |
| 0fc4 | PUSH1 | 0x01 |
| 0fc6 | SWAP6 | |
| 0fc7 | SWAP5 | |
| 0fc8 | SWAP4 | |
| 0fc9 | SWAP3 | |
| 0fca | LT | |
| 0fcb | PUSH2 | 0x0fdc |
| 0fce | JUMPI | |
| 0fcf | JUMPDEST | |
| 0fd0 | POP | |
| 0fd1 | POP | |
| 0fd2 | POP | |
| 0fd3 | DUP2 | |
| 0fd4 | SHL | |
| 0fd5 | ADD | |
| 0fd6 | SWAP1 | |
| 0fd7 | SSTORE | |
| 0fd8 | PUSH2 | 0x0bd6 |
| 0fdb | JUMP | |
| 0fdc | JUMPDEST | |
| 0fdd | ADD | |
| 0fde | MLOAD | |
| 0fdf | PUSH0 | |
| 0fe0 | NOT | |
| 0fe1 | PUSH1 | 0xf8 |
| 0fe3 | DUP5 | |
| 0fe4 | PUSH1 | 0x03 |
| 0fe6 | SHL | |
| 0fe7 | AND | |
| 0fe8 | SHR | |
| 0fe9 | NOT | |
| 0fea | AND | |
| 0feb | SWAP1 | |
| 0fec | SSTORE | |
| 0fed | DUP11 | |
| 0fee | DUP1 | |
| 0fef | DUP1 | |
| 0ff0 | PUSH2 | 0x0fcf |
| 0ff3 | JUMP | |
| 0ff4 | JUMPDEST | |
| 0ff5 | SWAP3 | |
| 0ff6 | SWAP4 | |
| 0ff7 | PUSH1 | 0x20 |
| 0ff9 | PUSH1 | 0x01 |
| 0ffb | DUP2 | |
| 0ffc | SWAP3 | |
| 0ffd | DUP8 | |
| 0ffe | DUP7 | |
| 0fff | ADD | |
| 1000 | MLOAD | |
| 1001 | DUP2 | |
| 1002 | SSTORE | |
| 1003 | ADD | |
| 1004 | SWAP6 | |
| 1005 | ADD | |
| 1006 | SWAP4 | |
| 1007 | ADD | |
| 1008 | PUSH2 | 0x0fb9 |
| 100b | JUMP | |
| 100c | JUMPDEST | |
| 100d | DUP3 | |
| 100e | DUP2 | |
| 100f | GT | |
| 1010 | ISZERO | |
| 1011 | PUSH2 | 0x0ba4 |
| 1014 | JUMPI | |
| 1015 | PUSH2 | 0x1040 |
| 1018 | SWAP1 | |
| 1019 | DUP5 | |
| 101a | PUSH0 | |
| 101b | MSTORE | |
| 101c | PUSH1 | 0x20 |
| 101e | PUSH0 | |
| 101f | KECCAK256 | |
| 1020 | SWAP1 | |
| 1021 | PUSH1 | 0x1f |
| 1023 | DUP6 | |
| 1024 | ADD | |
| 1025 | PUSH1 | 0x05 |
| 1027 | SHR | |
| 1028 | SWAP1 | |
| 1029 | PUSH1 | 0x20 |
| 102b | DUP7 | |
| 102c | LT | |
| 102d | PUSH2 | 0x0e48 |
| 1030 | JUMPI | |
| 1031 | PUSH1 | 0x1f |
| 1033 | DUP3 | |
| 1034 | SWAP2 | |
| 1035 | ADD | |
| 1036 | PUSH1 | 0x05 |
| 1038 | SHR | |
| 1039 | SUB | |
| 103a | SWAP2 | |
| 103b | ADD | |
| 103c | PUSH2 | 0x5264 |
| 103f | JUMP | |
| 1040 | JUMPDEST | |
| 1041 | DUP11 | |
| 1042 | PUSH2 | 0x0ba4 |
| 1045 | JUMP | |
| 1046 | JUMPDEST | |
| 1047 | SWAP1 | |
| 1048 | PUSH1 | 0x1f |
| 104a | NOT | |
| 104b | DUP4 | |
| 104c | AND | |
| 104d | SWAP2 | |
| 104e | DUP5 | |
| 104f | PUSH0 | |
| 1050 | MSTORE | |
| 1051 | DUP2 | |
| 1052 | PUSH0 | |
| 1053 | KECCAK256 | |
| 1054 | SWAP3 | |
| 1055 | PUSH0 | |
| 1056 | JUMPDEST | |
| 1057 | DUP2 | |
| 1058 | DUP2 | |
| 1059 | LT | |
| 105a | PUSH2 | 0x1091 |
| 105d | JUMPI | |
| 105e | POP | |
| 105f | SWAP1 | |
| 1060 | DUP5 | |
| 1061 | PUSH1 | 0x01 |
| 1063 | SWAP6 | |
| 1064 | SWAP5 | |
| 1065 | SWAP4 | |
| 1066 | SWAP3 | |
| 1067 | LT | |
| 1068 | PUSH2 | 0x1079 |
| 106b | JUMPI | |
| 106c | JUMPDEST | |
| 106d | POP | |
| 106e | POP | |
| 106f | POP | |
| 1070 | DUP2 | |
| 1071 | SHL | |
| 1072 | ADD | |
| 1073 | SWAP1 | |
| 1074 | SSTORE | |
| 1075 | PUSH2 | 0x0b6d |
| 1078 | JUMP | |
| 1079 | JUMPDEST | |
| 107a | ADD | |
| 107b | MLOAD | |
| 107c | PUSH0 | |
| 107d | NOT | |
| 107e | PUSH1 | 0xf8 |
| 1080 | DUP5 | |
| 1081 | PUSH1 | 0x03 |
| 1083 | SHL | |
| 1084 | AND | |
| 1085 | SHR | |
| 1086 | NOT | |
| 1087 | AND | |
| 1088 | SWAP1 | |
| 1089 | SSTORE | |
| 108a | DUP11 | |
| 108b | DUP1 | |
| 108c | DUP1 | |
| 108d | PUSH2 | 0x106c |
| 1090 | JUMP | |
| 1091 | JUMPDEST | |
| 1092 | SWAP3 | |
| 1093 | SWAP4 | |
| 1094 | PUSH1 | 0x20 |
| 1096 | PUSH1 | 0x01 |
| 1098 | DUP2 | |
| 1099 | SWAP3 | |
| 109a | DUP8 | |
| 109b | DUP7 | |
| 109c | ADD | |
| 109d | MLOAD | |
| 109e | DUP2 | |
| 109f | SSTORE | |
| 10a0 | ADD | |
| 10a1 | SWAP6 | |
| 10a2 | ADD | |
| 10a3 | SWAP4 | |
| 10a4 | ADD | |
| 10a5 | PUSH2 | 0x1056 |
| 10a8 | JUMP | |
| 10a9 | JUMPDEST | |
| 10aa | DUP3 | |
| 10ab | DUP2 | |
| 10ac | GT | |
| 10ad | ISZERO | |
| 10ae | PUSH2 | 0x0b3a |
| 10b1 | JUMPI | |
| 10b2 | PUSH2 | 0x10dd |
| 10b5 | SWAP1 | |
| 10b6 | DUP5 | |
| 10b7 | PUSH0 | |
| 10b8 | MSTORE | |
| 10b9 | PUSH1 | 0x20 |
| 10bb | PUSH0 | |
| 10bc | KECCAK256 | |
| 10bd | SWAP1 | |
| 10be | PUSH1 | 0x1f |
| 10c0 | DUP6 | |
| 10c1 | ADD | |
| 10c2 | PUSH1 | 0x05 |
| 10c4 | SHR | |
| 10c5 | SWAP1 | |
| 10c6 | PUSH1 | 0x20 |
| 10c8 | DUP7 | |
| 10c9 | LT | |
| 10ca | PUSH2 | 0x0e48 |
| 10cd | JUMPI | |
| 10ce | PUSH1 | 0x1f |
| 10d0 | DUP3 | |
| 10d1 | SWAP2 | |
| 10d2 | ADD | |
| 10d3 | PUSH1 | 0x05 |
| 10d5 | SHR | |
| 10d6 | SUB | |
| 10d7 | SWAP2 | |
| 10d8 | ADD | |
| 10d9 | PUSH2 | 0x5264 |
| 10dc | JUMP | |
| 10dd | JUMPDEST | |
| 10de | DUP11 | |
| 10df | PUSH2 | 0x0b3a |
| 10e2 | JUMP | |
| 10e3 | JUMPDEST | |
| 10e4 | DUP4 | |
| 10e5 | PUSH0 | |
| 10e6 | MSTORE | |
| 10e7 | PUSH1 | 0x03 |
| 10e9 | PUSH1 | 0x20 |
| 10eb | MSTORE | |
| 10ec | PUSH1 | 0x01 |
| 10ee | DUP1 | |
| 10ef | PUSH1 | 0xa0 |
| 10f1 | SHL | |
| 10f2 | SUB | |
| 10f3 | PUSH2 | 0x1101 |
| 10f6 | PUSH2 | 0x042f |
| 10f9 | PUSH1 | 0x40 |
| 10fb | PUSH0 | |
| 10fc | KECCAK256 | |
| 10fd | PUSH2 | 0x3eb7 |
| 1100 | JUMP | |
| 1101 | JUMPDEST | |
| 1102 | AND | |
| 1103 | DUP2 | |
| 1104 | DUP2 | |
| 1105 | SUB | |
| 1106 | PUSH2 | 0x1110 |
| 1109 | JUMPI | |
| 110a | JUMPDEST | |
| 110b | POP | |
| 110c | PUSH2 | 0x0aeb |
| 110f | JUMP | |
| 1110 | JUMPDEST | |
| 1111 | PUSH0 | |
| 1112 | MSTORE | |
| 1113 | PUSH1 | 0x15 |
| 1115 | PUSH1 | 0x20 |
| 1117 | MSTORE | |
| 1118 | PUSH1 | 0x40 |
| 111a | PUSH0 | |
| 111b | KECCAK256 | |
| 111c | PUSH1 | 0x01 |
| 111e | PUSH1 | 0x01 |
| 1120 | PUSH1 | 0x60 |
| 1122 | SHL | |
| 1123 | SUB | |
| 1124 | PUSH1 | 0xa0 |
| 1126 | SHL | |
| 1127 | DUP2 | |
| 1128 | SLOAD | |
| 1129 | AND | |
| 112a | SWAP1 | |
| 112b | SSTORE | |
| 112c | DUP10 | |
| 112d | PUSH2 | 0x110a |
| 1130 | JUMP | |
| 1131 | JUMPDEST | |
| 1132 | SWAP1 | |
| 1133 | PUSH4 | 0x13362de3 |
| 1138 | PUSH1 | 0xe0 |
| 113a | SHL | |
| 113b | PUSH0 | |
| 113c | MSTORE | |
| 113d | PUSH1 | 0x04 |
| 113f | MSTORE | |
| 1140 | PUSH1 | 0x24 |
| 1142 | MSTORE | |
| 1143 | PUSH1 | 0x44 |
| 1145 | PUSH0 | |
| 1146 | REVERT | |
| 1147 | JUMPDEST | |
| 1148 | POP | |
| 1149 | DUP5 | |
| 114a | DUP2 | |
| 114b | EQ | |
| 114c | ISZERO | |
| 114d | PUSH2 | 0x0acc |
| 1150 | JUMP | |
| 1151 | JUMPDEST | |
| 1152 | PUSH1 | 0x01 |
| 1154 | PUSH1 | 0x01 |
| 1156 | PUSH1 | 0x40 |
| 1158 | SHL | |
| 1159 | SUB | |
| 115a | DUP2 | |
| 115b | PUSH1 | 0x90 |
| 115d | SHR | |
| 115e | AND | |
| 115f | DUP1 | |
| 1160 | DUP11 | |
| 1161 | GT | |
| 1162 | ISZERO | |
| 1163 | PUSH2 | 0x11bc |
| 1166 | JUMPI | |
| 1167 | POP | |
| 1168 | PUSH1 | 0xd0 |
| 116a | SHR | |
| 116b | PUSH1 | 0xff |
| 116d | AND | |
| 116e | PUSH2 | 0x11a8 |
| 1171 | JUMPI | |
| 1172 | DUP2 | |
| 1173 | PUSH1 | 0x04 |
| 1175 | SWAP2 | |
| 1176 | DUP13 | |
| 1177 | SWAP4 | |
| 1178 | SLOAD | |
| 1179 | DUP9 | |
| 117a | MLOAD | |
| 117b | DUP2 | |
| 117c | SUB | |
| 117d | PUSH2 | 0x1187 |
| 1180 | JUMPI | |
| 1181 | JUMPDEST | |
| 1182 | POP | |
| 1183 | PUSH2 | 0x0a00 |
| 1186 | JUMP | |
| 1187 | JUMPDEST | |
| 1188 | PUSH0 | |
| 1189 | MSTORE | |
| 118a | PUSH1 | 0x0c |
| 118c | PUSH1 | 0x20 |
| 118e | MSTORE | |
| 118f | PUSH1 | 0x40 |
| 1191 | PUSH0 | |
| 1192 | KECCAK256 | |
| 1193 | PUSH1 | 0x01 |
| 1195 | PUSH1 | 0x01 |
| 1197 | PUSH1 | 0x60 |
| 1199 | SHL | |
| 119a | SUB | |
| 119b | PUSH1 | 0xa0 |
| 119d | SHL | |
| 119e | DUP2 | |
| 119f | SLOAD | |
| 11a0 | AND | |
| 11a1 | SWAP1 | |
| 11a2 | SSTORE | |
| 11a3 | DUP15 | |
| 11a4 | PUSH2 | 0x1181 |
| 11a7 | JUMP | |
| 11a8 | JUMPDEST | |
| 11a9 | POP | |
| 11aa | SLOAD | |
| 11ab | PUSH4 | 0xe41b98f7 |
| 11b0 | PUSH1 | 0xe0 |
| 11b2 | SHL | |
| 11b3 | PUSH0 | |
| 11b4 | MSTORE | |
| 11b5 | PUSH1 | 0x04 |
| 11b7 | MSTORE | |
| 11b8 | PUSH1 | 0x24 |
| 11ba | PUSH0 | |
| 11bb | REVERT | |
| 11bc | JUMPDEST | |
| 11bd | DUP10 | |
| 11be | SWAP1 | |
| 11bf | PUSH4 | 0xdf5abcab |
| 11c4 | PUSH1 | 0xe0 |
| 11c6 | SHL | |
| 11c7 | PUSH0 | |
| 11c8 | MSTORE | |
| 11c9 | PUSH1 | 0x04 |
| 11cb | MSTORE | |
| 11cc | PUSH1 | 0x24 |
| 11ce | MSTORE | |
| 11cf | PUSH1 | 0x44 |
| 11d1 | PUSH0 | |
| 11d2 | REVERT | |
| 11d3 | JUMPDEST | |
| 11d4 | DUP5 | |
| 11d5 | MLOAD | |
| 11d6 | PUSH3 | 0x3bdaab |
| 11da | PUSH1 | 0xe5 |
| 11dc | SHL | |
| 11dd | PUSH0 | |
| 11de | MSTORE | |
| 11df | PUSH1 | 0x04 |
| 11e1 | MSTORE | |
| 11e2 | PUSH1 | 0x24 |
| 11e4 | MSTORE | |
| 11e5 | PUSH1 | 0x44 |
| 11e7 | PUSH0 | |
| 11e8 | REVERT | |
| 11e9 | JUMPDEST | |
| 11ea | POP | |
| 11eb | DUP6 | |
| 11ec | DUP2 | |
| 11ed | EQ | |
| 11ee | ISZERO | |
| 11ef | PUSH2 | 0x097a |
| 11f2 | JUMP | |
| 11f3 | JUMPDEST | |
| 11f4 | DUP4 | |
| 11f5 | MLOAD | |
| 11f6 | PUSH4 | 0xe41b98f7 |
| 11fb | PUSH1 | 0xe0 |
| 11fd | SHL | |
| 11fe | PUSH0 | |
| 11ff | MSTORE | |
| 1200 | PUSH1 | 0x04 |
| 1202 | MSTORE | |
| 1203 | PUSH1 | 0x24 |
| 1205 | PUSH0 | |
| 1206 | REVERT | |
| 1207 | JUMPDEST | |
| 1208 | DUP5 | |
| 1209 | PUSH4 | 0x3131bf79 |
| 120e | PUSH1 | 0xe2 |
| 1210 | SHL | |
| 1211 | PUSH0 | |
| 1212 | MSTORE | |
| 1213 | PUSH1 | 0x04 |
| 1215 | MSTORE | |
| 1216 | PUSH1 | 0x24 |
| 1218 | PUSH0 | |
| 1219 | REVERT | |
| 121a | JUMPDEST | |
| 121b | PUSH2 | 0x1223 |
| 121e | SWAP1 | |
| 121f | PUSH2 | 0x3e2f |
| 1222 | JUMP | |
| 1223 | JUMPDEST | |
| 1224 | ADDRESS | |
| 1225 | PUSH0 | |
| 1226 | MSTORE | |
| 1227 | PUSH1 | 0x14 |
| 1229 | PUSH1 | 0x20 |
| 122b | MSTORE | |
| 122c | PUSH1 | 0x01 |
| 122e | PUSH1 | 0x01 |
| 1230 | PUSH1 | 0x40 |
| 1232 | SHL | |
| 1233 | SUB | |
| 1234 | PUSH1 | 0x40 |
| 1236 | PUSH0 | |
| 1237 | KECCAK256 | |
| 1238 | SWAP2 | |
| 1239 | AND | |
| 123a | PUSH1 | 0x01 |
| 123c | PUSH1 | 0x01 |
| 123e | PUSH1 | 0x40 |
| 1240 | SHL | |
| 1241 | SUB | |
| 1242 | NOT | |
| 1243 | DUP3 | |
| 1244 | SLOAD | |
| 1245 | AND | |
| 1246 | OR | |
| 1247 | SWAP1 | |
| 1248 | SSTORE | |
| 1249 | DUP10 | |
| 124a | PUSH2 | 0x0939 |
| 124d | JUMP | |
| 124e | JUMPDEST | |
| 124f | DUP5 | |
| 1250 | PUSH4 | 0x9ae9f73b |
| 1255 | PUSH1 | 0xe0 |
| 1257 | SHL | |
| 1258 | PUSH0 | |
| 1259 | MSTORE | |
| 125a | PUSH1 | 0x04 |
| 125c | MSTORE | |
| 125d | PUSH1 | 0x24 |
| 125f | PUSH0 | |
| 1260 | REVERT | |
| 1261 | JUMPDEST | |
| 1262 | PUSH2 | 0x1283 |
| 1265 | SWAP4 | |
| 1266 | POP | |
| 1267 | PUSH2 | 0x08ff |
| 126a | PUSH2 | 0x127d |
| 126d | SWAP2 | |
| 126e | PUSH1 | 0x24 |
| 1270 | PUSH2 | 0x0180 |
| 1273 | DUP12 | |
| 1274 | ADD | |
| 1275 | MLOAD | |
| 1276 | SWAP6 | |
| 1277 | ADD | |
| 1278 | SWAP1 | |
| 1279 | PUSH2 | 0x3e4d |
| 127c | JUMP | |
| 127d | JUMPDEST | |
| 127e | SWAP2 | |
| 127f | PUSH2 | 0x4bd9 |
| 1282 | JUMP | |
| 1283 | JUMPDEST | |
| 1284 | ISZERO | |
| 1285 | DUP12 | |
| 1286 | DUP1 | |
| 1287 | DUP1 | |
| 1288 | PUSH2 | 0x0915 |
| 128b | JUMP | |
| 128c | JUMPDEST | |
| 128d | PUSH4 | 0x88e08729 |
| 1292 | PUSH1 | 0xe0 |
| 1294 | SHL | |
| 1295 | PUSH0 | |
| 1296 | MSTORE | |
| 1297 | PUSH1 | 0x04 |
| 1299 | MSTORE | |
| 129a | PUSH1 | 0x24 |
| 129c | MSTORE | |
| 129d | PUSH1 | 0x44 |
| 129f | PUSH0 | |
| 12a0 | REVERT | |
| 12a1 | JUMPDEST | |
| 12a2 | PUSH2 | 0x12be |
| 12a5 | SWAP2 | |
| 12a6 | SWAP11 | |
| 12a7 | POP | |
| 12a8 | RETURNDATASIZE | |
| 12a9 | DUP1 | |
| 12aa | PUSH0 | |
| 12ab | DUP4 | |
| 12ac | RETURNDATACOPY | |
| 12ad | PUSH2 | 0x12b6 |
| 12b0 | DUP2 | |
| 12b1 | DUP4 | |
| 12b2 | PUSH2 | 0x3c98 |
| 12b5 | JUMP | |
| 12b6 | JUMPDEST | |
| 12b7 | DUP2 | |
| 12b8 | ADD | |
| 12b9 | SWAP1 | |
| 12ba | PUSH2 | 0x4133 |
| 12bd | JUMP | |
| 12be | JUMPDEST | |
| 12bf | SWAP9 | |
| 12c0 | DUP11 | |
| 12c1 | PUSH2 | 0x0845 |
| 12c4 | JUMP | |
| 12c5 | JUMPDEST | |
| 12c6 | PUSH1 | 0x40 |
| 12c8 | MLOAD | |
| 12c9 | RETURNDATASIZE | |
| 12ca | PUSH0 | |
| 12cb | DUP3 | |
| 12cc | RETURNDATACOPY | |
| 12cd | RETURNDATASIZE | |
| 12ce | SWAP1 | |
| 12cf | REVERT | |
| 12d0 | JUMPDEST | |
| 12d1 | PUSH0 | |
| 12d2 | SWAP4 | |
| 12d3 | SWAP3 | |
| 12d4 | SWAP2 | |
| 12d5 | SWAP8 | |
| 12d6 | POP | |
| 12d7 | PUSH2 | 0x12e9 |
| 12da | SWAP1 | |
| 12db | RETURNDATASIZE | |
| 12dc | DUP1 | |
| 12dd | DUP7 | |
| 12de | DUP4 | |
| 12df | RETURNDATACOPY | |
| 12e0 | PUSH2 | 0x12b6 |
| 12e3 | DUP2 | |
| 12e4 | DUP4 | |
| 12e5 | PUSH2 | 0x3c98 |
| 12e8 | JUMP | |
| 12e9 | JUMPDEST | |
| 12ea | SWAP7 | |
| 12eb | SWAP1 | |
| 12ec | SWAP2 | |
| 12ed | SWAP3 | |
| 12ee | PUSH2 | 0x0812 |
| 12f1 | JUMP | |
| 12f2 | JUMPDEST | |
| 12f3 | PUSH0 | |
| 12f4 | DUP1 | |
| 12f5 | REVERT | |
| 12f6 | JUMPDEST | |
| 12f7 | CALLVALUE | |
| 12f8 | PUSH2 | 0x12f2 |
| 12fb | JUMPI | |
| 12fc | PUSH1 | 0x20 |
| 12fe | CALLDATASIZE | |
| 12ff | PUSH1 | 0x03 |
| 1301 | NOT | |
| 1302 | ADD | |
| 1303 | SLT | |
| 1304 | PUSH2 | 0x12f2 |
| 1307 | JUMPI | |
| 1308 | PUSH2 | 0x130f |
| 130b | PUSH2 | 0x3bfa |
| 130e | JUMP | |
| 130f | JUMPDEST | |
| 1310 | PUSH1 | 0x40 |
| 1312 | MLOAD | |
| 1313 | PUSH2 | 0x131b |
| 1316 | DUP2 | |
| 1317 | PUSH2 | 0x3c7c |
| 131a | JUMP | |
| 131b | JUMPDEST | |
| 131c | PUSH0 | |
| 131d | DUP2 | |
| 131e | MSTORE | |
| 131f | PUSH1 | 0x20 |
| 1321 | DUP2 | |
| 1322 | ADD | |
| 1323 | PUSH0 | |
| 1324 | SWAP1 | |
| 1325 | MSTORE | |
| 1326 | PUSH1 | 0x40 |
| 1328 | DUP2 | |
| 1329 | ADD | |
| 132a | PUSH0 | |
| 132b | SWAP1 | |
| 132c | MSTORE | |
| 132d | PUSH1 | 0x60 |
| 132f | DUP2 | |
| 1330 | ADD | |
| 1331 | PUSH0 | |
| 1332 | SWAP1 | |
| 1333 | MSTORE | |
| 1334 | PUSH1 | 0x80 |
| 1336 | DUP2 | |
| 1337 | ADD | |
| 1338 | PUSH0 | |
| 1339 | SWAP1 | |
| 133a | MSTORE | |
| 133b | PUSH1 | 0xa0 |
| 133d | DUP2 | |
| 133e | ADD | |
| 133f | PUSH0 | |
| 1340 | SWAP1 | |
| 1341 | MSTORE | |
| 1342 | PUSH1 | 0xc0 |
| 1344 | DUP2 | |
| 1345 | ADD | |
| 1346 | PUSH0 | |
| 1347 | SWAP1 | |
| 1348 | MSTORE | |
| 1349 | PUSH1 | 0xe0 |
| 134b | DUP2 | |
| 134c | ADD | |
| 134d | PUSH0 | |
| 134e | SWAP1 | |
| 134f | MSTORE | |
| 1350 | PUSH2 | 0x0100 |
| 1353 | DUP2 | |
| 1354 | ADD | |
| 1355 | PUSH0 | |
| 1356 | SWAP1 | |
| 1357 | MSTORE | |
| 1358 | PUSH2 | 0x0120 |
| 135b | DUP2 | |
| 135c | ADD | |
| 135d | PUSH0 | |
| 135e | SWAP1 | |
| 135f | MSTORE | |
| 1360 | PUSH2 | 0x0140 |
| 1363 | DUP2 | |
| 1364 | ADD | |
| 1365 | PUSH0 | |
| 1366 | SWAP1 | |
| 1367 | MSTORE | |
| 1368 | PUSH2 | 0x0160 |
| 136b | ADD | |
| 136c | PUSH0 | |
| 136d | SWAP1 | |
| 136e | MSTORE | |
| 136f | PUSH1 | 0x01 |
| 1371 | PUSH1 | 0xa0 |
| 1373 | SHL | |
| 1374 | PUSH1 | 0x01 |
| 1376 | SWAP1 | |
| 1377 | SUB | |
| 1378 | AND | |
| 1379 | PUSH0 | |
| 137a | MSTORE | |
| 137b | PUSH1 | 0x02 |
| 137d | PUSH1 | 0x20 |
| 137f | MSTORE | |
| 1380 | PUSH1 | 0x40 |
| 1382 | PUSH0 | |
| 1383 | KECCAK256 | |
| 1384 | PUSH1 | 0x40 |
| 1386 | MLOAD | |
| 1387 | SWAP1 | |
| 1388 | PUSH2 | 0x1390 |
| 138b | DUP3 | |
| 138c | PUSH2 | 0x3c7c |
| 138f | JUMP | |
| 1390 | JUMPDEST | |
| 1391 | DUP1 | |
| 1392 | SLOAD | |
| 1393 | SWAP2 | |
| 1394 | DUP3 | |
| 1395 | DUP2 | |
| 1396 | MSTORE | |
| 1397 | PUSH1 | 0x01 |
| 1399 | DUP3 | |
| 139a | ADD | |
| 139b | SLOAD | |
| 139c | PUSH1 | 0x20 |
| 139e | DUP3 | |
| 139f | ADD | |
| 13a0 | SWAP1 | |
| 13a1 | DUP2 | |
| 13a2 | MSTORE | |
| 13a3 | PUSH1 | 0x02 |
| 13a5 | DUP4 | |
| 13a6 | ADD | |
| 13a7 | SLOAD | |
| 13a8 | PUSH1 | 0x40 |
| 13aa | DUP4 | |
| 13ab | ADD | |
| 13ac | SWAP1 | |
| 13ad | DUP2 | |
| 13ae | MSTORE | |
| 13af | PUSH1 | 0x03 |
| 13b1 | DUP5 | |
| 13b2 | ADD | |
| 13b3 | SLOAD | |
| 13b4 | PUSH1 | 0x60 |
| 13b6 | DUP5 | |
| 13b7 | ADD | |
| 13b8 | SWAP1 | |
| 13b9 | DUP2 | |
| 13ba | MSTORE | |
| 13bb | PUSH1 | 0x04 |
| 13bd | DUP6 | |
| 13be | ADD | |
| 13bf | SLOAD | |
| 13c0 | SWAP5 | |
| 13c1 | PUSH1 | 0x80 |
| 13c3 | DUP6 | |
| 13c4 | ADD | |
| 13c5 | SWAP6 | |
| 13c6 | DUP7 | |
| 13c7 | MSTORE | |
| 13c8 | PUSH1 | 0x05 |
| 13ca | ADD | |
| 13cb | SLOAD | |
| 13cc | SWAP5 | |
| 13cd | PUSH1 | 0xa0 |
| 13cf | DUP6 | |
| 13d0 | ADD | |
| 13d1 | PUSH1 | 0xff |
| 13d3 | DUP8 | |
| 13d4 | AND | |
| 13d5 | DUP2 | |
| 13d6 | MSTORE | |
| 13d7 | PUSH1 | 0xc0 |
| 13d9 | DUP7 | |
| 13da | ADD | |
| 13db | SWAP2 | |
| 13dc | DUP8 | |
| 13dd | PUSH1 | 0x08 |
| 13df | SHR | |
| 13e0 | PUSH1 | 0xff |
| 13e2 | AND | |
| 13e3 | DUP4 | |
| 13e4 | MSTORE | |
| 13e5 | PUSH1 | 0xe0 |
| 13e7 | DUP8 | |
| 13e8 | ADD | |
| 13e9 | SWAP4 | |
| 13ea | DUP9 | |
| 13eb | PUSH1 | 0x10 |
| 13ed | SHR | |
| 13ee | PUSH1 | 0x01 |
| 13f0 | PUSH1 | 0x01 |
| 13f2 | PUSH1 | 0x40 |
| 13f4 | SHL | |
| 13f5 | SUB | |
| 13f6 | AND | |
| 13f7 | DUP6 | |
| 13f8 | MSTORE | |
| 13f9 | PUSH2 | 0x0100 |
| 13fc | DUP9 | |
| 13fd | ADD | |
| 13fe | SWAP6 | |
| 13ff | DUP10 | |
| 1400 | PUSH1 | 0x50 |
| 1402 | SHR | |
| 1403 | PUSH1 | 0x01 |
| 1405 | PUSH1 | 0x01 |
| 1407 | PUSH1 | 0x40 |
| 1409 | SHL | |
| 140a | SUB | |
| 140b | AND | |
| 140c | DUP8 | |
| 140d | MSTORE | |
| 140e | PUSH2 | 0x0120 |
| 1411 | DUP10 | |
| 1412 | ADD | |
| 1413 | SWAP8 | |
| 1414 | DUP11 | |
| 1415 | PUSH1 | 0x90 |
| 1417 | SHR | |
| 1418 | PUSH1 | 0x01 |
| 141a | PUSH1 | 0x01 |
| 141c | PUSH1 | 0x40 |
| 141e | SHL | |
| 141f | SUB | |
| 1420 | AND | |
| 1421 | DUP10 | |
| 1422 | MSTORE | |
| 1423 | PUSH2 | 0x0140 |
| 1426 | DUP11 | |
| 1427 | ADD | |
| 1428 | SWAP10 | |
| 1429 | DUP12 | |
| 142a | PUSH1 | 0xd0 |
| 142c | SHR | |
| 142d | PUSH1 | 0xff |
| 142f | AND | |
| 1430 | ISZERO | |
| 1431 | ISZERO | |
| 1432 | DUP12 | |
| 1433 | MSTORE | |
| 1434 | PUSH2 | 0x0160 |
| 1437 | ADD | |
| 1438 | SWAP11 | |
| 1439 | PUSH1 | 0xd8 |
| 143b | SHR | |
| 143c | PUSH1 | 0xff |
| 143e | AND | |
| 143f | ISZERO | |
| 1440 | ISZERO | |
| 1441 | DUP12 | |
| 1442 | MSTORE | |
| 1443 | PUSH1 | 0x40 |
| 1445 | MLOAD | |
| 1446 | SWAP12 | |
| 1447 | DUP13 | |
| 1448 | MSTORE | |
| 1449 | MLOAD | |
| 144a | PUSH1 | 0x20 |
| 144c | DUP13 | |
| 144d | ADD | |
| 144e | MSTORE | |
| 144f | MLOAD | |
| 1450 | PUSH1 | 0x40 |
| 1452 | DUP12 | |
| 1453 | ADD | |
| 1454 | MSTORE | |
| 1455 | MLOAD | |
| 1456 | PUSH1 | 0x60 |
| 1458 | DUP11 | |
| 1459 | ADD | |
| 145a | MSTORE | |
| 145b | MLOAD | |
| 145c | PUSH1 | 0x80 |
| 145e | DUP10 | |
| 145f | ADD | |
| 1460 | MSTORE | |
| 1461 | MLOAD | |
| 1462 | PUSH1 | 0xff |
| 1464 | AND | |
| 1465 | PUSH1 | 0xa0 |
| 1467 | DUP9 | |
| 1468 | ADD | |
| 1469 | MSTORE | |
| 146a | MLOAD | |
| 146b | PUSH1 | 0xff |
| 146d | AND | |
| 146e | PUSH1 | 0xc0 |
| 1470 | DUP8 | |
| 1471 | ADD | |
| 1472 | MSTORE | |
| 1473 | MLOAD | |
| 1474 | PUSH1 | 0x01 |
| 1476 | PUSH1 | 0x01 |
| 1478 | PUSH1 | 0x40 |
| 147a | SHL | |
| 147b | SUB | |
| 147c | AND | |
| 147d | PUSH1 | 0xe0 |
| 147f | DUP7 | |
| 1480 | ADD | |
| 1481 | MSTORE | |
| 1482 | MLOAD | |
| 1483 | PUSH1 | 0x01 |
| 1485 | PUSH1 | 0x01 |
| 1487 | PUSH1 | 0x40 |
| 1489 | SHL | |
| 148a | SUB | |
| 148b | AND | |
| 148c | PUSH2 | 0x0100 |
| 148f | DUP6 | |
| 1490 | ADD | |
| 1491 | MSTORE | |
| 1492 | MLOAD | |
| 1493 | PUSH1 | 0x01 |
| 1495 | PUSH1 | 0x01 |
| 1497 | PUSH1 | 0x40 |
| 1499 | SHL | |
| 149a | SUB | |
| 149b | AND | |
| 149c | PUSH2 | 0x0120 |
| 149f | DUP5 | |
| 14a0 | ADD | |
| 14a1 | MSTORE | |
| 14a2 | MLOAD | |
| 14a3 | ISZERO | |
| 14a4 | ISZERO | |
| 14a5 | PUSH2 | 0x0140 |
| 14a8 | DUP4 | |
| 14a9 | ADD | |
| 14aa | MSTORE | |
| 14ab | MLOAD | |
| 14ac | ISZERO | |
| 14ad | ISZERO | |
| 14ae | PUSH2 | 0x0160 |
| 14b1 | DUP3 | |
| 14b2 | ADD | |
| 14b3 | MSTORE | |
| 14b4 | PUSH2 | 0x0180 |
| 14b7 | SWAP1 | |
| 14b8 | RETURN | |
| 14b9 | JUMPDEST | |
| 14ba | CALLVALUE | |
| 14bb | PUSH2 | 0x12f2 |
| 14be | JUMPI | |
| 14bf | PUSH0 | |
| 14c0 | CALLDATASIZE | |
| 14c1 | PUSH1 | 0x03 |
| 14c3 | NOT | |
| 14c4 | ADD | |
| 14c5 | SLT | |
| 14c6 | PUSH2 | 0x12f2 |
| 14c9 | JUMPI | |
| 14ca | PUSH1 | 0x12 |
| 14cc | SLOAD | |
| 14cd | PUSH1 | 0x40 |
| 14cf | MLOAD | |
| 14d0 | PUSH1 | 0x01 |
| 14d2 | PUSH1 | 0x01 |
| 14d4 | PUSH1 | 0xa0 |
| 14d6 | SHL | |
| 14d7 | SUB | |
| 14d8 | SWAP1 | |
| 14d9 | SWAP2 | |
| 14da | AND | |
| 14db | DUP2 | |
| 14dc | MSTORE | |
| 14dd | PUSH1 | 0x20 |
| 14df | SWAP1 | |
| 14e0 | RETURN | |
| 14e1 | JUMPDEST | |
| 14e2 | CALLVALUE | |
| 14e3 | PUSH2 | 0x12f2 |
| 14e6 | JUMPI | |
| 14e7 | PUSH1 | 0x20 |
| 14e9 | CALLDATASIZE | |
| 14ea | PUSH1 | 0x03 |
| 14ec | NOT | |
| 14ed | ADD | |
| 14ee | SLT | |
| 14ef | PUSH2 | 0x12f2 |
| 14f2 | JUMPI | |
| 14f3 | PUSH1 | 0x20 |
| 14f5 | PUSH2 | 0x0434 |
| 14f8 | PUSH2 | 0x14ff |
| 14fb | PUSH2 | 0x3bfa |
| 14fe | JUMP | |
| 14ff | JUMPDEST | |
| 1500 | PUSH2 | 0x43e2 |
| 1503 | JUMP | |
| 1504 | JUMPDEST | |
| 1505 | CALLVALUE | |
| 1506 | PUSH2 | 0x12f2 |
| 1509 | JUMPI | |
| 150a | PUSH0 | |
| 150b | CALLDATASIZE | |
| 150c | PUSH1 | 0x03 |
| 150e | NOT | |
| 150f | ADD | |
| 1510 | SLT | |
| 1511 | PUSH2 | 0x12f2 |
| 1514 | JUMPI | |
| 1515 | PUSH1 | 0x20 |
| 1517 | PUSH1 | 0x40 |
| 1519 | MLOAD | |
| 151a | PUSH2 | 0x0400 |
| 151d | DUP2 | |
| 151e | MSTORE | |
| 151f | RETURN | |
| 1520 | JUMPDEST | |
| 1521 | CALLVALUE | |
| 1522 | PUSH2 | 0x12f2 |
| 1525 | JUMPI | |
| 1526 | PUSH0 | |
| 1527 | CALLDATASIZE | |
| 1528 | PUSH1 | 0x03 |
| 152a | NOT | |
| 152b | ADD | |
| 152c | SLT | |
| 152d | PUSH2 | 0x12f2 |
| 1530 | JUMPI | |
| 1531 | PUSH1 | 0x20 |
| 1533 | PUSH1 | 0x40 |
| 1535 | MLOAD | |
| 1536 | PUSH32 | 0x6e3591285df1e4e62815fc41f5a94072fc4e3ab79993ede42c87f8995a9f8168 |
| 1557 | DUP2 | |
| 1558 | MSTORE | |
| 1559 | RETURN | |
| 155a | JUMPDEST | |
| 155b | CALLVALUE | |
| 155c | PUSH2 | 0x12f2 |
| 155f | JUMPI | |
| 1560 | PUSH1 | 0x20 |
| 1562 | CALLDATASIZE | |
| 1563 | PUSH1 | 0x03 |
| 1565 | NOT | |
| 1566 | ADD | |
| 1567 | SLT | |
| 1568 | PUSH2 | 0x12f2 |
| 156b | JUMPI | |
| 156c | PUSH1 | 0x01 |
| 156e | PUSH1 | 0x01 |
| 1570 | PUSH1 | 0xa0 |
| 1572 | SHL | |
| 1573 | SUB | |
| 1574 | PUSH2 | 0x157b |
| 1577 | PUSH2 | 0x3bfa |
| 157a | JUMP | |
| 157b | JUMPDEST | |
| 157c | AND | |
| 157d | PUSH0 | |
| 157e | MSTORE | |
| 157f | PUSH1 | 0x03 |
| 1581 | PUSH1 | 0x20 |
| 1583 | MSTORE | |
| 1584 | PUSH2 | 0x15a6 |
| 1587 | PUSH2 | 0x1592 |
| 158a | PUSH1 | 0x40 |
| 158c | PUSH0 | |
| 158d | KECCAK256 | |
| 158e | PUSH2 | 0x3eb7 |
| 1591 | JUMP | |
| 1592 | JUMPDEST | |
| 1593 | PUSH1 | 0x40 |
| 1595 | MLOAD | |
| 1596 | SWAP2 | |
| 1597 | DUP3 | |
| 1598 | SWAP2 | |
| 1599 | PUSH1 | 0x20 |
| 159b | DUP4 | |
| 159c | MSTORE | |
| 159d | PUSH1 | 0x20 |
| 159f | DUP4 | |
| 15a0 | ADD | |
| 15a1 | SWAP1 | |
| 15a2 | PUSH2 | 0x3c10 |
| 15a5 | JUMP | |
| 15a6 | JUMPDEST | |
| 15a7 | SUB | |
| 15a8 | SWAP1 | |
| 15a9 | RETURN | |
| 15aa | JUMPDEST | |
| 15ab | CALLVALUE | |
| 15ac | PUSH2 | 0x12f2 |
| 15af | JUMPI | |
| 15b0 | PUSH1 | 0x40 |
| 15b2 | CALLDATASIZE | |
| 15b3 | PUSH1 | 0x03 |
| 15b5 | NOT | |
| 15b6 | ADD | |
| 15b7 | SLT | |
| 15b8 | PUSH2 | 0x12f2 |
| 15bb | JUMPI | |
| 15bc | PUSH1 | 0x01 |
| 15be | PUSH1 | 0x01 |
| 15c0 | PUSH1 | 0xa0 |
| 15c2 | SHL | |
| 15c3 | SUB | |
| 15c4 | PUSH2 | 0x15cb |
| 15c7 | PUSH2 | 0x3bfa |
| 15ca | JUMP | |
| 15cb | JUMPDEST | |
| 15cc | AND | |
| 15cd | PUSH0 | |
| 15ce | MSTORE | |
| 15cf | PUSH1 | 0x15 |
| 15d1 | PUSH1 | 0x20 |
| 15d3 | MSTORE | |
| 15d4 | PUSH1 | 0x20 |
| 15d6 | PUSH1 | 0x01 |
| 15d8 | DUP1 | |
| 15d9 | PUSH1 | 0xa0 |
| 15db | SHL | |
| 15dc | SUB | |
| 15dd | PUSH1 | 0x40 |
| 15df | PUSH0 | |
| 15e0 | KECCAK256 | |
| 15e1 | SLOAD | |
| 15e2 | AND | |
| 15e3 | DUP1 | |
| 15e4 | ISZERO | |
| 15e5 | ISZERO | |
| 15e6 | SWAP1 | |
| 15e7 | DUP2 | |
| 15e8 | PUSH2 | 0x15f7 |
| 15eb | JUMPI | |
| 15ec | JUMPDEST | |
| 15ed | POP | |
| 15ee | PUSH1 | 0x40 |
| 15f0 | MLOAD | |
| 15f1 | SWAP1 | |
| 15f2 | ISZERO | |
| 15f3 | ISZERO | |
| 15f4 | DUP2 | |
| 15f5 | MSTORE | |
| 15f6 | RETURN | |
| 15f7 | JUMPDEST | |
| 15f8 | PUSH2 | 0x1605 |
| 15fb | SWAP2 | |
| 15fc | POP | |
| 15fd | PUSH1 | 0x24 |
| 15ff | CALLDATALOAD | |
| 1600 | SWAP1 | |
| 1601 | PUSH2 | 0x4036 |
| 1604 | JUMP | |
| 1605 | JUMPDEST | |
| 1606 | DUP3 | |
| 1607 | PUSH2 | 0x15ec |
| 160a | JUMP | |
| 160b | JUMPDEST | |
| 160c | CALLVALUE | |
| 160d | PUSH2 | 0x12f2 |
| 1610 | JUMPI | |
| 1611 | PUSH1 | 0x20 |
| 1613 | CALLDATASIZE | |
| 1614 | PUSH1 | 0x03 |
| 1616 | NOT | |
| 1617 | ADD | |
| 1618 | SLT | |
| 1619 | PUSH2 | 0x12f2 |
| 161c | JUMPI | |
| 161d | PUSH1 | 0x01 |
| 161f | PUSH1 | 0x01 |
| 1621 | PUSH1 | 0xa0 |
| 1623 | SHL | |
| 1624 | SUB | |
| 1625 | PUSH2 | 0x162c |
| 1628 | PUSH2 | 0x3bfa |
| 162b | JUMP | |
| 162c | JUMPDEST | |
| 162d | AND | |
| 162e | PUSH0 | |
| 162f | MSTORE | |
| 1630 | PUSH1 | 0x05 |
| 1632 | PUSH1 | 0x20 |
| 1634 | MSTORE | |
| 1635 | PUSH2 | 0x15a6 |
| 1638 | PUSH2 | 0x1592 |
| 163b | PUSH1 | 0x40 |
| 163d | PUSH0 | |
| 163e | KECCAK256 | |
| 163f | PUSH2 | 0x3eb7 |
| 1642 | JUMP | |
| 1643 | JUMPDEST | |
| 1644 | CALLVALUE | |
| 1645 | PUSH2 | 0x12f2 |
| 1648 | JUMPI | |
| 1649 | PUSH0 | |
| 164a | CALLDATASIZE | |
| 164b | PUSH1 | 0x03 |
| 164d | NOT | |
| 164e | ADD | |
| 164f | SLT | |
| 1650 | PUSH2 | 0x12f2 |
| 1653 | JUMPI | |
| 1654 | PUSH1 | 0x20 |
| 1656 | PUSH1 | 0x40 |
| 1658 | MLOAD | |
| 1659 | PUSH1 | 0x10 |
| 165b | DUP2 | |
| 165c | MSTORE | |
| 165d | RETURN | |
| 165e | JUMPDEST | |
| 165f | CALLVALUE | |
| 1660 | PUSH2 | 0x12f2 |
| 1663 | JUMPI | |
| 1664 | PUSH1 | 0x20 |
| 1666 | CALLDATASIZE | |
| 1667 | PUSH1 | 0x03 |
| 1669 | NOT | |
| 166a | ADD | |
| 166b | SLT | |
| 166c | PUSH2 | 0x12f2 |
| 166f | JUMPI | |
| 1670 | PUSH1 | 0x01 |
| 1672 | PUSH1 | 0x01 |
| 1674 | PUSH1 | 0xa0 |
| 1676 | SHL | |
| 1677 | SUB | |
| 1678 | PUSH2 | 0x167f |
| 167b | PUSH2 | 0x3bfa |
| 167e | JUMP | |
| 167f | JUMPDEST | |
| 1680 | AND | |
| 1681 | PUSH0 | |
| 1682 | MSTORE | |
| 1683 | PUSH1 | 0x07 |
| 1685 | PUSH1 | 0x20 |
| 1687 | MSTORE | |
| 1688 | PUSH2 | 0x15a6 |
| 168b | PUSH2 | 0x1592 |
| 168e | PUSH1 | 0x40 |
| 1690 | PUSH0 | |
| 1691 | KECCAK256 | |
| 1692 | PUSH2 | 0x3eb7 |
| 1695 | JUMP | |
| 1696 | JUMPDEST | |
| 1697 | CALLVALUE | |
| 1698 | PUSH2 | 0x12f2 |
| 169b | JUMPI | |
| 169c | PUSH0 | |
| 169d | CALLDATASIZE | |
| 169e | PUSH1 | 0x03 |
| 16a0 | NOT | |
| 16a1 | ADD | |
| 16a2 | SLT | |
| 16a3 | PUSH2 | 0x12f2 |
| 16a6 | JUMPI | |
| 16a7 | PUSH1 | 0x20 |
| 16a9 | PUSH1 | 0x40 |
| 16ab | MLOAD | |
| 16ac | DUP2 | |
| 16ad | DUP2 | |
| 16ae | MSTORE | |
| 16af | RETURN | |
| 16b0 | JUMPDEST | |
| 16b1 | CALLVALUE | |
| 16b2 | PUSH2 | 0x12f2 |
| 16b5 | JUMPI | |
| 16b6 | PUSH0 | |
| 16b7 | CALLDATASIZE | |
| 16b8 | PUSH1 | 0x03 |
| 16ba | NOT | |
| 16bb | ADD | |
| 16bc | SLT | |
| 16bd | PUSH2 | 0x12f2 |
| 16c0 | JUMPI | |
| 16c1 | PUSH1 | 0x20 |
| 16c3 | PUSH1 | 0x40 |
| 16c5 | MLOAD | |
| 16c6 | PUSH1 | 0x02 |
| 16c8 | DUP2 | |
| 16c9 | MSTORE | |
| 16ca | RETURN | |
| 16cb | JUMPDEST | |
| 16cc | CALLVALUE | |
| 16cd | PUSH2 | 0x12f2 |
| 16d0 | JUMPI | |
| 16d1 | PUSH1 | 0x20 |
| 16d3 | CALLDATASIZE | |
| 16d4 | PUSH1 | 0x03 |
| 16d6 | NOT | |
| 16d7 | ADD | |
| 16d8 | SLT | |
| 16d9 | PUSH2 | 0x12f2 |
| 16dc | JUMPI | |
| 16dd | PUSH1 | 0x04 |
| 16df | CALLDATALOAD | |
| 16e0 | PUSH0 | |
| 16e1 | MSTORE | |
| 16e2 | PUSH1 | 0x0c |
| 16e4 | PUSH1 | 0x20 |
| 16e6 | MSTORE | |
| 16e7 | PUSH1 | 0x20 |
| 16e9 | PUSH1 | 0x01 |
| 16eb | DUP1 | |
| 16ec | PUSH1 | 0xa0 |
| 16ee | SHL | |
| 16ef | SUB | |
| 16f0 | PUSH1 | 0x40 |
| 16f2 | PUSH0 | |
| 16f3 | KECCAK256 | |
| 16f4 | SLOAD | |
| 16f5 | AND | |
| 16f6 | PUSH1 | 0x40 |
| 16f8 | MLOAD | |
| 16f9 | SWAP1 | |
| 16fa | DUP2 | |
| 16fb | MSTORE | |
| 16fc | RETURN | |
| 16fd | JUMPDEST | |
| 16fe | CALLVALUE | |
| 16ff | PUSH2 | 0x12f2 |
| 1702 | JUMPI | |
| 1703 | PUSH0 | |
| 1704 | CALLDATASIZE | |
| 1705 | PUSH1 | 0x03 |
| 1707 | NOT | |
| 1708 | ADD | |
| 1709 | SLT | |
| 170a | PUSH2 | 0x12f2 |
| 170d | JUMPI | |
| 170e | PUSH1 | 0x20 |
| 1710 | PUSH1 | 0xff |
| 1712 | PUSH1 | 0x10 |
| 1714 | SLOAD | |
| 1715 | PUSH1 | 0xa0 |
| 1717 | SHR | |
| 1718 | AND | |
| 1719 | PUSH1 | 0x40 |
| 171b | MLOAD |