Cardona Testnet

Contract

0xF3713fc718c3cd75A8923992F244F9c4A8427Eb9

Overview

ETH Balance

0 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Poke_optimized_7...98287612025-01-11 19:32:0910 days ago1736623929IN
0xF3713fc7...4A8427Eb9
0 ETH0.000002190.031
Poke_optimized_7...98255832025-01-11 16:39:4710 days ago1736613587IN
0xF3713fc7...4A8427Eb9
0 ETH0.000008820.12275
Poke_optimized_7...98224302025-01-11 13:48:2310 days ago1736603303IN
0xF3713fc7...4A8427Eb9
0 ETH0.000013030.18125
Poke_optimized_7...98192502025-01-11 10:55:4310 days ago1736592943IN
0xF3713fc7...4A8427Eb9
0 ETH0.000032540.46625
Poke_optimized_7...98160822025-01-11 8:03:5310 days ago1736582633IN
0xF3713fc7...4A8427Eb9
0 ETH0.000014560.2025
Poke_optimized_7...98129062025-01-11 5:11:4711 days ago1736572307IN
0xF3713fc7...4A8427Eb9
0 ETH0.000003390.04725
Poke_optimized_7...98097292025-01-11 2:19:4211 days ago1736561982IN
0xF3713fc7...4A8427Eb9
0 ETH0.00000150.02125
Poke_optimized_7...98065652025-01-10 23:28:0711 days ago1736551687IN
0xF3713fc7...4A8427Eb9
0 ETH0.000000880.0125
Poke_optimized_7...98033922025-01-10 20:36:0411 days ago1736541364IN
0xF3713fc7...4A8427Eb9
0 ETH0.000000880.012625
Poke_optimized_7...98002232025-01-10 17:44:0311 days ago1736531043IN
0xF3713fc7...4A8427Eb9
0 ETH0.000013420.19
Poke_optimized_7...97970712025-01-10 14:52:1511 days ago1736520735IN
0xF3713fc7...4A8427Eb9
0 ETH0.000076511.06375
Poke_optimized_7...97939152025-01-10 12:00:1211 days ago1736510412IN
0xF3713fc7...4A8427Eb9
0 ETH0.000019060.265
Poke_optimized_7...97907622025-01-10 9:08:4511 days ago1736500125IN
0xF3713fc7...4A8427Eb9
0 ETH0.000031460.4375
Poke_optimized_7...97875962025-01-10 6:17:0311 days ago1736489823IN
0xF3713fc7...4A8427Eb9
0 ETH0.000006280.089375
Poke_optimized_7...97844172025-01-10 3:24:4612 days ago1736479486IN
0xF3713fc7...4A8427Eb9
0 ETH0.000008590.1195
Poke_optimized_7...97812472025-01-10 0:32:4812 days ago1736469168IN
0xF3713fc7...4A8427Eb9
0 ETH0.000001250.0175
Poke_optimized_7...97780902025-01-09 21:41:3212 days ago1736458892IN
0xF3713fc7...4A8427Eb9
0 ETH0.000001660.023875
Poke_optimized_7...97749142025-01-09 18:49:0912 days ago1736448549IN
0xF3713fc7...4A8427Eb9
0 ETH0.000006360.09125
Poke_optimized_7...97717572025-01-09 15:57:0312 days ago1736438223IN
0xF3713fc7...4A8427Eb9
0 ETH0.000023460.33625
Poke_optimized_7...97686032025-01-09 13:05:1212 days ago1736427912IN
0xF3713fc7...4A8427Eb9
0 ETH0.000018820.2675
Poke_optimized_7...97654442025-01-09 10:13:2312 days ago1736417603IN
0xF3713fc7...4A8427Eb9
0 ETH0.000020310.28875
Poke_optimized_7...97590782025-01-09 4:28:5413 days ago1736396934IN
0xF3713fc7...4A8427Eb9
0 ETH0.000038250.54375
Poke_optimized_7...97559002025-01-09 1:37:0813 days ago1736386628IN
0xF3713fc7...4A8427Eb9
0 ETH0.000001810.026
Poke_optimized_7...97432222025-01-08 14:09:2613 days ago1736345366IN
0xF3713fc7...4A8427Eb9
0 ETH0.000021280.3025
Poke_optimized_7...97400502025-01-08 11:16:4113 days ago1736335001IN
0xF3713fc7...4A8427Eb9
0 ETH0.000021810.31

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
101009322025-01-22 5:07:0439 mins ago1737522424
0xF3713fc7...4A8427Eb9
0 ETH
101009322025-01-22 5:07:0439 mins ago1737522424
0xF3713fc7...4A8427Eb9
0 ETH
100976592025-01-22 2:14:563 hrs ago1737512096
0xF3713fc7...4A8427Eb9
0 ETH
100976592025-01-22 2:14:563 hrs ago1737512096
0xF3713fc7...4A8427Eb9
0 ETH
100943902025-01-21 23:22:536 hrs ago1737501773
0xF3713fc7...4A8427Eb9
0 ETH
100943902025-01-21 23:22:536 hrs ago1737501773
0xF3713fc7...4A8427Eb9
0 ETH
100911232025-01-21 20:30:529 hrs ago1737491452
0xF3713fc7...4A8427Eb9
0 ETH
100911232025-01-21 20:30:529 hrs ago1737491452
0xF3713fc7...4A8427Eb9
0 ETH
100878582025-01-21 17:38:4812 hrs ago1737481128
0xF3713fc7...4A8427Eb9
0 ETH
100878582025-01-21 17:38:4812 hrs ago1737481128
0xF3713fc7...4A8427Eb9
0 ETH
100845992025-01-21 14:46:5314 hrs ago1737470813
0xF3713fc7...4A8427Eb9
0 ETH
100845992025-01-21 14:46:5314 hrs ago1737470813
0xF3713fc7...4A8427Eb9
0 ETH
100813342025-01-21 11:54:5517 hrs ago1737460495
0xF3713fc7...4A8427Eb9
0 ETH
100813342025-01-21 11:54:5517 hrs ago1737460495
0xF3713fc7...4A8427Eb9
0 ETH
100780662025-01-21 9:02:4620 hrs ago1737450166
0xF3713fc7...4A8427Eb9
0 ETH
100780662025-01-21 9:02:4620 hrs ago1737450166
0xF3713fc7...4A8427Eb9
0 ETH
100747982025-01-21 6:10:3223 hrs ago1737439832
0xF3713fc7...4A8427Eb9
0 ETH
100747982025-01-21 6:10:3223 hrs ago1737439832
0xF3713fc7...4A8427Eb9
0 ETH
100715252025-01-21 3:17:5526 hrs ago1737429475
0xF3713fc7...4A8427Eb9
0 ETH
100715252025-01-21 3:17:5526 hrs ago1737429475
0xF3713fc7...4A8427Eb9
0 ETH
100682622025-01-21 0:25:5729 hrs ago1737419157
0xF3713fc7...4A8427Eb9
0 ETH
100682622025-01-21 0:25:5729 hrs ago1737419157
0xF3713fc7...4A8427Eb9
0 ETH
100649692025-01-20 21:32:1032 hrs ago1737408730
0xF3713fc7...4A8427Eb9
0 ETH
100649692025-01-20 21:32:1032 hrs ago1737408730
0xF3713fc7...4A8427Eb9
0 ETH
100617072025-01-20 18:39:1435 hrs ago1737398354
0xF3713fc7...4A8427Eb9
0 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Chronicle_EBTCbadger_ETH_1

Compiler Version
v0.8.16+commit.07a7930e

Optimization Enabled:
Yes with 10000 runs

Other Settings:
london EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 9 : Scribe.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.16;

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

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

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

/**
 * @title Scribe
 * @custom:version 2.0.1
 *
 * @notice Efficient Schnorr multi-signature based Oracle
 *
 * @author Chronicle Labs, Inc
 * @custom:security-contact [email protected]
 */
