ETH Price: $3,393.88 (+4.38%)

Contract

0x24C392CDbF32Cf911B258981a66d5541d85269ce

Overview

ETH Balance

0 ETH

ETH Value

$0.00
Transaction Hash
Method
Block
From
To
Poke_optimized_7...192763762025-01-19 9:53:086 hrs ago1737280388IN
0x24C392CD...1d85269ce
0 ETH0.000078910.6375
Poke_optimized_7...192757942025-01-19 9:21:066 hrs ago1737278466IN
0x24C392CD...1d85269ce
0 ETH0.000113880.90125
Poke_optimized_7...192706422025-01-19 4:36:4111 hrs ago1737261401IN
0x24C392CD...1d85269ce
0 ETH0.000024160.19625
Poke_optimized_7...192612182025-01-18 19:58:3320 hrs ago1737230313IN
0x24C392CD...1d85269ce
0 ETH0.000027870.22625
Poke_optimized_7...192582752025-01-18 17:16:3622 hrs ago1737220596IN
0x24C392CD...1d85269ce
0 ETH0.000057390.45625
Poke_optimized_7...192568702025-01-18 15:58:4324 hrs ago1737215923IN
0x24C392CD...1d85269ce
0 ETH0.000063820.5175
Poke_optimized_7...192524002025-01-18 11:52:0028 hrs ago1737201120IN
0x24C392CD...1d85269ce
0 ETH0.000025760.20875
Poke_optimized_7...192440432025-01-18 4:08:2836 hrs ago1737173308IN
0x24C392CD...1d85269ce
0 ETH0.000042970.34625
Poke_optimized_7...192413462025-01-18 1:40:2038 hrs ago1737164420IN
0x24C392CD...1d85269ce
0 ETH0.000012230.099375
Poke_optimized_7...192319782025-01-17 17:06:2047 hrs ago1737133580IN
0x24C392CD...1d85269ce
0 ETH0.00003180.26125
Poke_optimized_7...192298982025-01-17 15:12:202 days ago1737126740IN
0x24C392CD...1d85269ce
0 ETH0.000049570.40125
Poke_optimized_7...192293232025-01-17 14:40:382 days ago1737124838IN
0x24C392CD...1d85269ce
0 ETH0.000025980.21125
Poke_optimized_7...192245562025-01-17 10:18:252 days ago1737109105IN
0x24C392CD...1d85269ce
0 ETH0.000019110.155
Poke_optimized_7...192152232025-01-17 1:44:142 days ago1737078254IN
0x24C392CD...1d85269ce
0 ETH0.000014430.1155
Poke_optimized_7...192142602025-01-17 0:50:252 days ago1737075025IN
0x24C392CD...1d85269ce
0 ETH0.00001020.083375
Poke_optimized_7...192048512025-01-16 16:15:522 days ago1737044152IN
0x24C392CD...1d85269ce
0 ETH0.000037850.3075
Poke_optimized_7...192046042025-01-16 16:01:583 days ago1737043318IN
0x24C392CD...1d85269ce
0 ETH0.000032660.2625
Poke_optimized_7...191970262025-01-16 8:57:553 days ago1737017875IN
0x24C392CD...1d85269ce
0 ETH0.000014950.12125
Poke_optimized_7...191903652025-01-16 2:47:573 days ago1736995677IN
0x24C392CD...1d85269ce
0 ETH0.00000550.044125
Poke_optimized_7...191874332025-01-16 0:05:543 days ago1736985954IN
0x24C392CD...1d85269ce
0 ETH0.000013540.1095
Poke_optimized_7...191839992025-01-15 20:54:463 days ago1736974486IN
0x24C392CD...1d85269ce
0 ETH0.00002580.21
Poke_optimized_7...191835052025-01-15 20:27:063 days ago1736972826IN
0x24C392CD...1d85269ce
0 ETH0.000035010.285
Poke_optimized_7...191763272025-01-15 13:38:244 days ago1736948304IN
0x24C392CD...1d85269ce
0 ETH0.000031350.25875
Poke_optimized_7...191752392025-01-15 12:34:434 days ago1736944483IN
0x24C392CD...1d85269ce
0 ETH0.000006980.056625
Poke_optimized_7...191664712025-01-15 2:01:554 days ago1736906515IN
0x24C392CD...1d85269ce
0 ETH0.000010010.08025

Latest 1 internal transaction

Parent Transaction Hash Block From To
93028782024-01-18 22:15:23366 days ago1705616123  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Chronicle_BTC_USD_3

Compiler Version
v0.8.16+commit.07a7930e

Optimization Enabled:
Yes with 10000 runs

