ETH Price: $1,978.30 (-4.38%)

Contract

0xCb5191a4Aa4baB2674C8A35e8917c14C164fa05c
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Poke229460312025-07-18 12:17:35231 days ago1752841055IN
0xCb5191a4...C164fa05c
0 ETH0.000355495.04193643
Poke229442352025-07-18 6:16:47231 days ago1752819407IN
0xCb5191a4...C164fa05c
0 ETH0.000352454.99881922
Poke229424462025-07-18 0:15:59232 days ago1752797759IN
0xCb5191a4...C164fa05c
0 ETH0.000212023.00713059
Poke229406522025-07-17 18:15:11232 days ago1752776111IN
0xCb5191a4...C164fa05c
0 ETH0.000544877.72780218
Poke229388522025-07-17 12:14:23232 days ago1752754463IN
0xCb5191a4...C164fa05c
0 ETH0.000295944.19882216
Poke229370522025-07-17 6:13:23232 days ago1752732803IN
0xCb5191a4...C164fa05c
0 ETH0.000078431.11235691
Poke229352562025-07-17 0:12:47233 days ago1752711167IN
0xCb5191a4...C164fa05c
0 ETH0.000132951.88562041
Poke229334622025-07-16 18:11:59233 days ago1752689519IN
0xCb5191a4...C164fa05c
0 ETH0.001439220.4118768
Poke229316672025-07-16 12:11:11233 days ago1752667871IN
0xCb5191a4...C164fa05c
0 ETH0.000263713.74019467
Poke229298672025-07-16 6:10:23233 days ago1752646223IN
0xCb5191a4...C164fa05c
0 ETH0.000057170.81097388
Poke229280752025-07-16 0:09:47234 days ago1752624587IN
0xCb5191a4...C164fa05c
0 ETH0.000104151.47720977
Rely227371822025-06-19 7:58:35260 days ago1750319915IN
0xCb5191a4...C164fa05c
0 ETH0.000029530.39170471
Deny227371652025-06-19 7:55:11260 days ago1750319711IN
0xCb5191a4...C164fa05c
0 ETH0.000010310.39433279
Rely227371042025-06-19 7:42:35260 days ago1750318955IN
0xCb5191a4...C164fa05c
0 ETH0.000035530.4713979
Deny227370992025-06-19 7:41:35260 days ago1750318895IN
0xCb5191a4...C164fa05c
0 ETH0.000010860.41569775
Rely227370932025-06-19 7:40:23260 days ago1750318823IN
0xCb5191a4...C164fa05c
0 ETH0.000010050.38108344
Rely227370922025-06-19 7:40:11260 days ago1750318811IN
0xCb5191a4...C164fa05c
0 ETH0.000010910.41357517
Set Bar Schnorr227370892025-06-19 7:39:35260 days ago1750318775IN
0xCb5191a4...C164fa05c
0 ETH0.000010760.41780436
Set Bar ECDSA227370872025-06-19 7:39:11260 days ago1750318751IN
0xCb5191a4...C164fa05c
0 ETH0.000010750.40772017
Set Bar ECDSA227370082025-06-19 7:23:11260 days ago1750317791IN
0xCb5191a4...C164fa05c
0 ETH0.000013160.42463572
Set Bar Schnorr227370072025-06-19 7:22:59260 days ago1750317779IN
0xCb5191a4...C164fa05c
0 ETH0.000011760.38724084
Rely227370022025-06-19 7:21:59260 days ago1750317719IN
0xCb5191a4...C164fa05c
0 ETH0.000028710.38086821
Rely227370002025-06-19 7:21:35260 days ago1750317695IN
0xCb5191a4...C164fa05c
0 ETH0.000029080.38580121
Kiss227368722025-06-19 6:55:59260 days ago1750316159IN
0xCb5191a4...C164fa05c
0 ETH0.000019570.35237372
Rely227368522025-06-19 6:51:47260 days ago1750315907IN
0xCb5191a4...C164fa05c
0 ETH0.00002660.35284231
View all transactions

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Method Block
From
To
0x60c06040227324012025-06-18 15:56:35261 days ago1750262195  Contract Creation0 ETH
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ChronicleVAO_Superstate_USTB_Consumer_1

Compiler Version
v0.8.28+commit.7893614a

Optimization Enabled:
Yes with 10000 runs

Other Settings:
cancun EvmVersion
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.28;

import {Toll} from "chronicle-std/toll/Toll.sol";

import {UScribe} from "uscribe/UScribe.sol";

import {IChronicleVAO_Superstate_USTB_Reader as IReader} from "./IReader.sol";

import {TollWithImmutableRouter} from "./TollWithImmutableRouter.sol";

// The poke struct is the single struct that is being poked.
struct PokeData {
    uint48 age;
    uint128 val;
}

/**
 * @title ChronicleVAO_Superstate_USTB_Consumer_1
 * @custom:version 1.2.0
 *
 * @author Chronicle Labs, Inc
 * @custom:security-contact security@chroniclelabs.org
 */