contract Scribe is IScribe, Auth, Toll {
    using LibSchnorr for LibSecp256k1.Point;
    using LibSecp256k1 for LibSecp256k1.Point;
    using LibSecp256k1 for LibSecp256k1.JacobianPoint;

    /// @inheritdoc IScribe
    uint8 public constant decimals = 18;

    /// @inheritdoc IScribe
    bytes32 public constant feedRegistrationMessage = keccak256(
        abi.encodePacked(
            "\x19Ethereum Signed Message:\n32",
            keccak256("Chronicle Feed Registration")
        )
    );

    /// @inheritdoc IChronicle
    bytes32 public immutable wat;

    // -- Storage --

    /// @dev Scribe's current value and corresponding age.
    PokeData internal _pokeData;

    /// @dev Statically allocated array of feeds' public keys.
    ///      Indexed via the public keys address' highest-order byte.
    LibSecp256k1.Point[256] internal _pubKeys;

    /// @inheritdoc IScribe
    /// @dev Note to have as last in storage to enable downstream contracts to
    ///      pack the slot.
    uint8 public bar;

    // -- Constructor --

    constructor(address initialAuthed, bytes32 wat_)
        payable
        Auth(initialAuthed)
    {
        require(wat_ != 0);

        // Set wat immutable.
        wat = wat_;

        // Let initial bar be 2.
        _setBar(2);
    }

    // -- Poke Functionality --

    /// @dev Optimized function selector: 0x00000082.
    ///      Note that this function is _not_ defined via the IScribe interface
    ///      and one should _not_ depend on it.
    function poke_optimized_7136211(
        PokeData calldata pokeData,
        SchnorrData calldata schnorrData
    ) external {
        _poke(pokeData, schnorrData);
    }

    /// @inheritdoc IScribe
    function poke(PokeData calldata pokeData, SchnorrData calldata schnorrData)
        external
    {
        _poke(pokeData, schnorrData);
    }

    function _poke(PokeData calldata pokeData, SchnorrData calldata schnorrData)
        internal
        virtual
    {
        // Revert if pokeData stale.
        if (pokeData.age <= _pokeData.age) {
            revert StaleMessage(pokeData.age, _pokeData.age);
        }
        // Revert if pokeData from the future.
        if (pokeData.age > uint32(block.timestamp)) {
            revert FutureMessage(pokeData.age, uint32(block.timestamp));
        }

        // Revert if schnorrData does not prove integrity of pokeData.
        bool ok;
        bytes memory err;
        // forgefmt: disable-next-item
        (ok, err) = _verifySchnorrSignature(
            constructPokeMessage(pokeData),
            schnorrData
        );
        if (!ok) {
            _revert(err);
        }

        // Store pokeData's val in _pokeData storage and set its age to now.
        _pokeData.val = pokeData.val;
        _pokeData.age = uint32(block.timestamp);

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

    /// @inheritdoc IScribe
    function constructPokeMessage(PokeData memory pokeData)
        public
        view
        returns (bytes32)
    {
        return keccak256(
            abi.encodePacked(
                "\x19Ethereum Signed Message:\n32",
                keccak256(abi.encodePacked(wat, pokeData.val, pokeData.age))
            )
        );
    }

    // -- Schnorr Signature Verification --

    /// @inheritdoc IScribe
    function isAcceptableSchnorrSignatureNow(
        bytes32 message,
        SchnorrData calldata schnorrData
    ) external view returns (bool) {
        bool ok;
        (ok, /*err*/ ) = _verifySchnorrSignature(message, schnorrData);

        return ok;
    }

    /// @custom:invariant Reverts iff out of gas.
    /// @custom:invariant Runtime is O(bar).
    function _verifySchnorrSignature(
        bytes32 message,
        SchnorrData calldata schnorrData
    ) internal view returns (bool, bytes memory) {
        // Let feedPubKey be the currently processed feed's public key.
        LibSecp256k1.Point memory feedPubKey;
        // Let feedId be the currently processed feed's id.
        uint8 feedId;
        // Let aggPubKey be the sum of processed feeds' public keys.
        // Note that Jacobian coordinates are used.
        LibSecp256k1.JacobianPoint memory aggPubKey;
        // Let bloom be a bloom filter to check for double signing attempts.
        uint bloom;

        // Fail if number feeds unequal to bar.
        //
        // Note that requiring equality constrains the verification's runtime
        // from Ω(bar) to Θ(bar).
        uint numberFeeds = schnorrData.feedIds.length;
        if (numberFeeds != bar) {
            return (false, _errorBarNotReached(uint8(numberFeeds), bar));
        }

        // Initiate feed variables with schnorrData's 0's feed index.
        feedId = uint8(schnorrData.feedIds[0]);
        feedPubKey = _pubKeys[feedId];

        // Fail if feed not lifted.
        if (feedPubKey.isZeroPoint()) {
            return (false, _errorInvalidFeedId(feedId));
        }

        // Initiate bloom filter with feedId set.
        bloom = 1 << feedId;

        // Initiate aggPubKey with value of first feed's public key.
        aggPubKey = feedPubKey.toJacobian();

        for (uint8 i = 1; i < numberFeeds;) {
            // Update feed variables.
            feedId = uint8(schnorrData.feedIds[i]);
            feedPubKey = _pubKeys[feedId];

            // Fail if feed not lifted.
            if (feedPubKey.isZeroPoint()) {
                return (false, _errorInvalidFeedId(feedId));
            }

            // Fail if double signing attempted.
            if (bloom & (1 << feedId) != 0) {
                return (false, _errorDoubleSigningAttempted(feedId));
            }
            // Update bloom filter.
            bloom |= 1 << feedId;

            // assert(aggPubKey.x != feedPubKey.x); // Indicates rogue-key attack

            // Add feedPubKey to already aggregated public keys.
            aggPubKey.addAffinePoint(feedPubKey);

            // forgefmt: disable-next-item
            unchecked { ++i; }
        }

        // Fail if signature verification fails.
        bool ok = aggPubKey.toAffine().verifySignature(
            message, schnorrData.signature, schnorrData.commitment
        );
        if (!ok) {
            return (false, _errorSchnorrSignatureInvalid());
        }

        // Otherwise Schnorr signature is valid.
        return (true, new bytes(0));
    }

    // -- Toll'ed Read Functionality --

    // - IChronicle Functions

    /// @inheritdoc IChronicle
    /// @dev Only callable by toll'ed address.
    function read() external view virtual toll returns (uint) {
        uint val = _pokeData.val;
        require(val != 0);
        return val;
    }

    /// @inheritdoc IChronicle
    /// @dev Only callable by toll'ed address.
    function tryRead() external view virtual toll returns (bool, uint) {
        uint val = _pokeData.val;
        return (val != 0, val);
    }

    /// @inheritdoc IChronicle
    /// @dev Only callable by toll'ed address.
    function readWithAge() external view virtual toll returns (uint, uint) {
        uint val = _pokeData.val;
        uint age = _pokeData.age;
        require(val != 0);
        return (val, age);
    }

    /// @inheritdoc IChronicle
    /// @dev Only callable by toll'ed address.
    function tryReadWithAge()
        external
        view
        virtual
        toll
        returns (bool, uint, uint)
    {
        uint val = _pokeData.val;
        uint age = _pokeData.age;
        return val != 0 ? (true, val, age) : (false, 0, 0);
    }

    // - MakerDAO Compatibility

    /// @inheritdoc IScribe
    /// @dev Only callable by toll'ed address.
    function peek() external view virtual toll returns (uint, bool) {
        uint val = _pokeData.val;
        return (val, val != 0);
    }

    /// @inheritdoc IScribe
    /// @dev Only callable by toll'ed address.
    function peep() external view virtual toll returns (uint, bool) {
        uint val = _pokeData.val;
        return (val, val != 0);
    }

    // - Chainlink Compatibility

    /// @inheritdoc IScribe
    /// @dev Only callable by toll'ed address.
    function latestRoundData()
        external
        view
        virtual
        toll
        returns (
            uint80 roundId,
            int answer,
            uint startedAt,
            uint updatedAt,
            uint80 answeredInRound
        )
    {
        roundId = 1;
        answer = int(uint(_pokeData.val));
        // assert(uint(answer) == uint(_pokeData.val));
        startedAt = 0;
        updatedAt = _pokeData.age;
        answeredInRound = roundId;
    }

    /// @inheritdoc IScribe
    /// @dev Only callable by toll'ed address.
    function latestAnswer() external view virtual toll returns (int) {
        uint val = _pokeData.val;
        return int(val);
    }

    // -- Public Read Functionality --

    /// @inheritdoc IScribe
    function feeds(address who) external view returns (bool) {
        uint8 feedId = uint8(uint(uint160(who)) >> 152);

        LibSecp256k1.Point memory pubKey = _pubKeys[feedId];

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

    /// @inheritdoc IScribe
    function feeds(uint8 feedId) external view returns (bool, address) {
        LibSecp256k1.Point memory pubKey = _pubKeys[feedId];

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

    /// @inheritdoc IScribe
    function feeds() external view returns (address[] memory) {
        address[] memory feeds_ = new address[](256);

        LibSecp256k1.Point memory pubKey;
        address feed;
        uint ctr;
        for (uint i; i < 256;) {
            pubKey = _pubKeys[uint8(i)];

            if (!pubKey.isZeroPoint()) {
                feed = pubKey.toAddress();

                feeds_[ctr] = feed;

                // forgefmt: disable-next-item
                unchecked { ++ctr; }
            }

            // forgefmt: disable-next-item
            unchecked { ++i; }
        }

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

        return feeds_;
    }

    // -- Auth'ed Functionality --

    /// @inheritdoc IScribe
    function lift(LibSecp256k1.Point memory pubKey, ECDSAData memory ecdsaData)
        external
        auth
        returns (uint8)
    {
        return _lift(pubKey, ecdsaData);
    }

    /// @inheritdoc IScribe
    function lift(
        LibSecp256k1.Point[] memory pubKeys,
        ECDSAData[] memory ecdsaDatas
    ) external auth returns (uint8[] memory) {
        require(pubKeys.length == ecdsaDatas.length);

        uint8[] memory feedIds = new uint8[](pubKeys.length);
        for (uint i; i < pubKeys.length;) {
            feedIds[i] = _lift(pubKeys[i], ecdsaDatas[i]);

            // forgefmt: disable-next-item
            unchecked { ++i; }
        }

        return feedIds;
    }

    function _lift(LibSecp256k1.Point memory pubKey, ECDSAData memory ecdsaData)
        internal
        returns (uint8)
    {
        address feed = pubKey.toAddress();
        // assert(feed != address(0));

        // forgefmt: disable-next-item
        address recovered = ecrecover(
            feedRegistrationMessage,
            ecdsaData.v,
            ecdsaData.r,
            ecdsaData.s
        );
        require(feed == recovered);

        uint8 feedId = uint8(uint(uint160(feed)) >> 152);

        LibSecp256k1.Point memory sPubKey = _pubKeys[feedId];
        if (sPubKey.isZeroPoint()) {
            _pubKeys[feedId] = pubKey;

            emit FeedLifted(msg.sender, feed);
        } else {
            // Note to be idempotent. However, disallow updating an id's feed
            // via lifting without dropping the previous feed.
            require(feed == sPubKey.toAddress());
        }

        return feedId;
    }

    /// @inheritdoc IScribe
    function drop(uint8 feedId) external auth {
        _drop(msg.sender, feedId);
    }

    /// @inheritdoc IScribe
    function drop(uint8[] memory feedIds) external auth {
        for (uint i; i < feedIds.length;) {
            _drop(msg.sender, feedIds[i]);

            // forgefmt: disable-next-item
            unchecked { ++i; }
        }
    }

    function _drop(address caller, uint8 feedId) internal virtual {
        LibSecp256k1.Point memory pubKey = _pubKeys[feedId];
        if (!pubKey.isZeroPoint()) {
            delete _pubKeys[feedId];

            emit FeedDropped(caller, pubKey.toAddress());
        }
    }

    /// @inheritdoc IScribe
    function setBar(uint8 bar_) external auth {
        _setBar(bar_);
    }

    function _setBar(uint8 bar_) internal virtual {
        require(bar_ != 0);

        if (bar != bar_) {
            emit BarUpdated(msg.sender, bar, bar_);
            bar = bar_;
        }
    }

    // -- Internal Helpers --

    function _revert(bytes memory err) internal pure {
        // assert(err.length != 0);
        assembly ("memory-safe") {
            let size := mload(err)
            let offset := add(err, 0x20)
            revert(offset, size)
        }
    }

    function _errorBarNotReached(uint8 got, uint8 want)
        internal
        pure
        returns (bytes memory)
    {
        // assert(got != want);
        return abi.encodeWithSelector(IScribe.BarNotReached.selector, got, want);
    }

    function _errorInvalidFeedId(uint8 feedId)
        internal
        pure
        returns (bytes memory)
    {
        // assert(_pubKeys[feedId].isZeroPoint());
        return abi.encodeWithSelector(IScribe.InvalidFeedId.selector, feedId);
    }

    function _errorDoubleSigningAttempted(uint8 feedId)
        internal
        pure
        returns (bytes memory)
    {
        return abi.encodeWithSelector(
            IScribe.DoubleSigningAttempted.selector, feedId
        );
    }

    function _errorSchnorrSignatureInvalid()
        internal
        pure
        returns (bytes memory)
    {
        return abi.encodeWithSelector(IScribe.SchnorrSignatureInvalid.selector);
    }

    // -- Overridden Toll Functions --

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

/**
 * @dev Contract overwrite to deploy contract instances with specific naming.
 *
 *      For more info, see docs/Deployment.md.
 */
contract Chronicle_EBTCbadger_ETH_1 is Scribe {
    constructor(address initialAuthed, bytes32 wat_)
        Scribe(initialAuthed, wat_)
    {}
}

File 2 of 9 : IChronicle.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

/**
 * @title IChronicle
 *
 * @notice Interface for Chronicle Protocol's oracle products
 */
interface IChronicle {
    /// @notice Returns the oracle's identifier.
    /// @return wat The oracle's identifier.
    function wat() external view returns (bytes32 wat);

    /// @notice Returns the oracle's current value.
    /// @dev Reverts if no value set.
    /// @return value The oracle's current value.
    function read() external view returns (uint value);

    /// @notice Returns the oracle's current value and its age.
    /// @dev Reverts if no value set.
    /// @return value The oracle's current value.
    /// @return age The value's age.
    function readWithAge() external view returns (uint value, uint age);

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

    /// @notice Returns the oracle's current value and its age.
    /// @return isValid True if value exists, false otherwise.
    /// @return value 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 isValid, uint value, uint age);
}

File 3 of 9 : Auth.sol
// 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];
    }
}

File 4 of 9 : Toll.sol
// 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];
    }
}