Other Settings:
default evmVersion
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.0
 *
 * @notice Efficient Schnorr multi-signature based Oracle
 */
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_BTC_USD_3 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)`.
    /// @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)`.
    /// @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/",
    "@script/chronicle-std/=lib/chronicle-std/script/",
    "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/",
    "greenhouse/=lib/greenhouse/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 Security Audit

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"}]

60a0346200019b57620023a590601f38839003908101601f19168201906001600160401b03821183831017620001a057808391604095869485528339810103126200019b5780516001600160a01b03811691908290036200019b576020015160008281528060205260018482205560015468010000000000000000811015620001875760018101806001558110156200017357600182527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b03191684179055835192817fe31c10b0adbedd0c6e5d024286c6eeead7761e65a67608dcf0b67604c0da7e2f8186a3811562000170575060805261020590815460ff811691600283036200012f575b84516121ee9081620001b78239608051818181610cba015261183e0152f35b60029281528260208201527f95623b9931156d6d5cb43881a13f223ae416fb199e5edf776efb38766f38cbea853392a260ff19161790553880808062000110565b80fd5b634e487b7160e01b82526032600452602482fd5b634e487b7160e01b82526041600452602482fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe60406080815260049081361015610016575b600080fd5b600091823560e01c9081608214610e4d5781630760861b14610faa5781630e5a6c7014610b8e5781630fce341514610f6257816310b07b7114610f1a578163224242ca14610e595781632f529d7314610e4d5781632fba4aa914610d97578163313ce56714610d7b578163393e5ede14610d265781633bee58f914610cdd5781634ca2992314610ca25781634fce7a2a14610c5c57816350d25bcd14610c0a57816357de26a414610bc357816359e02dd714610b8e57816365c4ce7a14610b5457816365fae35e14610b0a578163789d819114610a3c5781639954b0dc1461098f5781639c52a7f114610945578163acf40b6f146108e9578163b259da5c1461080d578163bf353dbb146107c8578163bfe5861f1461058f578163c83c63341461055a578163ceed3ef2146104db578163d0a5882a146104b7578163d63605b814610389578163dac42ad814610338578163f29c29c4146102fb578163fe66349514610233578163feaf968c146101bc575063febb0f7e1461019757600080fd5b346101b857816003193601126101b85760209060ff61020554169051908152f35b5080fd5b90503461022f578260031936011261022f573383526002602052818320541561021e5760a09263ffffffff915490835193600185526fffffffffffffffffffffffffffffffff8316602086015284015260801c16606082015260016080820152f35b63d957b5958352336020526024601cfd5b8280fd5b5050346101b85760206003193601126101b85761024e611321565b3383528260205281832054156102ea5760ff811680156102e65761020591825460ff811683810361027e57868651f35b855160ff9182168152921660208301527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009133907f95623b9931156d6d5cb43881a13f223ae416fb199e5edf776efb38766f38cbea90604090a2161790553880808080868651f35b8380fd5b634a0bfec18352336020526024601cfd5b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f5761033590611690565b51f35b82843461038657600319908282360112610386576024359167ffffffffffffffff83116101b857606090833603011261038657508261037c9160209401903561194c565b5090519015158152f35b80fd5b9190503461022f578260031936011261022f57805191612020830183811067ffffffffffffffff82111761048b5782526101008084526020946120003687870137808685516103d781611279565b82815201528092815b8381106103fb578487528551806103f7898261133f565b0390f35b8360ff8216101561045f576001908661041c6101fe83851b1660050161192e565b80518b82015117610430575b5050016103e0565b209095829173ffffffffffffffffffffffffffffffffffffffff16610455828b61167c565b5201948638610428565b6024836032847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b6024856041847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5050346101b857816003193601126101b8576020906104d46113a8565b9051908152f35b8383346101b857816003193601126101b857338252600260205280822054156105495791546060926fffffffffffffffffffffffffffffffff821692831561053e575063ffffffff6001939260801c16915b815193151584526020840152820152f35b92508291508161052d565b63d957b5958252336020526024601cfd5b5050346101b85760206003193601126101b857610575611321565b3383528260205281832054156102ea576103359033611f0c565b839150346101b857826003193601126101b85780359067ffffffffffffffff938483116102e657366023840112156102e657828201356105ce81611390565b926105db835194856112e0565b8184526020948585016024809460061b83010191368311610792578401905b82821061079a57505050813596871161079657366023880112156107965786013561062481611390565b96610631845198896112e0565b81885285880183606080940283010191368311610792578401905b828210610755575050505033855284845281852054156107475750815192855184036107435761069361067e85611390565b9461068b845196876112e0565b808652611390565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08186019201368337855b845181101561070057806106ea6106d86001938861167c565b516106e3838c61167c565b5190611dd6565b60ff6106f6838a61167c565b91169052016106bf565b509190858583519485948186019282875251809352850193925b82811061072957505050500390f35b835160ff168552869550938101939281019260010161071a565b8480fd5b634a0bfec18552338452601cfd5b838236031261079257878491875161076c816112c4565b61077585611331565b81528285013583820152888501358982015281520191019061064c565b8880fd5b8580fd5b85823603126107925787869182516107b181611279565b8435815282850135838201528152019101906105fa565b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f578282916020945280845220549051908152f35b828434610386576020806003193601126101b85783359367ffffffffffffffff851161022f573660238601121561022f578401359361084b85611390565b94610858855196876112e0565b80865260248387019160051b83010191368311610743576024849101915b8383106108d1575050505033825281815282822054156108c15750805b83518110156108bc57806108b660ff6108ae6001948861167c565b511633611f0c565b01610893565b509051f35b634a0bfec182523390526024601cfd5b81906108dc84611331565b8152019101908390610876565b82843461038657816003193601126103865781519261090784611279565b356fffffffffffffffffffffffffffffffff811681036101b85783526024359063ffffffff821682036103865750826104d4916020809501526117ea565b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f573383528260205281832054156102ea5761033590611575565b82843461038657806003193601126103865760036109ad81546115d1565b9082835b8351811015610a2c57806109c76109fd92611472565b905473ffffffffffffffffffffffffffffffffffffffff91861b1c81168752600260205287872054600114610a02575b50611620565b6109b1565b610a0b82611472565b905490861b1c16610a25610a1e85611620565b948761167c565b52876109f7565b8184528551806103f7868261133f565b839150346101b85760206003193601126101b857610a58611321565b90610100821015610ade5750610a74839160011b60050161192e565b8051602082015117610aa857505073ffffffffffffffffffffffffffffffffffffffff815b83519215158352166020820152f35b73ffffffffffffffffffffffffffffffffffffffff9250201673ffffffffffffffffffffffffffffffffffffffff600191610a99565b8260326024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f573383528260205281832054156102ea57610335906114a9565b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f576103359061173b565b5050346101b857816003193601126101b8576103f790610bac611d94565b915190815290151560208201529081906040820190565b90503461022f578260031936011261022f573383526002602052818320541561021e57546fffffffffffffffffffffffffffffffff1690811561022f576020925051908152f35b82843461038657806003193601126103865733815260026020528181205415610c4b57506fffffffffffffffffffffffffffffffff60209254169051908152f35b63d957b5959052336020526024601cfd5b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f57828291602094526002845220549051908152f35b5050346101b857816003193601126101b857602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f57818360019260209552600285522054149051908152f35b839150346101b857816003193601126101b8573382526002602052828220541561054957546fffffffffffffffffffffffffffffffff81169182156103865750825191825260801c63ffffffff166020820152f35b5050346101b857816003193601126101b8576020905160128152f35b8284346103865760206003193601126103865773ffffffffffffffffffffffffffffffffffffffff908335828116918282036103865761010060ff8360981c161015610e215750602094506101fe610df59160971c1660050161192e565b918251858401511715159283610e12575b50505090519015158152f35b84902016149050838080610e06565b806032877f4e487b71000000000000000000000000000000000000000000000000000000006024945252fd5b50505050610011611067565b828434610386578060031936011261038657600191610e7883546115d1565b918080855b610e95575b50506103f793508252519182918261133f565b8451811015610f155790610ee482610ead889461140c565b73ffffffffffffffffffffffffffffffffffffffff809254600392831b1c16855284602052858886205414610eeb575b5050611620565b9091610e7d565b610ef48361140c565b9054911b1c16610f0d610f0687611620565b968961167c565b528880610edd565b610e82565b9050823461038657806003193601126103865733815260026020528281205415610c4b57506fffffffffffffffffffffffffffffffff90541681519080151582526020820152f35b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f578183600192602095528085522054149051908152f35b90503461022f57600319360160a081126102e657821361022f57815190610fd082611279565b358152602435602082015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc36011261022f57815192611011846112c4565b60443560ff811681036101b8578452606435602085015260843583850152338152806020528281205415611056575061104e60209360ff92611dd6565b915191168152f35b634a0bfec19052336020526024601cfd5b50346100115760031980360160608112610011576040809112610011576044359167ffffffffffffffff8311610011576060908336030112610011576110ab6117b8565b9160049283549363ffffffff8092818760801c169182911611156112295750816110d36117b8565b81421691829116116111d557508351926110ec84611279565b6fffffffffffffffffffffffffffffffff93823585811681036100115781526024358481168103610011576111319261112c9160208401528401916117ea565b61194c565b9590156111cd5760009550836111456117cb565b167fffffffffffffffffffffffff000000000000000000000000000000000000000073ffffffff000000000000000000000000000000004260801b1692161717905561118f6117cb565b916111986117b8565b908451931683521660208201527f7045db5134e0c7ca4bff0c0e096616ef4ebb36b719cd00c5f0ba4f4475ecceee823392a251f35b855160208701fd5b9061122585926111e36117b8565b93517feea80f5200000000000000000000000000000000000000000000000000000000815263ffffffff94851693810193845293166020830152829160400190565b0390fd5b9061122585926112376117b8565b93517f76f4b87800000000000000000000000000000000000000000000000000000000815263ffffffff94851693810193845293166020830152829160400190565b6040810190811067ffffffffffffffff82111761129557604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761129557604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761129557604052565b6004359060ff8216820361001157565b359060ff8216820361001157565b6020908160408183019282815285518094520193019160005b828110611366575050505090565b835173ffffffffffffffffffffffffffffffffffffffff1685529381019392810192600101611358565b67ffffffffffffffff81116112955760051b60200190565b60405160208101907f19457468657265756d205369676e6564204d6573736167653a0a33320000000082527ff3acba882491058ea715223a1463b7d7e8610fbbb588100fb1e69a89099384a0603c820152603c8152611406816112c4565b51902090565b6001548110156114435760016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6003548110156114435760036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0190600090565b73ffffffffffffffffffffffffffffffffffffffff809116906000908282528160205260016040832054146115705760016040832055600154680100000000000000008110156115435761150481600186930160015561140c565b909283549160031b90811b9283911b169119161790557fe31c10b0adbedd0c6e5d024286c6eeead7761e65a67608dcf0b67604c0da7e2f3391604051a3565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b505050565b73ffffffffffffffffffffffffffffffffffffffff166000818152806020526040812054156115cd578060408120557f58466e5837b54e559819c9ba8a5d7c77c97c985d1aabf4bdc5f41069fa5d65a03391604051a3565b5050565b906115db82611390565b6115e860405191826112e0565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06116168294611390565b0190602036910137565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461164d5760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80518210156114435760209160051b010190565b6000338152806020526040812054156110565773ffffffffffffffffffffffffffffffffffffffff8092169182825260026020526001604083205414611570576001604083205560035468010000000000000000811015611543576116fc816001869301600355611472565b909283549160031b90811b9283911b169119161790557f75d30ca40c7bcd48e685894b82b864808b9cb566090efc53444a2e61742f18a33391604051a3565b600090338252816020526040822054156117a75773ffffffffffffffffffffffffffffffffffffffff169081815260026020526040812054156115cd578060408120557fdadd1471db1ea2f303654fb1bdcc010e5a664214ab41934c0f752aabca88a4913391604051a3565b634a0bfec18252336020526024601cfd5b60243563ffffffff811681036100115790565b6004356fffffffffffffffffffffffffffffffff811681036100115790565b602081519101517fffffffff00000000000000000000000000000000000000000000000000000000604051917fffffffffffffffffffffffffffffffff0000000000000000000000000000000060208401947f0000000000000000000000000000000000000000000000000000000000000000865260801b16604084015260e01b1660508201526034815261187e816112c4565b51902060405160208101917f19457468657265756d205369676e6564204d6573736167653a0a3332000000008352603c820152603c8152611406816112c4565b604051906118cb826112c4565b60006040838281528260208201520152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610011570180359067ffffffffffffffff82116100115760200191813603831361001157565b9060405161193b81611279565b602060018294805484520154910152565b906000602060405161195d81611279565b828152015261196a6118be565b5061197860408201826118dd565b93905060ff6102055416808503611d45575061199760408301836118dd565b156114435735916101008360f81c1015611443576119be6101fe8460f71c1660050161192e565b92835160208501511715611d335760019060f81c1b906119dc6118be565b5060208451940151604051946119f1866112c4565b855260208501526001604085015260015b60ff81169287841015611b9f57611a1c60408401846118dd565b8591951015611443576101008186013560f81c101561144357611a4b6101fe8287013560f71c1660050161192e565b94855160208701511715611b825760018282013560f81c1b8316611b315791600160ff94928194013560f81c1b179487805160208201516020828460408101517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f809881808099818099818099818a81808280099781898d510990820390089d8e936040848087800981808d8180856004099b8c9a089382039082030891800908910152099b09950151816002988d82039409900908840996828080888709810384820308818a800908809a520990098203948203900890090860208801520116611a02565b96509750505050509150604051927f1280090c000000000000000000000000000000000000000000000000000000006020850152602491013560f81c818401528252611b7c826112c4565b60009190565b959850955050505050611b9a9250013560f81c611f94565b600091565b505093929194505060006020604051611bb781611279565b828152015260405190611bc982611279565b60008252602082019060008252604081015190600091600190807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f915b611cf657505050907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f80926020828480099183838251098852015192099009905260208301359173ffffffffffffffffffffffffffffffffffffffff8316830361001157611c75933591611fd6565b15611ca857604051906020820182811067ffffffffffffffff821117611295578060009160405281845236903760019190565b604051907fbd2a556b000000000000000000000000000000000000000000000000000000006020830152600482526040820182811067ffffffffffffffff8211176112955760405260009190565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8183949693049281878509820390089290918202900380611c06565b9250509250611b9a915060f81c611f94565b6040517fce818a2400000000000000000000000000000000000000000000000000000000602082015260ff9586166024820152941660448086019190915284529150611b7c90506064836112e0565b33600052600260205260406000205415611dc4576fffffffffffffffffffffffffffffffff600454169081151590565b63d957b595600052336020526024601cfd5b6040918282209273ffffffffffffffffffffffffffffffffffffffff91828516926020611e34611e046113a8565b84518386015195870151875192835260ff9091166020830152604082019590955260608101949094526080840190565b836000948592838052039060015afa15611f00578082511684036101b85760ff8660981c1695610100871015611ed35760971c6101fe16906005820190611e7a8261192e565b8051602082015117611ec15750506020866006927f2c44ddc69b8b0966ef9e8edb873b850fb2eff06ca6e2bc37c9adf3551ec39e549697985190550151910155339251a390565b92509392955050201603610386575090565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b509051903d90823e3d90fd5b906101008110156114435760011b8060050190611f288261192e565b908151602083015117611f3c575b50505050565b60066000918260409555015573ffffffffffffffffffffffffffffffffffffffff918291201691167f9ec05f17908406877637da36ab29c002620cb544d0049837bfa095e62726455c6000604051a338808080611f36565b60ff604051917fc523c75e00000000000000000000000000000000000000000000000000000000602084015216602482015260248152611fd3816112c4565b90565b9190918115801561219a575b61219157602081019283518251947ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f80600781808a80098a09089083800903612185577ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641419283861015612178577f0100000000000000000000000000000000000000000000000000000000000000604051936020850198895260f81b16604084015260418301527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008760601b16606183015260558252608082019382851067ffffffffffffffff86111761129557601b6000968580600160ff8261213d987fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff809b60209f8e6040528c519020069851978894859251160198098303961693099003875260ff166020870152604086015260608501526080840190565b84805203019060015afa1561216c5773ffffffffffffffffffffffffffffffffffffffff806000511691161490565b6040513d6000823e3d90fd5b5050505050505050600090565b50505050505050600090565b50505050600090565b5073ffffffffffffffffffffffffffffffffffffffff841615611fe256fea2646970667358221220895d213c463d7c95fbdc1d40bad24b9af9da468e78539463324b0a7c23024c2064736f6c6343000810003300000000000000000000000039abd7819e5632fa06d2ecbba45dca5c90687ee34254432f55534400000000000000000000000000000000000000000000000000

