Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Latest 25 from a total of 25 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Poke_optimized_7... | 9828761 | 10 days ago | IN | 0 ETH | 0.00000219 | ||||
Poke_optimized_7... | 9825583 | 10 days ago | IN | 0 ETH | 0.00000882 | ||||
Poke_optimized_7... | 9822430 | 10 days ago | IN | 0 ETH | 0.00001303 | ||||
Poke_optimized_7... | 9819250 | 10 days ago | IN | 0 ETH | 0.00003254 | ||||
Poke_optimized_7... | 9816082 | 10 days ago | IN | 0 ETH | 0.00001456 | ||||
Poke_optimized_7... | 9812906 | 11 days ago | IN | 0 ETH | 0.00000339 | ||||
Poke_optimized_7... | 9809729 | 11 days ago | IN | 0 ETH | 0.0000015 | ||||
Poke_optimized_7... | 9806565 | 11 days ago | IN | 0 ETH | 0.00000088 | ||||
Poke_optimized_7... | 9803392 | 11 days ago | IN | 0 ETH | 0.00000088 | ||||
Poke_optimized_7... | 9800223 | 11 days ago | IN | 0 ETH | 0.00001342 | ||||
Poke_optimized_7... | 9797071 | 11 days ago | IN | 0 ETH | 0.00007651 | ||||
Poke_optimized_7... | 9793915 | 11 days ago | IN | 0 ETH | 0.00001906 | ||||
Poke_optimized_7... | 9790762 | 11 days ago | IN | 0 ETH | 0.00003146 | ||||
Poke_optimized_7... | 9787596 | 11 days ago | IN | 0 ETH | 0.00000628 | ||||
Poke_optimized_7... | 9784417 | 12 days ago | IN | 0 ETH | 0.00000859 | ||||
Poke_optimized_7... | 9781247 | 12 days ago | IN | 0 ETH | 0.00000125 | ||||
Poke_optimized_7... | 9778090 | 12 days ago | IN | 0 ETH | 0.00000166 | ||||
Poke_optimized_7... | 9774914 | 12 days ago | IN | 0 ETH | 0.00000636 | ||||
Poke_optimized_7... | 9771757 | 12 days ago | IN | 0 ETH | 0.00002346 | ||||
Poke_optimized_7... | 9768603 | 12 days ago | IN | 0 ETH | 0.00001882 | ||||
Poke_optimized_7... | 9765444 | 12 days ago | IN | 0 ETH | 0.00002031 | ||||
Poke_optimized_7... | 9759078 | 13 days ago | IN | 0 ETH | 0.00003825 | ||||
Poke_optimized_7... | 9755900 | 13 days ago | IN | 0 ETH | 0.00000181 | ||||
Poke_optimized_7... | 9743222 | 13 days ago | IN | 0 ETH | 0.00002128 | ||||
Poke_optimized_7... | 9740050 | 13 days ago | IN | 0 ETH | 0.00002181 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
10100932 | 39 mins ago | 0 ETH | ||||
10100932 | 39 mins ago | 0 ETH | ||||
10097659 | 3 hrs ago | 0 ETH | ||||
10097659 | 3 hrs ago | 0 ETH | ||||
10094390 | 6 hrs ago | 0 ETH | ||||
10094390 | 6 hrs ago | 0 ETH | ||||
10091123 | 9 hrs ago | 0 ETH | ||||
10091123 | 9 hrs ago | 0 ETH | ||||
10087858 | 12 hrs ago | 0 ETH | ||||
10087858 | 12 hrs ago | 0 ETH | ||||
10084599 | 14 hrs ago | 0 ETH | ||||
10084599 | 14 hrs ago | 0 ETH | ||||
10081334 | 17 hrs ago | 0 ETH | ||||
10081334 | 17 hrs ago | 0 ETH | ||||
10078066 | 20 hrs ago | 0 ETH | ||||
10078066 | 20 hrs ago | 0 ETH | ||||
10074798 | 23 hrs ago | 0 ETH | ||||
10074798 | 23 hrs ago | 0 ETH | ||||
10071525 | 26 hrs ago | 0 ETH | ||||
10071525 | 26 hrs ago | 0 ETH | ||||
10068262 | 29 hrs ago | 0 ETH | ||||
10068262 | 29 hrs ago | 0 ETH | ||||
10064969 | 32 hrs ago | 0 ETH | ||||
10064969 | 32 hrs ago | 0 ETH | ||||
10061707 | 35 hrs ago | 0 ETH |
Loading...
Loading
Contract Name:
Chronicle_EBTCbadger_ETH_1
Compiler Version
v0.8.16+commit.07a7930e
Optimization Enabled:
Yes with 10000 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.16; import {IChronicle} from "chronicle-std/IChronicle.sol"; import {Auth} from "chronicle-std/auth/Auth.sol"; import {Toll} from "chronicle-std/toll/Toll.sol"; import {IScribe} from "./IScribe.sol"; import {LibSchnorr} from "./libs/LibSchnorr.sol"; import {LibSecp256k1} from "./libs/LibSecp256k1.sol"; /** * @title Scribe * @custom:version 2.0.1 * * @notice Efficient Schnorr multi-signature based Oracle * * @author Chronicle Labs, Inc * @custom:security-contact [email protected] */ contract Scribe is IScribe, Auth, Toll { using LibSchnorr for LibSecp256k1.Point; using LibSecp256k1 for LibSecp256k1.Point; using LibSecp256k1 for LibSecp256k1.JacobianPoint; /// @inheritdoc IScribe uint8 public constant decimals = 18; /// @inheritdoc IScribe bytes32 public constant feedRegistrationMessage = keccak256( abi.encodePacked( "\x19Ethereum Signed Message:\n32", keccak256("Chronicle Feed Registration") ) ); /// @inheritdoc IChronicle bytes32 public immutable wat; // -- Storage -- /// @dev Scribe's current value and corresponding age. PokeData internal _pokeData; /// @dev Statically allocated array of feeds' public keys. /// Indexed via the public keys address' highest-order byte. LibSecp256k1.Point[256] internal _pubKeys; /// @inheritdoc IScribe /// @dev Note to have as last in storage to enable downstream contracts to /// pack the slot. uint8 public bar; // -- Constructor -- constructor(address initialAuthed, bytes32 wat_) payable Auth(initialAuthed) { require(wat_ != 0); // Set wat immutable. wat = wat_; // Let initial bar be 2. _setBar(2); } // -- Poke Functionality -- /// @dev Optimized function selector: 0x00000082. /// Note that this function is _not_ defined via the IScribe interface /// and one should _not_ depend on it. function poke_optimized_7136211( PokeData calldata pokeData, SchnorrData calldata schnorrData ) external { _poke(pokeData, schnorrData); } /// @inheritdoc IScribe function poke(PokeData calldata pokeData, SchnorrData calldata schnorrData) external { _poke(pokeData, schnorrData); } function _poke(PokeData calldata pokeData, SchnorrData calldata schnorrData) internal virtual { // Revert if pokeData stale. if (pokeData.age <= _pokeData.age) { revert StaleMessage(pokeData.age, _pokeData.age); } // Revert if pokeData from the future. if (pokeData.age > uint32(block.timestamp)) { revert FutureMessage(pokeData.age, uint32(block.timestamp)); } // Revert if schnorrData does not prove integrity of pokeData. bool ok; bytes memory err; // forgefmt: disable-next-item (ok, err) = _verifySchnorrSignature( constructPokeMessage(pokeData), schnorrData ); if (!ok) { _revert(err); } // Store pokeData's val in _pokeData storage and set its age to now. _pokeData.val = pokeData.val; _pokeData.age = uint32(block.timestamp); emit Poked(msg.sender, pokeData.val, pokeData.age); } /// @inheritdoc IScribe function constructPokeMessage(PokeData memory pokeData) public view returns (bytes32) { return keccak256( abi.encodePacked( "\x19Ethereum Signed Message:\n32", keccak256(abi.encodePacked(wat, pokeData.val, pokeData.age)) ) ); } // -- Schnorr Signature Verification -- /// @inheritdoc IScribe function isAcceptableSchnorrSignatureNow( bytes32 message, SchnorrData calldata schnorrData ) external view returns (bool) { bool ok; (ok, /*err*/ ) = _verifySchnorrSignature(message, schnorrData); return ok; } /// @custom:invariant Reverts iff out of gas. /// @custom:invariant Runtime is O(bar). function _verifySchnorrSignature( bytes32 message, SchnorrData calldata schnorrData ) internal view returns (bool, bytes memory) { // Let feedPubKey be the currently processed feed's public key. LibSecp256k1.Point memory feedPubKey; // Let feedId be the currently processed feed's id. uint8 feedId; // Let aggPubKey be the sum of processed feeds' public keys. // Note that Jacobian coordinates are used. LibSecp256k1.JacobianPoint memory aggPubKey; // Let bloom be a bloom filter to check for double signing attempts. uint bloom; // Fail if number feeds unequal to bar. // // Note that requiring equality constrains the verification's runtime // from Ω(bar) to Θ(bar). uint numberFeeds = schnorrData.feedIds.length; if (numberFeeds != bar) { return (false, _errorBarNotReached(uint8(numberFeeds), bar)); } // Initiate feed variables with schnorrData's 0's feed index. feedId = uint8(schnorrData.feedIds[0]); feedPubKey = _pubKeys[feedId]; // Fail if feed not lifted. if (feedPubKey.isZeroPoint()) { return (false, _errorInvalidFeedId(feedId)); } // Initiate bloom filter with feedId set. bloom = 1 << feedId; // Initiate aggPubKey with value of first feed's public key. aggPubKey = feedPubKey.toJacobian(); for (uint8 i = 1; i < numberFeeds;) { // Update feed variables. feedId = uint8(schnorrData.feedIds[i]); feedPubKey = _pubKeys[feedId]; // Fail if feed not lifted. if (feedPubKey.isZeroPoint()) { return (false, _errorInvalidFeedId(feedId)); } // Fail if double signing attempted. if (bloom & (1 << feedId) != 0) { return (false, _errorDoubleSigningAttempted(feedId)); } // Update bloom filter. bloom |= 1 << feedId; // assert(aggPubKey.x != feedPubKey.x); // Indicates rogue-key attack // Add feedPubKey to already aggregated public keys. aggPubKey.addAffinePoint(feedPubKey); // forgefmt: disable-next-item unchecked { ++i; } } // Fail if signature verification fails. bool ok = aggPubKey.toAffine().verifySignature( message, schnorrData.signature, schnorrData.commitment ); if (!ok) { return (false, _errorSchnorrSignatureInvalid()); } // Otherwise Schnorr signature is valid. return (true, new bytes(0)); } // -- Toll'ed Read Functionality -- // - IChronicle Functions /// @inheritdoc IChronicle /// @dev Only callable by toll'ed address. function read() external view virtual toll returns (uint) { uint val = _pokeData.val; require(val != 0); return val; } /// @inheritdoc IChronicle /// @dev Only callable by toll'ed address. function tryRead() external view virtual toll returns (bool, uint) { uint val = _pokeData.val; return (val != 0, val); } /// @inheritdoc IChronicle /// @dev Only callable by toll'ed address. function readWithAge() external view virtual toll returns (uint, uint) { uint val = _pokeData.val; uint age = _pokeData.age; require(val != 0); return (val, age); } /// @inheritdoc IChronicle /// @dev Only callable by toll'ed address. function tryReadWithAge() external view virtual toll returns (bool, uint, uint) { uint val = _pokeData.val; uint age = _pokeData.age; return val != 0 ? (true, val, age) : (false, 0, 0); } // - MakerDAO Compatibility /// @inheritdoc IScribe /// @dev Only callable by toll'ed address. function peek() external view virtual toll returns (uint, bool) { uint val = _pokeData.val; return (val, val != 0); } /// @inheritdoc IScribe /// @dev Only callable by toll'ed address. function peep() external view virtual toll returns (uint, bool) { uint val = _pokeData.val; return (val, val != 0); } // - Chainlink Compatibility /// @inheritdoc IScribe /// @dev Only callable by toll'ed address. function latestRoundData() external view virtual toll returns ( uint80 roundId, int answer, uint startedAt, uint updatedAt, uint80 answeredInRound ) { roundId = 1; answer = int(uint(_pokeData.val)); // assert(uint(answer) == uint(_pokeData.val)); startedAt = 0; updatedAt = _pokeData.age; answeredInRound = roundId; } /// @inheritdoc IScribe /// @dev Only callable by toll'ed address. function latestAnswer() external view virtual toll returns (int) { uint val = _pokeData.val; return int(val); } // -- Public Read Functionality -- /// @inheritdoc IScribe function feeds(address who) external view returns (bool) { uint8 feedId = uint8(uint(uint160(who)) >> 152); LibSecp256k1.Point memory pubKey = _pubKeys[feedId]; return !pubKey.isZeroPoint() && pubKey.toAddress() == who; } /// @inheritdoc IScribe function feeds(uint8 feedId) external view returns (bool, address) { LibSecp256k1.Point memory pubKey = _pubKeys[feedId]; return pubKey.isZeroPoint() ? (false, address(0)) : (true, pubKey.toAddress()); } /// @inheritdoc IScribe function feeds() external view returns (address[] memory) { address[] memory feeds_ = new address[](256); LibSecp256k1.Point memory pubKey; address feed; uint ctr; for (uint i; i < 256;) { pubKey = _pubKeys[uint8(i)]; if (!pubKey.isZeroPoint()) { feed = pubKey.toAddress(); feeds_[ctr] = feed; // forgefmt: disable-next-item unchecked { ++ctr; } } // forgefmt: disable-next-item unchecked { ++i; } } assembly ("memory-safe") { mstore(feeds_, ctr) } return feeds_; } // -- Auth'ed Functionality -- /// @inheritdoc IScribe function lift(LibSecp256k1.Point memory pubKey, ECDSAData memory ecdsaData) external auth returns (uint8) { return _lift(pubKey, ecdsaData); } /// @inheritdoc IScribe function lift( LibSecp256k1.Point[] memory pubKeys, ECDSAData[] memory ecdsaDatas ) external auth returns (uint8[] memory) { require(pubKeys.length == ecdsaDatas.length); uint8[] memory feedIds = new uint8[](pubKeys.length); for (uint i; i < pubKeys.length;) { feedIds[i] = _lift(pubKeys[i], ecdsaDatas[i]); // forgefmt: disable-next-item unchecked { ++i; } } return feedIds; } function _lift(LibSecp256k1.Point memory pubKey, ECDSAData memory ecdsaData) internal returns (uint8) { address feed = pubKey.toAddress(); // assert(feed != address(0)); // forgefmt: disable-next-item address recovered = ecrecover( feedRegistrationMessage, ecdsaData.v, ecdsaData.r, ecdsaData.s ); require(feed == recovered); uint8 feedId = uint8(uint(uint160(feed)) >> 152); LibSecp256k1.Point memory sPubKey = _pubKeys[feedId]; if (sPubKey.isZeroPoint()) { _pubKeys[feedId] = pubKey; emit FeedLifted(msg.sender, feed); } else { // Note to be idempotent. However, disallow updating an id's feed // via lifting without dropping the previous feed. require(feed == sPubKey.toAddress()); } return feedId; } /// @inheritdoc IScribe function drop(uint8 feedId) external auth { _drop(msg.sender, feedId); } /// @inheritdoc IScribe function drop(uint8[] memory feedIds) external auth { for (uint i; i < feedIds.length;) { _drop(msg.sender, feedIds[i]); // forgefmt: disable-next-item unchecked { ++i; } } } function _drop(address caller, uint8 feedId) internal virtual { LibSecp256k1.Point memory pubKey = _pubKeys[feedId]; if (!pubKey.isZeroPoint()) { delete _pubKeys[feedId]; emit FeedDropped(caller, pubKey.toAddress()); } } /// @inheritdoc IScribe function setBar(uint8 bar_) external auth { _setBar(bar_); } function _setBar(uint8 bar_) internal virtual { require(bar_ != 0); if (bar != bar_) { emit BarUpdated(msg.sender, bar, bar_); bar = bar_; } } // -- Internal Helpers -- function _revert(bytes memory err) internal pure { // assert(err.length != 0); assembly ("memory-safe") { let size := mload(err) let offset := add(err, 0x20) revert(offset, size) } } function _errorBarNotReached(uint8 got, uint8 want) internal pure returns (bytes memory) { // assert(got != want); return abi.encodeWithSelector(IScribe.BarNotReached.selector, got, want); } function _errorInvalidFeedId(uint8 feedId) internal pure returns (bytes memory) { // assert(_pubKeys[feedId].isZeroPoint()); return abi.encodeWithSelector(IScribe.InvalidFeedId.selector, feedId); } function _errorDoubleSigningAttempted(uint8 feedId) internal pure returns (bytes memory) { return abi.encodeWithSelector( IScribe.DoubleSigningAttempted.selector, feedId ); } function _errorSchnorrSignatureInvalid() internal pure returns (bytes memory) { return abi.encodeWithSelector(IScribe.SchnorrSignatureInvalid.selector); } // -- Overridden Toll Functions -- /// @dev Defines authorization for IToll's authenticated functions. function toll_auth() internal override(Toll) auth {} } /** * @dev Contract overwrite to deploy contract instances with specific naming. * * For more info, see docs/Deployment.md. */ contract Chronicle_EBTCbadger_ETH_1 is Scribe { constructor(address initialAuthed, bytes32 wat_) Scribe(initialAuthed, wat_) {} }
// 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); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import {IAuth} from "./IAuth.sol"; /** * @title Auth Module * * @dev The `Auth` contract module provides a basic access control mechanism, * where a set of addresses are granted access to protected functions. * These addresses are said to be _auth'ed_. * * Initially, the address given as constructor argument is the only address * auth'ed. Through the `rely(address)` and `deny(address)` functions, * auth'ed callers are able to grant/renounce auth to/from addresses. * * This module is used through inheritance. It will make available the * modifier `auth`, which can be applied to functions to restrict their * use to only auth'ed callers. */ abstract contract Auth is IAuth { /// @dev Mapping storing whether address is auth'ed. /// @custom:invariant Image of mapping is {0, 1}. /// ∀x ∊ Address: _wards[x] ∊ {0, 1} /// @custom:invariant Only address given as constructor argument is authenticated after deployment. /// deploy(initialAuthed) → (∀x ∊ Address: _wards[x] == 1 → x == initialAuthed) /// @custom:invariant Only functions `rely` and `deny` may mutate the mapping's state. /// ∀x ∊ Address: preTx(_wards[x]) != postTx(_wards[x]) /// → (msg.sig == "rely" ∨ msg.sig == "deny") /// @custom:invariant Mapping's state may only be mutated by authenticated caller. /// ∀x ∊ Address: preTx(_wards[x]) != postTx(_wards[x]) → _wards[msg.sender] = 1 mapping(address => uint) private _wards; /// @dev List of addresses possibly being auth'ed. /// @dev May contain duplicates. /// @dev May contain addresses not being auth'ed anymore. /// @custom:invariant Every address being auth'ed once is element of the list. /// ∀x ∊ Address: authed(x) -> x ∊ _wardsTouched address[] private _wardsTouched; /// @dev Ensures caller is auth'ed. modifier auth() { assembly ("memory-safe") { // Compute slot of _wards[msg.sender]. mstore(0x00, caller()) mstore(0x20, _wards.slot) let slot := keccak256(0x00, 0x40) // Revert if caller not auth'ed. let isAuthed := sload(slot) if iszero(isAuthed) { // Store selector of `NotAuthorized(address)`. mstore(0x00, 0x4a0bfec1) // Store msg.sender. mstore(0x20, caller()) // Revert with (offset, size). revert(0x1c, 0x24) } } _; } constructor(address initialAuthed) { _wards[initialAuthed] = 1; _wardsTouched.push(initialAuthed); // Note to use address(0) as caller to indicate address was auth'ed // during deployment. emit AuthGranted(address(0), initialAuthed); } /// @inheritdoc IAuth function rely(address who) external auth { if (_wards[who] == 1) return; _wards[who] = 1; _wardsTouched.push(who); emit AuthGranted(msg.sender, who); } /// @inheritdoc IAuth function deny(address who) external auth { if (_wards[who] == 0) return; _wards[who] = 0; emit AuthRenounced(msg.sender, who); } /// @inheritdoc IAuth function authed(address who) public view returns (bool) { return _wards[who] == 1; } /// @inheritdoc IAuth /// @custom:invariant Only contains auth'ed addresses. /// ∀x ∊ authed(): _wards[x] == 1 /// @custom:invariant Contains all auth'ed addresses. /// ∀x ∊ Address: _wards[x] == 1 → x ∊ authed() function authed() public view returns (address[] memory) { // Initiate array with upper limit length. address[] memory wardsList = new address[](_wardsTouched.length); // Iterate through all possible auth'ed addresses. uint ctr; for (uint i; i < wardsList.length; i++) { // Add address only if still auth'ed. if (_wards[_wardsTouched[i]] == 1) { wardsList[ctr++] = _wardsTouched[i]; } } // Set length of array to number of auth'ed addresses actually included. assembly ("memory-safe") { mstore(wardsList, ctr) } return wardsList; } /// @inheritdoc IAuth function wards(address who) public view returns (uint) { return _wards[who]; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import {IToll} from "./IToll.sol"; /** * @title Toll Module * * @notice "Toll paid, we kiss - but dissension looms, maybe diss?" * * @dev The `Toll` contract module provides a basic access control mechanism, * where a set of addresses are granted access to protected functions. * These addresses are said the be _tolled_. * * Initially, no address is tolled. Through the `kiss(address)` and * `diss(address)` functions, auth'ed callers are able to toll/de-toll * addresses. Authentication for these functions is defined via the * downstream implemented `toll_auth()` function. * * This module is used through inheritance. It will make available the * modifier `toll`, which can be applied to functions to restrict their * use to only tolled callers. */ abstract contract Toll is IToll { /// @dev Mapping storing whether address is tolled. /// @custom:invariant Image of mapping is {0, 1}. /// ∀x ∊ Address: _buds[x] ∊ {0, 1} /// @custom:invariant Only functions `kiss` and `diss` may mutate the mapping's state. /// ∀x ∊ Address: preTx(_buds[x]) != postTx(_buds[x]) /// → (msg.sig == "kiss" ∨ msg.sig == "diss") /// @custom:invariant Mapping's state may only be mutated by authenticated caller. /// ∀x ∊ Address: preTx(_buds[x]) != postTx(_buds[x]) /// → toll_auth() mapping(address => uint) private _buds; /// @dev List of addresses possibly being tolled. /// @dev May contain duplicates. /// @dev May contain addresses not being tolled anymore. /// @custom:invariant Every address being tolled once is element of the list. /// ∀x ∊ Address: tolled(x) → x ∊ _budsTouched address[] private _budsTouched; /// @dev Ensures caller is tolled. modifier toll() { assembly ("memory-safe") { // Compute slot of _buds[msg.sender]. mstore(0x00, caller()) mstore(0x20, _buds.slot) let slot := keccak256(0x00, 0x40) // Revert if caller not tolled. let isTolled := sload(slot) if iszero(isTolled) { // Store selector of `NotTolled(address)`. mstore(0x00, 0xd957b595) // Store msg.sender. mstore(0x20, caller()) // Revert with (offset, size). revert(0x1c, 0x24) } } _; } /// @dev Reverts if caller not allowed to access protected function. /// @dev Must be implemented in downstream contract. function toll_auth() internal virtual; /// @inheritdoc IToll function kiss(address who) external { toll_auth(); if (_buds[who] == 1) return; _buds[who] = 1; _budsTouched.push(who); emit TollGranted(msg.sender, who); } /// @inheritdoc IToll function diss(address who) external { toll_auth(); if (_buds[who] == 0) return; _buds[who] = 0; emit TollRenounced(msg.sender, who); } /// @inheritdoc IToll function tolled(address who) public view returns (bool) { return _buds[who] == 1; } /// @inheritdoc IToll /// @custom:invariant Only contains tolled addresses. /// ∀x ∊ tolled(): _tolled[x] /// @custom:invariant Contains all tolled addresses. /// ∀x ∊ Address: _tolled[x] == 1 → x ∊ tolled() function tolled() public view returns (address[] memory) { // Initiate array with upper limit length. address[] memory budsList = new address[](_budsTouched.length); // Iterate through all possible tolled addresses. uint ctr; for (uint i; i < budsList.length; i++) { // Add address only if still tolled. if (_buds[_budsTouched[i]] == 1) { budsList[ctr++] = _budsTouched[i]; } } // Set length of array to number of tolled addresses actually included. assembly ("memory-safe") { mstore(budsList, ctr) } return budsList; } /// @inheritdoc IToll function bud(address who) public view returns (uint) { return _buds[who]; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import {IChronicle} from "chronicle-std/IChronicle.sol"; import {LibSecp256k1} from "./libs/LibSecp256k1.sol"; interface IScribe is IChronicle { /// @dev PokeData encapsulates a value and its age. struct PokeData { uint128 val; uint32 age; } /// @dev SchnorrData encapsulates a (aggregated) Schnorr signature. /// Schnorr signatures are used to prove a PokeData's integrity. struct SchnorrData { bytes32 signature; address commitment; bytes feedIds; } /// @dev ECDSAData encapsulates an ECDSA signature. struct ECDSAData { uint8 v; bytes32 r; bytes32 s; } /// @notice Thrown if a poked value's age is not greater than the oracle's /// current value's age. /// @param givenAge The poked value's age. /// @param currentAge The oracle's current value's age. error StaleMessage(uint32 givenAge, uint32 currentAge); /// @notice Thrown if a poked value's age is greater than the current /// time. /// @param givenAge The poked value's age. /// @param currentTimestamp The current time. error FutureMessage(uint32 givenAge, uint32 currentTimestamp); /// @notice Thrown if Schnorr signature not signed by exactly bar many /// signers. /// @param numberSigners The number of signers for given Schnorr signature. /// @param bar The bar security parameter. error BarNotReached(uint8 numberSigners, uint8 bar); /// @notice Thrown if given feed id invalid. /// @param feedId The invalid feed id. error InvalidFeedId(uint8 feedId); /// @notice Thrown if double signing attempted. /// @param feedId The id of the feed attempting to double sign. error DoubleSigningAttempted(uint8 feedId); /// @notice Thrown if Schnorr signature verification failed. error SchnorrSignatureInvalid(); /// @notice Emitted when oracle was successfully poked. /// @param caller The caller's address. /// @param val The value poked. /// @param age The age of the value poked. event Poked(address indexed caller, uint128 val, uint32 age); /// @notice Emitted when new feed lifted. /// @param caller The caller's address. /// @param feed The feed address lifted. event FeedLifted(address indexed caller, address indexed feed); /// @notice Emitted when feed dropped. /// @param caller The caller's address. /// @param feed The feed address dropped. event FeedDropped(address indexed caller, address indexed feed); /// @notice Emitted when bar updated. /// @param caller The caller's address. /// @param oldBar The old bar's value. /// @param newBar The new bar's value. event BarUpdated(address indexed caller, uint8 oldBar, uint8 newBar); /// @notice Returns the feed registration message. /// @dev This message must be signed by a feed in order to be lifted. /// @return feedRegistrationMessage Chronicle Protocol's feed registration /// message. function feedRegistrationMessage() external view returns (bytes32 feedRegistrationMessage); /// @notice Returns the bar security parameter. /// @return bar The bar security parameter. function bar() external view returns (uint8 bar); /// @notice Returns the number of decimals of the oracle's value. /// @dev Provides partial compatibility with Chainlink's /// IAggregatorV3Interface. /// @return decimals The oracle value's number of decimals. function decimals() external view returns (uint8 decimals); /// @notice Returns the oracle's latest value. /// @dev Provides partial compatibility with Chainlink's /// IAggregatorV3Interface. /// @return roundId 1. /// @return answer The oracle's latest value. /// @return startedAt 0. /// @return updatedAt The timestamp of oracle's latest update. /// @return answeredInRound 1. function latestRoundData() external view returns ( uint80 roundId, int answer, uint startedAt, uint updatedAt, uint80 answeredInRound ); /// @notice Returns the oracle's latest value. /// @dev Provides partial compatibility with Chainlink's /// IAggregatorV3Interface. /// @custom:deprecated See https://docs.chain.link/data-feeds/api-reference/#latestanswer. /// @return answer The oracle's latest value. function latestAnswer() external view returns (int); /// @notice Pokes the oracle. /// @dev Expects `pokeData`'s age to be greater than the timestamp of the /// last successful poke. /// @dev Expects `pokeData`'s age to not be greater than the current time. /// @dev Expects `schnorrData` to prove `pokeData`'s integrity. /// See `isAcceptableSchnorrSignatureNow(bytes32,SchnorrData)(bool)`. /// @param pokeData The PokeData being poked. /// @param schnorrData The SchnorrData proving the `pokeData`'s /// integrity. function poke(PokeData calldata pokeData, SchnorrData calldata schnorrData) external; /// @notice Returns whether the Schnorr signature `schnorrData` is /// currently acceptable for message `message`. /// @dev Note that a valid Schnorr signature is only acceptable if the /// signature was signed by exactly bar many feeds. /// For more info, see `bar()(uint8)` and `feeds()(address[])`. /// @dev Note that bar and feeds are configurable, meaning a once acceptable /// Schnorr signature may become unacceptable in the future. /// @param message The message expected to be signed via `schnorrData`. /// @param schnorrData The SchnorrData to verify whether it proves /// the `message`'s integrity. /// @return ok True if Schnorr signature is acceptable, false otherwise. function isAcceptableSchnorrSignatureNow( bytes32 message, SchnorrData calldata schnorrData ) external view returns (bool ok); /// @notice Returns the message expected to be signed via Schnorr for /// `pokeData`. /// @dev The message is defined as: /// H(tag ‖ H(wat ‖ pokeData)), where H() is the keccak256 function. /// @param pokeData The pokeData to create the message for. /// @return pokeMessage Message for `pokeData`. function constructPokeMessage(PokeData calldata pokeData) external view returns (bytes32 pokeMessage); /// @notice Returns whether address `who` is a feed. /// @param who The address to check. /// @return isFeed True if `who` is feed, false otherwise. function feeds(address who) external view returns (bool isFeed); /// @notice Returns whether feed id `feedId` is a feed and, if so, the /// feed's address. /// @param feedId The feed id to check. /// @return isFeed True if `feedId` is a feed, false otherwise. /// @return feed Address of the feed with id `feedId` if `feedId` is a feed, /// zero-address otherwise. function feeds(uint8 feedId) external view returns (bool isFeed, address feed); /// @notice Returns list of feed addresses. /// @dev Note that this function has a high gas consumption and is not /// intended to be called onchain. /// @return feeds List of feed addresses. function feeds() external view returns (address[] memory feeds); /// @notice Lifts public key `pubKey` to being a feed. /// @dev Only callable by auth'ed address. /// @dev The message expected to be signed by `ecdsaData` is defined via /// `feedRegistrationMessage()(bytes32)`. /// @custom:security The lift function's proof of possession is vulnerable /// to rogue-key attacks. Additional verification MUST be /// performed before lifting to ensure a feed's public key /// validity. /// @param pubKey The public key of the feed. /// @param ecdsaData ECDSA signed message by the feed's public key. /// @return feedId The id of the newly lifted feed. function lift(LibSecp256k1.Point memory pubKey, ECDSAData memory ecdsaData) external returns (uint8 feedId); /// @notice Lifts public keys `pubKeys` to being feeds. /// @dev Only callable by auth'ed address. /// @dev The message expected to be signed by `ecdsaDatas` is defined via /// `feedRegistrationMessage()(bytes32)`. /// @custom:security The lift function's proof of possession is vulnerable /// to rogue-key attacks. Additional verification MUST be /// performed before lifting to ensure a feed's public key /// validity. /// @param pubKeys The public keys of the feeds. /// @param ecdsaDatas ECDSA signed message by the feeds' public keys. /// @return List of feed ids of the newly lifted feeds. function lift( LibSecp256k1.Point[] memory pubKeys, ECDSAData[] memory ecdsaDatas ) external returns (uint8[] memory); /// @notice Drops feed with id `feedId`. /// @dev Only callable by auth'ed address. /// @param feedId The feed id to drop. function drop(uint8 feedId) external; /// @notice Drops feeds with ids' `feedIds`. /// @dev Only callable by auth'ed address. /// @param feedIds The feed ids to drop. function drop(uint8[] memory feedIds) external; /// @notice Updates the bar security parameters to `bar`. /// @dev Only callable by auth'ed address. /// @dev Reverts if `bar` is zero. /// @param bar The value to update bar to. function setBar(uint8 bar) external; /// @notice Returns the oracle's current value. /// @custom:deprecated Use `tryRead()(bool,uint)` instead. /// @return value The oracle's current value if it exists, zero otherwise. /// @return isValid True if value exists, false otherwise. function peek() external view returns (uint value, bool isValid); /// @notice Returns the oracle's current value. /// @custom:deprecated Use `tryRead()(bool,uint)` instead. /// @return value The oracle's current value if it exists, zero otherwise. /// @return isValid True if value exists, false otherwise. function peep() external view returns (uint value, bool isValid); }
// 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; } }
// 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; } }
// 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); }
// 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); }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "chronicle-std/=lib/chronicle-std/src/", "lib/chronicle-std:src/=lib/chronicle-std/src/", "lib/chronicle-std:ds-test/=lib/chronicle-std/lib/forge-std/lib/ds-test/src/", "lib/chronicle-std:forge-std/=lib/chronicle-std/lib/forge-std/src/" ], "optimizer": { "enabled": true, "runs": 10000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "viaIR": true, "libraries": {} }
[{"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"}]
Contract Creation Code
60a0346200019b57620023a590601f38839003908101601f19168201906001600160401b03821183831017620001a057808391604095869485528339810103126200019b5780516001600160a01b03811691908290036200019b576020015160008281528060205260018482205560015468010000000000000000811015620001875760018101806001558110156200017357600182527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b03191684179055835192817fe31c10b0adbedd0c6e5d024286c6eeead7761e65a67608dcf0b67604c0da7e2f8186a3811562000170575060805261020590815460ff811691600283036200012f575b84516121ee9081620001b78239608051818181610cba015261183e0152f35b60029281528260208201527f95623b9931156d6d5cb43881a13f223ae416fb199e5edf776efb38766f38cbea853392a260ff19161790553880808062000110565b80fd5b634e487b7160e01b82526032600452602482fd5b634e487b7160e01b82526041600452602482fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe60406080815260049081361015610016575b600080fd5b600091823560e01c9081608214610e4d5781630760861b14610faa5781630e5a6c7014610b8e5781630fce341514610f6257816310b07b7114610f1a578163224242ca14610e595781632f529d7314610e4d5781632fba4aa914610d97578163313ce56714610d7b578163393e5ede14610d265781633bee58f914610cdd5781634ca2992314610ca25781634fce7a2a14610c5c57816350d25bcd14610c0a57816357de26a414610bc357816359e02dd714610b8e57816365c4ce7a14610b5457816365fae35e14610b0a578163789d819114610a3c5781639954b0dc1461098f5781639c52a7f114610945578163acf40b6f146108e9578163b259da5c1461080d578163bf353dbb146107c8578163bfe5861f1461058f578163c83c63341461055a578163ceed3ef2146104db578163d0a5882a146104b7578163d63605b814610389578163dac42ad814610338578163f29c29c4146102fb578163fe66349514610233578163feaf968c146101bc575063febb0f7e1461019757600080fd5b346101b857816003193601126101b85760209060ff61020554169051908152f35b5080fd5b90503461022f578260031936011261022f573383526002602052818320541561021e5760a09263ffffffff915490835193600185526fffffffffffffffffffffffffffffffff8316602086015284015260801c16606082015260016080820152f35b63d957b5958352336020526024601cfd5b8280fd5b5050346101b85760206003193601126101b85761024e611321565b3383528260205281832054156102ea5760ff811680156102e65761020591825460ff811683810361027e57868651f35b855160ff9182168152921660208301527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009133907f95623b9931156d6d5cb43881a13f223ae416fb199e5edf776efb38766f38cbea90604090a2161790553880808080868651f35b8380fd5b634a0bfec18352336020526024601cfd5b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f5761033590611690565b51f35b82843461038657600319908282360112610386576024359167ffffffffffffffff83116101b857606090833603011261038657508261037c9160209401903561194c565b5090519015158152f35b80fd5b9190503461022f578260031936011261022f57805191612020830183811067ffffffffffffffff82111761048b5782526101008084526020946120003687870137808685516103d781611279565b82815201528092815b8381106103fb578487528551806103f7898261133f565b0390f35b8360ff8216101561045f576001908661041c6101fe83851b1660050161192e565b80518b82015117610430575b5050016103e0565b209095829173ffffffffffffffffffffffffffffffffffffffff16610455828b61167c565b5201948638610428565b6024836032847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b6024856041847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5050346101b857816003193601126101b8576020906104d46113a8565b9051908152f35b8383346101b857816003193601126101b857338252600260205280822054156105495791546060926fffffffffffffffffffffffffffffffff821692831561053e575063ffffffff6001939260801c16915b815193151584526020840152820152f35b92508291508161052d565b63d957b5958252336020526024601cfd5b5050346101b85760206003193601126101b857610575611321565b3383528260205281832054156102ea576103359033611f0c565b839150346101b857826003193601126101b85780359067ffffffffffffffff938483116102e657366023840112156102e657828201356105ce81611390565b926105db835194856112e0565b8184526020948585016024809460061b83010191368311610792578401905b82821061079a57505050813596871161079657366023880112156107965786013561062481611390565b96610631845198896112e0565b81885285880183606080940283010191368311610792578401905b828210610755575050505033855284845281852054156107475750815192855184036107435761069361067e85611390565b9461068b845196876112e0565b808652611390565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08186019201368337855b845181101561070057806106ea6106d86001938861167c565b516106e3838c61167c565b5190611dd6565b60ff6106f6838a61167c565b91169052016106bf565b509190858583519485948186019282875251809352850193925b82811061072957505050500390f35b835160ff168552869550938101939281019260010161071a565b8480fd5b634a0bfec18552338452601cfd5b838236031261079257878491875161076c816112c4565b61077585611331565b81528285013583820152888501358982015281520191019061064c565b8880fd5b8580fd5b85823603126107925787869182516107b181611279565b8435815282850135838201528152019101906105fa565b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f578282916020945280845220549051908152f35b828434610386576020806003193601126101b85783359367ffffffffffffffff851161022f573660238601121561022f578401359361084b85611390565b94610858855196876112e0565b80865260248387019160051b83010191368311610743576024849101915b8383106108d1575050505033825281815282822054156108c15750805b83518110156108bc57806108b660ff6108ae6001948861167c565b511633611f0c565b01610893565b509051f35b634a0bfec182523390526024601cfd5b81906108dc84611331565b8152019101908390610876565b82843461038657816003193601126103865781519261090784611279565b356fffffffffffffffffffffffffffffffff811681036101b85783526024359063ffffffff821682036103865750826104d4916020809501526117ea565b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f573383528260205281832054156102ea5761033590611575565b82843461038657806003193601126103865760036109ad81546115d1565b9082835b8351811015610a2c57806109c76109fd92611472565b905473ffffffffffffffffffffffffffffffffffffffff91861b1c81168752600260205287872054600114610a02575b50611620565b6109b1565b610a0b82611472565b905490861b1c16610a25610a1e85611620565b948761167c565b52876109f7565b8184528551806103f7868261133f565b839150346101b85760206003193601126101b857610a58611321565b90610100821015610ade5750610a74839160011b60050161192e565b8051602082015117610aa857505073ffffffffffffffffffffffffffffffffffffffff815b83519215158352166020820152f35b73ffffffffffffffffffffffffffffffffffffffff9250201673ffffffffffffffffffffffffffffffffffffffff600191610a99565b8260326024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f573383528260205281832054156102ea57610335906114a9565b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f576103359061173b565b5050346101b857816003193601126101b8576103f790610bac611d94565b915190815290151560208201529081906040820190565b90503461022f578260031936011261022f573383526002602052818320541561021e57546fffffffffffffffffffffffffffffffff1690811561022f576020925051908152f35b82843461038657806003193601126103865733815260026020528181205415610c4b57506fffffffffffffffffffffffffffffffff60209254169051908152f35b63d957b5959052336020526024601cfd5b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f57828291602094526002845220549051908152f35b5050346101b857816003193601126101b857602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f57818360019260209552600285522054149051908152f35b839150346101b857816003193601126101b8573382526002602052828220541561054957546fffffffffffffffffffffffffffffffff81169182156103865750825191825260801c63ffffffff166020820152f35b5050346101b857816003193601126101b8576020905160128152f35b8284346103865760206003193601126103865773ffffffffffffffffffffffffffffffffffffffff908335828116918282036103865761010060ff8360981c161015610e215750602094506101fe610df59160971c1660050161192e565b918251858401511715159283610e12575b50505090519015158152f35b84902016149050838080610e06565b806032877f4e487b71000000000000000000000000000000000000000000000000000000006024945252fd5b50505050610011611067565b828434610386578060031936011261038657600191610e7883546115d1565b918080855b610e95575b50506103f793508252519182918261133f565b8451811015610f155790610ee482610ead889461140c565b73ffffffffffffffffffffffffffffffffffffffff809254600392831b1c16855284602052858886205414610eeb575b5050611620565b9091610e7d565b610ef48361140c565b9054911b1c16610f0d610f0687611620565b968961167c565b528880610edd565b610e82565b9050823461038657806003193601126103865733815260026020528281205415610c4b57506fffffffffffffffffffffffffffffffff90541681519080151582526020820152f35b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f578183600192602095528085522054149051908152f35b90503461022f57600319360160a081126102e657821361022f57815190610fd082611279565b358152602435602082015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc36011261022f57815192611011846112c4565b60443560ff811681036101b8578452606435602085015260843583850152338152806020528281205415611056575061104e60209360ff92611dd6565b915191168152f35b634a0bfec19052336020526024601cfd5b50346100115760031980360160608112610011576040809112610011576044359167ffffffffffffffff8311610011576060908336030112610011576110ab6117b8565b9160049283549363ffffffff8092818760801c169182911611156112295750816110d36117b8565b81421691829116116111d557508351926110ec84611279565b6fffffffffffffffffffffffffffffffff93823585811681036100115781526024358481168103610011576111319261112c9160208401528401916117ea565b61194c565b9590156111cd5760009550836111456117cb565b167fffffffffffffffffffffffff000000000000000000000000000000000000000073ffffffff000000000000000000000000000000004260801b1692161717905561118f6117cb565b916111986117b8565b908451931683521660208201527f7045db5134e0c7ca4bff0c0e096616ef4ebb36b719cd00c5f0ba4f4475ecceee823392a251f35b855160208701fd5b9061122585926111e36117b8565b93517feea80f5200000000000000000000000000000000000000000000000000000000815263ffffffff94851693810193845293166020830152829160400190565b0390fd5b9061122585926112376117b8565b93517f76f4b87800000000000000000000000000000000000000000000000000000000815263ffffffff94851693810193845293166020830152829160400190565b6040810190811067ffffffffffffffff82111761129557604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761129557604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761129557604052565b6004359060ff8216820361001157565b359060ff8216820361001157565b6020908160408183019282815285518094520193019160005b828110611366575050505090565b835173ffffffffffffffffffffffffffffffffffffffff1685529381019392810192600101611358565b67ffffffffffffffff81116112955760051b60200190565b60405160208101907f19457468657265756d205369676e6564204d6573736167653a0a33320000000082527ff3acba882491058ea715223a1463b7d7e8610fbbb588100fb1e69a89099384a0603c820152603c8152611406816112c4565b51902090565b6001548110156114435760016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6003548110156114435760036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0190600090565b73ffffffffffffffffffffffffffffffffffffffff809116906000908282528160205260016040832054146115705760016040832055600154680100000000000000008110156115435761150481600186930160015561140c565b909283549160031b90811b9283911b169119161790557fe31c10b0adbedd0c6e5d024286c6eeead7761e65a67608dcf0b67604c0da7e2f3391604051a3565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b505050565b73ffffffffffffffffffffffffffffffffffffffff166000818152806020526040812054156115cd578060408120557f58466e5837b54e559819c9ba8a5d7c77c97c985d1aabf4bdc5f41069fa5d65a03391604051a3565b5050565b906115db82611390565b6115e860405191826112e0565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06116168294611390565b0190602036910137565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461164d5760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80518210156114435760209160051b010190565b6000338152806020526040812054156110565773ffffffffffffffffffffffffffffffffffffffff8092169182825260026020526001604083205414611570576001604083205560035468010000000000000000811015611543576116fc816001869301600355611472565b909283549160031b90811b9283911b169119161790557f75d30ca40c7bcd48e685894b82b864808b9cb566090efc53444a2e61742f18a33391604051a3565b600090338252816020526040822054156117a75773ffffffffffffffffffffffffffffffffffffffff169081815260026020526040812054156115cd578060408120557fdadd1471db1ea2f303654fb1bdcc010e5a664214ab41934c0f752aabca88a4913391604051a3565b634a0bfec18252336020526024601cfd5b60243563ffffffff811681036100115790565b6004356fffffffffffffffffffffffffffffffff811681036100115790565b602081519101517fffffffff00000000000000000000000000000000000000000000000000000000604051917fffffffffffffffffffffffffffffffff0000000000000000000000000000000060208401947f0000000000000000000000000000000000000000000000000000000000000000865260801b16604084015260e01b1660508201526034815261187e816112c4565b51902060405160208101917f19457468657265756d205369676e6564204d6573736167653a0a3332000000008352603c820152603c8152611406816112c4565b604051906118cb826112c4565b60006040838281528260208201520152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610011570180359067ffffffffffffffff82116100115760200191813603831361001157565b9060405161193b81611279565b602060018294805484520154910152565b906000602060405161195d81611279565b828152015261196a6118be565b5061197860408201826118dd565b93905060ff6102055416808503611d45575061199760408301836118dd565b156114435735916101008360f81c1015611443576119be6101fe8460f71c1660050161192e565b92835160208501511715611d335760019060f81c1b906119dc6118be565b5060208451940151604051946119f1866112c4565b855260208501526001604085015260015b60ff81169287841015611b9f57611a1c60408401846118dd565b8591951015611443576101008186013560f81c101561144357611a4b6101fe8287013560f71c1660050161192e565b94855160208701511715611b825760018282013560f81c1b8316611b315791600160ff94928194013560f81c1b179487805160208201516020828460408101517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f809881808099818099818099818a81808280099781898d510990820390089d8e936040848087800981808d8180856004099b8c9a089382039082030891800908910152099b09950151816002988d82039409900908840996828080888709810384820308818a800908809a520990098203948203900890090860208801520116611a02565b96509750505050509150604051927f1280090c000000000000000000000000000000000000000000000000000000006020850152602491013560f81c818401528252611b7c826112c4565b60009190565b959850955050505050611b9a9250013560f81c611f94565b600091565b505093929194505060006020604051611bb781611279565b828152015260405190611bc982611279565b60008252602082019060008252604081015190600091600190807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f915b611cf657505050907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f80926020828480099183838251098852015192099009905260208301359173ffffffffffffffffffffffffffffffffffffffff8316830361001157611c75933591611fd6565b15611ca857604051906020820182811067ffffffffffffffff821117611295578060009160405281845236903760019190565b604051907fbd2a556b000000000000000000000000000000000000000000000000000000006020830152600482526040820182811067ffffffffffffffff8211176112955760405260009190565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8183949693049281878509820390089290918202900380611c06565b9250509250611b9a915060f81c611f94565b6040517fce818a2400000000000000000000000000000000000000000000000000000000602082015260ff9586166024820152941660448086019190915284529150611b7c90506064836112e0565b33600052600260205260406000205415611dc4576fffffffffffffffffffffffffffffffff600454169081151590565b63d957b595600052336020526024601cfd5b6040918282209273ffffffffffffffffffffffffffffffffffffffff91828516926020611e34611e046113a8565b84518386015195870151875192835260ff9091166020830152604082019590955260608101949094526080840190565b836000948592838052039060015afa15611f00578082511684036101b85760ff8660981c1695610100871015611ed35760971c6101fe16906005820190611e7a8261192e565b8051602082015117611ec15750506020866006927f2c44ddc69b8b0966ef9e8edb873b850fb2eff06ca6e2bc37c9adf3551ec39e549697985190550151910155339251a390565b92509392955050201603610386575090565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b509051903d90823e3d90fd5b906101008110156114435760011b8060050190611f288261192e565b908151602083015117611f3c575b50505050565b60066000918260409555015573ffffffffffffffffffffffffffffffffffffffff918291201691167f9ec05f17908406877637da36ab29c002620cb544d0049837bfa095e62726455c6000604051a338808080611f36565b60ff604051917fc523c75e00000000000000000000000000000000000000000000000000000000602084015216602482015260248152611fd3816112c4565b90565b9190918115801561219a575b61219157602081019283518251947ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f80600781808a80098a09089083800903612185577ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641419283861015612178577f0100000000000000000000000000000000000000000000000000000000000000604051936020850198895260f81b16604084015260418301527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008760601b16606183015260558252608082019382851067ffffffffffffffff86111761129557601b6000968580600160ff8261213d987fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff809b60209f8e6040528c519020069851978894859251160198098303961693099003875260ff166020870152604086015260608501526080840190565b84805203019060015afa1561216c5773ffffffffffffffffffffffffffffffffffffffff806000511691161490565b6040513d6000823e3d90fd5b5050505050505050600090565b50505050505050600090565b50505050600090565b5073ffffffffffffffffffffffffffffffffffffffff841615611fe256fea2646970667358221220caf6176518531103c5a0ccc82f9a708985c1b7d7f716a674cac9f04bd0b6740f64736f6c6343000810003300000000000000000000000074258a92611e029b748f79c50024dd851339db1545425443236261646765722f4554480000000000000000000000000000000000
Deployed Bytecode
0x60406080815260049081361015610016575b600080fd5b600091823560e01c9081608214610e4d5781630760861b14610faa5781630e5a6c7014610b8e5781630fce341514610f6257816310b07b7114610f1a578163224242ca14610e595781632f529d7314610e4d5781632fba4aa914610d97578163313ce56714610d7b578163393e5ede14610d265781633bee58f914610cdd5781634ca2992314610ca25781634fce7a2a14610c5c57816350d25bcd14610c0a57816357de26a414610bc357816359e02dd714610b8e57816365c4ce7a14610b5457816365fae35e14610b0a578163789d819114610a3c5781639954b0dc1461098f5781639c52a7f114610945578163acf40b6f146108e9578163b259da5c1461080d578163bf353dbb146107c8578163bfe5861f1461058f578163c83c63341461055a578163ceed3ef2146104db578163d0a5882a146104b7578163d63605b814610389578163dac42ad814610338578163f29c29c4146102fb578163fe66349514610233578163feaf968c146101bc575063febb0f7e1461019757600080fd5b346101b857816003193601126101b85760209060ff61020554169051908152f35b5080fd5b90503461022f578260031936011261022f573383526002602052818320541561021e5760a09263ffffffff915490835193600185526fffffffffffffffffffffffffffffffff8316602086015284015260801c16606082015260016080820152f35b63d957b5958352336020526024601cfd5b8280fd5b5050346101b85760206003193601126101b85761024e611321565b3383528260205281832054156102ea5760ff811680156102e65761020591825460ff811683810361027e57868651f35b855160ff9182168152921660208301527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009133907f95623b9931156d6d5cb43881a13f223ae416fb199e5edf776efb38766f38cbea90604090a2161790553880808080868651f35b8380fd5b634a0bfec18352336020526024601cfd5b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f5761033590611690565b51f35b82843461038657600319908282360112610386576024359167ffffffffffffffff83116101b857606090833603011261038657508261037c9160209401903561194c565b5090519015158152f35b80fd5b9190503461022f578260031936011261022f57805191612020830183811067ffffffffffffffff82111761048b5782526101008084526020946120003687870137808685516103d781611279565b82815201528092815b8381106103fb578487528551806103f7898261133f565b0390f35b8360ff8216101561045f576001908661041c6101fe83851b1660050161192e565b80518b82015117610430575b5050016103e0565b209095829173ffffffffffffffffffffffffffffffffffffffff16610455828b61167c565b5201948638610428565b6024836032847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b6024856041847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5050346101b857816003193601126101b8576020906104d46113a8565b9051908152f35b8383346101b857816003193601126101b857338252600260205280822054156105495791546060926fffffffffffffffffffffffffffffffff821692831561053e575063ffffffff6001939260801c16915b815193151584526020840152820152f35b92508291508161052d565b63d957b5958252336020526024601cfd5b5050346101b85760206003193601126101b857610575611321565b3383528260205281832054156102ea576103359033611f0c565b839150346101b857826003193601126101b85780359067ffffffffffffffff938483116102e657366023840112156102e657828201356105ce81611390565b926105db835194856112e0565b8184526020948585016024809460061b83010191368311610792578401905b82821061079a57505050813596871161079657366023880112156107965786013561062481611390565b96610631845198896112e0565b81885285880183606080940283010191368311610792578401905b828210610755575050505033855284845281852054156107475750815192855184036107435761069361067e85611390565b9461068b845196876112e0565b808652611390565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08186019201368337855b845181101561070057806106ea6106d86001938861167c565b516106e3838c61167c565b5190611dd6565b60ff6106f6838a61167c565b91169052016106bf565b509190858583519485948186019282875251809352850193925b82811061072957505050500390f35b835160ff168552869550938101939281019260010161071a565b8480fd5b634a0bfec18552338452601cfd5b838236031261079257878491875161076c816112c4565b61077585611331565b81528285013583820152888501358982015281520191019061064c565b8880fd5b8580fd5b85823603126107925787869182516107b181611279565b8435815282850135838201528152019101906105fa565b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f578282916020945280845220549051908152f35b828434610386576020806003193601126101b85783359367ffffffffffffffff851161022f573660238601121561022f578401359361084b85611390565b94610858855196876112e0565b80865260248387019160051b83010191368311610743576024849101915b8383106108d1575050505033825281815282822054156108c15750805b83518110156108bc57806108b660ff6108ae6001948861167c565b511633611f0c565b01610893565b509051f35b634a0bfec182523390526024601cfd5b81906108dc84611331565b8152019101908390610876565b82843461038657816003193601126103865781519261090784611279565b356fffffffffffffffffffffffffffffffff811681036101b85783526024359063ffffffff821682036103865750826104d4916020809501526117ea565b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f573383528260205281832054156102ea5761033590611575565b82843461038657806003193601126103865760036109ad81546115d1565b9082835b8351811015610a2c57806109c76109fd92611472565b905473ffffffffffffffffffffffffffffffffffffffff91861b1c81168752600260205287872054600114610a02575b50611620565b6109b1565b610a0b82611472565b905490861b1c16610a25610a1e85611620565b948761167c565b52876109f7565b8184528551806103f7868261133f565b839150346101b85760206003193601126101b857610a58611321565b90610100821015610ade5750610a74839160011b60050161192e565b8051602082015117610aa857505073ffffffffffffffffffffffffffffffffffffffff815b83519215158352166020820152f35b73ffffffffffffffffffffffffffffffffffffffff9250201673ffffffffffffffffffffffffffffffffffffffff600191610a99565b8260326024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f573383528260205281832054156102ea57610335906114a9565b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff8116810361022f576103359061173b565b5050346101b857816003193601126101b8576103f790610bac611d94565b915190815290151560208201529081906040820190565b90503461022f578260031936011261022f573383526002602052818320541561021e57546fffffffffffffffffffffffffffffffff1690811561022f576020925051908152f35b82843461038657806003193601126103865733815260026020528181205415610c4b57506fffffffffffffffffffffffffffffffff60209254169051908152f35b63d957b5959052336020526024601cfd5b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f57828291602094526002845220549051908152f35b5050346101b857816003193601126101b857602090517f45425443236261646765722f45544800000000000000000000000000000000008152f35b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f57818360019260209552600285522054149051908152f35b839150346101b857816003193601126101b8573382526002602052828220541561054957546fffffffffffffffffffffffffffffffff81169182156103865750825191825260801c63ffffffff166020820152f35b5050346101b857816003193601126101b8576020905160128152f35b8284346103865760206003193601126103865773ffffffffffffffffffffffffffffffffffffffff908335828116918282036103865761010060ff8360981c161015610e215750602094506101fe610df59160971c1660050161192e565b918251858401511715159283610e12575b50505090519015158152f35b84902016149050838080610e06565b806032877f4e487b71000000000000000000000000000000000000000000000000000000006024945252fd5b50505050610011611067565b828434610386578060031936011261038657600191610e7883546115d1565b918080855b610e95575b50506103f793508252519182918261133f565b8451811015610f155790610ee482610ead889461140c565b73ffffffffffffffffffffffffffffffffffffffff809254600392831b1c16855284602052858886205414610eeb575b5050611620565b9091610e7d565b610ef48361140c565b9054911b1c16610f0d610f0687611620565b968961167c565b528880610edd565b610e82565b9050823461038657806003193601126103865733815260026020528281205415610c4b57506fffffffffffffffffffffffffffffffff90541681519080151582526020820152f35b90503461022f57602060031936011261022f573573ffffffffffffffffffffffffffffffffffffffff811680910361022f578183600192602095528085522054149051908152f35b90503461022f57600319360160a081126102e657821361022f57815190610fd082611279565b358152602435602082015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc36011261022f57815192611011846112c4565b60443560ff811681036101b8578452606435602085015260843583850152338152806020528281205415611056575061104e60209360ff92611dd6565b915191168152f35b634a0bfec19052336020526024601cfd5b50346100115760031980360160608112610011576040809112610011576044359167ffffffffffffffff8311610011576060908336030112610011576110ab6117b8565b9160049283549363ffffffff8092818760801c169182911611156112295750816110d36117b8565b81421691829116116111d557508351926110ec84611279565b6fffffffffffffffffffffffffffffffff93823585811681036100115781526024358481168103610011576111319261112c9160208401528401916117ea565b61194c565b9590156111cd5760009550836111456117cb565b167fffffffffffffffffffffffff000000000000000000000000000000000000000073ffffffff000000000000000000000000000000004260801b1692161717905561118f6117cb565b916111986117b8565b908451931683521660208201527f7045db5134e0c7ca4bff0c0e096616ef4ebb36b719cd00c5f0ba4f4475ecceee823392a251f35b855160208701fd5b9061122585926111e36117b8565b93517feea80f5200000000000000000000000000000000000000000000000000000000815263ffffffff94851693810193845293166020830152829160400190565b0390fd5b9061122585926112376117b8565b93517f76f4b87800000000000000000000000000000000000000000000000000000000815263ffffffff94851693810193845293166020830152829160400190565b6040810190811067ffffffffffffffff82111761129557604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761129557604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761129557604052565b6004359060ff8216820361001157565b359060ff8216820361001157565b6020908160408183019282815285518094520193019160005b828110611366575050505090565b835173ffffffffffffffffffffffffffffffffffffffff1685529381019392810192600101611358565b67ffffffffffffffff81116112955760051b60200190565b60405160208101907f19457468657265756d205369676e6564204d6573736167653a0a33320000000082527ff3acba882491058ea715223a1463b7d7e8610fbbb588100fb1e69a89099384a0603c820152603c8152611406816112c4565b51902090565b6001548110156114435760016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6003548110156114435760036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0190600090565b73ffffffffffffffffffffffffffffffffffffffff809116906000908282528160205260016040832054146115705760016040832055600154680100000000000000008110156115435761150481600186930160015561140c565b909283549160031b90811b9283911b169119161790557fe31c10b0adbedd0c6e5d024286c6eeead7761e65a67608dcf0b67604c0da7e2f3391604051a3565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b505050565b73ffffffffffffffffffffffffffffffffffffffff166000818152806020526040812054156115cd578060408120557f58466e5837b54e559819c9ba8a5d7c77c97c985d1aabf4bdc5f41069fa5d65a03391604051a3565b5050565b906115db82611390565b6115e860405191826112e0565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06116168294611390565b0190602036910137565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461164d5760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80518210156114435760209160051b010190565b6000338152806020526040812054156110565773ffffffffffffffffffffffffffffffffffffffff8092169182825260026020526001604083205414611570576001604083205560035468010000000000000000811015611543576116fc816001869301600355611472565b909283549160031b90811b9283911b169119161790557f75d30ca40c7bcd48e685894b82b864808b9cb566090efc53444a2e61742f18a33391604051a3565b600090338252816020526040822054156117a75773ffffffffffffffffffffffffffffffffffffffff169081815260026020526040812054156115cd578060408120557fdadd1471db1ea2f303654fb1bdcc010e5a664214ab41934c0f752aabca88a4913391604051a3565b634a0bfec18252336020526024601cfd5b60243563ffffffff811681036100115790565b6004356fffffffffffffffffffffffffffffffff811681036100115790565b602081519101517fffffffff00000000000000000000000000000000000000000000000000000000604051917fffffffffffffffffffffffffffffffff0000000000000000000000000000000060208401947f45425443236261646765722f4554480000000000000000000000000000000000865260801b16604084015260e01b1660508201526034815261187e816112c4565b51902060405160208101917f19457468657265756d205369676e6564204d6573736167653a0a3332000000008352603c820152603c8152611406816112c4565b604051906118cb826112c4565b60006040838281528260208201520152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610011570180359067ffffffffffffffff82116100115760200191813603831361001157565b9060405161193b81611279565b602060018294805484520154910152565b906000602060405161195d81611279565b828152015261196a6118be565b5061197860408201826118dd565b93905060ff6102055416808503611d45575061199760408301836118dd565b156114435735916101008360f81c1015611443576119be6101fe8460f71c1660050161192e565b92835160208501511715611d335760019060f81c1b906119dc6118be565b5060208451940151604051946119f1866112c4565b855260208501526001604085015260015b60ff81169287841015611b9f57611a1c60408401846118dd565b8591951015611443576101008186013560f81c101561144357611a4b6101fe8287013560f71c1660050161192e565b94855160208701511715611b825760018282013560f81c1b8316611b315791600160ff94928194013560f81c1b179487805160208201516020828460408101517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f809881808099818099818099818a81808280099781898d510990820390089d8e936040848087800981808d8180856004099b8c9a089382039082030891800908910152099b09950151816002988d82039409900908840996828080888709810384820308818a800908809a520990098203948203900890090860208801520116611a02565b96509750505050509150604051927f1280090c000000000000000000000000000000000000000000000000000000006020850152602491013560f81c818401528252611b7c826112c4565b60009190565b959850955050505050611b9a9250013560f81c611f94565b600091565b505093929194505060006020604051611bb781611279565b828152015260405190611bc982611279565b60008252602082019060008252604081015190600091600190807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f915b611cf657505050907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f80926020828480099183838251098852015192099009905260208301359173ffffffffffffffffffffffffffffffffffffffff8316830361001157611c75933591611fd6565b15611ca857604051906020820182811067ffffffffffffffff821117611295578060009160405281845236903760019190565b604051907fbd2a556b000000000000000000000000000000000000000000000000000000006020830152600482526040820182811067ffffffffffffffff8211176112955760405260009190565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8183949693049281878509820390089290918202900380611c06565b9250509250611b9a915060f81c611f94565b6040517fce818a2400000000000000000000000000000000000000000000000000000000602082015260ff9586166024820152941660448086019190915284529150611b7c90506064836112e0565b33600052600260205260406000205415611dc4576fffffffffffffffffffffffffffffffff600454169081151590565b63d957b595600052336020526024601cfd5b6040918282209273ffffffffffffffffffffffffffffffffffffffff91828516926020611e34611e046113a8565b84518386015195870151875192835260ff9091166020830152604082019590955260608101949094526080840190565b836000948592838052039060015afa15611f00578082511684036101b85760ff8660981c1695610100871015611ed35760971c6101fe16906005820190611e7a8261192e565b8051602082015117611ec15750506020866006927f2c44ddc69b8b0966ef9e8edb873b850fb2eff06ca6e2bc37c9adf3551ec39e549697985190550151910155339251a390565b92509392955050201603610386575090565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b509051903d90823e3d90fd5b906101008110156114435760011b8060050190611f288261192e565b908151602083015117611f3c575b50505050565b60066000918260409555015573ffffffffffffffffffffffffffffffffffffffff918291201691167f9ec05f17908406877637da36ab29c002620cb544d0049837bfa095e62726455c6000604051a338808080611f36565b60ff604051917fc523c75e00000000000000000000000000000000000000000000000000000000602084015216602482015260248152611fd3816112c4565b90565b9190918115801561219a575b61219157602081019283518251947ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f80600781808a80098a09089083800903612185577ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641419283861015612178577f0100000000000000000000000000000000000000000000000000000000000000604051936020850198895260f81b16604084015260418301527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008760601b16606183015260558252608082019382851067ffffffffffffffff86111761129557601b6000968580600160ff8261213d987fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff809b60209f8e6040528c519020069851978894859251160198098303961693099003875260ff166020870152604086015260608501526080840190565b84805203019060015afa1561216c5773ffffffffffffffffffffffffffffffffffffffff806000511691161490565b6040513d6000823e3d90fd5b5050505050505050600090565b50505050505050600090565b50505050600090565b5073ffffffffffffffffffffffffffffffffffffffff841615611fe256fea2646970667358221220caf6176518531103c5a0ccc82f9a708985c1b7d7f716a674cac9f04bd0b6740f64736f6c63430008100033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000074258a92611e029b748f79c50024dd851339db1545425443236261646765722f4554480000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : initialAuthed (address): 0x74258A92611e029b748F79c50024DD851339dB15
Arg [1] : wat_ (bytes32): 0x45425443236261646765722f4554480000000000000000000000000000000000
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000074258a92611e029b748f79c50024dd851339db15
Arg [1] : 45425443236261646765722f4554480000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.