File 5 of 9 : IScribe.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

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

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

interface IScribe is IChronicle {
    /// @dev PokeData encapsulates a value and its age.
    struct PokeData {
        uint128 val;
        uint32 age;
    }

    /// @dev SchnorrData encapsulates a (aggregated) Schnorr signature.
    ///      Schnorr signatures are used to prove a PokeData's integrity.
    struct SchnorrData {
        bytes32 signature;
        address commitment;
        bytes feedIds;
    }

    /// @dev ECDSAData encapsulates an ECDSA signature.
    struct ECDSAData {
        uint8 v;
        bytes32 r;
        bytes32 s;
    }

    /// @notice Thrown if a poked value's age is not greater than the oracle's
    ///         current value's age.
    /// @param givenAge The poked value's age.
    /// @param currentAge The oracle's current value's age.
    error StaleMessage(uint32 givenAge, uint32 currentAge);

    /// @notice Thrown if a poked value's age is greater than the current
    ///         time.
    /// @param givenAge The poked value's age.
    /// @param currentTimestamp The current time.
    error FutureMessage(uint32 givenAge, uint32 currentTimestamp);

    /// @notice Thrown if Schnorr signature not signed by exactly bar many
    ///         signers.
    /// @param numberSigners The number of signers for given Schnorr signature.
    /// @param bar The bar security parameter.
    error BarNotReached(uint8 numberSigners, uint8 bar);

    /// @notice Thrown if given feed id invalid.
    /// @param feedId The invalid feed id.
    error InvalidFeedId(uint8 feedId);

    /// @notice Thrown if double signing attempted.
    /// @param feedId The id of the feed attempting to double sign.
    error DoubleSigningAttempted(uint8 feedId);

    /// @notice Thrown if Schnorr signature verification failed.
    error SchnorrSignatureInvalid();

    /// @notice Emitted when oracle was successfully poked.
    /// @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, uint32 age);

    /// @notice Emitted when new feed lifted.
    /// @param caller The caller's address.
    /// @param feed The feed address lifted.
    event FeedLifted(address indexed caller, address indexed feed);

    /// @notice Emitted when feed dropped.
    /// @param caller The caller's address.
    /// @param feed The feed address dropped.
    event FeedDropped(address indexed caller, address indexed feed);

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

    /// @notice Returns the feed registration message.
    /// @dev This message must be signed by a feed in order to be lifted.
    /// @return feedRegistrationMessage Chronicle Protocol's feed registration
    ///                                 message.
    function feedRegistrationMessage()
        external
        view
        returns (bytes32 feedRegistrationMessage);

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

    /// @notice Returns the number of decimals of the oracle's value.
    /// @dev Provides partial compatibility with Chainlink's
    ///      IAggregatorV3Interface.
    /// @return decimals The oracle value's number of decimals.
    function decimals() external view returns (uint8 decimals);

    /// @notice Returns the oracle's latest value.
    /// @dev Provides partial compatibility with Chainlink's
    ///      IAggregatorV3Interface.
    /// @return roundId 1.
    /// @return answer The oracle's latest value.
    /// @return startedAt 0.
    /// @return updatedAt The timestamp of oracle's latest update.
    /// @return answeredInRound 1.
    function latestRoundData()
        external
        view
        returns (
            uint80 roundId,
            int answer,
            uint startedAt,
            uint updatedAt,
            uint80 answeredInRound
        );