contract ChronicleVAO_Superstate_USTB_Consumer_1 is
    UScribe,
    TollWithImmutableRouter,
    IReader
{

    /// @notice Thrown if attempted to poke a stale message.
    error StaleMessage();

    /// @notice Thrown if attempted to poke a future message.
    error FutureMessage();

    /// @notice Emitted when a poke is received.
    /// @param caller The caller's address.
    /// @param val The value poked.
    /// @param age The age of the value poked.
    event Poked(address indexed caller, uint128 val, uint48 age);

    //--------------------------------------------------------------------------
    // Storage

    /// @dev The last received poke data (note that age is the block timestamp
    ///      when the poke data was received).
    ///
    /// @dev Note that any data signed beforehand is deemed stale and not
    ///      accepted.
    PokeData internal _pokeData;

    //--------------------------------------------------------------------------
    // Constructor

    constructor(address initialAuthed, address router)
        UScribe(initialAuthed, "VAO::Superstate_USTB")
        TollWithImmutableRouter(router)
    {}

    /// @dev Defines authorization for IToll's authenticated functions.
    function toll_auth() internal override(TollWithImmutableRouter) auth {}

    //--------------------------------------------------------------------------
    // Poke Functionality

    /// @dev Function to handle state update.
    ///
    ///      This function is being called by the upstream uScribe
    ///      implementation iff the poke's signature verification succeeded.
    ///
    ///      Therefore, this function MUST only verify the payload contains
    ///      correctly encoded, non-stale and non-future data before committing a state update.
    ///
    /// @dev Reverts if:
    ///      - Decoding payload to expected format fails
    ///
    /// @dev Returns error if:
    ///      - Payload is stale
    ///      - Payload is signed at a future date to block timestamp
    ///
    /// @dev The payload is expected to be encoded using the PokeData struct
    ///      containing the fields:
    ///
    ///      - age: uint48
    ///      - val: uint128
    ///
    ///  @dev The age stored after a poke is equal to the current block time,
    ///       not the age sent in the poke.
    function _poke(bytes calldata payload)
        internal
        override(UScribe)
        returns (bytes4)
    {
        PokeData memory pokeData = abi.decode(payload, (PokeData));

        // Fail if payload stale.
        if (pokeData.age <= _pokeData.age) {
            return StaleMessage.selector;
        }

        // Fail if payload from the future.
        if (pokeData.age > block.timestamp) {
            return FutureMessage.selector;
        }

        // Store the poke data.
        _pokeData = PokeData({val: pokeData.val, age: uint48(block.timestamp)});

        emit Poked(msg.sender, pokeData.val, pokeData.age);

        return _NO_ERR;
    }

    //--------------------------------------------------------------------------
    // IReader Functionality
    //
    // Note that read functions differ from Scribe with regards to `val = 0` not
    // being a failure code. Read function only revert/fail if `age = 0`,
    // implying no valid poke occured yet.
    //
    // Side effect of this is that the read functions cannot be disabled.

    //// @inheritdoc IVAOReader
    function read() public view toll returns (uint val) {
        bool ok;
        (ok, val,) = _tryReadWithAge();
        require(ok);
    }

    //// @inheritdoc IVAOReader
    function tryRead() public view toll returns (bool ok, uint val) {
        (ok, val,) = _tryReadWithAge();
        // assert(ok || val == 0);
    }

    //// @inheritdoc IVAOReader
    function readWithAge() public view toll returns (uint val, uint age) {
        bool ok;
        (ok, val, age) = _tryReadWithAge();
        require(ok);
    }

    //// @inheritdoc IVAOReader
    function tryReadWithAge()
        public
        view
        toll
        returns (bool ok, uint val, uint age)
    {
        (ok, val, age) = _tryReadWithAge();
    }

    function _tryReadWithAge()
        internal
        view
        returns (bool ok, uint val, uint age)
    {
        PokeData memory pokeData = _pokeData;
        val = pokeData.val;
        age = pokeData.age;
        ok = age != 0;
        // assert(ok || val == 0);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

import {IToll} from "./IToll.sol";

/**
 * @title Toll Module
 *
 * @notice "Toll paid, we kiss - but dissension looms, maybe diss?"
 *
 * @dev The `Toll` contract module provides a basic access control mechanism,
 *      where a set of addresses are granted access to protected functions.
 *      These addresses are said the be _tolled_.
 *
 *      Initially, no address is tolled. Through the `kiss(address)` and
 *      `diss(address)` functions, auth'ed callers are able to toll/de-toll
 *      addresses. Authentication for these functions is defined via the
 *      downstream implemented `toll_auth()` function.
 *
 *      This module is used through inheritance. It will make available the
 *      modifier `toll`, which can be applied to functions to restrict their
 *      use to only tolled callers.
 */
abstract contract Toll is IToll {
    /// @dev Mapping storing whether address is tolled.
    /// @custom:invariant Image of mapping is {0, 1}.
    ///                     ∀x ∊ Address: _buds[x] ∊ {0, 1}
    /// @custom:invariant Only functions `kiss` and `diss` may mutate the mapping's state.
    ///                     ∀x ∊ Address: preTx(_buds[x]) != postTx(_buds[x])
    ///                                     → (msg.sig == "kiss" ∨ msg.sig == "diss")
    /// @custom:invariant Mapping's state may only be mutated by authenticated caller.
    ///                     ∀x ∊ Address: preTx(_buds[x]) != postTx(_buds[x])
    ///                                     → toll_auth()
    mapping(address => uint) private _buds;

    /// @dev List of addresses possibly being tolled.
    /// @dev May contain duplicates.
    /// @dev May contain addresses not being tolled anymore.
    /// @custom:invariant Every address being tolled once is element of the list.
    ///                     ∀x ∊ Address: tolled(x) → x ∊ _budsTouched
    address[] private _budsTouched;

    /// @dev Ensures caller is tolled.
    modifier toll() {
        assembly ("memory-safe") {
            // Compute slot of _buds[msg.sender].
            mstore(0x00, caller())
            mstore(0x20, _buds.slot)
            let slot := keccak256(0x00, 0x40)

            // Revert if caller not tolled.
            let isTolled := sload(slot)
            if iszero(isTolled) {
                // Store selector of `NotTolled(address)`.
                mstore(0x00, 0xd957b595)
                // Store msg.sender.
                mstore(0x20, caller())
                // Revert with (offset, size).
                revert(0x1c, 0x24)
            }
        }
        _;
    }

    /// @dev Reverts if caller not allowed to access protected function.
    /// @dev Must be implemented in downstream contract.
    function toll_auth() internal virtual;

    /// @inheritdoc IToll
    function kiss(address who) external {
        toll_auth();

        if (_buds[who] == 1) return;

        _buds[who] = 1;
        _budsTouched.push(who);
        emit TollGranted(msg.sender, who);
    }

    /// @inheritdoc IToll
    function diss(address who) external {
        toll_auth();

        if (_buds[who] == 0) return;

        _buds[who] = 0;
        emit TollRenounced(msg.sender, who);
    }

    /// @inheritdoc IToll
    function tolled(address who) public view returns (bool) {
        return _buds[who] == 1;
    }

    /// @inheritdoc IToll
    /// @custom:invariant Only contains tolled addresses.
    ///                     ∀x ∊ tolled(): _tolled[x]
    /// @custom:invariant Contains all tolled addresses.
    ///                     ∀x ∊ Address: _tolled[x] == 1 → x ∊ tolled()
    function tolled() public view returns (address[] memory) {
        // Initiate array with upper limit length.
        address[] memory budsList = new address[](_budsTouched.length);

        // Iterate through all possible tolled addresses.
        uint ctr;
        for (uint i; i < budsList.length; i++) {
            // Add address only if still tolled.
            if (_buds[_budsTouched[i]] == 1) {
                budsList[ctr++] = _budsTouched[i];
            }
        }

        // Set length of array to number of tolled addresses actually included.
        assembly ("memory-safe") {
            mstore(budsList, ctr)
        }

        return budsList;
    }

    /// @inheritdoc IToll
    function bud(address who) public view returns (uint) {
        return _buds[who];
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

import {Auth} from "chronicle-std/auth/Auth.sol";

import {IUScribe} from "./IUScribe.sol";
import {UPokeData, SchnorrData, ECDSAData} from "./Types.sol";

import {LibSchnorr} from "./libs/LibSchnorr.sol";
import {LibSecp256k1} from "./libs/LibSecp256k1.sol";

/**
 * @title UScribe
 * @custom:version 1.2.0
 *
 * @notice A universal Oracle
 *
 * @author Chronicle Labs, Inc
 * @custom:security-contact security@chroniclelabs.org
 */
abstract contract UScribe is IUScribe, Auth {
    using LibSchnorr for LibSecp256k1.Point;
    using LibSecp256k1 for LibSecp256k1.Point;
    using LibSecp256k1 for LibSecp256k1.JacobianPoint;

    //--------------------------------------------------------------------------
    // Constants and Immutables

    bytes4 internal constant _NO_ERR = bytes4(0);

    bytes32 public immutable wat;

    // Note that strings cannot be marked as immutable.
    // @custom:invariant Is immutable.
    string private _name;

    //--------------------------------------------------------------------------
    // Storage

    struct SchnorrStorage {
        LibSecp256k1.Point[256] pubKeys;
        uint8 bar;
    }

    SchnorrStorage private __schnorrStorage;

    struct ECDSAStorage {
        address[256] validators;
        uint8 bar;
    }

    ECDSAStorage private __ecdsaStorage;

    //--------------------------------------------------------------------------
    // Constructor

    constructor(address initialAuthed, string memory name_)
        Auth(initialAuthed)
    {
        require(bytes(name_).length != 0);

        _name = name_;
        wat = keccak256(bytes(name_));

        // Note to not have bars of zero.
        __schnorrStorage.bar = type(uint8).max;
        __ecdsaStorage.bar = type(uint8).max;
    }

    /// @inheritdoc IUScribe
    function name() external view returns (string memory) {
        return _name;
    }

    //--------------------------------------------------------------------------
    // Consumer Implemented Functionality

    /// @dev Function implemented in downstream consumer contract to handle
    ///      application specific state update.
    ///
    /// @dev The implementation MUST deserialize the payload and perform
    ///      necessary sanity checks.
    ///
    ///      It SHOULD NOT revert but instead return the error types' selector
    ///      whenever possible. This allows uScribe to wrap the application
    ///      specific error into a `PokeError_ConsumerRejectedPayload()` error.
    ///
    ///      To indicate a successful poke, the function MUST return the
    ///      `_NO_ERR = bytes4(0)` constant.
    ///
    /// @dev Note that this function is vulnerable to replay attacks.
    ///
    ///      Consumers MUST implement application specific logic to prevent
    ///      replayability issues. uScribe only verifies that the respective
    ///      validators attested to the payload at some point in time, ie
    ///      uScribe performs a stateless signature verification.
    ///
    ///      Note that this requires the payload to contain sufficient data for
    ///      the consumer logic to protect against replayability issues.
    ///
    ///      Protections against replayability issues MAY be including a nonce
    ///      in the payload or only accepting payloads with strictly
    ///      monotonically increasing timestamps.
    ///
    ///      To protect against cross-chain replayability issues the payload
    ///      MAY be expected to include the chain's id.
    ///
    /// @param payload The verified payload blob.
    /// @return bytes4 `_NO_ERR` if poke successful, application's error type
    ///                selector otherwise.
    function _poke(bytes calldata payload) internal virtual returns (bytes4);

    //--------------------------------------------------------------------------
    // Poke Functionality

    /// @inheritdoc IUScribe
    function poke(UPokeData calldata uPokeData, SchnorrData calldata schnorr)
        external
    {
        bytes4 err;
        bytes32 message;

        // Construct Schnorr Chronicle Signed Message of uPokeData.
        message = constructChronicleSignedMessage({
            scheme: bytes32("SCHNORR"),
            uPokeData: uPokeData
        });

        // Verify Schnorr signature.
        err = __verifySchnorrSignature(message, schnorr);
        if (err != _NO_ERR) {
            revert PokeError_VerificationFailed(err);
        }

        // Poke's security verified.
        emit UPoked(msg.sender, uPokeData.proofURI);

        // Forward payload to consumer.
        err = _poke(uPokeData.payload);
        if (err != _NO_ERR) {
            revert PokeError_ConsumerRejectedPayload(err);
        }
    }

    /// @inheritdoc IUScribe
    function poke(UPokeData calldata uPokeData, ECDSAData[] calldata ecdsas)
        external
    {
        bytes4 err;
        bytes32 message;

        // Construct ECDSA Chronicle Signed Message of uPokeData.
        message = constructChronicleSignedMessage({
            scheme: bytes32("ECDSA"),
            uPokeData: uPokeData
        });

        // Verify ECDSA signatures.
        err = __verifyECDSASignatures(message, ecdsas);
        if (err != _NO_ERR) {
            revert PokeError_VerificationFailed(err);
        }

        // Poke's security verified.
        emit UPoked(msg.sender, uPokeData.proofURI);

        // Forward payload to consumer.
        err = _poke(uPokeData.payload);
        if (err != _NO_ERR) {
            revert PokeError_ConsumerRejectedPayload(err);
        }
    }

    //--------------------------------------------------------------------------
    // Chronicle Signed Message Functionality

    /// @inheritdoc IUScribe
    function constructChronicleSignedMessage(
        bytes32 scheme,
        UPokeData calldata uPokeData
    ) public view returns (bytes32) {
        return keccak256(
            abi.encodePacked(
                "\x19Chronicle Signed Message:\n32",
                keccak256(
                    abi.encodePacked(
                        scheme,
                        wat,
                        keccak256(abi.encodePacked(uPokeData.payload)),
                        keccak256(abi.encodePacked(uPokeData.proofURI))
                    )
                )
            )
        );
    }

    //--------------------------------------------------------------------------
    // Signature Verification Functionality

    /// @custom:invariant Reverts iff out of gas.
    /// @custom:invariant Runtime is O(__schnorrStorage.bar).
    function __verifySchnorrSignature(
        bytes32 message,
        SchnorrData calldata schnorr
    ) private view returns (bytes4) {
        // Let pubKey be the currently processed validator's public key.
        LibSecp256k1.Point memory pubKey;
        // Let id be the currently processed validator's id.
        uint8 id;
        // Let aggPubKey be the sum of processed validator public keys.
        // Note that Jacobian coordinates are used.
        LibSecp256k1.JacobianPoint memory aggPubKey;
        // Let bloom be a bloom filter to guarantee signer uniqueness.
        uint bloom;

        // Fail if number of validators unequal to bar.
        //
        // Note that requiring equality constrains the verification's runtime
        // from Ω(bar) to Θ(bar).
        uint bar = __schnorrStorage.bar;
        if (schnorr.validatorIds.length != bar) {
            return VerificationError_BarNotReached.selector;
        }

        // Initiate validator variables.
        id = uint8(schnorr.validatorIds[0]);
        pubKey = __schnorrStorage.pubKeys[id];
        if (pubKey.isZeroPoint()) {
            return VerificationError_ValidatorInvalid.selector;
        }

        // Initiate bloom filter and aggPubKey.
        bloom = 1 << id;
        aggPubKey = pubKey.toJacobian();

        // Aggregation loop.
        for (uint i = 1; i < bar; i++) {
            // Update validator variables.
            id = uint8(schnorr.validatorIds[i]);
            pubKey = __schnorrStorage.pubKeys[id];
            if (pubKey.isZeroPoint()) {
                return VerificationError_ValidatorInvalid.selector;
            }

            // Fail if double signing attempted.
            if (bloom & (1 << id) != 0) {
                return VerificationError_DoubleSigningAttempted.selector;
            }

            // Update bloom filter.
            bloom |= 1 << id;

            // Add pubKey to aggPubKey.
            aggPubKey.addAffinePoint(pubKey);
        }

        // Perform signature verification.
        bool ok = aggPubKey.toAffine().verifySignature(
            message, schnorr.signature, schnorr.commitment
        );
        if (!ok) {
            return VerificationError_SignatureInvalid.selector;
        }

        return _NO_ERR;
    }

    /// @custom:invariant Reverts iff out of gas.
    /// @custom:invariant Runtime is O(__ecdsaStorage.bar).
    function __verifyECDSASignatures(
        bytes32 message,
        ECDSAData[] calldata ecdsas
    ) private view returns (bytes4) {
        // Let ecdsa be the currently processed ECDSA signature.
        ECDSAData memory ecdsa;
        // Let signer be the currently processed ECDSA signature's signer.
        address signer;
        // Let id the the currently processed ECDSA signature's signer id.
        uint id;
        // Let bloom be a bloom filter to guarantee signer uniqueness.
        uint bloom;

        // Fail if number of validators unequal to bar.
        //
        // Note that requiring equality constrains the verification's runtime
        // from Ω(bar) to Θ(bar).
        uint bar = __ecdsaStorage.bar;
        if (ecdsas.length != bar) {
            return VerificationError_BarNotReached.selector;
        }

        for (uint i; i < bar; i++) {
            // Update ECDSA variables.
            ecdsa = ecdsas[i];
            signer = ecrecover(message, ecdsa.v, ecdsa.r, ecdsa.s);
            id = uint160(signer) >> 152;

            // Fail if signature invalid or signer not a validator.
            // forgefmt: disable-next-item
            if (signer == address(0) || __ecdsaStorage.validators[id] != signer) {
                return VerificationError_SignatureInvalid.selector;
            }

            // Fail if double signing attempted.
            if (bloom & (1 << id) != 0) {
                return VerificationError_DoubleSigningAttempted.selector;
            }

            // Update bloom filter.
            bloom |= 1 << id;
        }

        return _NO_ERR;
    }

    //--------------------------------------------------------------------------
    // Auth'ed Functionality

    //----------------------------------
    // SchnorrStorage

    /// @inheritdoc IUScribe
    function liftSchnorr(LibSecp256k1.Point[] calldata pubKeys) external auth {
        for (uint i; i < pubKeys.length; i++) {
            LibSecp256k1.Point memory pubKey = pubKeys[i];
            require(!pubKey.isZeroPoint());
            // assert(pubKey.toAddress() != address(0));

            address validator = pubKey.toAddress();
            uint id = uint160(validator) >> 152;

            LibSecp256k1.Point memory sPubKey = __schnorrStorage.pubKeys[id];
            if (sPubKey.isZeroPoint()) {
                __schnorrStorage.pubKeys[id] = pubKey;
                emit ValidatorLiftedSchnorr(msg.sender, validator);
            } else {
                require(validator == sPubKey.toAddress());
            }
        }
    }

    /// @inheritdoc IUScribe
    function dropSchnorr(uint8[] calldata ids) external auth {
        for (uint i; i < ids.length; i++) {
            uint8 id = ids[i];

            LibSecp256k1.Point memory pubKey = __schnorrStorage.pubKeys[id];
            if (!pubKey.isZeroPoint()) {
                delete __schnorrStorage.pubKeys[id];
                emit ValidatorDroppedSchnorr(msg.sender, pubKey.toAddress());
            }
        }
    }

    /// @inheritdoc IUScribe
    function setBarSchnorr(uint8 bar) external auth {
        require(bar != 0);

        if (__schnorrStorage.bar != bar) {
            emit BarUpdatedSchnorr(msg.sender, __schnorrStorage.bar, bar);
            __schnorrStorage.bar = bar;
        }
    }

    //----------------------------------
    // ECDSAStorage

    /// @inheritdoc IUScribe
    function liftECDSA(address[] calldata validators) external auth {
        for (uint i; i < validators.length; i++) {
            address validator = validators[i];
            require(validator != address(0));

            uint id = uint160(validator) >> 152;

            if (__ecdsaStorage.validators[id] == address(0)) {
                __ecdsaStorage.validators[id] = validator;
                emit ValidatorLiftedECDSA(msg.sender, validator);
            } else {
                require(__ecdsaStorage.validators[id] == validator);
            }
        }
    }

    /// @inheritdoc IUScribe
    function dropECDSA(uint8[] calldata ids) external auth {
        for (uint i; i < ids.length; i++) {
            uint8 id = ids[i];
            address validator = __ecdsaStorage.validators[id];

            if (validator != address(0)) {
                // assert(uint160(validator) >> 152 == id);
                delete __ecdsaStorage.validators[id];
                emit ValidatorDroppedECDSA(msg.sender, validator);
            }
        }
    }

    /// @inheritdoc IUScribe
    function setBarECDSA(uint8 bar) external auth {
        require(bar != 0);

        if (__ecdsaStorage.bar != bar) {
            emit BarUpdatedECDSA(msg.sender, __ecdsaStorage.bar, bar);
            __ecdsaStorage.bar = bar;
        }
    }

    //--------------------------------------------------------------------------
    // Public View Functions

    //----------------------------------
    // SchnorrStorage

    /// @inheritdoc IUScribe
    function validatorsSchnorr(address who) external view returns (bool) {
        uint id = uint160(who) >> 152;
        LibSecp256k1.Point memory pubKey = __schnorrStorage.pubKeys[id];

        return !pubKey.isZeroPoint() && pubKey.toAddress() == who;
    }

    /// @inheritdoc IUScribe
    function validatorsSchnorr(uint8 id)
        external
        view
        returns (bool, address)
    {
        LibSecp256k1.Point memory pubKey = __schnorrStorage.pubKeys[id];

        return !pubKey.isZeroPoint()
            ? (true, pubKey.toAddress())
            : (false, address(0));
    }

    /// @inheritdoc IUScribe
    function validatorsSchnorr() external view returns (address[] memory) {
        address[] memory validators = new address[](256);

        LibSecp256k1.Point memory pubKey;
        uint ctr;
        for (uint i; i < 256; i++) {
            pubKey = __schnorrStorage.pubKeys[i];

            if (!pubKey.isZeroPoint()) {
                validators[ctr++] = pubKey.toAddress();
            }
        }

        assembly ("memory-safe") {
            mstore(validators, ctr)
        }

        return validators;
    }

    /// @inheritdoc IUScribe
    function barSchnorr() external view returns (uint8) {
        return __schnorrStorage.bar;
    }

    //----------------------------------
    // ECDSAStorage

    /// @inheritdoc IUScribe
    function validatorsECDSA(address who) external view returns (bool) {
        uint id = uint160(who) >> 152;

        return who != address(0) && __ecdsaStorage.validators[id] == who;
    }

    /// @inheritdoc IUScribe
    function validatorsECDSA(uint id) external view returns (bool, address) {
        address validator = __ecdsaStorage.validators[id];

        return validator != address(0) ? (true, validator) : (false, address(0));
    }

    /// @inheritdoc IUScribe
    function validatorsECDSA() external view returns (address[] memory) {
        address[] memory validators = new address[](256);

        address validator;
        uint ctr;
        for (uint i; i < 256; i++) {
            validator = __ecdsaStorage.validators[i];

            if (validator != address(0)) {
                validators[ctr++] = validator;
            }
        }

        assembly ("memory-safe") {
            mstore(validators, ctr)
        }

        return validators;
    }

    /// @inheritdoc IUScribe
    function barECDSA() external view returns (uint8) {
        return __ecdsaStorage.bar;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

interface IChronicleVAO_Superstate_USTB_Reader {
    /// @notice Returns the oracle's current value.
    /// @dev Reverts if:
    ///      - Not yet poked
    /// @return val The oracle's current value.
    function read() external view returns (uint val);

    /// @notice Returns the oracle's current value.
    /// @return ok True if previously poked, false otherwise.
    /// @return val The oracle's current value if it exists, zero otherwise.
    function tryRead() external view returns (bool ok, uint val);

    /// @notice Returns the oracle's current value and its age.
    /// @dev Reverts if:
    ///      - Not yet poked
    /// @return val The oracle's current value.
    /// @return age The value's age.
    function readWithAge() external view returns (uint val, uint age);

    /// @notice Returns the oracle's current value and its age.
    /// @return ok True if previously poked, false otherwise.
    /// @return val The oracle's current value if it exists, zero otherwise.
    /// @return age The value's age if value exists, zero otherwise.
    function tryReadWithAge()
        external
        view
        returns (bool ok, uint val, uint age);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {IToll} from "chronicle-std/toll/IToll.sol";

/**
 * @title TollWithImmutableRouter
 *
 * @notice "Toll paid, we kiss - but dissension looms, maybe diss?"
 *
 * @dev The `TollWithImmutableRouter` contract module provides a basic access
 *      control mechanism, where a set of addresses are granted access to
 *      protected functions.
 *      These addresses are said the be _tolled_.
 *
 *      Note that this module differs from chronicle-std/Toll in that a router
 *      address given at construction is immutably tolled.
 *
 *      This path reduces gas costs for customers connecting to the router
 *      instead of directly reading from the uscribe consumer.
 *
 *      Initially, only the router is tolled. Through the `kiss(address)` and
 *      `diss(address)` functions, auth'ed callers are able to toll/de-toll
 *      addresses. Authentication for these functions is defined via the
 *      downstream implemented `toll_auth()` function.
 *
 *      This module is used through inheritance. It will make available the
 *      modifier `toll`, which can be applied to functions to restrict their
 *      use to only tolled callers.
 */
abstract contract TollWithImmutableRouter is IToll {
    /// @dev Address of the immutably tolled router.
    address private immutable _router;

    /// @dev Mapping storing whether address is tolled.
    /// @custom:invariant Image of mapping is {0, 1}.
    ///                     ∀x ∊ Address: _buds[x] ∊ {0, 1}
    /// @custom:invariant Only functions `kiss`, `diss` or constructor may
    ///                   mutate the mapping's state.
    ///                     ∀x ∊ Address: preTx(_buds[x]) != postTx(_buds[x])
    ///                                     → (msg.sig == "kiss" ∨ msg.sig == "diss" ∨ msg.sig == "")
    /// @custom:invariant Mapping's state may only be mutated by authenticated
    ///                   caller or during construction.
    ///                     ∀x ∊ Address: preTx(_buds[x]) != postTx(_buds[x])
    ///                                     → (toll_auth() ∨ msg.sig == "")
    mapping(address => uint) private _buds;

    /// @dev List of addresses possibly being tolled.
    /// @dev May contain duplicates.
    /// @dev May contain addresses not being tolled anymore.
    /// @custom:invariant Every address being tolled once is element of the list.
    ///                     ∀x ∊ Address: tolled(x) → x ∊ _budsTouched
    address[] private _budsTouched;

    constructor(address router) {
        _router = router;

        _buds[router] = 1;
        _budsTouched.push(router);
        emit TollGranted(msg.sender, router);
    }

    /// @dev Ensures caller is tolled.
    modifier toll() {
        if (msg.sender != _router) {
            assembly ("memory-safe") {
                // Compute slot of _buds[msg.sender].
                mstore(0x00, caller())
                mstore(0x20, _buds.slot)
                let slot := keccak256(0x00, 0x40)

                // Revert if caller not tolled.
                let isTolled := sload(slot)
                if iszero(isTolled) {
                    // Store selector of `NotTolled(address)`.
                    mstore(0x00, 0xd957b595)
                    // Store msg.sender.
                    mstore(0x20, caller())
                    // Revert with (offset, size).
                    revert(0x1c, 0x24)
                }
            }
        }
        _;
    }

    /// @dev Reverts if caller not allowed to access protected function.
    /// @dev Must be implemented in downstream contract.
    function toll_auth() internal virtual;

    /// @inheritdoc IToll
    function kiss(address who) external {
        toll_auth();

        if (_buds[who] == 1) return;

        _buds[who] = 1;
        _budsTouched.push(who);
        emit TollGranted(msg.sender, who);
    }

    /// @inheritdoc IToll
    function diss(address who) external {
        toll_auth();

        require(who != _router, "TollWithImmutableRouter: cannot diss router");

        if (_buds[who] == 0) return;

        _buds[who] = 0;
        emit TollRenounced(msg.sender, who);
    }

    /// @inheritdoc IToll
    function tolled(address who) public view returns (bool) {
        return _buds[who] == 1;
    }

    /// @inheritdoc IToll
    /// @custom:invariant Only contains tolled addresses.
    ///                     ∀x ∊ tolled(): _buds[x] == 1
    /// @custom:invariant Contains all tolled addresses.
    ///                     ∀x ∊ Address: _buds[x] == 1 → x ∊ tolled()
    function tolled() public view returns (address[] memory) {
        // Initiate array with upper limit length.
        address[] memory budsList = new address[](_budsTouched.length);

        // Iterate through all possible tolled addresses.
        uint ctr;
        for (uint i; i < budsList.length; i++) {
            // Add address only if still tolled.
            if (_buds[_budsTouched[i]] == 1) {
                budsList[ctr++] = _budsTouched[i];
            }
        }

        // Set length of array to number of tolled addresses actually included.
        assembly ("memory-safe") {
            mstore(budsList, ctr)
        }

        return budsList;
    }

    /// @inheritdoc IToll
    function bud(address who) public view returns (uint) {
        return _buds[who];
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

interface IToll {
    /// @notice Thrown by protected function if caller not tolled.
    /// @param caller The caller's address.
    error NotTolled(address caller);

    /// @notice Emitted when toll granted to address.
    /// @param caller The caller's address.
    /// @param who The address toll got granted to.
    event TollGranted(address indexed caller, address indexed who);

    /// @notice Emitted when toll renounced from address.
    /// @param caller The caller's address.
    /// @param who The address toll got renounced from.
    event TollRenounced(address indexed caller, address indexed who);

    /// @notice Grants address `who` toll.
    /// @dev Only callable by auth'ed address.
    /// @param who The address to grant toll.
    function kiss(address who) external;

    /// @notice Renounces address `who`'s toll.
    /// @dev Only callable by auth'ed address.
    /// @param who The address to renounce toll.
    function diss(address who) external;

    /// @notice Returns whether address `who` is tolled.
    /// @param who The address to check.
    /// @return True if `who` is tolled, false otherwise.
    function tolled(address who) external view returns (bool);

    /// @notice Returns full list of addresses tolled.
    /// @dev May contain duplicates.
    /// @return List of addresses tolled.
    function tolled() external view returns (address[] memory);

    /// @notice Returns whether address `who` is tolled.
    /// @custom:deprecated Use `tolled(address)(bool)` instead.
    /// @param who The address to check.
    /// @return 1 if `who` is tolled, 0 otherwise.
    function bud(address who) external view returns (uint);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

import {IAuth} from "./IAuth.sol";

/**
 * @title Auth Module
 *
 * @dev The `Auth` contract module provides a basic access control mechanism,
 *      where a set of addresses are granted access to protected functions.
 *      These addresses are said to be _auth'ed_.
 *
 *      Initially, the address given as constructor argument is the only address
 *      auth'ed. Through the `rely(address)` and `deny(address)` functions,
 *      auth'ed callers are able to grant/renounce auth to/from addresses.
 *
 *      This module is used through inheritance. It will make available the
 *      modifier `auth`, which can be applied to functions to restrict their
 *      use to only auth'ed callers.
 */
abstract contract Auth is IAuth {
    /// @dev Mapping storing whether address is auth'ed.
    /// @custom:invariant Image of mapping is {0, 1}.
    ///                     ∀x ∊ Address: _wards[x] ∊ {0, 1}
    /// @custom:invariant Only address given as constructor argument is authenticated after deployment.
    ///                     deploy(initialAuthed) → (∀x ∊ Address: _wards[x] == 1 → x == initialAuthed)
    /// @custom:invariant Only functions `rely` and `deny` may mutate the mapping's state.
    ///                     ∀x ∊ Address: preTx(_wards[x]) != postTx(_wards[x])
    ///                                     → (msg.sig == "rely" ∨ msg.sig == "deny")
    /// @custom:invariant Mapping's state may only be mutated by authenticated caller.
    ///                     ∀x ∊ Address: preTx(_wards[x]) != postTx(_wards[x]) → _wards[msg.sender] = 1
    mapping(address => uint) private _wards;

    /// @dev List of addresses possibly being auth'ed.
    /// @dev May contain duplicates.
    /// @dev May contain addresses not being auth'ed anymore.
    /// @custom:invariant Every address being auth'ed once is element of the list.
    ///                     ∀x ∊ Address: authed(x) -> x ∊ _wardsTouched
    address[] private _wardsTouched;

    /// @dev Ensures caller is auth'ed.
    modifier auth() {
        assembly ("memory-safe") {
            // Compute slot of _wards[msg.sender].
            mstore(0x00, caller())
            mstore(0x20, _wards.slot)
            let slot := keccak256(0x00, 0x40)

            // Revert if caller not auth'ed.
            let isAuthed := sload(slot)
            if iszero(isAuthed) {
                // Store selector of `NotAuthorized(address)`.
                mstore(0x00, 0x4a0bfec1)
                // Store msg.sender.
                mstore(0x20, caller())
                // Revert with (offset, size).
                revert(0x1c, 0x24)
            }
        }
        _;
    }

    constructor(address initialAuthed) {
        _wards[initialAuthed] = 1;
        _wardsTouched.push(initialAuthed);

        // Note to use address(0) as caller to indicate address was auth'ed
        // during deployment.
        emit AuthGranted(address(0), initialAuthed);
    }

    /// @inheritdoc IAuth
    function rely(address who) external auth {
        if (_wards[who] == 1) return;

        _wards[who] = 1;
        _wardsTouched.push(who);
        emit AuthGranted(msg.sender, who);
    }

    /// @inheritdoc IAuth
    function deny(address who) external auth {
        if (_wards[who] == 0) return;

        _wards[who] = 0;
        emit AuthRenounced(msg.sender, who);
    }

    /// @inheritdoc IAuth
    function authed(address who) public view returns (bool) {
        return _wards[who] == 1;
    }

    /// @inheritdoc IAuth
    /// @custom:invariant Only contains auth'ed addresses.
    ///                     ∀x ∊ authed(): _wards[x] == 1
    /// @custom:invariant Contains all auth'ed addresses.
    ///                     ∀x ∊ Address: _wards[x] == 1 → x ∊ authed()
    function authed() public view returns (address[] memory) {
        // Initiate array with upper limit length.
        address[] memory wardsList = new address[](_wardsTouched.length);

        // Iterate through all possible auth'ed addresses.
        uint ctr;
        for (uint i; i < wardsList.length; i++) {
            // Add address only if still auth'ed.
            if (_wards[_wardsTouched[i]] == 1) {
                wardsList[ctr++] = _wardsTouched[i];
            }
        }

        // Set length of array to number of auth'ed addresses actually included.
        assembly ("memory-safe") {
            mstore(wardsList, ctr)
        }

        return wardsList;
    }

    /// @inheritdoc IAuth
    function wards(address who) public view returns (uint) {
        return _wards[who];
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {UPokeData, SchnorrData, ECDSAData} from "./Types.sol";
import {LibSecp256k1} from "./libs/LibSecp256k1.sol";

interface IUScribe {
    //--------------------------------------------------------------------------
    // Errors

    /// @notice Thrown if poke verification failed.
    /// @param err The verification error.
    error PokeError_VerificationFailed(bytes4 err);

    /// @notice Thrown if poke rejected by consumer.
    /// @param err The consumer error.
    error PokeError_ConsumerRejectedPayload(bytes4 err);

    //----------------------------------
    // Verification Errors

    /// @notice Verification error thrown via `PokeError_VerificationFailed` if
    ///         poke did not reach bar threshold.
    error VerificationError_BarNotReached();

    /// @notice Verification error thrown via `PokeError_VerificationFailed` if
    ///         poke attempted double signing.
    error VerificationError_DoubleSigningAttempted();

    /// @notice Verification error thrown via `PokeError_VerificationFailed` if
    ///         poke included invalid validator.
    error VerificationError_ValidatorInvalid();

    /// @notice Verification error thrown via `PokeError_VerificationFailed` if
    ///         poke included invalid signature.
    error VerificationError_SignatureInvalid();

    //--------------------------------------------------------------------------
    // Events

    /// @notice Emitted when oracle was successfully poked.
    /// @param caller The caller's address.
    /// @param proofURI Optional URI to validity proof.
    event UPoked(address indexed caller, string proofURI);

    /// @notice Emitted when new validator lifted for Schnorr verification.
    /// @param caller The caller's address.
    /// @param validator The validator address lifted.
    event ValidatorLiftedSchnorr(
        address indexed caller, address indexed validator
    );

    /// @notice Emitted when validator dropped from Schnorr verification.
    /// @param caller The caller's address.
    /// @param validator The validator address dropped.
    event ValidatorDroppedSchnorr(
        address indexed caller, address indexed validator
    );

    /// @notice Emitted when bar for Schnorr verification updated.
    /// @param caller The caller's address.
    /// @param oldBar The old bar's value.
    /// @param newBar The new bar's value.
    event BarUpdatedSchnorr(address indexed caller, uint8 oldBar, uint8 newBar);

    /// @notice Emitted when new validator lifted for ECDSA verification.
    /// @param caller The caller's address.
    /// @param validator The validator address lifted.
    event ValidatorLiftedECDSA(
        address indexed caller, address indexed validator
    );

    /// @notice Emitted when validator dropped from ECDSA verification.
    /// @param caller The caller's address.
    /// @param validator The validator address dropped.
    event ValidatorDroppedECDSA(
        address indexed caller, address indexed validator
    );

    /// @notice Emitted when bar for ECDSA verification updated.
    /// @param caller The caller's address.
    /// @param oldBar The old bar's value.
    /// @param newBar The new bar's value.
    event BarUpdatedECDSA(address indexed caller, uint8 oldBar, uint8 newBar);

    //--------------------------------------------------------------------------
    // Poke Functionality

    /// @notice Pokes the oracle using Schnorr verification.
    /// @param uPokeData The UPokeData being poked.
    /// @param schnorrData The SchnorrData proving the `uPokeData`'s integrity.
    function poke(
        UPokeData calldata uPokeData,
        SchnorrData calldata schnorrData
    ) external;

    /// @notice Pokes the oracle using ECDSA verification.
    /// @param uPokeData The UPokeData being poked.
    /// @param ecdsaDatas The list of ECDSAData proving the `uPokeData`'s
    ///                   integrity.
    function poke(UPokeData calldata uPokeData, ECDSAData[] calldata ecdsaDatas)
        external;

    /// @notice Construct a Chronicle Signed Message.
    /// @param scheme The scheme to construct the message for.
    /// @param uPokeData The UPokeData to inlcude in the message.
    function constructChronicleSignedMessage(
        bytes32 scheme,
        UPokeData calldata uPokeData
    ) external view returns (bytes32);

    //--------------------------------------------------------------------------
    // Auth'ed Functionality

    /// @notice Lifts list of public keys `pubKeys` for Schnorr verification.
    /// @dev Only callable by auth'ed address.
    /// @param pubKeys The list of public keys to lift.
    function liftSchnorr(LibSecp256k1.Point[] calldata pubKeys) external;

    /// @notice Drops list of validator ids `ids` from Schnorr verification.
    /// @dev Only callable by auth'ed address.
    /// @param ids The list of validator ids to drop.
    function dropSchnorr(uint8[] calldata ids) external;

    /// @notice Updates the bar security parameter for Schnorr verification.
    /// @dev Only callable by auth'ed address.
    /// @param bar The value to update bar to.
    function setBarSchnorr(uint8 bar) external;

    /// @notice Lifts list of addresses `validators` for ECDSA verification.
    /// @dev Only callable by auth'ed address.
    /// @param validators The list of addresses to lift.
    function liftECDSA(address[] calldata validators) external;

    /// @notice Drops list of validator ids `ids` from ECDSA verification.
    /// @dev Only callable by auth'ed address.
    /// @param ids The list of validator ids to drop.
    function dropECDSA(uint8[] calldata ids) external;

    /// @notice Updates the bar security parameter for ECDSA verification.
    /// @dev Only callable by auth'ed address.
    /// @param bar The value to update bar to.
    function setBarECDSA(uint8 bar) external;

    //--------------------------------------------------------------------------
    // Public View Functions

    /// @notice Returns the oracle's identifier.
    /// @dev The wat is derived from `name()`:
    ///
    ///      ```solidity
    ///      assert(wat() = keccak256(bytes(name())));
    ///      ```
    /// @return bytes32 The oracle's identifier.
    function wat() external view returns (bytes32);

    /// @notice Returns the oracle's name.
    /// @return string The oracle's name.
    function name() external view returns (string memory);

    /// @notice Returns whether address `who` is a validator for Schnorr
    ///         verification.
    /// @param who The address to check.
    /// @return bool True if `who` is a validator for Schnorr verification,
    ///              false otherwise.
    function validatorsSchnorr(address who) external view returns (bool);

    /// @notice Returns whether validator id `id` is a validator for Schnorr
    ///         verification and, if so, the validator's address.
    /// @param id The validator id to check.
    /// @return bool True if `who` is a validator for Schnorr verification,
    ///              false otherwise.
    /// @return address Address of the validator if `id` is a validator for
    ///                 Schnorr verification, zero address otherwise.
    function validatorsSchnorr(uint8 id)
        external
        view
        returns (bool, address);

    /// @notice Returns the lift of validator addresses for Schnorr
    ///         verification.
    /// @return address[] The lift of validator addresses for Schnorr
    ///                   verification.
    function validatorsSchnorr() external view returns (address[] memory);

    /// @notice Returns the bar security parameter for Schnorr verification.
    /// @return uint8 The bar security parameter for Schnorr verification.
    function barSchnorr() external view returns (uint8);

    /// @notice Returns whether address `who` is a validator for ECDSA
    ///         verification.
    /// @param who The address to check.
    /// @return bool True if `who` is a validator for ECDSA verification, false
    ///              otherwise.
    function validatorsECDSA(address who) external view returns (bool);

    /// @notice Returns whether validator id `id` is a validator for ECDSA
    ///         verification and, if so, the validator's address.
    /// @param id The validator id to check.
    /// @return bool True if `who` is a validator for ECDSA verification,
    ///              false otherwise.
    /// @return address Address of the validator if `id` is a validator for
    ///                 ECDSA verification, zero address otherwise.
    function validatorsECDSA(uint id) external view returns (bool, address);

    /// @notice Returns the lift of validator addresses for ECDSA verification.
    /// @return address[] The lift of validator addresses for ECDSA
    ///                   verification.
    function validatorsECDSA() external view returns (address[] memory);

    /// @notice Returns the bar security parameter for ECDSA verification.
    /// @return uint8 The bar security parameter for ECDSA verification.
    function barECDSA() external view returns (uint8);
}

File 9 of 12 : Types.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

struct UPokeData {
    bytes payload;
    string proofURI;
}

struct SchnorrData {
    bytes32 signature;
    address commitment;
    bytes validatorIds;
}

struct ECDSAData {
    uint8 v;
    bytes32 r;
    bytes32 s;
}

File 10 of 12 : LibSchnorr.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

import {LibSecp256k1} from "./LibSecp256k1.sol";

///////////////////////////////////////////////////////////////////////////////
//
// Library copied from Scribe@v2.0.1
//
// Reference: https://github.com/chronicleprotocol/scribe/blob/7d2106a265a8d82f259b506c4c8fec42002546ef/src/libs/LibSchnorr.sol
//
///////////////////////////////////////////////////////////////////////////////

/**
 * @title LibSchnorr
 *
 * @notice Custom-purpose library for Schnorr signature verification on the
 *         secp256k1 curve
 */
library LibSchnorr {
    using LibSecp256k1 for LibSecp256k1.Point;

    /// @dev Returns whether `signature` and `commitment` sign via `pubKey`
    ///      message `message`.
    ///
    /// @custom:invariant Reverts iff out of gas.
    /// @custom:invariant Uses constant amount of gas.
    function verifySignature(
        LibSecp256k1.Point memory pubKey,
        bytes32 message,
        bytes32 signature,
        address commitment
    ) internal pure returns (bool) {
        // Return false if signature or commitment is zero.
        if (signature == 0 || commitment == address(0)) {
            return false;
        }

        // Note to enforce pubKey is valid secp256k1 point.
        //
        // While the Scribe contract ensures to only verify signatures for valid
        // public keys, this check is enabled as an additional defense
        // mechanism.
        if (!pubKey.isOnCurve()) {
            return false;
        }

        // Note to enforce signature is less than Q to prevent signature
        // malleability.
        //
        // While the Scribe contract only accepts messages with strictly
        // monotonically increasing timestamps, circumventing replay attack
        // vectors and therefore also signature malleability issues at a higher
        // level, this check is enabled as an additional defense mechanism.
        if (uint(signature) >= LibSecp256k1.Q()) {
            return false;
        }

        // Construct challenge = H(Pₓ ‖ Pₚ ‖ m ‖ Rₑ) mod Q
        uint challenge = uint(
            keccak256(
                abi.encodePacked(
                    pubKey.x, uint8(pubKey.yParity()), message, commitment
                )
            )
        ) % LibSecp256k1.Q();

        // Compute msgHash = -sig * Pₓ      (mod Q)
        //                 = Q - (sig * Pₓ) (mod Q)
        //
        // Unchecked because the only protected operation performed is the
        // subtraction from Q where the subtrahend is the result of a (mod Q)
        // computation, i.e. the subtrahend is guaranteed to be less than Q.
        uint msgHash;
        unchecked {
            msgHash = LibSecp256k1.Q()
                - mulmod(uint(signature), pubKey.x, LibSecp256k1.Q());
        }

        // Compute v = Pₚ + 27
        //
        // Unchecked because pubKey.yParity() ∊ {0, 1} which cannot overflow
        // by adding 27.
        uint v;
        unchecked {
            v = pubKey.yParity() + 27;
        }

        // Set r = Pₓ
        uint r = pubKey.x;

        // Compute s = Q - (e * Pₓ) (mod Q)
        //
        // Unchecked because the only protected operation performed is the
        // subtraction from Q where the subtrahend is the result of a (mod Q)
        // computation, i.e. the subtrahend is guaranteed to be less than Q.
        uint s;
        unchecked {
            s = LibSecp256k1.Q() - mulmod(challenge, pubKey.x, LibSecp256k1.Q());
        }

        // Compute ([s]G - [e]P)ₑ via ecrecover.
        address recovered =
            ecrecover(bytes32(msgHash), uint8(v), bytes32(r), bytes32(s));

        // Verification succeeds iff ([s]G - [e]P)ₑ = Rₑ.
        //
        // Note that commitment is guaranteed to not be zero.
        return commitment == recovered;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

///////////////////////////////////////////////////////////////////////////////
//
// Library copied from Scribe@v2.0.1
//
// Reference: https://github.com/chronicleprotocol/scribe/blob/7d2106a265a8d82f259b506c4c8fec42002546ef/src/libs/LibSecp256k1.sol
//
///////////////////////////////////////////////////////////////////////////////

/**
 * @title LibSecp256k1
 *
 * @notice Library for secp256k1 elliptic curve computations
 *
 * @dev This library was developed to efficiently compute aggregated public
 *      keys for Schnorr signatures based on secp256k1, i.e. it is _not_ a
 *      general purpose elliptic curve library!
 *
 *      References to the Ethereum Yellow Paper are based on the following
 *      version: "BERLIN VERSION beacfbd – 2022-10-24".
 */
library LibSecp256k1 {
    using LibSecp256k1 for LibSecp256k1.Point;
    using LibSecp256k1 for LibSecp256k1.JacobianPoint;

    uint private constant ADDRESS_MASK =
        0x000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    // -- Secp256k1 Constants --
    //
    // Taken from https://www.secg.org/sec2-v2.pdf.
    // See section 2.4.1 "Recommended Parameters secp256k1".

    uint private constant _A = 0;
    uint private constant _B = 7;
    uint private constant _P =
        0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F;

    /// @dev Returns the order of the group.
    function Q() internal pure returns (uint) {
        return
            0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141;
    }

    /// @dev Returns the generator G.
    ///      Note that the generator is also called base point.
    function G() internal pure returns (Point memory) {
        return Point({
            x: 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,
            y: 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
        });
    }

    /// @dev Returns the zero point.
    function ZERO_POINT() internal pure returns (Point memory) {
        return Point({x: 0, y: 0});
    }

    // -- (Affine) Point --

    /// @dev Point encapsulates a secp256k1 point in Affine coordinates.
    struct Point {
        uint x;
        uint y;
    }

    /// @dev Returns the Ethereum address of `self`.
    ///
    /// @dev An Ethereum address is defined as the rightmost 160 bits of the
    ///      keccak256 hash of the concatenation of the hex-encoded x and y
    ///      coordinates of the corresponding ECDSA public key.
    ///      See "Appendix F: Signing Transactions" §134 in the Yellow Paper.
    function toAddress(Point memory self) internal pure returns (address) {
        address addr;
        // Functionally equivalent Solidity code:
        // addr = address(uint160(uint(keccak256(abi.encode(self.x, self.y)))));
        assembly ("memory-safe") {
            addr := and(keccak256(self, 0x40), ADDRESS_MASK)
        }
        return addr;
    }

    /// @dev Returns Affine point `self` in Jacobian coordinates.
    function toJacobian(Point memory self)
        internal
        pure
        returns (JacobianPoint memory)
    {
        return JacobianPoint({x: self.x, y: self.y, z: 1});
    }

    /// @dev Returns whether `self` is the zero point.
    function isZeroPoint(Point memory self) internal pure returns (bool) {
        return (self.x | self.y) == 0;
    }

    /// @dev Returns whether `self` is a point on the curve.
    ///
    /// @dev The secp256k1 curve is specified as y² ≡ x³ + ax + b (mod P)
    ///      where:
    ///         a = 0
    ///         b = 7
    function isOnCurve(Point memory self) internal pure returns (bool) {
        uint left = mulmod(self.y, self.y, _P);
        // Note that adding a * x can be waived as ∀x: a * x = 0.
        uint right =
            addmod(mulmod(self.x, mulmod(self.x, self.x, _P), _P), _B, _P);

        return left == right;
    }

    /// @dev Returns the parity of `self`'s y coordinate.
    ///
    /// @dev The value 0 represents an even y value and 1 represents an odd y
    ///      value.
    ///      See "Appendix F: Signing Transactions" in the Yellow Paper.
    function yParity(Point memory self) internal pure returns (uint) {
        return self.y & 1;
    }

    // -- Jacobian Point --

    /// @dev JacobianPoint encapsulates a secp256k1 point in Jacobian
    ///      coordinates.
    struct JacobianPoint {
        uint x;
        uint y;
        uint z;
    }

    /// @dev Returns Jacobian point `self` in Affine coordinates.
    ///
    /// @custom:invariant Reverts iff out of gas.
    /// @custom:invariant Does not run into an infinite loop.
    function toAffine(JacobianPoint memory self)
        internal
        pure
        returns (Point memory)
    {
        Point memory result;

        // Compute z⁻¹, i.e. the modular inverse of self.z.
        uint zInv = _invMod(self.z);

        // Compute (z⁻¹)² (mod P)
        uint zInv_2 = mulmod(zInv, zInv, _P);

        // Compute self.x * (z⁻¹)² (mod P), i.e. the x coordinate of given
        // Jacobian point in Affine representation.
        result.x = mulmod(self.x, zInv_2, _P);

        // Compute self.y * (z⁻¹)³ (mod P), i.e. the y coordinate of given
        // Jacobian point in Affine representation.
        result.y = mulmod(self.y, mulmod(zInv, zInv_2, _P), _P);

        return result;
    }

    /// @dev Adds Affine point `p` to Jacobian point `self`.
    ///
    ///      It is the caller's responsibility to ensure given points are on the
    ///      curve!
    ///
    ///      Computation based on: https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#addition-madd-2007-bl.
    ///
    ///      Note that the formula assumes z2 = 1, which always holds if z2's
    ///      point is given in Affine coordinates.
    ///
    ///      Note that eventhough the function is marked as pure, to be
    ///      understood as only being dependent on the input arguments, it
    ///      nevertheless has side effects by writing the result into the
    ///      `self` memory variable.
    ///
    /// @custom:invariant Only mutates `self` memory variable.
    /// @custom:invariant Reverts iff out of gas.
    /// @custom:invariant Uses constant amount of gas.
    function addAffinePoint(JacobianPoint memory self, Point memory p)
        internal
        pure
    {
        // Addition formula:
        //      x = r² - j - (2 * v)             (mod P)
        //      y = (r * (v - x)) - (2 * y1 * j) (mod P)
        //      z = (z1 + h)² - z1² - h²         (mod P)
        //
        // where:
        //      r = 2 * (s - y1) (mod P)
        //      j = h * i        (mod P)
        //      v = x1 * i       (mod P)
        //      h = u - x1       (mod P)
        //      s = y2 * z1³     (mod P)       Called s2 in reference
        //      i = 4 * h²       (mod P)
        //      u = x2 * z1²     (mod P)       Called u2 in reference
        //
        // and:
        //      x1 = self.x
        //      y1 = self.y
        //      z1 = self.z
        //      x2 = p.x
        //      y2 = p.y
        //
        // Note that in order to save memory allocations the result is stored
        // in the self variable, i.e. the following holds true after the
        // functions execution:
        //      x = self.x
        //      y = self.y
        //      z = self.z

        // Cache self's coordinates on stack.
        uint x1 = self.x;
        uint y1 = self.y;
        uint z1 = self.z;

        // Compute z1_2 = z1²     (mod P)
        //              = z1 * z1 (mod P)
        uint z1_2 = mulmod(z1, z1, _P);

        // Compute h = u        - x1       (mod P)
        //           = u        + (P - x1) (mod P)
        //           = x2 * z1² + (P - x1) (mod P)
        //
        // Unchecked because the only protected operation performed is P - x1
        // where x1 is guaranteed by the caller to be an x coordinate belonging
        // to a point on the curve, i.e. being less than P.
        uint h;
        unchecked {
            h = addmod(mulmod(p.x, z1_2, _P), _P - x1, _P);
        }

        // Compute h_2 = h²    (mod P)
        //             = h * h (mod P)
        uint h_2 = mulmod(h, h, _P);

        // Compute i = 4 * h² (mod P)
        uint i = mulmod(4, h_2, _P);

        // Compute z = (z1 + h)² - z1²       - h²       (mod P)
        //           = (z1 + h)² - z1²       + (P - h²) (mod P)
        //           = (z1 + h)² + (P - z1²) + (P - h²) (mod P)
        //             ╰───────╯   ╰───────╯   ╰──────╯
        //               left         mid       right
        //
        // Unchecked because the only protected operations performed are
        // subtractions from P where the subtrahend is the result of a (mod P)
        // computation, i.e. the subtrahend being guaranteed to be less than P.
        unchecked {
            uint left = mulmod(addmod(z1, h, _P), addmod(z1, h, _P), _P);
            uint mid = _P - z1_2;
            uint right = _P - h_2;

            self.z = addmod(left, addmod(mid, right, _P), _P);
        }

        // Compute v = x1 * i (mod P)
        uint v = mulmod(x1, i, _P);

        // Compute j = h * i (mod P)
        uint j = mulmod(h, i, _P);

        // Compute r = 2 * (s               - y1)       (mod P)
        //           = 2 * (s               + (P - y1)) (mod P)
        //           = 2 * ((y2 * z1³)      + (P - y1)) (mod P)
        //           = 2 * ((y2 * z1² * z1) + (P - y1)) (mod P)
        //
        // Unchecked because the only protected operation performed is P - y1
        // where y1 is guaranteed by the caller to be an y coordinate belonging
        // to a point on the curve, i.e. being less than P.
        uint r;
        unchecked {
            r = mulmod(
                2,
                addmod(mulmod(p.y, mulmod(z1_2, z1, _P), _P), _P - y1, _P),
                _P
            );
        }

        // Compute x = r² - j - (2 * v)             (mod P)
        //           = r² - j + (P - (2 * v))       (mod P)
        //           = r² + (P - j) + (P - (2 * v)) (mod P)
        //                  ╰─────╯   ╰───────────╯
        //                    mid         right
        //
        // Unchecked because the only protected operations performed are
        // subtractions from P where the subtrahend is the result of a (mod P)
        // computation, i.e. the subtrahend being guaranteed to be less than P.
        unchecked {
            uint r_2 = mulmod(r, r, _P);
            uint mid = _P - j;
            uint right = _P - mulmod(2, v, _P);

            self.x = addmod(r_2, addmod(mid, right, _P), _P);
        }

        // Compute y = (r * (v - x))       - (2 * y1 * j)       (mod P)
        //           = (r * (v - x))       + (P - (2 * y1 * j)) (mod P)
        //           = (r * (v + (P - x))) + (P - (2 * y1 * j)) (mod P)
        //             ╰─────────────────╯   ╰────────────────╯
        //                    left                 right
        //
        // Unchecked because the only protected operations performed are
        // subtractions from P where the subtrahend is the result of a (mod P)
        // computation, i.e. the subtrahend being guaranteed to be less than P.
        unchecked {
            uint left = mulmod(r, addmod(v, _P - self.x, _P), _P);
            uint right = _P - mulmod(2, mulmod(y1, j, _P), _P);

            self.y = addmod(left, right, _P);
        }
    }

    // -- Private Helpers --

    /// @dev Returns the modular inverse of `x` for modulo `_P`.
    ///
    ///      It is the caller's responsibility to ensure `x` is less than `_P`!
    ///
    ///      The modular inverse of `x` is x⁻¹ such that x * x⁻¹ ≡ 1 (mod P).
    ///
    /// @dev Modified from Jordi Baylina's [ecsol](https://github.com/jbaylina/ecsol/blob/c2256afad126b7500e6f879a9369b100e47d435d/ec.sol#L51-L67).
    ///
    /// @custom:invariant Reverts iff out of gas.
    /// @custom:invariant Does not run into an infinite loop.
    function _invMod(uint x) private pure returns (uint) {
        uint t;
        uint q;
        uint newT = 1;
        uint r = _P;

        assembly ("memory-safe") {
            // Implemented in assembly to circumvent division-by-zero
            // and over-/underflow protection.
            //
            // Functionally equivalent Solidity code:
            //      while (x != 0) {
            //          q = r / x;
            //          (t, newT) = (newT, addmod(t, (_P - mulmod(q, newT, _P)), _P));
            //          (r, x) = (x, r - (q * x));
            //      }
            //
            // For the division r / x, x is guaranteed to not be zero via the
            // loop condition.
            //
            // The subtraction of form P - mulmod(_, _, P) is guaranteed to not
            // underflow due to the subtrahend being a (mod P) result,
            // i.e. the subtrahend being guaranteed to be less than P.
            //
            // The subterm q * x is guaranteed to not overflow because
            // q * x ≤ r due to q = ⎣r / x⎦.
            //
            // The term r - (q * x) is guaranteed to not underflow because
            // q * x ≤ r and therefore r - (q * x) ≥ 0.
            for {} x {} {
                q := div(r, x)

                let tmp := t
                t := newT
                newT := addmod(tmp, sub(_P, mulmod(q, newT, _P)), _P)

                tmp := r
                r := x
                x := sub(tmp, mul(q, x))
            }
        }

        return t;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

interface IAuth {
    /// @notice Thrown by protected function if caller not auth'ed.
    /// @param caller The caller's address.
    error NotAuthorized(address caller);

    /// @notice Emitted when auth granted to address.
    /// @param caller The caller's address.
    /// @param who The address auth got granted to.
    event AuthGranted(address indexed caller, address indexed who);

    /// @notice Emitted when auth renounced from address.
    /// @param caller The caller's address.
    /// @param who The address auth got renounced from.
    event AuthRenounced(address indexed caller, address indexed who);

    /// @notice Grants address `who` auth.
    /// @dev Only callable by auth'ed address.
    /// @param who The address to grant auth.
    function rely(address who) external;

    /// @notice Renounces address `who`'s auth.
    /// @dev Only callable by auth'ed address.
    /// @param who The address to renounce auth.
    function deny(address who) external;

    /// @notice Returns whether address `who` is auth'ed.
    /// @param who The address to check.
    /// @return True if `who` is auth'ed, false otherwise.
    function authed(address who) external view returns (bool);

    /// @notice Returns full list of addresses granted auth.
    /// @dev May contain duplicates.
    /// @return List of addresses granted auth.
    function authed() external view returns (address[] memory);

    /// @notice Returns whether address `who` is auth'ed.
    /// @custom:deprecated Use `authed(address)(bool)` instead.
    /// @param who The address to check.
    /// @return 1 if `who` is auth'ed, 0 otherwise.
    function wards(address who) external view returns (uint);
}

Settings
{
  "remappings": [
    "ds-test/=lib/chronicle-std/lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "chronicle-std/=lib/chronicle-std/src/",
    "greenhouse/=lib/greenhouse/src/",
    "uscribe/=lib/uscribe/src/",
    "test-uscribe/=lib/uscribe/test/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "@script/chronicle-std/=lib/greenhouse/lib/chronicle-std/script/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": true,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"initialAuthed","type":"address"},{"internalType":"address","name":"router","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"FutureMessage","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"NotAuthorized","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"NotTolled","type":"error"},{"inputs":[{"internalType":"bytes4","name":"err","type":"bytes4"}],"name":"PokeError_ConsumerRejectedPayload","type":"error"},{"inputs":[{"internalType":"bytes4","name":"err","type":"bytes4"}],"name":"PokeError_VerificationFailed","type":"error"},{"inputs":[],"name":"StaleMessage","type":"error"},{"inputs":[],"name":"VerificationError_BarNotReached","type":"error"},{"inputs":[],"name":"VerificationError_DoubleSigningAttempted","type":"error"},{"inputs":[],"name":"VerificationError_SignatureInvalid","type":"error"},{"inputs":[],"name":"VerificationError_ValidatorInvalid","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"who","type":"address"}],"name":"AuthGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"who","type":"address"}],"name":"AuthRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint8","name":"oldBar","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"newBar","type":"uint8"}],"name":"BarUpdatedECDSA","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint8","name":"oldBar","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"newBar","type":"uint8"}],"name":"BarUpdatedSchnorr","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint128","name":"val","type":"uint128"},{"indexed":false,"internalType":"uint48","name":"age","type":"uint48"}],"name":"Poked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"who","type":"address"}],"name":"TollGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"who","type":"address"}],"name":"TollRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"string","name":"proofURI","type":"string"}],"name":"UPoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"validator","type":"address"}],"name":"ValidatorDroppedECDSA","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"validator","type":"address"}],"name":"ValidatorDroppedSchnorr","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"validator","type":"address"}],"name":"ValidatorLiftedECDSA","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"validator","type":"address"}],"name":"ValidatorLiftedSchnorr","type":"event"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"authed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"authed","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"barECDSA","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"barSchnorr","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"bud","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"scheme","type":"bytes32"},{"components":[{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"string","name":"proofURI","type":"string"}],"internalType":"struct UPokeData","name":"uPokeData","type":"tuple"}],"name":"constructChronicleSignedMessage","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"deny","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"diss","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8[]","name":"ids","type":"uint8[]"}],"name":"dropECDSA","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8[]","name":"ids","type":"uint8[]"}],"name":"dropSchnorr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"kiss","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"validators","type":"address[]"}],"name":"liftECDSA","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct LibSecp256k1.Point[]","name":"pubKeys","type":"tuple[]"}],"name":"liftSchnorr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"string","name":"proofURI","type":"string"}],"internalType":"struct UPokeData","name":"uPokeData","type":"tuple"},{"components":[{"internalType":"bytes32","name":"signature","type":"bytes32"},{"internalType":"address","name":"commitment","type":"address"},{"internalType":"bytes","name":"validatorIds","type":"bytes"}],"internalType":"struct SchnorrData","name":"schnorr","type":"tuple"}],"name":"poke","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"string","name":"proofURI","type":"string"}],"internalType":"struct UPokeData","name":"uPokeData","type":"tuple"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct ECDSAData[]","name":"ecdsas","type":"tuple[]"}],"name":"poke","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"read","outputs":[{"internalType":"uint256","name":"val","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"readWithAge","outputs":[{"internalType":"uint256","name":"val","type":"uint256"},{"internalType":"uint256","name":"age","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"rely","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"bar","type":"uint8"}],"name":"setBarECDSA","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"bar","type":"uint8"}],"name":"setBarSchnorr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"tolled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tolled","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tryRead","outputs":[{"internalType":"bool","name":"ok","type":"bool"},{"internalType":"uint256","name":"val","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tryReadWithAge","outputs":[{"internalType":"bool","name":"ok","type":"bool"},{"internalType":"uint256","name":"val","type":"uint256"},{"internalType":"uint256","name":"age","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"validatorsECDSA","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"validatorsECDSA","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"validatorsECDSA","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"validatorsSchnorr","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"validatorsSchnorr","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"id","type":"uint8"}],"name":"validatorsSchnorr","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"wards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wat","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"}]

