false
false
Blockchain
Blocks
Blocks
Uncles
Forked Blocks (Reorgs)
Transactions
Validated
Pending
Verified contracts
Tokens
All
KCS
APIs
GraphQL
RPC
Eth RPC
/
Search
/
Search
Connection Lost
New Solidity Smart Contract Verification
Contract Address
The 0x address supplied on contract creation.
Is Yul contract
No
Yes
Select Yes if you want to verify Yul contract.
Contract Name
Must match the name specified in the code. For example, in
contract MyContract {..}
MyContract
is the contract name.
Include nightly builds
No
Yes
Select yes if you want to show nightly builds.
Compiler
v0.8.30+commit.73712a01
v0.8.29+commit.ab55807c
v0.8.28+commit.7893614a
v0.8.27+commit.40a35a09
v0.8.26+commit.8a97fa7a
v0.8.25+commit.b61c2a91
v0.8.24+commit.e11b9ed9
v0.8.23+commit.f704f362
v0.8.22+commit.4fc1097e
v0.8.21+commit.d9974bed
v0.8.20+commit.a1b79de6
v0.8.19+commit.7dd6d404
v0.8.18+commit.87f61d96
v0.8.17+commit.8df45f5f
v0.8.16+commit.07a7930e
v0.8.15+commit.e14f2714
v0.8.14+commit.80d49f37
v0.8.13+commit.abaa5c0e
v0.8.12+commit.f00d7308
v0.8.11+commit.d7f03943
v0.8.10+commit.fc410830
v0.8.9+commit.e5eed63a
v0.8.8+commit.dddeac2f
v0.8.7+commit.e28d00a7
v0.8.6+commit.11564f7e
v0.8.5+commit.a4f2e591
v0.8.4+commit.c7e474f2
v0.8.3+commit.8d00100c
v0.8.2+commit.661d1103
v0.8.1+commit.df193b15
v0.8.0+commit.c7dfd78e
v0.7.6+commit.7338295f
v0.7.5+commit.eb77ed08
v0.7.4+commit.3f05b770
v0.7.3+commit.9bfce1f6
v0.7.2+commit.51b20bc0
v0.7.1+commit.f4a555be
v0.7.0+commit.9e61f92b
v0.6.12+commit.27d51765
v0.6.11+commit.5ef660b1
v0.6.10+commit.00c0fcaf
v0.6.9+commit.3e3065ac
v0.6.8+commit.0bbfe453
v0.6.7+commit.b8d736ae
v0.6.6+commit.6c089d02
v0.6.5+commit.f956cc89
v0.6.4+commit.1dca32f3
v0.6.3+commit.8dda9521
v0.6.2+commit.bacdbe57
v0.6.1+commit.e6f7d5a4
v0.6.0+commit.26b70077
v0.5.17+commit.d19bba13
v0.5.16+commit.9c3226ce
v0.5.15+commit.6a57276f
v0.5.14+commit.01f1aaa4
v0.5.13+commit.5b0b510c
v0.5.12+commit.7709ece9
v0.5.11+commit.22be8592
v0.5.10+commit.5a6ea5b1
v0.5.9+commit.c68bc34e
v0.5.8+commit.23d335f2
v0.5.7+commit.6da8b019
v0.5.6+commit.b259423e
v0.5.5+commit.47a71e8f
v0.5.4+commit.9549d8ff
v0.5.3+commit.10d17f24
v0.5.2+commit.1df8f40c
v0.5.1+commit.c8a2cb62
v0.5.0+commit.1d4f565a
v0.4.26+commit.4563c3fc
v0.4.25+commit.59dbf8f1
v0.4.24+commit.e67f0147
v0.4.23+commit.124ca40d
v0.4.22+commit.4cb486ee
v0.4.21+commit.dfe3193c
v0.4.20+commit.3155dd80
v0.4.19+commit.c4cbbb05
v0.4.18+commit.9cf6e910
v0.4.17+commit.bdeb9e52
v0.4.16+commit.d7661dd9
v0.4.15+commit.8b45bddb
v0.4.14+commit.c2215d46
v0.4.13+commit.0fb4cb1a
v0.4.12+commit.194ff033
v0.4.11+commit.68ef5810
v0.4.10+commit.9e8cc01b
The compiler version is specified in
pragma solidity X.X.X
. Use the compiler version rather than the nightly build. If using the Solidity compiler, run
solc —version
to check.
EVM Version
homestead
tangerineWhistle
spuriousDragon
byzantium
constantinople
petersburg
istanbul
berlin
london
paris
shanghai
default
The EVM version the contract is written for. If the bytecode does not match the version, we try to verify using the latest EVM version.
EVM version details
.
Optimization
No
Yes
If you enabled optimization during compilation, select yes.
Optimization runs
Enter the Solidity Contract Code
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; interface AccessControllerInterface { function hasAccess(address user, bytes calldata data) external view returns (bool); } // File contracts/interfaces/AggregatorInterface.sol interface AggregatorInterface { function latestAnswer() external view returns (int256); function latestTimestamp() external view returns (uint256); function latestRound() external view returns (uint256); function getAnswer(uint256 roundId) external view returns (int256); function getTimestamp(uint256 roundId) external view returns (uint256); event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt); } // File contracts/interfaces/AggregatorV3Interface.sol interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); // getRoundData and latestRoundData should both raise "No data present" // if they do not have data to report, instead of returning unset values // which could be misinterpreted as actual reported values. function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); } // File contracts/interfaces/AggregatorV2V3Interface.sol interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {} // File contracts/interfaces/TypeAndVersionInterface.sol abstract contract TypeAndVersionInterface { function typeAndVersion() external pure virtual returns (string memory); } // File contracts/interfaces/OwnableInterface.sol interface OwnableInterface { function owner() external returns (address); function transferOwnership(address recipient) external; function acceptOwnership() external; } // File contracts/ConfirmedOwnerWithProposal.sol /** * @title The ConfirmedOwner contract * @notice A contract with helpers for basic contract ownership. */ contract ConfirmedOwnerWithProposal is OwnableInterface { address private s_owner; address private s_pendingOwner; event OwnershipTransferRequested(address indexed from, address indexed to); event OwnershipTransferred(address indexed from, address indexed to); constructor(address newOwner, address pendingOwner) { require(newOwner != address(0), "Cannot set owner to zero"); s_owner = newOwner; if (pendingOwner != address(0)) { _transferOwnership(pendingOwner); } } /** * @notice Allows an owner to begin transferring ownership to a new address, * pending. */ function transferOwnership(address to) public override onlyOwner { _transferOwnership(to); } /** * @notice Allows an ownership transfer to be completed by the recipient. */ function acceptOwnership() external override { require(msg.sender == s_pendingOwner, "Must be proposed owner"); address oldOwner = s_owner; s_owner = msg.sender; s_pendingOwner = address(0); emit OwnershipTransferred(oldOwner, msg.sender); } /** * @notice Get the current owner */ function owner() public view override returns (address) { return s_owner; } /** * @notice validate, transfer ownership, and emit relevant events */ function _transferOwnership(address to) private { require(to != msg.sender, "Cannot transfer to self"); s_pendingOwner = to; emit OwnershipTransferRequested(s_owner, to); } /** * @notice validate access */ function _validateOwnership() internal view { require(msg.sender == s_owner, "Only callable by owner"); } /** * @notice Reverts if called by anyone other than the contract owner. */ modifier onlyOwner() { _validateOwnership(); _; } } // File contracts/ConfirmedOwner.sol /** * @title The ConfirmedOwner contract * @notice A contract with helpers for basic contract ownership. */ contract ConfirmedOwner is ConfirmedOwnerWithProposal { constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {} } // File contracts/OwnerIsCreator.sol /** * @title The OwnerIsCreator contract * @notice A contract with helpers for basic contract ownership. */ contract OwnerIsCreator is ConfirmedOwner { constructor() ConfirmedOwner(msg.sender) {} } // File contracts/SafeMath.sol /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, "SafeMath: division by zero"); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } } // File contracts/interfaces/IMojitoOracle.sol interface IMojitoOracle { function getMojitoTwap(bytes32 pairId) external view returns (uint256); function currencyPairId(string memory) external view returns (bytes32); function lookupERC2362ID(bytes32 _erc2362id) external view returns (string memory _caption); } // File contracts/interfaces/IERC2362.sol /** * @dev EIP2362 Interface for pull oracles * https://github.com/adoracles/EIPs/blob/erc-2362/EIPS/eip-2362.md */ interface IERC2362 { /** * @dev Exposed function pertaining to EIP standards * @param _id bytes32 ID of the query * @return int,uint,uint returns the value, timestamp, and status code of query */ function valueFor(bytes32 _id) external view returns ( int256, uint256, uint256 ); } // File contracts/AnchoredView.sol contract AnchoredView is OwnerIsCreator { using SafeMath for uint256; bool public validateAnswerEnabled; /// @notice how many digits of precision to retain, in 1e-decimals token units uint256 public immutable answerBaseUnit; struct MojitoConfig { bool available; bytes32 pairA; uint256 pairABaseUnit; } MojitoConfig internal mojitoConfig; /// @notice emitted when mojito config are set event MojitoConfigSet(bool available, bytes32 pairA, uint256 pairABaseUnit); struct WitnetConfig { bool available; bytes32 pairA; bytes32 pairB; uint256 pairABaseUnit; uint256 pairBBaseUnit; } WitnetConfig internal witnetConfig; /// @notice emitted when witnet config are set event WitnetConfigSet(bool available, bytes32 pairA, bytes32 pairB, uint256 pairABaseUnit, uint256 pairBBaseUnit); // The price oracle IMojitoOracle public mojitoOracle; IERC2362 public witnetOracle; /** * @notice emitted when a new mojito oracle contract is set * @param old the address prior to the current setting * @param current the address of the new mojito oracle contract */ event MojitoOracleSet(IMojitoOracle old, IMojitoOracle current); /** * @notice emitted when a new witnet oracle contract is set * @param old the address prior to the current setting * @param current the address of the new witnet oracle contract */ event WitnetOracleSet(IERC2362 old, IERC2362 current); event ValidateAnswerEnabled(); event ValidateAnswerDisabled(); /* * @param _mojitoOracle address of the mojito oracle contract * @param _witnetOracle address of the witnet oracle contract * @param _decimals answers are stored in fixed-point format, with this many digits of precision * @param _validateAnswerEnabled whether to enable the switch for validate answer */ constructor( address _mojitoOracle, address _witnetOracle, uint8 _decimals, bool _validateAnswerEnabled ) { _setMojitoOracle(IMojitoOracle(_mojitoOracle)); _setWitnetOracle(IERC2362(_witnetOracle)); // pow(10, _decimals) answerBaseUnit = 10**_decimals; validateAnswerEnabled = _validateAnswerEnabled; } /** * @notice sets the mojito twap oracle * @param _oracle the address of the mojito oracle contract */ function setMojitoOracle(IMojitoOracle _oracle) external onlyOwner { _setMojitoOracle(_oracle); } function _setMojitoOracle(IMojitoOracle _oracle) internal { IMojitoOracle oldOracle = mojitoOracle; if (_oracle != oldOracle) { mojitoOracle = _oracle; emit MojitoOracleSet(oldOracle, _oracle); } } /** * @notice sets the witnet oracle * @param _oracle the address of the witnet oracle contract */ function setWitnetOracle(IERC2362 _oracle) external onlyOwner { _setWitnetOracle(_oracle); } function _setWitnetOracle(IERC2362 _oracle) internal { IERC2362 oldOracle = witnetOracle; if (_oracle != oldOracle) { witnetOracle = _oracle; emit WitnetOracleSet(oldOracle, _oracle); } } function _getMojitoPriceInternal() internal view returns (uint256) { if (mojitoConfig.available) { uint256 twapPrice = mojitoOracle.getMojitoTwap(mojitoConfig.pairA); return twapPrice.mul(answerBaseUnit).div(mojitoConfig.pairABaseUnit); } return 0; } function _getWitnetPriceInternal() internal view returns (uint256) { if (witnetConfig.available) { int256 pairAPrice; (pairAPrice, , ) = witnetOracle.valueFor(witnetConfig.pairA); if (witnetConfig.pairB == "") { return uint256(pairAPrice).mul(answerBaseUnit).div(witnetConfig.pairABaseUnit); } else { int256 pairBPrice; (pairBPrice, , ) = witnetOracle.valueFor(witnetConfig.pairB); return uint256(pairAPrice).mul(uint256(pairBPrice)).mul(answerBaseUnit).div(witnetConfig.pairABaseUnit).div( witnetConfig.pairBBaseUnit ); } } return 0; } /** * @notice sets mojito parameters * @param _available is the price available * @param _pairA pairA erc2362 asset id * @param _pairABaseUnit pairA decimals * @dev must be called by owner */ function setMojitoConfig( bool _available, bytes32 _pairA, uint256 _pairABaseUnit ) external onlyOwner { mojitoConfig.available = _available; mojitoConfig.pairA = _pairA; mojitoConfig.pairABaseUnit = _pairABaseUnit; emit MojitoConfigSet(_available, _pairA, _pairABaseUnit); } /* * @notice gets the mojito config * @return The config object */ function getMojitoConfig() external view returns ( bool available, bytes32 pairA, uint256 pairABaseUnit ) { return (mojitoConfig.available, mojitoConfig.pairA, mojitoConfig.pairABaseUnit); } /** * @notice sets winet parameters * @param _available is the price available * @param _pairA pairA erc2362 asset id * @param _pairB pairB erc2362 asset id, optimal exchange rate when used * @param _pairABaseUnit pairA decimals * @param _pairBBaseUnit pairB decimals * @dev must be called by owner */ function setWitnetConfig( bool _available, bytes32 _pairA, bytes32 _pairB, uint256 _pairABaseUnit, uint256 _pairBBaseUnit ) external onlyOwner { witnetConfig.available = _available; witnetConfig.pairA = _pairA; witnetConfig.pairB = _pairB; witnetConfig.pairABaseUnit = _pairABaseUnit; witnetConfig.pairBBaseUnit = _pairBBaseUnit; emit WitnetConfigSet(_available, _pairA, _pairB, _pairABaseUnit, _pairBBaseUnit); } /* * @notice gets the witnet config * @return The config object */ function getWitnetConfig() external view returns ( bool available, bytes32 pairA, bytes32 pairB, uint256 pairABaseUnit, uint256 pairBBaseUnit ) { return ( witnetConfig.available, witnetConfig.pairA, witnetConfig.pairB, witnetConfig.pairABaseUnit, witnetConfig.pairBBaseUnit ); } /** * @notice Get the mojito oracle twap for a underlying * @return Price denominated in USD, with 8 decimals */ function getMojitoPrice() external view returns (uint256) { return _getMojitoPriceInternal(); } /** * @notice Get the witnet oracle price for a underlying * @return Price denominated in USD, with 8 decimals */ function getWitnetPrice() external view returns (uint256) { return _getWitnetPriceInternal(); } /** * @notice makes the answer validate enforced */ function enableAnswerValidate() external onlyOwner { if (!validateAnswerEnabled) { validateAnswerEnabled = true; emit ValidateAnswerEnabled(); } } /** * @notice makes the answer validate unenforced */ function disableAnswerValidate() external onlyOwner { if (validateAnswerEnabled) { validateAnswerEnabled = false; emit ValidateAnswerDisabled(); } } } // File contracts/OffchainAggregator.sol /** * @notice Onchain verification of reports from the offchain reporting protocol * @dev For details on its operation, see the offchain reporting protocol design * @dev doc, which refers to this contract as simply the "contract". */ contract OffchainAggregator is OwnerIsCreator, AggregatorV2V3Interface, TypeAndVersionInterface, AnchoredView { using SafeMath for uint256; // Storing these fields used on the hot path in a HotVars variable reduces the // retrieval of all of them to a single SLOAD. If any further fields are // added, make sure that storage of the struct still takes at most 32 bytes. struct HotVars { // Oracle Aggregators expose a roundId to consumers. The offchain reporting // protocol does not use this id anywhere. We increment it whenever a new // transmission is made to provide callers with contiguous ids for successive // reports. uint32 latestAggregatorRoundId; } HotVars internal s_hotVars; // Transmission records the median answer from the transmit transaction at time timestamp struct Transmission { int192 answer; // 192 bits ought to be enough for anyone uint32 observationsTimestamp; // when were observations made offchain uint32 transmissionTimestamp; // when was report received onchain } mapping(uint32 => Transmission) /* aggregator round ID */ internal s_transmissions; // incremented each time a new config is posted. This count is incorporated // into the config digest to prevent replay attacks. uint32 internal s_configCount; // makes it easier for offchain systems to extract config from logs uint32 internal s_latestConfigBlockNumber; // makes it easier for offchain systems to extract config from logs address internal s_latestTransmitter; // lowest answers for calculating the old price or the anchor price uint8 public lowerBoundAnchorRatio; //0.8e2 // highest answers for calculating the old price or the anchor price uint8 public upperBoundAnchorRatio; //1.2e2 uint8 internal constant minLowerBoundAnchorRatio = 0.8e2; uint8 internal constant maxUpperBoundAnchorRatio = 1.2e2; struct Transmitter { bool active; // Index of oracle in s_signersList/s_transmittersList uint8 index; } mapping(address => Transmitter) /* transmitter address */ internal s_transmitters; struct Signer { bool active; // Index of oracle in s_signersList/s_transmittersList uint8 index; } mapping(address => Signer) /* signer address */ internal s_signers; // s_signersList contains the signing address of each oracle address[] internal s_signersList; // s_transmittersList contains the transmission address of each oracle, // i.e. the address the oracle actually sends transactions to the contract from address[] internal s_transmittersList; /* * @param _lowerBoundAnchorRatio lowest answers for calculating the old price or the anchor price * @param _upperBoundAnchorRatio highest answers for calculating the old price or the anchor price * @param _decimals answers are stored in fixed-point format, with this many digits of precision * @param _description short human-readable description of observable this contract's answers pertain to * @param _mojitoOracle address of the mojito oracle contract * @param _witnetOracle address of the witnet oracle contract * @param _validateAnswerEnabled whether to enable the switch for validate answer */ constructor( uint8 _lowerBoundAnchorRatio, uint8 _upperBoundAnchorRatio, uint8 _decimals, string memory _description, address _mojitoOracle, address _witnetOracle, bool _validateAnswerEnabled ) AnchoredView(_mojitoOracle, _witnetOracle, _decimals, _validateAnswerEnabled) { lowerBoundAnchorRatio = _lowerBoundAnchorRatio; upperBoundAnchorRatio = _upperBoundAnchorRatio; decimals = _decimals; s_description = _description; } /* * Versioning */ function typeAndVersion() external pure virtual override returns (string memory) { return "OffchainAggregator 1.0.0"; } /* * AnchorRatio logic */ event AnchorRatioUpdated(uint8 lowerBoundAnchorRatio, uint8 upperBoundAnchorRatio); function setAnchorRatio(uint8 _lowerBoundAnchorRatio, uint8 _upperBoundAnchorRatio) external onlyOwner { require( minLowerBoundAnchorRatio <= _lowerBoundAnchorRatio, "lowerBoundAnchorRatio must greater or equal to minLowerBoundAnchorRatio" ); require( maxUpperBoundAnchorRatio >= _upperBoundAnchorRatio, "upperBoundAnchorRatio must Less than or equal to maxUpperBoundAnchorRatio" ); require( _upperBoundAnchorRatio > _lowerBoundAnchorRatio, "upperBoundAnchorRatio must Less than lowerBoundAnchorRatio" ); lowerBoundAnchorRatio = _lowerBoundAnchorRatio; upperBoundAnchorRatio = _upperBoundAnchorRatio; emit AnchorRatioUpdated(lowerBoundAnchorRatio, upperBoundAnchorRatio); } /* * Config logic */ /** * @notice triggers a new run of the offchain reporting protocol * @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis * @param configCount ordinal number of this config setting among all config settings over the life of this contract * @param signers ith element is address ith oracle uses to sign a report * @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method */ event ConfigSet(uint32 previousConfigBlockNumber, uint64 configCount, address[] signers, address[] transmitters); /** * @notice sets offchain reporting protocol configuration incl. participating oracles * @param _transmitters addresses oracles use to transmit the reports */ function setConfig(address[] calldata _signers, address[] calldata _transmitters) external onlyOwner { require(_signers.length == _transmitters.length, "oracle length mismatch"); // remove any old signer/transmitter addresses uint256 oldLength = s_signersList.length; for (uint256 i = 0; i < oldLength; i++) { address signer = s_signersList[i]; address transmitter = s_transmittersList[i]; delete s_signers[signer]; delete s_transmitters[transmitter]; } delete s_signersList; delete s_transmittersList; // add new signer/transmitter addresses for (uint256 i = 0; i < _signers.length; i++) { require(!s_signers[_signers[i]].active, "repeated signer address"); s_signers[_signers[i]] = Signer({active: true, index: uint8(i)}); require(!s_transmitters[_transmitters[i]].active, "repeated transmitter address"); s_transmitters[_transmitters[i]] = Transmitter({active: true, index: uint8(i)}); } s_signersList = _signers; s_transmittersList = _transmitters; uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; s_latestConfigBlockNumber = uint32(block.number); s_configCount += 1; emit ConfigSet(previousConfigBlockNumber, s_configCount, _signers, _transmitters); } /** * @notice information about current offchain reporting protocol configuration * @return configCount ordinal number of current config, out of all configs applied to this contract so far * @return blockNumber block at which this config was set */ function latestConfigDetails() external view returns (uint32 configCount, uint32 blockNumber) { return (s_configCount, s_latestConfigBlockNumber); } /** * @return list of addresses permitted to transmit reports to this contract * @dev The list will match the order used to specify the transmitter during setConfig */ function getTransmitters() external view returns (address[] memory) { return s_transmittersList; } /* * Transmission logic */ /** * @notice indicates that a new report was transmitted * @param aggregatorRoundId the round to which this report was assigned * @param answer median of the observations attached this report * @param transmitter address from which the report was transmitted * @param observationsTimestamp when were observations made offchain */ event NewTransmission( uint32 indexed aggregatorRoundId, int192 answer, address transmitter, uint32 observationsTimestamp ); /* * @notice details about the most transmission details * @return nextTransmitter who will be next to transmit the report * @return afterNextTransmitter who will transmit the report next afterwards * @return nextIndex the index of the next transmitter * @return length the length of the s_transmittersList * @return roundId aggregator round of latest report * @return answer median value from latest report * @return startedAt when the latest report was transmitted * @return updatedAt when the latest report was transmitted */ function latestTransmissionDetails() external view returns ( address nextTransmitter, address afterNextTransmitter, uint8 nextIndex, uint256 transmittersLength, uint80 roundId, int192 answer, uint256 startedAt, uint256 updatedAt ) { require(msg.sender == tx.origin, "Only callable by EOA"); nextIndex = 0; uint8 afterNextIndex = 0; // Calculating the index of the next transmitter uint256 s_length = s_transmittersList.length; if (s_length > 0) { // the index of the current transmitter Transmitter memory s_transmitter; s_transmitter = s_transmitters[s_latestTransmitter]; if (s_transmitter.active) { nextIndex = s_transmitter.index; nextIndex++; if (s_length == nextIndex) { nextIndex = 0; } } afterNextIndex = nextIndex; afterNextIndex++; if (s_length == afterNextIndex) { afterNextIndex = 0; } nextTransmitter = s_transmittersList[nextIndex]; afterNextTransmitter = s_transmittersList[afterNextIndex]; } roundId = s_hotVars.latestAggregatorRoundId; Transmission memory transmission = s_transmissions[uint32(roundId)]; return ( nextTransmitter, afterNextTransmitter, nextIndex, s_length, roundId, transmission.answer, transmission.observationsTimestamp, transmission.transmissionTimestamp ); } // The constant-length components of the msg.data sent to transmit. // See the "If we wanted to call sam" example on for example reasoning // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT = 4 + // function selector 32 + // word containing start location of abiencoded _report value 32 + // _rs value 32 + // _ss value 32 + // _vs value 32 + // word containing length of _report 0; // placeholder function expectedMsgDataLength() private pure returns (uint256 length) { // calldata will never be big enough to make this overflow return uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + 64 + // one byte pure entry in _report 0; // placeholder } /** * @notice transmit is called to post a new report to the contract * @param _report serialized report, which the signatures are signing. See parsing code below for format. * @param _rs the R components of the signature on report. * @param _ss the S components of the signature on report. * @param _vs the V component of the signature on report. */ function transmit( // NOTE: If these parameters are changed, expectedMsgDataLength and/or // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly bytes calldata _report, // ECDSA signature bytes32 _rs, bytes32 _ss, uint8 _vs ) external { require(s_transmitters[msg.sender].active, "unauthorized transmitter"); require(msg.data.length == expectedMsgDataLength(), "transmit message length mismatch"); uint192 median; uint32 observationsTimestamp; (median, observationsTimestamp) = abi.decode(_report, (uint192, uint32)); uint32 s_latestTimestamp = s_transmissions[s_hotVars.latestAggregatorRoundId].transmissionTimestamp; require(observationsTimestamp > s_latestTimestamp, "invalid observations timestamp"); // Verify signatures attached to report { bytes32 h = keccak256(_report); Signer memory signer; address signerAddress = ecrecover(h, _vs + 27, _rs, _ss); signer = s_signers[signerAddress]; require(signer.active, "signature error"); } if (validateAnswerEnabled) { if (_validateAnswer(uint256(median))) { _transmit(int192(median), observationsTimestamp); } } else { uint256 previousAnswer = uint192(s_transmissions[s_hotVars.latestAggregatorRoundId].answer); if (previousAnswer > 0) { require(isWithinAnchor(median, previousAnswer), "median is out of min-max range"); } _transmit(int192(median), observationsTimestamp); } } function transmitWithForce(uint192 median) external onlyOwner { _transmit(int192(median), uint32(block.timestamp)); } function _transmit(int192 median, uint32 observationsTimestamp) internal { HotVars memory hotVars = s_hotVars; // cache read from storage hotVars.latestAggregatorRoundId++; s_transmissions[hotVars.latestAggregatorRoundId] = Transmission({ answer: median, observationsTimestamp: observationsTimestamp, transmissionTimestamp: uint32(block.timestamp) }); s_latestTransmitter = msg.sender; emit NewTransmission(hotVars.latestAggregatorRoundId, median, msg.sender, observationsTimestamp); // Emit these for backwards compatability with offchain consumers // that only support legacy events emit NewRound( hotVars.latestAggregatorRoundId, address(0x0), // use zero address since we don't have anybody "starting" the round here observationsTimestamp ); emit AnswerUpdated(median, hotVars.latestAggregatorRoundId, block.timestamp); // persist updates to hotVars s_hotVars = hotVars; } /// @notice The event emitted when new prices are posted but the stored price is not updated due to the anchor event AnswerGuarded( uint32 indexed aggregatorRoundId, uint256 reporterPrice, uint256 anchorMojitoPrice, uint256 anchorWitnetPrice, uint256 updatedAt ); /** * @notice This is called by the reporter whenever a new price is posted on-chain * @param reporterPrice the price from the reporter * @return valid bool */ function _validateAnswer(uint256 reporterPrice) internal returns (bool) { uint256 anchorMojitoPrice = _getMojitoPriceInternal(); if (isWithinAnchor(reporterPrice, anchorMojitoPrice)) { return true; } else { uint256 anchorWitnetPrice = _getWitnetPriceInternal(); if (isWithinAnchor(reporterPrice, anchorWitnetPrice)) { return true; } else { emit AnswerGuarded( s_hotVars.latestAggregatorRoundId + 1, reporterPrice, anchorMojitoPrice, anchorWitnetPrice, block.timestamp ); return false; } } } /** * @notice This is called by the reporter whenever a new price is posted on-chain * @param reporterPrice the price from the reporter * @param anchorPrice the price from the other contract * @return valid bool */ function isWithinAnchor(uint256 reporterPrice, uint256 anchorPrice) internal view returns (bool) { if (reporterPrice > 0 && anchorPrice > 0) { uint256 minAnswer = anchorPrice.mul(lowerBoundAnchorRatio).div(1e2); uint256 maxAnswer = anchorPrice.mul(upperBoundAnchorRatio).div(1e2); return minAnswer <= reporterPrice && reporterPrice <= maxAnswer; } return false; } /* * v2 Aggregator interface */ /** * @notice median from the most recent report */ function latestAnswer() public view virtual override returns (int256) { return s_transmissions[s_hotVars.latestAggregatorRoundId].answer; } /** * @notice timestamp of block in which last report was transmitted */ function latestTimestamp() public view virtual override returns (uint256) { return s_transmissions[s_hotVars.latestAggregatorRoundId].transmissionTimestamp; } /** * @notice Aggregator round (NOT OCR round) in which last report was transmitted */ function latestRound() public view virtual override returns (uint256) { return s_hotVars.latestAggregatorRoundId; } /** * @notice median of report from given aggregator round (NOT OCR round) * @param _roundId the aggregator round of the target report */ function getAnswer(uint256 _roundId) public view virtual override returns (int256) { if (_roundId > 0xFFFFFFFF) { return 0; } return s_transmissions[uint32(_roundId)].answer; } /** * @notice timestamp of block in which report from given aggregator round was transmitted * @param _roundId aggregator round (NOT OCR round) of target report */ function getTimestamp(uint256 _roundId) public view virtual override returns (uint256) { if (_roundId > 0xFFFFFFFF) { return 0; } return s_transmissions[uint32(_roundId)].transmissionTimestamp; } /* * v3 Aggregator interface */ string private constant V3_NO_DATA_ERROR = "No data present"; /** * @return answers are stored in fixed-point format, with this many digits of precision */ uint8 public immutable override decimals; /** * @notice aggregator contract version */ uint256 public constant override version = 1; string internal s_description; /** * @notice human-readable description of observable this contract is reporting on */ function description() public view virtual override returns (string memory) { return s_description; } /** * @notice details for the given aggregator round * @param _roundId target aggregator round (NOT OCR round). Must fit in uint32 * @return roundId _roundId * @return answer median of report from given _roundId * @return startedAt timestamp of block in which report from given _roundId was transmitted * @return updatedAt timestamp of block in which report from given _roundId was transmitted * @return answeredInRound _roundId */ function getRoundData(uint80 _roundId) public view virtual override returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ) { require(_roundId <= 0xFFFFFFFF, V3_NO_DATA_ERROR); Transmission memory transmission = s_transmissions[uint32(_roundId)]; return ( _roundId, transmission.answer, transmission.observationsTimestamp, transmission.transmissionTimestamp, _roundId ); } /** * @notice aggregator details for the most recently transmitted report * @return roundId aggregator round of latest report (NOT OCR round) * @return answer median of latest report * @return startedAt timestamp of block containing latest report * @return updatedAt timestamp of block containing latest report * @return answeredInRound aggregator round of latest report */ function latestRoundData() public view virtual override returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ) { roundId = s_hotVars.latestAggregatorRoundId; // Skipped for compatability with existing FluxAggregator in which latestRoundData never reverts. // require(roundId != 0, V3_NO_DATA_ERROR); Transmission memory transmission = s_transmissions[uint32(roundId)]; return ( roundId, transmission.answer, transmission.observationsTimestamp, transmission.transmissionTimestamp, roundId ); } } // File contracts/SimpleWriteAccessController.sol /** * @title SimpleWriteAccessController * @notice Gives access to accounts explicitly added to an access list by the * controller's owner. * @dev does not make any special permissions for externally, see * SimpleReadAccessController for that. */ contract SimpleWriteAccessController is AccessControllerInterface, OwnerIsCreator { bool public checkEnabled; mapping(address => bool) internal accessList; event AddedAccess(address user); event RemovedAccess(address user); event CheckAccessEnabled(); event CheckAccessDisabled(); constructor() { checkEnabled = true; } /** * @notice Returns the access of an address * @param _user The address to query */ function hasAccess(address _user, bytes memory) public view virtual override returns (bool) { return accessList[_user] || !checkEnabled; } /** * @notice Adds an address to the access list * @param _user The address to add */ function addAccess(address _user) external onlyOwner { if (!accessList[_user]) { accessList[_user] = true; emit AddedAccess(_user); } } /** * @notice Removes an address from the access list * @param _user The address to remove */ function removeAccess(address _user) external onlyOwner { if (accessList[_user]) { accessList[_user] = false; emit RemovedAccess(_user); } } /** * @notice makes the access check enforced */ function enableAccessCheck() external onlyOwner { if (!checkEnabled) { checkEnabled = true; emit CheckAccessEnabled(); } } /** * @notice makes the access check unenforced */ function disableAccessCheck() external onlyOwner { if (checkEnabled) { checkEnabled = false; emit CheckAccessDisabled(); } } /** * @dev reverts if the caller does not have access */ modifier checkAccess() { require(hasAccess(msg.sender, msg.data), "No access"); _; } } // File contracts/SimpleReadAccessController.sol /** * @title SimpleReadAccessController * @notice Gives access to: * - any externally owned account (note that offchain actors can always read * any contract storage regardless of onchain access control measures, so this * does not weaken the access control while improving usability) * - accounts explicitly added to an access list * @dev SimpleReadAccessController is not suitable for access controlling writes * since it grants any externally owned account access! See * SimpleWriteAccessController for that. */ contract SimpleReadAccessController is SimpleWriteAccessController { /** * @notice Returns the access of an address * @param _user The address to query */ function hasAccess(address _user, bytes memory _calldata) public view virtual override returns (bool) { return super.hasAccess(_user, _calldata) || _user == tx.origin; } } // File contracts/AccessControlledOffchainAggregator.sol /** * @notice Wrapper of OffchainAggregator which checks read access on Aggregator-interface methods */ contract AccessControlledOffchainAggregator is OffchainAggregator, SimpleReadAccessController { constructor( uint8 _lowerBoundAnchorRatio, uint8 _upperBoundAnchorRatio, uint8 _decimals, string memory _description, address _mojitoOracle, address _witnetOracle, bool _validateAnswerEnabled ) OffchainAggregator( _lowerBoundAnchorRatio, _upperBoundAnchorRatio, _decimals, _description, _mojitoOracle, _witnetOracle, _validateAnswerEnabled ) {} /* * Versioning */ function typeAndVersion() external pure virtual override returns (string memory) { return "AccessControlledOffchainAggregator 1.0.0"; } /* * v2 Aggregator interface */ /// @inheritdoc OffchainAggregator function latestAnswer() public view override checkAccess returns (int256) { return super.latestAnswer(); } /// @inheritdoc OffchainAggregator function latestTimestamp() public view override checkAccess returns (uint256) { return super.latestTimestamp(); } /// @inheritdoc OffchainAggregator function latestRound() public view override checkAccess returns (uint256) { return super.latestRound(); } /// @inheritdoc OffchainAggregator function getAnswer(uint256 _roundId) public view override checkAccess returns (int256) { return super.getAnswer(_roundId); } /// @inheritdoc OffchainAggregator function getTimestamp(uint256 _roundId) public view override checkAccess returns (uint256) { return super.getTimestamp(_roundId); } /* * v3 Aggregator interface */ /// @inheritdoc OffchainAggregator function description() public view override checkAccess returns (string memory) { return super.description(); } /// @inheritdoc OffchainAggregator function getRoundData(uint80 _roundId) public view override checkAccess returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ) { return super.getRoundData(_roundId); } /// @inheritdoc OffchainAggregator function latestRoundData() public view override checkAccess returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ) { return super.latestRoundData(); } }
We recommend using flattened code. This is necessary if your code utilizes a library or inherits dependencies. Use the
POA solidity flattener or the
truffle flattener
.
Try to fetch constructor arguments automatically
No
Yes
ABI-encoded Constructor Arguments (if required by the contract)
000000000000000000000000000000000000000000000000000000000000005f0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000e000000000000000000000000009515646b5833526dff12fae9b03754c7f0e0a8f000000000000000000000000d39d4d972c7e166856c4eb29e54d3548b4597f5300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000009455448202f205553440000000000000000000000000000000000000000000000
Add arguments in
ABI hex encoded form
. Constructor arguments are written right to left, and will be found at the end of the input created bytecode. They may also be
parsed here.
Add Contract Libraries
Contract Libraries
Library 1 Name
A library name called in the .sol file. Multiple libraries (up to 10) may be added for each contract. Click the Add Library button to add an additional one.
Library 1 Address
The 0x library address. This can be found in the generated json file or Truffle output (if using truffle).
Library 2 Name
Library 2 Address
Library 3 Name
Library 3 Address
Library 4 Name
Library 4 Address
Library 5 Name
Library 5 Address
Library 6 Name
Library 6 Address
Library 7 Name
Library 7 Address
Library 8 Name
Library 8 Address
Library 9 Name
Library 9 Address
Library 10 Name
Library 10 Address
Add Library
Loading...
Verify & publish
Cancel
Ok
Ok
Ok
No
Yes