    /// @notice Returns the oracle's latest value.
    /// @dev Provides partial compatibility with Chainlink's
    ///      IAggregatorV3Interface.
    /// @custom:deprecated See https://docs.chain.link/data-feeds/api-reference/#latestanswer.
    /// @return answer The oracle's latest value.
    function latestAnswer() external view returns (int);

    /// @notice Pokes the oracle.
    /// @dev Expects `pokeData`'s age to be greater than the timestamp of the
    ///      last successful poke.
    /// @dev Expects `pokeData`'s age to not be greater than the current time.
    /// @dev Expects `schnorrData` to prove `pokeData`'s integrity.
    ///      See `isAcceptableSchnorrSignatureNow(bytes32,SchnorrData)(bool)`.
    /// @param pokeData The PokeData being poked.
    /// @param schnorrData The SchnorrData proving the `pokeData`'s
    ///                    integrity.
    function poke(PokeData calldata pokeData, SchnorrData calldata schnorrData)
        external;

    /// @notice Returns whether the Schnorr signature `schnorrData` is
    ///         currently acceptable for message `message`.
    /// @dev Note that a valid Schnorr signature is only acceptable if the
    ///      signature was signed by exactly bar many feeds.
    ///      For more info, see `bar()(uint8)` and `feeds()(address[])`.
    /// @dev Note that bar and feeds are configurable, meaning a once acceptable
    ///      Schnorr signature may become unacceptable in the future.
    /// @param message The message expected to be signed via `schnorrData`.
    /// @param schnorrData The SchnorrData to verify whether it proves
    ///                    the `message`'s integrity.
    /// @return ok True if Schnorr signature is acceptable, false otherwise.
    function isAcceptableSchnorrSignatureNow(
        bytes32 message,
        SchnorrData calldata schnorrData
    ) external view returns (bool ok);

    /// @notice Returns the message expected to be signed via Schnorr for
    ///         `pokeData`.
    /// @dev The message is defined as:
    ///         H(tag ‖ H(wat ‖ pokeData)), where H() is the keccak256 function.
    /// @param pokeData The pokeData to create the message for.
    /// @return pokeMessage Message for `pokeData`.
    function constructPokeMessage(PokeData calldata pokeData)
        external
        view
        returns (bytes32 pokeMessage);

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

    /// @notice Returns whether feed id `feedId` is a feed and, if so, the
    ///         feed's address.
    /// @param feedId The feed id to check.
    /// @return isFeed True if `feedId` is a feed, false otherwise.
    /// @return feed Address of the feed with id `feedId` if `feedId` is a feed,
    ///              zero-address otherwise.
    function feeds(uint8 feedId)
        external
        view
        returns (bool isFeed, address feed);

    /// @notice Returns list of feed addresses.
    /// @dev Note that this function has a high gas consumption and is not
    ///      intended to be called onchain.
    /// @return feeds List of feed addresses.
    function feeds() external view returns (address[] memory feeds);

    /// @notice Lifts public key `pubKey` to being a feed.
    /// @dev Only callable by auth'ed address.
    /// @dev The message expected to be signed by `ecdsaData` is defined via
    ///      `feedRegistrationMessage()(bytes32)`.
    /// @custom:security The lift function's proof of possession is vulnerable
    ///                  to rogue-key attacks. Additional verification MUST be
    ///                  performed before lifting to ensure a feed's public key
    ///                  validity.
    /// @param pubKey The public key of the feed.
    /// @param ecdsaData ECDSA signed message by the feed's public key.
    /// @return feedId The id of the newly lifted feed.
    function lift(LibSecp256k1.Point memory pubKey, ECDSAData memory ecdsaData)
        external
        returns (uint8 feedId);

    /// @notice Lifts public keys `pubKeys` to being feeds.
    /// @dev Only callable by auth'ed address.
    /// @dev The message expected to be signed by `ecdsaDatas` is defined via
    ///      `feedRegistrationMessage()(bytes32)`.
    /// @custom:security The lift function's proof of possession is vulnerable
    ///                  to rogue-key attacks. Additional verification MUST be
    ///                  performed before lifting to ensure a feed's public key
    ///                  validity.
    /// @param pubKeys The public keys of the feeds.
    /// @param ecdsaDatas ECDSA signed message by the feeds' public keys.
    /// @return List of feed ids of the newly lifted feeds.
    function lift(
        LibSecp256k1.Point[] memory pubKeys,
        ECDSAData[] memory ecdsaDatas
    ) external returns (uint8[] memory);

    /// @notice Drops feed with id `feedId`.
    /// @dev Only callable by auth'ed address.
    /// @param feedId The feed id to drop.
    function drop(uint8 feedId) external;

    /// @notice Drops feeds with ids' `feedIds`.
    /// @dev Only callable by auth'ed address.
    /// @param feedIds The feed ids to drop.
    function drop(uint8[] memory feedIds) external;

    /// @notice Updates the bar security parameters to `bar`.
    /// @dev Only callable by auth'ed address.
    /// @dev Reverts if `bar` is zero.
    /// @param bar The value to update bar to.
    function setBar(uint8 bar) external;

    /// @notice Returns the oracle's current value.
    /// @custom:deprecated Use `tryRead()(bool,uint)` instead.
    /// @return value The oracle's current value if it exists, zero otherwise.
    /// @return isValid True if value exists, false otherwise.
    function peek() external view returns (uint value, bool isValid);

    /// @notice Returns the oracle's current value.
    /// @custom:deprecated Use `tryRead()(bool,uint)` instead.
    /// @return value The oracle's current value if it exists, zero otherwise.
    /// @return isValid True if value exists, false otherwise.
    function peep() external view returns (uint value, bool isValid);
}

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

import {LibSecp256k1} from "./LibSecp256k1.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;
    }
}

File 7 of 9 : LibSecp256k1.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