60c0604052346103aa57604051601f612b4b38819003918201601f19168301916001600160401b038311848410176102a65780849260409485528339810103126103aa576100586020610051836103ae565b92016103ae565b604080519192919081016001600160401b038111828210176102a6576040526014815260208101917f56414f3a3a537570657273746174655f55535442000000000000000000000000835260018060a01b0316805f525f602052600160405f2055600154680100000000000000008110156102a65760018101806001558110156102925760015f9081527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf69190910180546001600160a01b031916831790557fe31c10b0adbedd0c6e5d024286c6eeead7761e65a67608dcf0b67604c0da7e2f8180a3805180156103aa576001600160401b0381116102a657600254600181811c911680156103a0575b602082101461038c57601f8111610329575b50806020601f82116001146102c5575f916102ba575b508160011b915f199060031b1c1916176002555b51902060805260ff80196102035416176102035560ff8019610304541617610304558060a05260018060a01b0316805f52610305602052600160405f205561030654680100000000000000008110156102a657600181018061030655811015610292576103065f5260205f20018160018060a01b031982541617905560405190337f75d30ca40c7bcd48e685894b82b864808b9cb566090efc53444a2e61742f18a35f80a361278890816103c3823960805181818161033901528181610ba00152818161100a01526114b2015260a05181818161064601528181610f4601528181611145015281816115650152611b2c0152f35b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b90508201515f61018a565b60025f9081528181209250601f198416905b818110610311575090836001949392106102f9575b5050811b0160025561019e565b8401515f1960f88460031b161c191690555f806102ec565b919260206001819286890151815501940192016102d7565b60025f527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace601f830160051c81019160208410610382575b601f0160051c01905b8181106103775750610174565b5f815560010161036a565b9091508190610361565b634e487b7160e01b5f52602260045260245ffd5b90607f1690610162565b5f80fd5b51906001600160a01b03821682036103aa5756fe6080806040526004361015610012575f80fd5b5f3560e01c90816306fdde03146116bb575080630e947235146116125780630fce3415146115c857806310b07b711461153e578063140432091461139c57806318969a2d146112b5578063224242ca1461121457806338e3e013146111ac578063393e5ede1461111e5780633bee58f9146110d257806344baa5fd1461102d5780634ca2992314610ff35780634fce7a2a14610faa57806357de26a414610f1f5780635b2f752514610efe5780635ffcbba714610e1b578063635d4acd14610d8857806365c4ce7a14610d4e57806365fae35e14610d035780638575738614610a675780638cf6a8f1146109e55780639954b0dc146109275780639c52a7f1146108dc578063a7260f9f146107b5578063bf353dbb1461076e578063cb8370a3146106af578063ceed3ef21461061f578063e32da6e81461049d578063e891c0951461047c578063ef4097cc146103c2578063f0b76dd714610288578063f29c29c41461024c5763fc8717c314610187575f80fd5b34610248576020600319360112610248576101a061180c565b61010081101561021b576101b99060011b600301611ad0565b80516020820151171561021357604073ffffffffffffffffffffffffffffffffffffffff91201660015b60408051911515825273ffffffffffffffffffffffffffffffffffffffff909216602082015290819081015b0390f35b505f806101e3565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f80fd5b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff811681036102485761028690611d58565b005b346102485760406003193601126102485760243567ffffffffffffffff8111610248578060040190604060031982360301126102485761030160209260246102d08280611924565b6102f68760405183819483830196873781015f838201520301601f198101835282611901565b519020930190611924565b6103278460405183819483830196873781015f838201520301601f198101835282611901565b519020604051908382019260043584527f00000000000000000000000000000000000000000000000000000000000000006040840152606083015260808201526080815261037660a082611901565b519020604051828101917f194368726f6e69636c65205369676e6564204d6573736167653a0a33320000008352603d820152603d81526103b7605d82611901565b519020604051908152f35b34610248576020600319360112610248576103db61180c565b335f525f60205260405f20541561046b5760ff8116908115610248576103045460ff811683810361040857005b6040805160ff92831681529390911660208401527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009233917ff1f337dab208fa554bd26f24051a905078905ccd741043ca59e486a3b9e03f4c91a2161761030455005b634a0bfec15f52336020526024601cfd5b34610248575f60031936011261024857602060ff6102035416604051908152f35b346102485760206003193601126102485760043567ffffffffffffffff811161024857366023820112156102485780600401359067ffffffffffffffff8211610248573660248360061b8301011161024857335f525f60205260405f20541561046b575f5b82811015610286578060061b82019060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8336030112610248576040519161054a8361189c565b604460248201359182855201356020840191818352171561024857604083209073ffffffffffffffffffffffffffffffffffffffff82169161010060ff8260981c16101561021b5760971c6101fe1690600382016105a781611ad0565b958651602088015117155f146105f257519055516004919091015560019250337f189ea7fe6fa9a5be238df17366f57d37c1943a76871a92123a439f66bc4893355f80a35b01610502565b505050509091604073ffffffffffffffffffffffffffffffffffffffff91201603610248576001906105ec565b34610248575f6003193601126102485773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361068c575b6060610677611dfa565b90604051921515835260208301526040820152f35b335f5261030560205260405f205461066d5763d957b5955f52336020526024601cfd5b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff81168082036102485761010060ff8360981c16101561021b5761072d7401fffffffffffffffffffffffffffffffffffffffe6101fe6d01fffffffffffffffffffffffffe60209560971c161616600301611ad0565b90815183830151171515918261074a575b50506040519015158152f35b6040902073ffffffffffffffffffffffffffffffffffffffff16149050828061073e565b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff8116809103610248575f525f602052602060405f2054604051908152f35b346102485760206003193601126102485760043567ffffffffffffffff8111610248576107e690369060040161181c565b90335f525f60205260405f20541561046b575f5b82811061080357005b61081661081182858561199c565b611d37565b9073ffffffffffffffffffffffffffffffffffffffff82169182156102485760ff9060981c1691610100831015928361021b57610204019273ffffffffffffffffffffffffffffffffffffffff84541680155f146108ca575061021b5782817fffffffffffffffffffffffff00000000000000000000000000000000000000006001955416179055337fafb0e3c5f69ca0548e193d035ea46175485ad76d40ebac3f49531a414447047f5f80a35b016107fa565b919293505003610248576001906108c4565b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff8116810361024857335f525f60205260405f20541561046b5761028690611cdc565b34610248575f60031936011261024857610943610306546119d2565b5f905f5b81518110156109d2578073ffffffffffffffffffffffffffffffffffffffff610971600193611a1b565b90549060031b1c165f526103056020528160405f205414610993575b01610947565b73ffffffffffffffffffffffffffffffffffffffff6109b182611a1b565b90549060031b1c166109cc6109c586611a4a565b9585611aa4565b5261098d565b5061020f9181526040519182918261184d565b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff8116908181036102485760981c60ff16908015159081610a36575b6020826040519015158152f35b905061010082101561021b5773ffffffffffffffffffffffffffffffffffffffff6020926102040154161482610a29565b346102485760406003193601126102485760043567ffffffffffffffff8111610248578060040190604060031982360301126102485760243567ffffffffffffffff811161024857366023820112156102485780600401359067ffffffffffffffff8211610248573660246060840283010111610248577fffffffff0000000000000000000000000000000000000000000000000000000091610c2a91602480610b118880611924565b610b38602060405183819483830196873781015f838201520301601f198101835282611901565b519020960195610b488789611924565b610b6f602060405183819483830196873781015f838201520301601f198101835282611901565b5190206040519060208201927f454344534100000000000000000000000000000000000000000000000000000084527f000000000000000000000000000000000000000000000000000000000000000060408401526060830152608082015260808152610bdd60a082611901565b51902060405160208101917f194368726f6e69636c65205369676e6564204d6573736167653a0a33320000008352603d820152603d8152610c1f605d82611901565b519020910190612387565b1680610cd8577fffffffff00000000000000000000000000000000000000000000000000000000610ca5610c9f85610c967f16f91548bee0e0722f10b5b21a55dae299cd9024229347fd3063ffe2eee8ea34610c868884611924565b6040513394909283929083611975565b0390a280611924565b90612213565b1680610cad57005b7fda45eb1c000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7fc61f8ee6000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff8116810361024857335f525f60205260405f20541561046b5761028690611c22565b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff811681036102485761028690611aee565b34610248575f60031936011261024857604051601f19612020610dab8184611901565b6101008352013660208301375f5f5b610100811015610e0a5760019073ffffffffffffffffffffffffffffffffffffffff8161020401541680610df0575b5001610dba565b610e03610dfc85611a4a565b9486611aa4565b5284610de9565b8183526040518061020f858261184d565b346102485760206003193601126102485760043567ffffffffffffffff811161024857610e4c90369060040161181c565b90335f525f60205260405f20541561046b575f5b828110610e6957005b610e7c610e7782858561199c565b6119ac565b9061010082101561021b57600191821b80600301610e9981611ad0565b8051602082015117610eaf575b50505001610e60565b5f600473ffffffffffffffffffffffffffffffffffffffff94826040955501552016337f52ce30f1a5a6d183f1c399b08dbbebaa6bcd0e2a3f6da47ff3b6984b863d28de5f80a3848080610ea6565b34610248575f60031936011261024857602060ff6103045416604051908152f35b34610248575f6003193601126102485773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163303610f87575b610f75611dfa565b50901561024857602090604051908152f35b335f5261030560205260405f2054610f6d5763d957b5955f52336020526024601cfd5b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff8116809103610248575f52610305602052602060405f2054604051908152f35b34610248575f6003193601126102485760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610248575f60031936011261024857604051601f196120206110508184611901565b6101008352013660208301376040516110688161189c565b5f81525f6020820152505f905f5b6101008110156109d25760019061109181831b600301611ad0565b80516020820151176110a5575b5001611076565b604073ffffffffffffffffffffffffffffffffffffffff9120166110cb6109c586611a4a565b528461109e565b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff8116809103610248575f526103056020526020600160405f205414604051908152f35b34610248575f6003193601126102485773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163303611189575b611174611dfa565b91156102485760409182519182526020820152f35b335f5261030560205260405f205461116c5763d957b5955f52336020526024601cfd5b346102485760206003193601126102485760043561010081101561021b57610204015473ffffffffffffffffffffffffffffffffffffffff16801561021357604080516001815273ffffffffffffffffffffffffffffffffffffffff92909216602083015290f35b34610248575f6003193601126102485761122f6001546119d2565b5f905f5b81518110156109d2578073ffffffffffffffffffffffffffffffffffffffff61125d600193611a03565b90549060031b1c165f525f6020528160405f20541461127d575b01611233565b73ffffffffffffffffffffffffffffffffffffffff61129b82611a03565b90549060031b1c166112af6109c586611a4a565b52611277565b346102485760206003193601126102485760043567ffffffffffffffff8111610248576112e690369060040161181c565b90335f525f60205260405f20541561046b575f5b82811061130357005b611311610e7782858561199c565b9061010082101561021b576001916102040173ffffffffffffffffffffffffffffffffffffffff815416908161134a575b5050016112fa565b7fffffffffffffffffffffffff00000000000000000000000000000000000000008154169055337f7d553b93bbf05f357fad190f996038832a2de9be7a99c6647f6b047cf3284fc95f80a38480611342565b346102485760406003193601126102485760043567ffffffffffffffff8111610248578060040190604060031982360301126102485760243567ffffffffffffffff8111610248576060600319823603011261024857610c2a7fffffffff000000000000000000000000000000000000000000000000000000009160246114238680611924565b61144a602060405183819483830196873781015f838201520301601f198101835282611901565b51902094019361145a8587611924565b611481602060405183819483830196873781015f838201520301601f198101835282611901565b5190206040519060208201927f5343484e4f52520000000000000000000000000000000000000000000000000084527f0000000000000000000000000000000000000000000000000000000000000000604084015260608301526080820152608081526114ef60a082611901565b51902060405160208101917f194368726f6e69636c65205369676e6564204d6573736167653a0a33320000008352603d820152603d8152611531605d82611901565b5190209060040190611e59565b34610248575f6003193601126102485773ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036115a5575b6040611596611dfa565b50825191151582526020820152f35b335f5261030560205260405f205461158c5763d957b5955f52336020526024601cfd5b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff8116809103610248575f525f6020526020600160405f205414604051908152f35b346102485760206003193601126102485761162b61180c565b335f525f60205260405f20541561046b5760ff8116908115610248576102035460ff811683810361165857005b6040805160ff92831681529390911660208401527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009233917f6725eac4d9463d79b15ccb65e620936de0a75d44795151a2fc5a6f62f1dc376c91a2161761020355005b34610248575f600319360112610248575f90600254918260011c60018416938415611802575b6020821085146117d557818452602084019490811561179c575060011461173e575b5090611713816040930382611901565b601f19601f8351948593602085525180918160208701528686015e5f85828601015201168101030190f35b91905060025f527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace915f905b80821061178257509091508101602001611713611703565b91926001816020925483858801015201910190929161176a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016855250151560051b82016020019050611713611703565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b90607f16906116e1565b6004359060ff8216820361024857565b9181601f840112156102485782359167ffffffffffffffff8311610248576020808501948460051b01011161024857565b60206040818301928281528451809452019201905f5b8181106118705750505090565b825173ffffffffffffffffffffffffffffffffffffffff16845260209384019390920191600101611863565b6040810190811067ffffffffffffffff8211176118b857604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6060810190811067ffffffffffffffff8211176118b857604052565b90601f601f19910116810190811067ffffffffffffffff8211176118b857604052565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610248570180359067ffffffffffffffff82116102485760200191813603831361024857565b90601f83604094601f199360208652816020870152868601375f8582860101520116010190565b919081101561021b5760051b0190565b3560ff811681036102485790565b67ffffffffffffffff81116118b85760051b60200190565b906119dc826119ba565b6119e96040519182611901565b828152601f196119f982946119ba565b0190602036910137565b60015481101561021b5760015f5260205f2001905f90565b6103065481101561021b576103065f5260205f2001905f90565b805482101561021b575f5260205f2001905f90565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611a775760010190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b805182101561021b5760209160051b010190565b60405190611ac58261189c565b5f6020838281520152565b90604051611add8161189c565b602060018294805484520154910152565b335f525f60205260405f20541561046b5773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168114611b9e57805f5261030560205260405f205415611b9b57805f526103056020525f6040812055337fdadd1471db1ea2f303654fb1bdcc010e5a664214ab41934c0f752aabca88a4915f80a3565b50565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f546f6c6c57697468496d6d757461626c65526f757465723a2063616e6e6f742060448201527f6469737320726f757465720000000000000000000000000000000000000000006064820152fd5b73ffffffffffffffffffffffffffffffffffffffff811690815f525f602052600160405f205414611cd857815f525f602052600160405f205560015490680100000000000000008210156118b857611c85826001611cb194016001556001611a35565b90919073ffffffffffffffffffffffffffffffffffffffff8084549260031b9316831b921b1916179055565b337fe31c10b0adbedd0c6e5d024286c6eeead7761e65a67608dcf0b67604c0da7e2f5f80a3565b5050565b73ffffffffffffffffffffffffffffffffffffffff16805f525f60205260405f205415611b9b57805f525f6020525f6040812055337f58466e5837b54e559819c9ba8a5d7c77c97c985d1aabf4bdc5f41069fa5d65a05f80a3565b3573ffffffffffffffffffffffffffffffffffffffff811681036102485790565b335f525f60205260405f20541561046b5773ffffffffffffffffffffffffffffffffffffffff811690815f52610305602052600160405f205414611cd857815f52610305602052600160405f20556103065490680100000000000000008210156118b857611c85826001611dd3940161030655610306611a35565b337f75d30ca40c7bcd48e685894b82b864808b9cb566090efc53444a2e61742f18a35f80a3565b604051611e068161189c565b602061030754916fffffffffffffffffffffffffffffffff65ffffffffffff84169384835260301c1691829101529080151592565b60405190611e48826118e5565b5f6040838281528260208201520152565b9190611e63611ab8565b50611e6c611e3b565b5060ff6102035416604082019381611e848685611924565b9050036121eb57611e958584611924565b1561021b57358060f81c9061010082101561021b576101fe80611ebf9260f71c1616600301611ad0565b928351916020850192835117156121c0576001909791971b93611ee0611e3b565b505191519660405192611ef2846118e5565b8352602083019788526040830194600186526001925f935b838110612023575050505050611f1e611ab8565b5060405192611f2c8461189c565b5f84525f602085015251955f96600190807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f915b611fe657505050957ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8092611fb99798828085800980935109875251920990096020830152611fb160208401611d37565b92359161253d565b15611fc2575f90565b7fcbc4755f0000000000000000000000000000000000000000000000000000000090565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8183949b930492818c8509820390089290918202900380611f60565b61202d828a611924565b82101561021b57810135908160f81c9161010083101561021b576101fe8061205c9260f71c1616600301611ad0565b9384519260208601938451171561218f576001901b9081811661215e57179387518d51978b5190612131576001947ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f83818f818f978f9982809b818b8180809e819a82809a818085819609809c510990820390089d8e91838b818080878009928184600409998a988d0893820390820308918009089052099b099b519282039409900908600209948180808660020981038382030881888009088098525f9e09600209820394820390089009088c5201611f0a565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b507fe7908552000000000000000000000000000000000000000000000000000000009c505050505050505050505050565b507f552e5639000000000000000000000000000000000000000000000000000000009c505050505050505050505050565b507f552e56390000000000000000000000000000000000000000000000000000000096505050505050565b507f19877c600000000000000000000000000000000000000000000000000000000093505050565b908160409181010312610248576040519061222d8261189c565b803565ffffffffffff81169182820361024857602091845201356fffffffffffffffffffffffffffffffff811691828203610248576020840190828252610307549065ffffffffffff821681111561235d5742106123345765ffffffffffff937fffffffffffffffffffff0000000000000000000000000000000000000000000075ffffffffffffffffffffffffffffffff0000000000006fffffffffffffffffffffffffffffffff958742169360206040516122e98161189c565b868152015260301b169216171761030755511691511660405191825260208201527f9f8b8154174dc4a9ed8bbe5a985ecf6d8b2db481a1c64a02c8d94ae7929e0ba660403392a25f90565b50505050507f5507d1ac0000000000000000000000000000000000000000000000000000000090565b5050505050507f4ef874670000000000000000000000000000000000000000000000000000000090565b61238f611e3b565b505f9160ff610304541693848103612514575f935b8585106123b5575050505050505f90565b8185101561021b57606085028301606081360312610248576040516123d9816118e5565b81359160ff83168084036102485761242e836020955f9552604086850135948588840152013590816040820152506040519384938b859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa15612509575f5160ff73ffffffffffffffffffffffffffffffffffffffff82169160981c169080159081156124d9575b506124ae576001901b80821661248357600191179401936123a4565b505050505050507fe79085520000000000000000000000000000000000000000000000000000000090565b505050505050507fcbc4755f0000000000000000000000000000000000000000000000000000000090565b905061010082101561021b5773ffffffffffffffffffffffffffffffffffffffff8261020401541614155f612467565b6040513d5f823e3d90fd5b50505050507f19877c600000000000000000000000000000000000000000000000000000000090565b909180158015612734575b61272c57602082019081517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8060078187518181800990090891800903612723577ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141811015612723576126f683601b60017ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141806020995f9951908951907f0100000000000000000000000000000000000000000000000000000000000000604051928e840194855260f81b16604083015260418201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008d60601b16606182015260558152612658607582611901565b5190200695845190097ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036414103955116019051809460ff7ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641416040519788970991865290921660ff16602085015260408401527ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410360608301526080820190565b838052039060015afa156125095773ffffffffffffffffffffffffffffffffffffffff805f511691161490565b50505050505f90565b505050505f90565b5073ffffffffffffffffffffffffffffffffffffffff84161561254856fea26469706673582212207274edf763fbf257186cd3efc51a4a943890b9382d23ffbbe1fc72e40ad8b46864736f6c634300081c003300000000000000000000000074258a92611e029b748f79c50024dd851339db15000000000000000000000000d40d9e595bdf98731fbf70da31217c7d7654db61