Deployed Bytecode

0x60406080815260049081361015610016575b600080fd5b600091823560e01c9081608214610e4d5781630760861b14610faa5781630e5a6c7014610b8e5781630fce341514610f6257816310b07b7114610f1a578163224242ca14610e595781632f529d7314610e4d5781632fba4aa914610d97578163313ce56714610d7b578163393e5ede14610d265781633bee58f914610cdd5781634ca2992314610ca25781634fce7a2a14610c5c57816350d25bcd14610c0a57816357de26a414610bc357816359e02dd714610b8e57816365c4ce7a14610b5457816365fae35e14610b0a578163789d819114610a3c5781639954b0dc1461098f5781639c52a7f114610945578163acf40b6f146108e9578163b259da5c1461080d578163bf353dbb146107c8578163bfe5861f1461058f578163c83c63341461055a578163ceed3ef2146104db578163d0a5882a146104b7578163d63605b814610389578163dac42ad814610338578163f29c29c4146102fb578163fe66349514610233578163feaf968c146101bc575063febb0f7e1461019757600080fd5b346101b857816003193601126101b85760209060ff61020554169051908152f35b5080fd5b90503461022f578260031936011261022f573383526002602052818320541561021e5760a09263ffffffff915490835193600185526fffffffffffffffffffffffffffffffff8316602086015284015260801c16606082015260016080820152f35b63d957b5958352336020526024601cfd5b8280fd5b5050346101b85760206003193601126101b85761024e611321565b3383528260205281832054156102ea5760ff811680156102e65761020591825460ff811683810361027e57868651f35b855160ff9182168152921660208301527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009133907f95623b9931156d6d5cb43881a13f223ae416fb199e5edf776efb38766f38cbea90604090a2161790553880808080868651f35b8380fd5b634a0bfec18352336020526024601cfd5b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f5761033590611690565b51f35b82843461038657600319908282360112610386576024359167ffffffffffffffff83116101b857606090833603011261038657508261037c9160209401903561194c565b5090519015158152f35b80fd5b9190503461022f578260031936011261022f57805191612020830183811067ffffffffffffffff82111761048b5782526101008084526020946120003687870137808685516103d781611279565b82815201528092815b8381106103fb578487528551806103f7898261133f565b0390f35b8360ff8216101561045f576001908661041c6101fe83851b1660050161192e565b80518b82015117610430575b5050016103e0565b209095829173ffffffffffffffffffffffffffffffffffffffff16610455828b61167c565b5201948638610428565b6024836032847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b6024856041847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5050346101b857816003193601126101b8576020906104d46113a8565b9051908152f35b8383346101b857816003193601126101b857338252600260205280822054156105495791546060926fffffffffffffffffffffffffffffffff821692831561053e575063ffffffff6001939260801c16915b815193151584526020840152820152f35b92508291508161052d565b63d957b5958252336020526024601cfd5b5050346101b85760206003193601126101b857610575611321565b3383528260205281832054156102ea576103359033611f0c565b839150346101b857826003193601126101b85780359067ffffffffffffffff938483116102e657366023840112156102e657828201356105ce81611390565b926105db835194856112e0565b8184526020948585016024809460061b83010191368311610792578401905b82821061079a57505050813596871161079657366023880112156107965786013561062481611390565b96610631845198896112e0565b81885285880183606080940283010191368311610792578401905b828210610755575050505033855284845281852054156107475750815192855184036107435761069361067e85611390565b9461068b845196876112e0565b808652611390565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08186019201368337855b845181101561070057806106ea6106d86001938861167c565b516106e3838c61167c565b5190611dd6565b60ff6106f6838a61167c565b91169052016106bf565b509190858583519485948186019282875251809352850193925b82811061072957505050500390f35b835160ff168552869550938101939281019260010161071a565b8480fd5b634a0bfec18552338452601cfd5b838236031261079257878491875161076c816112c4565b61077585611331565b81528285013583820152888501358982015281520191019061064c565b8880fd5b8580fd5b85823603126107925787869182516107b181611279565b8435815282850135838201528152019101906105fa565b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f578282916020945280845220549051908152f35b828434610386576020806003193601126101b85783359367ffffffffffffffff851161022f573660238601121561022f578401359361084b85611390565b94610858855196876112e0565b80865260248387019160051b83010191368311610743576024849101915b8383106108d1575050505033825281815282822054156108c15750805b83518110156108bc57806108b660ff6108ae6001948861167c565b511633611f0c565b01610893565b509051f35b634a0bfec182523390526024601cfd5b81906108dc84611331565b8152019101908390610876565b82843461038657816003193601126103865781519261090784611279565b356fffffffffffffffffffffffffffffffff811681036101b85783526024359063ffffffff821682036103865750826104d4916020809501526117ea565b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f573383528260205281832054156102ea5761033590611575565b82843461038657806003193601126103865760036109ad81546115d1565b9082835b8351811015610a2c57806109c76109fd92611472565b905473ffffffffffffffffffffffffffffffffffffffff91861b1c81168752600260205287872054600114610a02575b50611620565b6109b1565b610a0b82611472565b905490861b1c16610a25610a1e85611620565b948761167c565b52876109f7565b8184528551806103f7868261133f565b839150346101b85760206003193601126101b857610a58611321565b90610100821015610ade5750610a74839160011b60050161192e565b8051602082015117610aa857505073ffffffffffffffffffffffffffffffffffffffff815b83519215158352166020820152f35b73ffffffffffffffffffffffffffffffffffffffff9250201673ffffffffffffffffffffffffffffffffffffffff600191610a99565b8260326024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f573383528260205281832054156102ea57610335906114a9565b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f576103359061173b565b5050346101b857816003193601126101b8576103f790610bac611d94565b915190815290151560208201529081906040820190565b90503461022f578260031936011261022f573383526002602052818320541561021e57546fffffffffffffffffffffffffffffffff1690811561022f576020925051908152f35b82843461038657806003193601126103865733815260026020528181205415610c4b57506fffffffffffffffffffffffffffffffff60209254169051908152f35b63d957b5959052336020526024601cfd5b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f57828291602094526002845220549051908152f35b5050346101b857816003193601126101b857602090517f4254432f555344000000000000000000000000000000000000000000000000008152f35b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f57818360019260209552600285522054149051908152f35b839150346101b857816003193601126101b8573382526002602052828220541561054957546fffffffffffffffffffffffffffffffff81169182156103865750825191825260801c63ffffffff166020820152f35b5050346101b857816003193601126101b8576020905160128152f35b8284346103865760206003193601126103865773ffffffffffffffffffffffffffffffffffffffff908335828116918282036103865761010060ff8360981c161015610e215750602094506101fe610df59160971c1660050161192e565b918251858401511715159283610e12575b50505090519015158152f35b84902016149050838080610e06565b806032877f4e487b71000000000000000000000000000000000000000000000000000000006024945252fd5b50505050610011611067565b828434610386578060031936011261038657600191610e7883546115d1565b918080855b610e95575b50506103f793508252519182918261133f565b8451811015610f155790610ee482610ead889461140c565b73ffffffffffffffffffffffffffffffffffffffff809254600392831b1c16855284602052858886205414610eeb575b5050611620565b9091610e7d565b610ef48361140c565b9054911b1c16610f0d610f0687611620565b968961167c565b528880610edd565b610e82565b9050823461038657806003193601126103865733815260026020528281205415610c4b57506fffffffffffffffffffffffffffffffff90541681519080151582526020820152f35b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f578183600192602095528085522054149051908152f35b90503461022f57600319360160a081126102e657821361022f57815190610fd082611279565b358152602435602082015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc36011261022f57815192611011846112c4565b60443560ff811681036101b8578452606435602085015260843583850152338152806020528281205415611056575061104e60209360ff92611dd6565b915191168152f35b634a0bfec19052336020526024601cfd5b50346100115760031980360160608112610011576040809112610011576044359167ffffffffffffffff8311610011576060908336030112610011576110ab6117b8565b9160049283549363ffffffff8092818760801c169182911611156112295750816110d36117b8565b81421691829116116111d557508351926110ec84611279565b6fffffffffffffffffffffffffffffffff93823585811681036100115781526024358481168103610011576111319261112c9160208401528401916117ea565b61194c565b9590156111cd5760009550836111456117cb565b167fffffffffffffffffffffffff000000000000000000000000000000000000000073ffffffff000000000000000000000000000000004260801b1692161717905561118f6117cb565b916111986117b8565b908451931683521660208201527f7045db5134e0c7ca4bff0c0e096616ef4ebb36b719cd00c5f0ba4f4475ecceee823392a251f35b855160208701fd5b9061122585926111e36117b8565b93517feea80f5200000000000000000000000000000000000000000000000000000000815263ffffffff94851693810193845293166020830152829160400190565b0390fd5b9061122585926112376117b8565b93517f76f4b87800000000000000000000000000000000000000000000000000000000815263ffffffff94851693810193845293166020830152829160400190565b6040810190811067ffffffffffffffff82111761129557604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761129557604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761129557604052565b6004359060ff8216820361001157565b359060ff8216820361001157565b6020908160408183019282815285518094520193019160005b828110611366575050505090565b835173ffffffffffffffffffffffffffffffffffffffff1685529381019392810192600101611358565b67ffffffffffffffff81116112955760051b60200190565b60405160208101907f19457468657265756d205369676e6564204d6573736167653a0a33320000000082527ff3acba882491058ea715223a1463b7d7e8610fbbb588100fb1e69a89099384a0603c820152603c8152611406816112c4565b51902090565b6001548110156114435760016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6003548110156114435760036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0190600090565b73ffffffffffffffffffffffffffffffffffffffff809116906000908282528160205260016040832054146115705760016040832055600154680100000000000000008110156115435761150481600186930160015561140c565b909283549160031b90811b9283911b169119161790557fe31c10b0adbedd0c6e5d024286c6eeead7761e65a67608dcf0b67604c0da7e2f3391604051a3565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b505050565b73ffffffffffffffffffffffffffffffffffffffff166000818152806020526040812054156115cd578060408120557f58466e5837b54e559819c9ba8a5d7c77c97c985d1aabf4bdc5f41069fa5d65a03391604051a3565b5050565b906115db82611390565b6115e860405191826112e0565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06116168294611390565b0190602036910137565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461164d5760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80518210156114435760209160051b010190565b6000338152806020526040812054156110565773ffffffffffffffffffffffffffffffffffffffff8092169182825260026020526001604083205414611570576001604083205560035468010000000000000000811015611543576116fc816001869301600355611472565b909283549160031b90811b9283911b169119161790557f75d30ca40c7bcd48e685894b82b864808b9cb566090efc53444a2e61742f18a33391604051a3565b600090338252816020526040822054156117a75773ffffffffffffffffffffffffffffffffffffffff169081815260026020526040812054156115cd578060408120557fdadd1471db1ea2f303654fb1bdcc010e5a664214ab41934c0f752aabca88a4913391604051a3565b634a0bfec18252336020526024601cfd5b60243563ffffffff811681036100115790565b6004356fffffffffffffffffffffffffffffffff811681036100115790565b602081519101517fffffffff00000000000000000000000000000000000000000000000000000000604051917fffffffffffffffffffffffffffffffff0000000000000000000000000000000060208401947f4254432f55534400000000000000000000000000000000000000000000000000865260801b16604084015260e01b1660508201526034815261187e816112c4565b51902060405160208101917f19457468657265756d205369676e6564204d6573736167653a0a3332000000008352603c820152603c8152611406816112c4565b604051906118cb826112c4565b60006040838281528260208201520152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610011570180359067ffffffffffffffff82116100115760200191813603831361001157565b9060405161193b81611279565b602060018294805484520154910152565b906000602060405161195d81611279565b828152015261196a6118be565b5061197860408201826118dd565b93905060ff6102055416808503611d45575061199760408301836118dd565b156114435735916101008360f81c1015611443576119be6101fe8460f71c1660050161192e565b92835160208501511715611d335760019060f81c1b906119dc6118be565b5060208451940151604051946119f1866112c4565b855260208501526001604085015260015b60ff81169287841015611b9f57611a1c60408401846118dd565b8591951015611443576101008186013560f81c101561144357611a4b6101fe8287013560f71c1660050161192e565b94855160208701511715611b825760018282013560f81c1b8316611b315791600160ff94928194013560f81c1b179487805160208201516020828460408101517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f809881808099818099818099818a81808280099781898d510990820390089d8e936040848087800981808d8180856004099b8c9a089382039082030891800908910152099b09950151816002988d82039409900908840996828080888709810384820308818a800908809a520990098203948203900890090860208801520116611a02565b96509750505050509150604051927f1280090c000000000000000000000000000000000000000000000000000000006020850152602491013560f81c818401528252611b7c826112c4565b60009190565b959850955050505050611b9a9250013560f81c611f94565b600091565b505093929194505060006020604051611bb781611279565b828152015260405190611bc982611279565b60008252602082019060008252604081015190600091600190807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f915b611cf657505050907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f80926020828480099183838251098852015192099009905260208301359173ffffffffffffffffffffffffffffffffffffffff8316830361001157611c75933591611fd6565b15611ca857604051906020820182811067ffffffffffffffff821117611295578060009160405281845236903760019190565b604051907fbd2a556b000000000000000000000000000000000000000000000000000000006020830152600482526040820182811067ffffffffffffffff8211176112955760405260009190565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8183949693049281878509820390089290918202900380611c06565b9250509250611b9a915060f81c611f94565b6040517fce818a2400000000000000000000000000000000000000000000000000000000602082015260ff9586166024820152941660448086019190915284529150611b7c90506064836112e0565b33600052600260205260406000205415611dc4576fffffffffffffffffffffffffffffffff600454169081151590565b63d957b595600052336020526024601cfd5b6040918282209273ffffffffffffffffffffffffffffffffffffffff91828516926020611e34611e046113a8565b84518386015195870151875192835260ff9091166020830152604082019590955260608101949094526080840190565b836000948592838052039060015afa15611f00578082511684036101b85760ff8660981c1695610100871015611ed35760971c6101fe16906005820190611e7a8261192e565b8051602082015117611ec15750506020866006927f2c44ddc69b8b0966ef9e8edb873b850fb2eff06ca6e2bc37c9adf3551ec39e549697985190550151910155339251a390565b92509392955050201603610386575090565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b509051903d90823e3d90fd5b906101008110156114435760011b8060050190611f288261192e565b908151602083015117611f3c575b50505050565b60066000918260409555015573ffffffffffffffffffffffffffffffffffffffff918291201691167f9ec05f17908406877637da36ab29c002620cb544d0049837bfa095e62726455c6000604051a338808080611f36565b60ff604051917fc523c75e00000000000000000000000000000000000000000000000000000000602084015216602482015260248152611fd3816112c4565b90565b9190918115801561219a575b61219157602081019283518251947ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f80600781808a80098a09089083800903612185577ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641419283861015612178577f0100000000000000000000000000000000000000000000000000000000000000604051936020850198895260f81b16604084015260418301527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008760601b16606183015260558252608082019382851067ffffffffffffffff86111761129557601b6000968580600160ff8261213d987fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff809b60209f8e6040528c519020069851978894859251160198098303961693099003875260ff166020870152604086015260608501526080840190565b84805203019060015afa1561216c5773ffffffffffffffffffffffffffffffffffffffff806000511691161490565b6040513d6000823e3d90fd5b5050505050505050600090565b50505050505050600090565b50505050600090565b5073ffffffffffffffffffffffffffffffffffffffff841615611fe256fea2646970667358221220895d213c463d7c95fbdc1d40bad24b9af9da468e78539463324b0a7c23024c2064736f6c63430008100033

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

00000000000000000000000039abd7819e5632fa06d2ecbba45dca5c90687ee34254432f55534400000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : initialAuthed (address): 0x39aBD7819E5632Fa06D2ECBba45Dca5c90687EE3
Arg [1] : wat_ (bytes32): 0x4254432f55534400000000000000000000000000000000000000000000000000

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000039abd7819e5632fa06d2ecbba45dca5c90687ee3
Arg [1] : 4254432f55534400000000000000000000000000000000000000000000000000


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.