/**
 * @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;
    }
}

File 8 of 9 : IAuth.sol
// 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);
}

File 9 of 9 : IToll.sol
// 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);
}

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

Contract ABI

[{"inputs":[{"internalType":"address","name":"initialAuthed","type":"address"},{"internalType":"bytes32","name":"wat_","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint8","name":"numberSigners","type":"uint8"},{"internalType":"uint8","name":"bar","type":"uint8"}],"name":"BarNotReached","type":"error"},{"inputs":[{"internalType":"uint8","name":"feedId","type":"uint8"}],"name":"DoubleSigningAttempted","type":"error"},{"inputs":[{"internalType":"uint32","name":"givenAge","type":"uint32"},{"internalType":"uint32","name":"currentTimestamp","type":"uint32"}],"name":"FutureMessage","type":"error"},{"inputs":[{"internalType":"uint8","name":"feedId","type":"uint8"}],"name":"InvalidFeedId","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":[],"name":"SchnorrSignatureInvalid","type":"error"},{"inputs":[{"internalType":"uint32","name":"givenAge","type":"uint32"},{"internalType":"uint32","name":"currentAge","type":"uint32"}],"name":"StaleMessage","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":"BarUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"feed","type":"address"}],"name":"FeedDropped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"feed","type":"address"}],"name":"FeedLifted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint128","name":"val","type":"uint128"},{"indexed":false,"internalType":"uint32","name":"age","type":"uint32"}],"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"},{"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":"bar","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":[{"components":[{"internalType":"uint128","name":"val","type":"uint128"},{"internalType":"uint32","name":"age","type":"uint32"}],"internalType":"struct IScribe.PokeData","name":"pokeData","type":"tuple"}],"name":"constructPokeMessage","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"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":"feedIds","type":"uint8[]"}],"name":"drop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"feedId","type":"uint8"}],"name":"drop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feedRegistrationMessage","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"feeds","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"feedId","type":"uint8"}],"name":"feeds","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeds","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"message","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"signature","type":"bytes32"},{"internalType":"address","name":"commitment","type":"address"},{"internalType":"bytes","name":"feedIds","type":"bytes"}],"internalType":"struct IScribe.SchnorrData","name":"schnorrData","type":"tuple"}],"name":"isAcceptableSchnorrSignatureNow","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"kiss","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"latestAnswer","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestRoundData","outputs":[{"internalType":"uint80","name":"roundId","type":"uint80"},{"internalType":"int256","name":"answer","type":"int256"},{"internalType":"uint256","name":"startedAt","type":"uint256"},{"internalType":"uint256","name":"updatedAt","type":"uint256"},{"internalType":"uint80","name":"answeredInRound","type":"uint80"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct LibSecp256k1.Point","name":"pubKey","type":"tuple"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct IScribe.ECDSAData","name":"ecdsaData","type":"tuple"}],"name":"lift","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"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[]"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct IScribe.ECDSAData[]","name":"ecdsaDatas","type":"tuple[]"}],"name":"lift","outputs":[{"internalType":"uint8[]","name":"","type":"uint8[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"peek","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"peep","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"val","type":"uint128"},{"internalType":"uint32","name":"age","type":"uint32"}],"internalType":"struct IScribe.PokeData","name":"pokeData","type":"tuple"},{"components":[{"internalType":"bytes32","name":"signature","type":"bytes32"},{"internalType":"address","name":"commitment","type":"address"},{"internalType":"bytes","name":"feedIds","type":"bytes"}],"internalType":"struct IScribe.SchnorrData","name":"schnorrData","type":"tuple"}],"name":"poke","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"val","type":"uint128"},{"internalType":"uint32","name":"age","type":"uint32"}],"internalType":"struct IScribe.PokeData","name":"pokeData","type":"tuple"},{"components":[{"internalType":"bytes32","name":"signature","type":"bytes32"},{"internalType":"address","name":"commitment","type":"address"},{"internalType":"bytes","name":"feedIds","type":"bytes"}],"internalType":"struct IScribe.SchnorrData","name":"schnorrData","type":"tuple"}],"name":"poke_optimized_7136211","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"read","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"readWithAge","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","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":"setBar","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":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tryReadWithAge","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"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"}]

60a0346200019b57620023a590601f38839003908101601f19168201906001600160401b03821183831017620001a057808391604095869485528339810103126200019b5780516001600160a01b03811691908290036200019b576020015160008281528060205260018482205560015468010000000000000000811015620001875760018101806001558110156200017357600182527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b03191684179055835192817fe31c10b0adbedd0c6e5d024286c6eeead7761e65a67608dcf0b67604c0da7e2f8186a3811562000170575060805261020590815460ff811691600283036200012f575b84516121ee9081620001b78239608051818181610cba015261183e0152f35b60029281528260208201527f95623b9931156d6d5cb43881a13f223ae416fb199e5edf776efb38766f38cbea853392a260ff19161790553880808062000110565b80fd5b634e487b7160e01b82526032600452602482fd5b634e487b7160e01b82526041600452602482fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe60406080815260049081361015610016575b600080fd5b600091823560e01c9081608214610e4d5781630760861b14610faa5781630e5a6c7014610b8e5781630fce341514610f6257816310b07b7114610f1a578163224242ca14610e595781632f529d7314610e4d5781632fba4aa914610d97578163313ce56714610d7b578163393e5ede14610d265781633bee58f914610cdd5781634ca2992314610ca25781634fce7a2a14610c5c57816350d25bcd14610c0a57816357de26a414610bc357816359e02dd714610b8e57816365c4ce7a14610b5457816365fae35e14610b0a578163789d819114610a3c5781639954b0dc1461098f5781639c52a7f114610945578163acf40b6f146108e9578163b259da5c1461080d578163bf353dbb146107c8578163bfe5861f1461058f578163c83c63341461055a578163ceed3ef2146104db578163d0a5882a146104b7578163d63605b814610389578163dac42ad814610338578163f29c29c4146102fb578163fe66349514610233578163feaf968c146101bc575063febb0f7e1461019757600080fd5b346101b857816003193601126101b85760209060ff61020554169051908152f35b5080fd5b90503461022f578260031936011261022f573383526002602052818320541561021e5760a09263ffffffff915490835193600185526fffffffffffffffffffffffffffffffff8316602086015284015260801c16606082015260016080820152f35b63d957b5958352336020526024601cfd5b8280fd5b5050346101b85760206003193601126101b85761024e611321565b3383528260205281832054156102ea5760ff811680156102e65761020591825460ff811683810361027e57868651f35b855160ff9182168152921660208301527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009133907f95623b9931156d6d5cb43881a13f223ae416fb199e5edf776efb38766f38cbea90604090a2161790553880808080868651f35b8380fd5b634a0bfec18352336020526024601cfd5b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f5761033590611690565b51f35b82843461038657600319908282360112610386576024359167ffffffffffffffff83116101b857606090833603011261038657508261037c9160209401903561194c565b5090519015158152f35b80fd5b9190503461022f578260031936011261022f57805191612020830183811067ffffffffffffffff82111761048b5782526101008084526020946120003687870137808685516103d781611279565b82815201528092815b8381106103fb578487528551806103f7898261133f565b0390f35b8360ff8216101561045f576001908661041c6101fe83851b1660050161192e565b80518b82015117610430575b5050016103e0565b209095829173ffffffffffffffffffffffffffffffffffffffff16610455828b61167c565b5201948638610428565b6024836032847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b6024856041847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5050346101b857816003193601126101b8576020906104d46113a8565b9051908152f35b8383346101b857816003193601126101b857338252600260205280822054156105495791546060926fffffffffffffffffffffffffffffffff821692831561053e575063ffffffff6001939260801c16915b815193151584526020840152820152f35b92508291508161052d565b63d957b5958252336020526024601cfd5b5050346101b85760206003193601126101b857610575611321565b3383528260205281832054156102ea576103359033611f0c565b839150346101b857826003193601126101b85780359067ffffffffffffffff938483116102e657366023840112156102e657828201356105ce81611390565b926105db835194856112e0565b8184526020948585016024809460061b83010191368311610792578401905b82821061079a57505050813596871161079657366023880112156107965786013561062481611390565b96610631845198896112e0565b81885285880183606080940283010191368311610792578401905b828210610755575050505033855284845281852054156107475750815192855184036107435761069361067e85611390565b9461068b845196876112e0565b808652611390565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08186019201368337855b845181101561070057806106ea6106d86001938861167c565b516106e3838c61167c565b5190611dd6565b60ff6106f6838a61167c565b91169052016106bf565b509190858583519485948186019282875251809352850193925b82811061072957505050500390f35b835160ff168552869550938101939281019260010161071a565b8480fd5b634a0bfec18552338452601cfd5b838236031261079257878491875161076c816112c4565b61077585611331565b81528285013583820152888501358982015281520191019061064c565b8880fd5b8580fd5b85823603126107925787869182516107b181611279565b8435815282850135838201528152019101906105fa565b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f578282916020945280845220549051908152f35b828434610386576020806003193601126101b85783359367ffffffffffffffff851161022f573660238601121561022f578401359361084b85611390565b94610858855196876112e0565b80865260248387019160051b83010191368311610743576024849101915b8383106108d1575050505033825281815282822054156108c15750805b83518110156108bc57806108b660ff6108ae6001948861167c565b511633611f0c565b01610893565b509051f35b634a0bfec182523390526024601cfd5b81906108dc84611331565b8152019101908390610876565b82843461038657816003193601126103865781519261090784611279565b356fffffffffffffffffffffffffffffffff811681036101b85783526024359063ffffffff821682036103865750826104d4916020809501526117ea565b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f573383528260205281832054156102ea5761033590611575565b82843461038657806003193601126103865760036109ad81546115d1565b9082835b8351811015610a2c57806109c76109fd92611472565b905473ffffffffffffffffffffffffffffffffffffffff91861b1c81168752600260205287872054600114610a02575b50611620565b6109b1565b610a0b82611472565b905490861b1c16610a25610a1e85611620565b948761167c565b52876109f7565b8184528551806103f7868261133f565b839150346101b85760206003193601126101b857610a58611321565b90610100821015610ade5750610a74839160011b60050161192e565b8051602082015117610aa857505073ffffffffffffffffffffffffffffffffffffffff815b83519215158352166020820152f35b73ffffffffffffffffffffffffffffffffffffffff9250201673ffffffffffffffffffffffffffffffffffffffff600191610a99565b8260326024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f573383528260205281832054156102ea57610335906114a9565b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f576103359061173b565b5050346101b857816003193601126101b8576103f790610bac611d94565b915190815290151560208201529081906040820190565b90503461022f578260031936011261022f573383526002602052818320541561021e57546fffffffffffffffffffffffffffffffff1690811561022f576020925051908152f35b82843461038657806003193601126103865733815260026020528181205415610c4b57506fffffffffffffffffffffffffffffffff60209254169051908152f35b63d957b5959052336020526024601cfd5b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f57828291602094526002845220549051908152f35b5050346101b857816003193601126101b857602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f57818360019260209552600285522054149051908152f35b839150346101b857816003193601126101b8573382526002602052828220541561054957546fffffffffffffffffffffffffffffffff81169182156103865750825191825260801c63ffffffff166020820152f35b5050346101b857816003193601126101b8576020905160128152f35b8284346103865760206003193601126103865773ffffffffffffffffffffffffffffffffffffffff908335828116918282036103865761010060ff8360981c161015610e215750602094506101fe610df59160971c1660050161192e565b918251858401511715159283610e12575b50505090519015158152f35b84902016149050838080610e06565b806032877f4e487b71000000000000000000000000000000000000000000000000000000006024945252fd5b50505050610011611067565b828434610386578060031936011261038657600191610e7883546115d1565b918080855b610e95575b50506103f793508252519182918261133f565b8451811015610f155790610ee482610ead889461140c565b73ffffffffffffffffffffffffffffffffffffffff809254600392831b1c16855284602052858886205414610eeb575b5050611620565b9091610e7d565b610ef48361140c565b9054911b1c16610f0d610f0687611620565b968961167c565b528880610edd565b610e82565b9050823461038657806003193601126103865733815260026020528281205415610c4b57506fffffffffffffffffffffffffffffffff90541681519080151582526020820152f35b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f578183600192602095528085522054149051908152f35b90503461022f57600319360160a081126102e657821361022f57815190610fd082611279565b358152602435602082015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc36011261022f57815192611011846112c4565b60443560ff811681036101b8578452606435602085015260843583850152338152806020528281205415611056575061104e60209360ff92611dd6565b915191168152f35b634a0bfec19052336020526024601cfd5b50346100115760031980360160608112610011576040809112610011576044359167ffffffffffffffff8311610011576060908336030112610011576110ab6117b8565b9160049283549363ffffffff8092818760801c169182911611156112295750816110d36117b8565b81421691829116116111d557508351926110ec84611279565b6fffffffffffffffffffffffffffffffff93823585811681036100115781526024358481168103610011576111319261112c9160208401528401916117ea565b61194c565b9590156111cd5760009550836111456117cb565b167fffffffffffffffffffffffff000000000000000000000000000000000000000073ffffffff000000000000000000000000000000004260801b1692161717905561118f6117cb565b916111986117b8565b908451931683521660208201527f7045db5134e0c7ca4bff0c0e096616ef4ebb36b719cd00c5f0ba4f4475ecceee823392a251f35b855160208701fd5b9061122585926111e36117b8565b93517feea80f5200000000000000000000000000000000000000000000000000000000815263ffffffff94851693810193845293166020830152829160400190565b0390fd5b9061122585926112376117b8565b93517f76f4b87800000000000000000000000000000000000000000000000000000000815263ffffffff94851693810193845293166020830152829160400190565b6040810190811067ffffffffffffffff82111761129557604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761129557604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761129557604052565b6004359060ff8216820361001157565b359060ff8216820361001157565b6020908160408183019282815285518094520193019160005b828110611366575050505090565b835173ffffffffffffffffffffffffffffffffffffffff1685529381019392810192600101611358565b67ffffffffffffffff81116112955760051b60200190565b60405160208101907f19457468657265756d205369676e6564204d6573736167653a0a33320000000082527ff3acba882491058ea715223a1463b7d7e8610fbbb588100fb1e69a89099384a0603c820152603c8152611406816112c4565b51902090565b6001548110156114435760016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6003548110156114435760036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0190600090565b73ffffffffffffffffffffffffffffffffffffffff809116906000908282528160205260016040832054146115705760016040832055600154680100000000000000008110156115435761150481600186930160015561140c565b909283549160031b90811b9283911b169119161790557fe31c10b0adbedd0c6e5d024286c6eeead7761e65a67608dcf0b67604c0da7e2f3391604051a3565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b505050565b73ffffffffffffffffffffffffffffffffffffffff166000818152806020526040812054156115cd578060408120557f58466e5837b54e559819c9ba8a5d7c77c97c985d1aabf4bdc5f41069fa5d65a03391604051a3565b5050565b906115db82611390565b6115e860405191826112e0565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06116168294611390565b0190602036910137565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461164d5760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80518210156114435760209160051b010190565b6000338152806020526040812054156110565773ffffffffffffffffffffffffffffffffffffffff8092169182825260026020526001604083205414611570576001604083205560035468010000000000000000811015611543576116fc816001869301600355611472565b909283549160031b90811b9283911b169119161790557f75d30ca40c7bcd48e685894b82b864808b9cb566090efc53444a2e61742f18a33391604051a3565b600090338252816020526040822054156117a75773ffffffffffffffffffffffffffffffffffffffff169081815260026020526040812054156115cd578060408120557fdadd1471db1ea2f303654fb1bdcc010e5a664214ab41934c0f752aabca88a4913391604051a3565b634a0bfec18252336020526024601cfd5b60243563ffffffff811681036100115790565b6004356fffffffffffffffffffffffffffffffff811681036100115790565b602081519101517fffffffff00000000000000000000000000000000000000000000000000000000604051917fffffffffffffffffffffffffffffffff0000000000000000000000000000000060208401947f0000000000000000000000000000000000000000000000000000000000000000865260801b16604084015260e01b1660508201526034815261187e816112c4565b51902060405160208101917f19457468657265756d205369676e6564204d6573736167653a0a3332000000008352603c820152603c8152611406816112c4565b604051906118cb826112c4565b60006040838281528260208201520152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610011570180359067ffffffffffffffff82116100115760200191813603831361001157565b9060405161193b81611279565b602060018294805484520154910152565b906000602060405161195d81611279565b828152015261196a6118be565b5061197860408201826118dd565b93905060ff6102055416808503611d45575061199760408301836118dd565b156114435735916101008360f81c1015611443576119be6101fe8460f71c1660050161192e565b92835160208501511715611d335760019060f81c1b906119dc6118be565b5060208451940151604051946119f1866112c4565b855260208501526001604085015260015b60ff81169287841015611b9f57611a1c60408401846118dd565b8591951015611443576101008186013560f81c101561144357611a4b6101fe8287013560f71c1660050161192e565b94855160208701511715611b825760018282013560f81c1b8316611b315791600160ff94928194013560f81c1b179487805160208201516020828460408101517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f809881808099818099818099818a81808280099781898d510990820390089d8e936040848087800981808d8180856004099b8c9a089382039082030891800908910152099b09950151816002988d82039409900908840996828080888709810384820308818a800908809a520990098203948203900890090860208801520116611a02565b96509750505050509150604051927f1280090c000000000000000000000000000000000000000000000000000000006020850152602491013560f81c818401528252611b7c826112c4565b60009190565b959850955050505050611b9a9250013560f81c611f94565b600091565b505093929194505060006020604051611bb781611279565b828152015260405190611bc982611279565b60008252602082019060008252604081015190600091600190807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f915b611cf657505050907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f80926020828480099183838251098852015192099009905260208301359173ffffffffffffffffffffffffffffffffffffffff8316830361001157611c75933591611fd6565b15611ca857604051906020820182811067ffffffffffffffff821117611295578060009160405281845236903760019190565b604051907fbd2a556b000000000000000000000000000000000000000000000000000000006020830152600482526040820182811067ffffffffffffffff8211176112955760405260009190565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8183949693049281878509820390089290918202900380611c06565b9250509250611b9a915060f81c611f94565b6040517fce818a2400000000000000000000000000000000000000000000000000000000602082015260ff9586166024820152941660448086019190915284529150611b7c90506064836112e0565b33600052600260205260406000205415611dc4576fffffffffffffffffffffffffffffffff600454169081151590565b63d957b595600052336020526024601cfd5b6040918282209273ffffffffffffffffffffffffffffffffffffffff91828516926020611e34611e046113a8565b84518386015195870151875192835260ff9091166020830152604082019590955260608101949094526080840190565b836000948592838052039060015afa15611f00578082511684036101b85760ff8660981c1695610100871015611ed35760971c6101fe16906005820190611e7a8261192e565b8051602082015117611ec15750506020866006927f2c44ddc69b8b0966ef9e8edb873b850fb2eff06ca6e2bc37c9adf3551ec39e549697985190550151910155339251a390565b92509392955050201603610386575090565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b509051903d90823e3d90fd5b906101008110156114435760011b8060050190611f288261192e565b908151602083015117611f3c575b50505050565b60066000918260409555015573ffffffffffffffffffffffffffffffffffffffff918291201691167f9ec05f17908406877637da36ab29c002620cb544d0049837bfa095e62726455c6000604051a338808080611f36565b60ff604051917fc523c75e00000000000000000000000000000000000000000000000000000000602084015216602482015260248152611fd3816112c4565b90565b9190918115801561219a575b61219157602081019283518251947ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f80600781808a80098a09089083800903612185577ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641419283861015612178577f0100000000000000000000000000000000000000000000000000000000000000604051936020850198895260f81b16604084015260418301527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008760601b16606183015260558252608082019382851067ffffffffffffffff86111761129557601b6000968580600160ff8261213d987fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff809b60209f8e6040528c519020069851978894859251160198098303961693099003875260ff166020870152604086015260608501526080840190565b84805203019060015afa1561216c5773ffffffffffffffffffffffffffffffffffffffff806000511691161490565b6040513d6000823e3d90fd5b5050505050505050600090565b50505050505050600090565b50505050600090565b5073ffffffffffffffffffffffffffffffffffffffff841615611fe256fea2646970667358221220caf6176518531103c5a0ccc82f9a708985c1b7d7f716a674cac9f04bd0b6740f64736f6c6343000810003300000000000000000000000074258a92611e029b748f79c50024dd851339db1545425443236261646765722f4554480000000000000000000000000000000000

Deployed Bytecode

0x60406080815260049081361015610016575b600080fd5b600091823560e01c9081608214610e4d5781630760861b14610faa5781630e5a6c7014610b8e5781630fce341514610f6257816310b07b7114610f1a578163224242ca14610e595781632f529d7314610e4d5781632fba4aa914610d97578163313ce56714610d7b578163393e5ede14610d265781633bee58f914610cdd5781634ca2992314610ca25781634fce7a2a14610c5c57816350d25bcd14610c0a57816357de26a414610bc357816359e02dd714610b8e57816365c4ce7a14610b5457816365fae35e14610b0a578163789d819114610a3c5781639954b0dc1461098f5781639c52a7f114610945578163acf40b6f146108e9578163b259da5c1461080d578163bf353dbb146107c8578163bfe5861f1461058f578163c83c63341461055a578163ceed3ef2146104db578163d0a5882a146104b7578163d63605b814610389578163dac42ad814610338578163f29c29c4146102fb578163fe66349514610233578163feaf968c146101bc575063febb0f7e1461019757600080fd5b346101b857816003193601126101b85760209060ff61020554169051908152f35b5080fd5b90503461022f578260031936011261022f573383526002602052818320541561021e5760a09263ffffffff915490835193600185526fffffffffffffffffffffffffffffffff8316602086015284015260801c16606082015260016080820152f35b63d957b5958352336020526024601cfd5b8280fd5b5050346101b85760206003193601126101b85761024e611321565b3383528260205281832054156102ea5760ff811680156102e65761020591825460ff811683810361027e57868651f35b855160ff9182168152921660208301527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009133907f95623b9931156d6d5cb43881a13f223ae416fb199e5edf776efb38766f38cbea90604090a2161790553880808080868651f35b8380fd5b634a0bfec18352336020526024601cfd5b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f5761033590611690565b51f35b82843461038657600319908282360112610386576024359167ffffffffffffffff83116101b857606090833603011261038657508261037c9160209401903561194c565b5090519015158152f35b80fd5b9190503461022f578260031936011261022f57805191612020830183811067ffffffffffffffff82111761048b5782526101008084526020946120003687870137808685516103d781611279565b82815201528092815b8381106103fb578487528551806103f7898261133f565b0390f35b8360ff8216101561045f576001908661041c6101fe83851b1660050161192e565b80518b82015117610430575b5050016103e0565b209095829173ffffffffffffffffffffffffffffffffffffffff16610455828b61167c565b5201948638610428565b6024836032847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b6024856041847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5050346101b857816003193601126101b8576020906104d46113a8565b9051908152f35b8383346101b857816003193601126101b857338252600260205280822054156105495791546060926fffffffffffffffffffffffffffffffff821692831561053e575063ffffffff6001939260801c16915b815193151584526020840152820152f35b92508291508161052d565b63d957b5958252336020526024601cfd5b5050346101b85760206003193601126101b857610575611321565b3383528260205281832054156102ea576103359033611f0c565b839150346101b857826003193601126101b85780359067ffffffffffffffff938483116102e657366023840112156102e657828201356105ce81611390565b926105db835194856112e0565b8184526020948585016024809460061b83010191368311610792578401905b82821061079a57505050813596871161079657366023880112156107965786013561062481611390565b96610631845198896112e0565b81885285880183606080940283010191368311610792578401905b828210610755575050505033855284845281852054156107475750815192855184036107435761069361067e85611390565b9461068b845196876112e0565b808652611390565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08186019201368337855b845181101561070057806106ea6106d86001938861167c565b516106e3838c61167c565b5190611dd6565b60ff6106f6838a61167c565b91169052016106bf565b509190858583519485948186019282875251809352850193925b82811061072957505050500390f35b835160ff168552869550938101939281019260010161071a565b8480fd5b634a0bfec18552338452601cfd5b838236031261079257878491875161076c816112c4565b61077585611331565b81528285013583820152888501358982015281520191019061064c565b8880fd5b8580fd5b85823603126107925787869182516107b181611279565b8435815282850135838201528152019101906105fa565b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f578282916020945280845220549051908152f35b828434610386576020806003193601126101b85783359367ffffffffffffffff851161022f573660238601121561022f578401359361084b85611390565b94610858855196876112e0565b80865260248387019160051b83010191368311610743576024849101915b8383106108d1575050505033825281815282822054156108c15750805b83518110156108bc57806108b660ff6108ae6001948861167c565b511633611f0c565b01610893565b509051f35b634a0bfec182523390526024601cfd5b81906108dc84611331565b8152019101908390610876565b82843461038657816003193601126103865781519261090784611279565b356fffffffffffffffffffffffffffffffff811681036101b85783526024359063ffffffff821682036103865750826104d4916020809501526117ea565b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f573383528260205281832054156102ea5761033590611575565b82843461038657806003193601126103865760036109ad81546115d1565b9082835b8351811015610a2c57806109c76109fd92611472565b905473ffffffffffffffffffffffffffffffffffffffff91861b1c81168752600260205287872054600114610a02575b50611620565b6109b1565b610a0b82611472565b905490861b1c16610a25610a1e85611620565b948761167c565b52876109f7565b8184528551806103f7868261133f565b839150346101b85760206003193601126101b857610a58611321565b90610100821015610ade5750610a74839160011b60050161192e565b8051602082015117610aa857505073ffffffffffffffffffffffffffffffffffffffff815b83519215158352166020820152f35b73ffffffffffffffffffffffffffffffffffffffff9250201673ffffffffffffffffffffffffffffffffffffffff600191610a99565b8260326024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f573383528260205281832054156102ea57610335906114a9565b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f576103359061173b565b5050346101b857816003193601126101b8576103f790610bac611d94565b915190815290151560208201529081906040820190565b90503461022f578260031936011261022f573383526002602052818320541561021e57546fffffffffffffffffffffffffffffffff1690811561022f576020925051908152f35b82843461038657806003193601126103865733815260026020528181205415610c4b57506fffffffffffffffffffffffffffffffff60209254169051908152f35b63d957b5959052336020526024601cfd5b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f57828291602094526002845220549051908152f35b5050346101b857816003193601126101b857602090517f45425443236261646765722f45544800000000000000000000000000000000008152f35b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f57818360019260209552600285522054149051908152f35b839150346101b857816003193601126101b8573382526002602052828220541561054957546fffffffffffffffffffffffffffffffff81169182156103865750825191825260801c63ffffffff166020820152f35b5050346101b857816003193601126101b8576020905160128152f35b8284346103865760206003193601126103865773ffffffffffffffffffffffffffffffffffffffff908335828116918282036103865761010060ff8360981c161015610e215750602094506101fe610df59160971c1660050161192e565b918251858401511715159283610e12575b50505090519015158152f35b84902016149050838080610e06565b806032877f4e487b71000000000000000000000000000000000000000000000000000000006024945252fd5b50505050610011611067565b828434610386578060031936011261038657600191610e7883546115d1565b918080855b610e95575b50506103f793508252519182918261133f565b8451811015610f155790610ee482610ead889461140c565b73ffffffffffffffffffffffffffffffffffffffff809254600392831b1c16855284602052858886205414610eeb575b5050611620565b9091610e7d565b610ef48361140c565b9054911b1c16610f0d610f0687611620565b968961167c565b528880610edd565b610e82565b9050823461038657806003193601126103865733815260026020528281205415610c4b57506fffffffffffffffffffffffffffffffff90541681519080151582526020820152f35b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f578183600192602095528085522054149051908152f35b90503461022f57600319360160a081126102e657821361022f57815190610fd082611279565b358152602435602082015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc36011261022f57815192611011846112c4565b60443560ff811681036101b8578452606435602085015260843583850152338152806020528281205415611056575061104e60209360ff92611dd6565b915191168152f35b634a0bfec19052336020526024601cfd5b50346100115760031980360160608112610011576040809112610011576044359167ffffffffffffffff8311610011576060908336030112610011576110ab6117b8565b9160049283549363ffffffff8092818760801c169182911611156112295750816110d36117b8565b81421691829116116111d557508351926110ec84611279565b6fffffffffffffffffffffffffffffffff93823585811681036100115781526024358481168103610011576111319261112c9160208401528401916117ea565b61194c565b9590156111cd5760009550836111456117cb565b167fffffffffffffffffffffffff000000000000000000000000000000000000000073ffffffff000000000000000000000000000000004260801b1692161717905561118f6117cb565b916111986117b8565b908451931683521660208201527f7045db5134e0c7ca4bff0c0e096616ef4ebb36b719cd00c5f0ba4f4475ecceee823392a251f35b855160208701fd5b9061122585926111e36117b8565b93517feea80f5200000000000000000000000000000000000000000000000000000000815263ffffffff94851693810193845293166020830152829160400190565b0390fd5b9061122585926112376117b8565b93517f76f4b87800000000000000000000000000000000000000000000000000000000815263ffffffff94851693810193845293166020830152829160400190565b6040810190811067ffffffffffffffff82111761129557604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761129557604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761129557604052565b6004359060ff8216820361001157565b359060ff8216820361001157565b6020908160408183019282815285518094520193019160005b828110611366575050505090565b835173ffffffffffffffffffffffffffffffffffffffff1685529381019392810192600101611358565b67ffffffffffffffff81116112955760051b60200190565b60405160208101907f19457468657265756d205369676e6564204d6573736167653a0a33320000000082527ff3acba882491058ea715223a1463b7d7e8610fbbb588100fb1e69a89099384a0603c820152603c8152611406816112c4565b51902090565b6001548110156114435760016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6003548110156114435760036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0190600090565b73ffffffffffffffffffffffffffffffffffffffff809116906000908282528160205260016040832054146115705760016040832055600154680100000000000000008110156115435761150481600186930160015561140c565b909283549160031b90811b9283911b169119161790557fe31c10b0adbedd0c6e5d024286c6eeead7761e65a67608dcf0b67604c0da7e2f3391604051a3565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b505050565b73ffffffffffffffffffffffffffffffffffffffff166000818152806020526040812054156115cd578060408120557f58466e5837b54e559819c9ba8a5d7c77c97c985d1aabf4bdc5f41069fa5d65a03391604051a3565b5050565b906115db82611390565b6115e860405191826112e0565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06116168294611390565b0190602036910137565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461164d5760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80518210156114435760209160051b010190565b6000338152806020526040812054156110565773ffffffffffffffffffffffffffffffffffffffff8092169182825260026020526001604083205414611570576001604083205560035468010000000000000000811015611543576116fc816001869301600355611472565b909283549160031b90811b9283911b169119161790557f75d30ca40c7bcd48e685894b82b864808b9cb566090efc53444a2e61742f18a33391604051a3565b600090338252816020526040822054156117a75773ffffffffffffffffffffffffffffffffffffffff169081815260026020526040812054156115cd578060408120557fdadd1471db1ea2f303654fb1bdcc010e5a664214ab41934c0f752aabca88a4913391604051a3565b634a0bfec18252336020526024601cfd5b60243563ffffffff811681036100115790565b6004356fffffffffffffffffffffffffffffffff811681036100115790565b602081519101517fffffffff00000000000000000000000000000000000000000000000000000000604051917fffffffffffffffffffffffffffffffff0000000000000000000000000000000060208401947f45425443236261646765722f4554480000000000000000000000000000000000865260801b16604084015260e01b1660508201526034815261187e816112c4565b51902060405160208101917f19457468657265756d205369676e6564204d6573736167653a0a3332000000008352603c820152603c8152611406816112c4565b604051906118cb826112c4565b60006040838281528260208201520152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610011570180359067ffffffffffffffff82116100115760200191813603831361001157565b9060405161193b81611279565b602060018294805484520154910152565b906000602060405161195d81611279565b828152015261196a6118be565b5061197860408201826118dd565b93905060ff6102055416808503611d45575061199760408301836118dd565b156114435735916101008360f81c1015611443576119be6101fe8460f71c1660050161192e565b92835160208501511715611d335760019060f81c1b906119dc6118be565b5060208451940151604051946119f1866112c4565b855260208501526001604085015260015b60ff81169287841015611b9f57611a1c60408401846118dd565b8591951015611443576101008186013560f81c101561144357611a4b6101fe8287013560f71c1660050161192e565b94855160208701511715611b825760018282013560f81c1b8316611b315791600160ff94928194013560f81c1b179487805160208201516020828460408101517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f809881808099818099818099818a81808280099781898d510990820390089d8e936040848087800981808d8180856004099b8c9a089382039082030891800908910152099b09950151816002988d82039409900908840996828080888709810384820308818a800908809a520990098203948203900890090860208801520116611a02565b96509750505050509150604051927f1280090c000000000000000000000000000000000000000000000000000000006020850152602491013560f81c818401528252611b7c826112c4565b60009190565b959850955050505050611b9a9250013560f81c611f94565b600091565b505093929194505060006020604051611bb781611279565b828152015260405190611bc982611279565b60008252602082019060008252604081015190600091600190807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f915b611cf657505050907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f80926020828480099183838251098852015192099009905260208301359173ffffffffffffffffffffffffffffffffffffffff8316830361001157611c75933591611fd6565b15611ca857604051906020820182811067ffffffffffffffff821117611295578060009160405281845236903760019190565b604051907fbd2a556b000000000000000000000000000000000000000000000000000000006020830152600482526040820182811067ffffffffffffffff8211176112955760405260009190565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8183949693049281878509820390089290918202900380611c06565b9250509250611b9a915060f81c611f94565b6040517fce818a2400000000000000000000000000000000000000000000000000000000602082015260ff9586166024820152941660448086019190915284529150611b7c90506064836112e0565b33600052600260205260406000205415611dc4576fffffffffffffffffffffffffffffffff600454169081151590565b63d957b595600052336020526024601cfd5b6040918282209273ffffffffffffffffffffffffffffffffffffffff91828516926020611e34611e046113a8565b84518386015195870151875192835260ff9091166020830152604082019590955260608101949094526080840190565b836000948592838052039060015afa15611f00578082511684036101b85760ff8660981c1695610100871015611ed35760971c6101fe16906005820190611e7a8261192e565b8051602082015117611ec15750506020866006927f2c44ddc69b8b0966ef9e8edb873b850fb2eff06ca6e2bc37c9adf3551ec39e549697985190550151910155339251a390565b92509392955050201603610386575090565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b509051903d90823e3d90fd5b906101008110156114435760011b8060050190611f288261192e565b908151602083015117611f3c575b50505050565b60066000918260409555015573ffffffffffffffffffffffffffffffffffffffff918291201691167f9ec05f17908406877637da36ab29c002620cb544d0049837bfa095e62726455c6000604051a338808080611f36565b60ff604051917fc523c75e00000000000000000000000000000000000000000000000000000000602084015216602482015260248152611fd3816112c4565b90565b9190918115801561219a575b61219157602081019283518251947ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f80600781808a80098a09089083800903612185577ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641419283861015612178577f0100000000000000000000000000000000000000000000000000000000000000604051936020850198895260f81b16604084015260418301527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008760601b16606183015260558252608082019382851067ffffffffffffffff86111761129557601b6000968580600160ff8261213d987fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff809b60209f8e6040528c519020069851978894859251160198098303961693099003875260ff166020870152604086015260608501526080840190565b84805203019060015afa1561216c5773ffffffffffffffffffffffffffffffffffffffff806000511691161490565b6040513d6000823e3d90fd5b5050505050505050600090565b50505050505050600090565b50505050600090565b5073ffffffffffffffffffffffffffffffffffffffff841615611fe256fea2646970667358221220caf6176518531103c5a0ccc82f9a708985c1b7d7f716a674cac9f04bd0b6740f64736f6c63430008100033

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

00000000000000000000000074258a92611e029b748f79c50024dd851339db1545425443236261646765722f4554480000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : initialAuthed (address): 0x74258A92611e029b748F79c50024DD851339dB15
Arg [1] : wat_ (bytes32): 0x45425443236261646765722f4554480000000000000000000000000000000000

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000074258a92611e029b748f79c50024dd851339db15
Arg [1] : 45425443236261646765722f4554480000000000000000000000000000000000


Block Transaction Gas Used Reward
view all blocks sequenced

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

Validator Index Block Amount
View All Withdrawals

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