Deployed Bytecode

0x6080806040526004361015610012575f80fd5b5f3560e01c90816306fdde03146116bb575080630e947235146116125780630fce3415146115c857806310b07b711461153e578063140432091461139c57806318969a2d146112b5578063224242ca1461121457806338e3e013146111ac578063393e5ede1461111e5780633bee58f9146110d257806344baa5fd1461102d5780634ca2992314610ff35780634fce7a2a14610faa57806357de26a414610f1f5780635b2f752514610efe5780635ffcbba714610e1b578063635d4acd14610d8857806365c4ce7a14610d4e57806365fae35e14610d035780638575738614610a675780638cf6a8f1146109e55780639954b0dc146109275780639c52a7f1146108dc578063a7260f9f146107b5578063bf353dbb1461076e578063cb8370a3146106af578063ceed3ef21461061f578063e32da6e81461049d578063e891c0951461047c578063ef4097cc146103c2578063f0b76dd714610288578063f29c29c41461024c5763fc8717c314610187575f80fd5b34610248576020600319360112610248576101a061180c565b61010081101561021b576101b99060011b600301611ad0565b80516020820151171561021357604073ffffffffffffffffffffffffffffffffffffffff91201660015b60408051911515825273ffffffffffffffffffffffffffffffffffffffff909216602082015290819081015b0390f35b505f806101e3565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f80fd5b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff811681036102485761028690611d58565b005b346102485760406003193601126102485760243567ffffffffffffffff8111610248578060040190604060031982360301126102485761030160209260246102d08280611924565b6102f68760405183819483830196873781015f838201520301601f198101835282611901565b519020930190611924565b6103278460405183819483830196873781015f838201520301601f198101835282611901565b519020604051908382019260043584527fe4ee0a2eb1d0299212172dfca37468f842440be7d40e2589e57b6f0689b1373c6040840152606083015260808201526080815261037660a082611901565b519020604051828101917f194368726f6e69636c65205369676e6564204d6573736167653a0a33320000008352603d820152603d81526103b7605d82611901565b519020604051908152f35b34610248576020600319360112610248576103db61180c565b335f525f60205260405f20541561046b5760ff8116908115610248576103045460ff811683810361040857005b6040805160ff92831681529390911660208401527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009233917ff1f337dab208fa554bd26f24051a905078905ccd741043ca59e486a3b9e03f4c91a2161761030455005b634a0bfec15f52336020526024601cfd5b34610248575f60031936011261024857602060ff6102035416604051908152f35b346102485760206003193601126102485760043567ffffffffffffffff811161024857366023820112156102485780600401359067ffffffffffffffff8211610248573660248360061b8301011161024857335f525f60205260405f20541561046b575f5b82811015610286578060061b82019060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8336030112610248576040519161054a8361189c565b604460248201359182855201356020840191818352171561024857604083209073ffffffffffffffffffffffffffffffffffffffff82169161010060ff8260981c16101561021b5760971c6101fe1690600382016105a781611ad0565b958651602088015117155f146105f257519055516004919091015560019250337f189ea7fe6fa9a5be238df17366f57d37c1943a76871a92123a439f66bc4893355f80a35b01610502565b505050509091604073ffffffffffffffffffffffffffffffffffffffff91201603610248576001906105ec565b34610248575f6003193601126102485773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d40d9e595bdf98731fbf70da31217c7d7654db6116330361068c575b6060610677611dfa565b90604051921515835260208301526040820152f35b335f5261030560205260405f205461066d5763d957b5955f52336020526024601cfd5b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff81168082036102485761010060ff8360981c16101561021b5761072d7401fffffffffffffffffffffffffffffffffffffffe6101fe6d01fffffffffffffffffffffffffe60209560971c161616600301611ad0565b90815183830151171515918261074a575b50506040519015158152f35b6040902073ffffffffffffffffffffffffffffffffffffffff16149050828061073e565b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff8116809103610248575f525f602052602060405f2054604051908152f35b346102485760206003193601126102485760043567ffffffffffffffff8111610248576107e690369060040161181c565b90335f525f60205260405f20541561046b575f5b82811061080357005b61081661081182858561199c565b611d37565b9073ffffffffffffffffffffffffffffffffffffffff82169182156102485760ff9060981c1691610100831015928361021b57610204019273ffffffffffffffffffffffffffffffffffffffff84541680155f146108ca575061021b5782817fffffffffffffffffffffffff00000000000000000000000000000000000000006001955416179055337fafb0e3c5f69ca0548e193d035ea46175485ad76d40ebac3f49531a414447047f5f80a35b016107fa565b919293505003610248576001906108c4565b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff8116810361024857335f525f60205260405f20541561046b5761028690611cdc565b34610248575f60031936011261024857610943610306546119d2565b5f905f5b81518110156109d2578073ffffffffffffffffffffffffffffffffffffffff610971600193611a1b565b90549060031b1c165f526103056020528160405f205414610993575b01610947565b73ffffffffffffffffffffffffffffffffffffffff6109b182611a1b565b90549060031b1c166109cc6109c586611a4a565b9585611aa4565b5261098d565b5061020f9181526040519182918261184d565b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff8116908181036102485760981c60ff16908015159081610a36575b6020826040519015158152f35b905061010082101561021b5773ffffffffffffffffffffffffffffffffffffffff6020926102040154161482610a29565b346102485760406003193601126102485760043567ffffffffffffffff8111610248578060040190604060031982360301126102485760243567ffffffffffffffff811161024857366023820112156102485780600401359067ffffffffffffffff8211610248573660246060840283010111610248577fffffffff0000000000000000000000000000000000000000000000000000000091610c2a91602480610b118880611924565b610b38602060405183819483830196873781015f838201520301601f198101835282611901565b519020960195610b488789611924565b610b6f602060405183819483830196873781015f838201520301601f198101835282611901565b5190206040519060208201927f454344534100000000000000000000000000000000000000000000000000000084527fe4ee0a2eb1d0299212172dfca37468f842440be7d40e2589e57b6f0689b1373c60408401526060830152608082015260808152610bdd60a082611901565b51902060405160208101917f194368726f6e69636c65205369676e6564204d6573736167653a0a33320000008352603d820152603d8152610c1f605d82611901565b519020910190612387565b1680610cd8577fffffffff00000000000000000000000000000000000000000000000000000000610ca5610c9f85610c967f16f91548bee0e0722f10b5b21a55dae299cd9024229347fd3063ffe2eee8ea34610c868884611924565b6040513394909283929083611975565b0390a280611924565b90612213565b1680610cad57005b7fda45eb1c000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7fc61f8ee6000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff8116810361024857335f525f60205260405f20541561046b5761028690611c22565b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff811681036102485761028690611aee565b34610248575f60031936011261024857604051601f19612020610dab8184611901565b6101008352013660208301375f5f5b610100811015610e0a5760019073ffffffffffffffffffffffffffffffffffffffff8161020401541680610df0575b5001610dba565b610e03610dfc85611a4a565b9486611aa4565b5284610de9565b8183526040518061020f858261184d565b346102485760206003193601126102485760043567ffffffffffffffff811161024857610e4c90369060040161181c565b90335f525f60205260405f20541561046b575f5b828110610e6957005b610e7c610e7782858561199c565b6119ac565b9061010082101561021b57600191821b80600301610e9981611ad0565b8051602082015117610eaf575b50505001610e60565b5f600473ffffffffffffffffffffffffffffffffffffffff94826040955501552016337f52ce30f1a5a6d183f1c399b08dbbebaa6bcd0e2a3f6da47ff3b6984b863d28de5f80a3848080610ea6565b34610248575f60031936011261024857602060ff6103045416604051908152f35b34610248575f6003193601126102485773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d40d9e595bdf98731fbf70da31217c7d7654db61163303610f87575b610f75611dfa565b50901561024857602090604051908152f35b335f5261030560205260405f2054610f6d5763d957b5955f52336020526024601cfd5b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff8116809103610248575f52610305602052602060405f2054604051908152f35b34610248575f6003193601126102485760206040517fe4ee0a2eb1d0299212172dfca37468f842440be7d40e2589e57b6f0689b1373c8152f35b34610248575f60031936011261024857604051601f196120206110508184611901565b6101008352013660208301376040516110688161189c565b5f81525f6020820152505f905f5b6101008110156109d25760019061109181831b600301611ad0565b80516020820151176110a5575b5001611076565b604073ffffffffffffffffffffffffffffffffffffffff9120166110cb6109c586611a4a565b528461109e565b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff8116809103610248575f526103056020526020600160405f205414604051908152f35b34610248575f6003193601126102485773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d40d9e595bdf98731fbf70da31217c7d7654db61163303611189575b611174611dfa565b91156102485760409182519182526020820152f35b335f5261030560205260405f205461116c5763d957b5955f52336020526024601cfd5b346102485760206003193601126102485760043561010081101561021b57610204015473ffffffffffffffffffffffffffffffffffffffff16801561021357604080516001815273ffffffffffffffffffffffffffffffffffffffff92909216602083015290f35b34610248575f6003193601126102485761122f6001546119d2565b5f905f5b81518110156109d2578073ffffffffffffffffffffffffffffffffffffffff61125d600193611a03565b90549060031b1c165f525f6020528160405f20541461127d575b01611233565b73ffffffffffffffffffffffffffffffffffffffff61129b82611a03565b90549060031b1c166112af6109c586611a4a565b52611277565b346102485760206003193601126102485760043567ffffffffffffffff8111610248576112e690369060040161181c565b90335f525f60205260405f20541561046b575f5b82811061130357005b611311610e7782858561199c565b9061010082101561021b576001916102040173ffffffffffffffffffffffffffffffffffffffff815416908161134a575b5050016112fa565b7fffffffffffffffffffffffff00000000000000000000000000000000000000008154169055337f7d553b93bbf05f357fad190f996038832a2de9be7a99c6647f6b047cf3284fc95f80a38480611342565b346102485760406003193601126102485760043567ffffffffffffffff8111610248578060040190604060031982360301126102485760243567ffffffffffffffff8111610248576060600319823603011261024857610c2a7fffffffff000000000000000000000000000000000000000000000000000000009160246114238680611924565b61144a602060405183819483830196873781015f838201520301601f198101835282611901565b51902094019361145a8587611924565b611481602060405183819483830196873781015f838201520301601f198101835282611901565b5190206040519060208201927f5343484e4f52520000000000000000000000000000000000000000000000000084527fe4ee0a2eb1d0299212172dfca37468f842440be7d40e2589e57b6f0689b1373c604084015260608301526080820152608081526114ef60a082611901565b51902060405160208101917f194368726f6e69636c65205369676e6564204d6573736167653a0a33320000008352603d820152603d8152611531605d82611901565b5190209060040190611e59565b34610248575f6003193601126102485773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d40d9e595bdf98731fbf70da31217c7d7654db611633036115a5575b6040611596611dfa565b50825191151582526020820152f35b335f5261030560205260405f205461158c5763d957b5955f52336020526024601cfd5b346102485760206003193601126102485760043573ffffffffffffffffffffffffffffffffffffffff8116809103610248575f525f6020526020600160405f205414604051908152f35b346102485760206003193601126102485761162b61180c565b335f525f60205260405f20541561046b5760ff8116908115610248576102035460ff811683810361165857005b6040805160ff92831681529390911660208401527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009233917f6725eac4d9463d79b15ccb65e620936de0a75d44795151a2fc5a6f62f1dc376c91a2161761020355005b34610248575f600319360112610248575f90600254918260011c60018416938415611802575b6020821085146117d557818452602084019490811561179c575060011461173e575b5090611713816040930382611901565b601f19601f8351948593602085525180918160208701528686015e5f85828601015201168101030190f35b91905060025f527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace915f905b80821061178257509091508101602001611713611703565b91926001816020925483858801015201910190929161176a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016855250151560051b82016020019050611713611703565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b90607f16906116e1565b6004359060ff8216820361024857565b9181601f840112156102485782359167ffffffffffffffff8311610248576020808501948460051b01011161024857565b60206040818301928281528451809452019201905f5b8181106118705750505090565b825173ffffffffffffffffffffffffffffffffffffffff16845260209384019390920191600101611863565b6040810190811067ffffffffffffffff8211176118b857604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6060810190811067ffffffffffffffff8211176118b857604052565b90601f601f19910116810190811067ffffffffffffffff8211176118b857604052565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610248570180359067ffffffffffffffff82116102485760200191813603831361024857565b90601f83604094601f199360208652816020870152868601375f8582860101520116010190565b919081101561021b5760051b0190565b3560ff811681036102485790565b67ffffffffffffffff81116118b85760051b60200190565b906119dc826119ba565b6119e96040519182611901565b828152601f196119f982946119ba565b0190602036910137565b60015481101561021b5760015f5260205f2001905f90565b6103065481101561021b576103065f5260205f2001905f90565b805482101561021b575f5260205f2001905f90565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611a775760010190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b805182101561021b5760209160051b010190565b60405190611ac58261189c565b5f6020838281520152565b90604051611add8161189c565b602060018294805484520154910152565b335f525f60205260405f20541561046b5773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d40d9e595bdf98731fbf70da31217c7d7654db61168114611b9e57805f5261030560205260405f205415611b9b57805f526103056020525f6040812055337fdadd1471db1ea2f303654fb1bdcc010e5a664214ab41934c0f752aabca88a4915f80a3565b50565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f546f6c6c57697468496d6d757461626c65526f757465723a2063616e6e6f742060448201527f6469737320726f757465720000000000000000000000000000000000000000006064820152fd5b73ffffffffffffffffffffffffffffffffffffffff811690815f525f602052600160405f205414611cd857815f525f602052600160405f205560015490680100000000000000008210156118b857611c85826001611cb194016001556001611a35565b90919073ffffffffffffffffffffffffffffffffffffffff8084549260031b9316831b921b1916179055565b337fe31c10b0adbedd0c6e5d024286c6eeead7761e65a67608dcf0b67604c0da7e2f5f80a3565b5050565b73ffffffffffffffffffffffffffffffffffffffff16805f525f60205260405f205415611b9b57805f525f6020525f6040812055337f58466e5837b54e559819c9ba8a5d7c77c97c985d1aabf4bdc5f41069fa5d65a05f80a3565b3573ffffffffffffffffffffffffffffffffffffffff811681036102485790565b335f525f60205260405f20541561046b5773ffffffffffffffffffffffffffffffffffffffff811690815f52610305602052600160405f205414611cd857815f52610305602052600160405f20556103065490680100000000000000008210156118b857611c85826001611dd3940161030655610306611a35565b337f75d30ca40c7bcd48e685894b82b864808b9cb566090efc53444a2e61742f18a35f80a3565b604051611e068161189c565b602061030754916fffffffffffffffffffffffffffffffff65ffffffffffff84169384835260301c1691829101529080151592565b60405190611e48826118e5565b5f6040838281528260208201520152565b9190611e63611ab8565b50611e6c611e3b565b5060ff6102035416604082019381611e848685611924565b9050036121eb57611e958584611924565b1561021b57358060f81c9061010082101561021b576101fe80611ebf9260f71c1616600301611ad0565b928351916020850192835117156121c0576001909791971b93611ee0611e3b565b505191519660405192611ef2846118e5565b8352602083019788526040830194600186526001925f935b838110612023575050505050611f1e611ab8565b5060405192611f2c8461189c565b5f84525f602085015251955f96600190807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f915b611fe657505050957ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8092611fb99798828085800980935109875251920990096020830152611fb160208401611d37565b92359161253d565b15611fc2575f90565b7fcbc4755f0000000000000000000000000000000000000000000000000000000090565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8183949b930492818c8509820390089290918202900380611f60565b61202d828a611924565b82101561021b57810135908160f81c9161010083101561021b576101fe8061205c9260f71c1616600301611ad0565b9384519260208601938451171561218f576001901b9081811661215e57179387518d51978b5190612131576001947ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f83818f818f978f9982809b818b8180809e819a82809a818085819609809c510990820390089d8e91838b818080878009928184600409998a988d0893820390820308918009089052099b099b519282039409900908600209948180808660020981038382030881888009088098525f9e09600209820394820390089009088c5201611f0a565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b507fe7908552000000000000000000000000000000000000000000000000000000009c505050505050505050505050565b507f552e5639000000000000000000000000000000000000000000000000000000009c505050505050505050505050565b507f552e56390000000000000000000000000000000000000000000000000000000096505050505050565b507f19877c600000000000000000000000000000000000000000000000000000000093505050565b908160409181010312610248576040519061222d8261189c565b803565ffffffffffff81169182820361024857602091845201356fffffffffffffffffffffffffffffffff811691828203610248576020840190828252610307549065ffffffffffff821681111561235d5742106123345765ffffffffffff937fffffffffffffffffffff0000000000000000000000000000000000000000000075ffffffffffffffffffffffffffffffff0000000000006fffffffffffffffffffffffffffffffff958742169360206040516122e98161189c565b868152015260301b169216171761030755511691511660405191825260208201527f9f8b8154174dc4a9ed8bbe5a985ecf6d8b2db481a1c64a02c8d94ae7929e0ba660403392a25f90565b50505050507f5507d1ac0000000000000000000000000000000000000000000000000000000090565b5050505050507f4ef874670000000000000000000000000000000000000000000000000000000090565b61238f611e3b565b505f9160ff610304541693848103612514575f935b8585106123b5575050505050505f90565b8185101561021b57606085028301606081360312610248576040516123d9816118e5565b81359160ff83168084036102485761242e836020955f9552604086850135948588840152013590816040820152506040519384938b859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa15612509575f5160ff73ffffffffffffffffffffffffffffffffffffffff82169160981c169080159081156124d9575b506124ae576001901b80821661248357600191179401936123a4565b505050505050507fe79085520000000000000000000000000000000000000000000000000000000090565b505050505050507fcbc4755f0000000000000000000000000000000000000000000000000000000090565b905061010082101561021b5773ffffffffffffffffffffffffffffffffffffffff8261020401541614155f612467565b6040513d5f823e3d90fd5b50505050507f19877c600000000000000000000000000000000000000000000000000000000090565b909180158015612734575b61272c57602082019081517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8060078187518181800990090891800903612723577ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141811015612723576126f683601b60017ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141806020995f9951908951907f0100000000000000000000000000000000000000000000000000000000000000604051928e840194855260f81b16604083015260418201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008d60601b16606182015260558152612658607582611901565b5190200695845190097ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036414103955116019051809460ff7ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641416040519788970991865290921660ff16602085015260408401527ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410360608301526080820190565b838052039060015afa156125095773ffffffffffffffffffffffffffffffffffffffff805f511691161490565b50505050505f90565b505050505f90565b5073ffffffffffffffffffffffffffffffffffffffff84161561254856fea26469706673582212207274edf763fbf257186cd3efc51a4a943890b9382d23ffbbe1fc72e40ad8b46864736f6c634300081c0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000074258a92611e029b748f79c50024dd851339db15000000000000000000000000d40d9e595bdf98731fbf70da31217c7d7654db61

-----Decoded View---------------
Arg [0] : initialAuthed (address): 0x74258A92611e029b748F79c50024DD851339dB15
Arg [1] : router (address): 0xD40d9E595Bdf98731FBF70da31217C7D7654Db61

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000074258a92611e029b748f79c50024dd851339db15
Arg [1] : 000000000000000000000000d40d9e595bdf98731fbf70da31217c7d7654db61


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.