Source Code
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
There are no matching entriesUpdate your filters to view other transactions | |||||||||
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
AccessControlledOffchainAggregator
Compiler Version
v0.7.6+commit.7338295f
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.1;
import "./OffchainAggregator.sol";
import "./SimpleReadAccessController.sol";
/**
* @notice Wrapper of OffchainAggregator which checks read access on Aggregator-interface methods
*/
contract AccessControlledOffchainAggregator is OffchainAggregator, SimpleReadAccessController {
constructor(
uint32 _maximumGasPrice,
uint32 _reasonableGasPrice,
uint32 _microLinkPerEth,
uint32 _linkGweiPerObservation,
uint32 _linkGweiPerTransmission,
LinkTokenInterface _link,
int192 _minAnswer,
int192 _maxAnswer,
AccessControllerInterface _billingAccessController,
AccessControllerInterface _requesterAccessController,
uint8 _decimals,
string memory description
)
OffchainAggregator(
_maximumGasPrice,
_reasonableGasPrice,
_microLinkPerEth,
_linkGweiPerObservation,
_linkGweiPerTransmission,
_link,
_minAnswer,
_maxAnswer,
_billingAccessController,
_requesterAccessController,
_decimals,
description
) {
}
/*
* Versioning
*/
function typeAndVersion()
external
override
pure
virtual
returns (string memory)
{
return "AccessControlledOffchainAggregator 3.0.0";
}
/*
* v2 Aggregator interface
*/
/// @inheritdoc OffchainAggregator
function latestAnswer()
public
override
view
checkAccess()
returns (int256)
{
return super.latestAnswer();
}
/// @inheritdoc OffchainAggregator
function latestTimestamp()
public
override
view
checkAccess()
returns (uint256)
{
return super.latestTimestamp();
}
/// @inheritdoc OffchainAggregator
function latestRound()
public
override
view
checkAccess()
returns (uint256)
{
return super.latestRound();
}
/// @inheritdoc OffchainAggregator
function getAnswer(uint256 _roundId)
public
override
view
checkAccess()
returns (int256)
{
return super.getAnswer(_roundId);
}
/// @inheritdoc OffchainAggregator
function getTimestamp(uint256 _roundId)
public
override
view
checkAccess()
returns (uint256)
{
return super.getTimestamp(_roundId);
}
/*
* v3 Aggregator interface
*/
/// @inheritdoc OffchainAggregator
function description()
public
override
view
checkAccess()
returns (string memory)
{
return super.description();
}
/// @inheritdoc OffchainAggregator
function getRoundData(uint80 _roundId)
public
override
view
checkAccess()
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
)
{
return super.getRoundData(_roundId);
}
/// @inheritdoc OffchainAggregator
function latestRoundData()
public
override
view
checkAccess()
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
)
{
return super.latestRoundData();
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
import "./AccessControllerInterface.sol";
import "./AggregatorV2V3Interface.sol";
import "./AggregatorValidatorInterface.sol";
import "./LinkTokenInterface.sol";
import "./Owned.sol";
import "./OffchainAggregatorBilling.sol";
import "./TypeAndVersionInterface.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 Owned, OffchainAggregatorBilling, AggregatorV2V3Interface, TypeAndVersionInterface {
uint256 constant private maxUint32 = (1 << 32) - 1;
// 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 {
// Provides 128 bits of security against 2nd pre-image attacks, but only
// 64 bits against collisions. This is acceptable, since a malicious owner has
// easier way of messing up the protocol than to find hash collisions.
bytes16 latestConfigDigest;
uint40 latestEpochAndRound; // 32 most sig bits for epoch, 8 least sig bits for round
// Current bound assumed on number of faulty/dishonest oracles participating
// in the protocol, this value is referred to as f in the design
uint8 threshold;
// Chainlink 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
uint64 timestamp;
}
mapping(uint32 /* aggregator round ID */ => Transmission) 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;
uint32 internal s_latestConfigBlockNumber; // makes it easier for offchain systems
// to extract config from logs.
// Lowest answer the system is allowed to report in response to transmissions
int192 immutable public minAnswer;
// Highest answer the system is allowed to report in response to transmissions
int192 immutable public maxAnswer;
/*
* @param _maximumGasPrice highest gas price for which transmitter will be compensated
* @param _reasonableGasPrice transmitter will receive reward for gas prices under this value
* @param _microLinkPerEth reimbursement per ETH of gas cost, in 1e-6LINK units
* @param _linkGweiPerObservation reward to oracle for contributing an observation to a successfully transmitted report, in 1e-9LINK units
* @param _linkGweiPerTransmission reward to transmitter of a successful report, in 1e-9LINK units
* @param _link address of the LINK contract
* @param _minAnswer lowest answer the median of a report is allowed to be
* @param _maxAnswer highest answer the median of a report is allowed to be
* @param _billingAccessController access controller for billing admin functions
* @param _requesterAccessController access controller for requesting new rounds
* @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
*/
constructor(
uint32 _maximumGasPrice,
uint32 _reasonableGasPrice,
uint32 _microLinkPerEth,
uint32 _linkGweiPerObservation,
uint32 _linkGweiPerTransmission,
LinkTokenInterface _link,
int192 _minAnswer,
int192 _maxAnswer,
AccessControllerInterface _billingAccessController,
AccessControllerInterface _requesterAccessController,
uint8 _decimals,
string memory _description
)
OffchainAggregatorBilling(_maximumGasPrice, _reasonableGasPrice, _microLinkPerEth,
_linkGweiPerObservation, _linkGweiPerTransmission, _link,
_billingAccessController
)
{
decimals = _decimals;
s_description = _description;
setRequesterAccessController(_requesterAccessController);
setValidatorConfig(AggregatorValidatorInterface(0x0), 0);
minAnswer = _minAnswer;
maxAnswer = _maxAnswer;
}
/*
* Versioning
*/
function typeAndVersion()
external
override
pure
virtual
returns (string memory)
{
return "OffchainAggregator 3.0.0";
}
/*
* 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
* @param threshold maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly
* @param encodedConfigVersion version of the serialization format used for "encoded" parameter
* @param encoded serialized data used by oracles to configure their offchain operation
*/
event ConfigSet(
uint32 previousConfigBlockNumber,
uint64 configCount,
address[] signers,
address[] transmitters,
uint8 threshold,
uint64 encodedConfigVersion,
bytes encoded
);
// Reverts transaction if config args are invalid
modifier checkConfigValid (
uint256 _numSigners, uint256 _numTransmitters, uint256 _threshold
) {
require(_numSigners <= maxNumOracles, "too many signers");
require(_threshold > 0, "threshold must be positive");
require(
_numSigners == _numTransmitters,
"oracle addresses out of registration"
);
require(_numSigners > 3*_threshold, "faulty-oracle threshold too high");
_;
}
/**
* @notice sets offchain reporting protocol configuration incl. participating oracles
* @param _signers addresses with which oracles sign the reports
* @param _transmitters addresses oracles use to transmit the reports
* @param _threshold number of faulty oracles the system can tolerate
* @param _encodedConfigVersion version number for offchainEncoding schema
* @param _encoded encoded off-chain oracle configuration
*/
function setConfig(
address[] calldata _signers,
address[] calldata _transmitters,
uint8 _threshold,
uint64 _encodedConfigVersion,
bytes calldata _encoded
)
external
checkConfigValid(_signers.length, _transmitters.length, _threshold)
onlyOwner()
{
while (s_signers.length != 0) { // remove any old signer/transmitter addresses
uint lastIdx = s_signers.length - 1;
address signer = s_signers[lastIdx];
address transmitter = s_transmitters[lastIdx];
payOracle(transmitter);
delete s_oracles[signer];
delete s_oracles[transmitter];
s_signers.pop();
s_transmitters.pop();
}
for (uint i = 0; i < _signers.length; i++) { // add new signer/transmitter addresses
require(
s_oracles[_signers[i]].role == Role.Unset,
"repeated signer address"
);
s_oracles[_signers[i]] = Oracle(uint8(i), Role.Signer);
require(s_payees[_transmitters[i]] != address(0), "payee must be set");
require(
s_oracles[_transmitters[i]].role == Role.Unset,
"repeated transmitter address"
);
s_oracles[_transmitters[i]] = Oracle(uint8(i), Role.Transmitter);
s_signers.push(_signers[i]);
s_transmitters.push(_transmitters[i]);
}
s_hotVars.threshold = _threshold;
uint32 previousConfigBlockNumber = s_latestConfigBlockNumber;
s_latestConfigBlockNumber = uint32(block.number);
s_configCount += 1;
uint64 configCount = s_configCount;
{
s_hotVars.latestConfigDigest = configDigestFromConfigData(
address(this),
configCount,
_signers,
_transmitters,
_threshold,
_encodedConfigVersion,
_encoded
);
s_hotVars.latestEpochAndRound = 0;
}
emit ConfigSet(
previousConfigBlockNumber,
configCount,
_signers,
_transmitters,
_threshold,
_encodedConfigVersion,
_encoded
);
}
function configDigestFromConfigData(
address _contractAddress,
uint64 _configCount,
address[] calldata _signers,
address[] calldata _transmitters,
uint8 _threshold,
uint64 _encodedConfigVersion,
bytes calldata _encodedConfig
) internal pure returns (bytes16) {
return bytes16(keccak256(abi.encode(_contractAddress, _configCount,
_signers, _transmitters, _threshold, _encodedConfigVersion, _encodedConfig
)));
}
/**
* @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
* @return configDigest domain-separation tag for current config (see configDigestFromConfigData)
*/
function latestConfigDetails()
external
view
returns (
uint32 configCount,
uint32 blockNumber,
bytes16 configDigest
)
{
return (s_configCount, s_latestConfigBlockNumber, s_hotVars.latestConfigDigest);
}
/**
* @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 transmitters()
external
view
returns(address[] memory)
{
return s_transmitters;
}
/*
* On-chain validation logc
*/
// Configuration for validator
struct ValidatorConfig {
AggregatorValidatorInterface validator;
uint32 gasLimit;
}
ValidatorConfig private s_validatorConfig;
/**
* @notice indicates that the validator configuration has been set
* @param previousValidator previous validator contract
* @param previousGasLimit previous gas limit for validate calls
* @param currentValidator current validator contract
* @param currentGasLimit current gas limit for validate calls
*/
event ValidatorConfigSet(
AggregatorValidatorInterface indexed previousValidator,
uint32 previousGasLimit,
AggregatorValidatorInterface indexed currentValidator,
uint32 currentGasLimit
);
/**
* @notice validator configuration
* @return validator validator contract
* @return gasLimit gas limit for validate calls
*/
function validatorConfig()
external
view
returns (AggregatorValidatorInterface validator, uint32 gasLimit)
{
ValidatorConfig memory vc = s_validatorConfig;
return (vc.validator, vc.gasLimit);
}
/**
* @notice sets validator configuration
* @dev set _newValidator to 0x0 to disable validate calls
* @param _newValidator address of the new validator contract
* @param _newGasLimit new gas limit for validate calls
*/
function setValidatorConfig(AggregatorValidatorInterface _newValidator, uint32 _newGasLimit)
public
onlyOwner()
{
ValidatorConfig memory previous = s_validatorConfig;
if (previous.validator != _newValidator || previous.gasLimit != _newGasLimit) {
s_validatorConfig = ValidatorConfig({
validator: _newValidator,
gasLimit: _newGasLimit
});
emit ValidatorConfigSet(previous.validator, previous.gasLimit, _newValidator, _newGasLimit);
}
}
function validateAnswer(
uint32 _aggregatorRoundId,
int256 _answer
)
private
{
ValidatorConfig memory vc = s_validatorConfig;
if (address(vc.validator) == address(0)) {
return;
}
uint32 prevAggregatorRoundId = _aggregatorRoundId - 1;
int256 prevAggregatorRoundAnswer = s_transmissions[prevAggregatorRoundId].answer;
// We do not want the validator to ever prevent reporting, so we limit its
// gas usage and catch any errors that may arise.
try vc.validator.validate{gas: vc.gasLimit}(
prevAggregatorRoundId,
prevAggregatorRoundAnswer,
_aggregatorRoundId,
_answer
) {} catch {}
}
/*
* requestNewRound logic
*/
AccessControllerInterface internal s_requesterAccessController;
/**
* @notice emitted when a new requester access controller contract is set
* @param old the address prior to the current setting
* @param current the address of the new access controller contract
*/
event RequesterAccessControllerSet(AccessControllerInterface old, AccessControllerInterface current);
/**
* @notice emitted to immediately request a new round
* @param requester the address of the requester
* @param configDigest the latest transmission's configDigest
* @param epoch the latest transmission's epoch
* @param round the latest transmission's round
*/
event RoundRequested(address indexed requester, bytes16 configDigest, uint32 epoch, uint8 round);
/**
* @notice address of the requester access controller contract
* @return requester access controller address
*/
function requesterAccessController()
external
view
returns (AccessControllerInterface)
{
return s_requesterAccessController;
}
/**
* @notice sets the requester access controller
* @param _requesterAccessController designates the address of the new requester access controller
*/
function setRequesterAccessController(AccessControllerInterface _requesterAccessController)
public
onlyOwner()
{
AccessControllerInterface oldController = s_requesterAccessController;
if (_requesterAccessController != oldController) {
s_requesterAccessController = AccessControllerInterface(_requesterAccessController);
emit RequesterAccessControllerSet(oldController, _requesterAccessController);
}
}
/**
* @notice immediately requests a new round
* @return the aggregatorRoundId of the next round. Note: The report for this round may have been
* transmitted (but not yet mined) *before* requestNewRound() was even called. There is *no*
* guarantee of causality between the request and the report at aggregatorRoundId.
*/
function requestNewRound() external returns (uint80) {
require(msg.sender == owner || s_requesterAccessController.hasAccess(msg.sender, msg.data),
"Only owner&requester can call");
HotVars memory hotVars = s_hotVars;
emit RoundRequested(
msg.sender,
hotVars.latestConfigDigest,
uint32(s_hotVars.latestEpochAndRound >> 8),
uint8(s_hotVars.latestEpochAndRound)
);
return hotVars.latestAggregatorRoundId + 1;
}
/*
* 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 observations observations transmitted with this report
* @param rawReportContext signature-replay-prevention domain-separation tag
*/
event NewTransmission(
uint32 indexed aggregatorRoundId,
int192 answer,
address transmitter,
int192[] observations,
bytes observers,
bytes32 rawReportContext
);
// decodeReport is used to check that the solidity and go code are using the
// same format. See TestOffchainAggregator.testDecodeReport and TestReportParsing
function decodeReport(bytes memory _report)
internal
pure
returns (
bytes32 rawReportContext,
bytes32 rawObservers,
int192[] memory observations
)
{
(rawReportContext, rawObservers, observations) = abi.decode(_report,
(bytes32, bytes32, int192[]));
}
// Used to relieve stack pressure in transmit
struct ReportData {
HotVars hotVars; // Only read from storage once
bytes observers; // ith element is the index of the ith observer
int192[] observations; // ith element is the ith observation
bytes vs; // jth element is the v component of the jth signature
bytes32 rawReportContext;
}
/*
* @notice details about the most recent report
* @return configDigest domain separation tag for the latest report
* @return epoch epoch in which the latest report was generated
* @return round OCR round in which the latest report was generated
* @return latestAnswer median value from latest report
* @return latestTimestamp when the latest report was transmitted
*/
function latestTransmissionDetails()
external
view
returns (
bytes16 configDigest,
uint32 epoch,
uint8 round,
int192 latestAnswer,
uint64 latestTimestamp
)
{
require(msg.sender == tx.origin, "Only callable by EOA");
return (
s_hotVars.latestConfigDigest,
uint32(s_hotVars.latestEpochAndRound >> 8),
uint8(s_hotVars.latestEpochAndRound),
s_transmissions[s_hotVars.latestAggregatorRoundId].answer,
s_transmissions[s_hotVars.latestAggregatorRoundId].timestamp
);
}
// 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 + // word containing location start of abiencoded _rs value
32 + // word containing start location of abiencoded _ss value
32 + // _rawVs value
32 + // word containing length of _report
32 + // word containing length _rs
32 + // word containing length of _ss
0; // placeholder
function expectedMsgDataLength(
bytes calldata _report, bytes32[] calldata _rs, bytes32[] calldata _ss
) private pure returns (uint256 length)
{
// calldata will never be big enough to make this overflow
return uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) +
_report.length + // one byte pure entry in _report
_rs.length * 32 + // 32 bytes per entry in _rs
_ss.length * 32 + // 32 bytes per entry in _ss
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. The ith element of the observers component must be the index in s_signers of the address for the ith signature
* @param _rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries
* @param _ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries
* @param _rawVs ith element is the the V component of the ith signature
*/
function transmit(
// NOTE: If these parameters are changed, expectedMsgDataLength and/or
// TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly
bytes calldata _report,
bytes32[] calldata _rs, bytes32[] calldata _ss, bytes32 _rawVs // signatures
)
external
{
uint256 initialGas = gasleft(); // This line must come first
// Make sure the transmit message-length matches the inputs. Otherwise, the
// transmitter could append an arbitrarily long (up to gas-block limit)
// string of 0 bytes, which we would reimburse at a rate of 16 gas/byte, but
// which would only cost the transmitter 4 gas/byte. (Appendix G of the
// yellow paper, p. 25, for G_txdatazero and EIP 2028 for G_txdatanonzero.)
// This could amount to reimbursement profit of 36 million gas, given a 3MB
// zero tail.
require(msg.data.length == expectedMsgDataLength(_report, _rs, _ss),
"transmit message too long");
ReportData memory r; // Relieves stack pressure
{
r.hotVars = s_hotVars; // cache read from storage
bytes32 rawObservers;
(r.rawReportContext, rawObservers, r.observations) = abi.decode(
_report, (bytes32, bytes32, int192[])
);
// rawReportContext consists of:
// 11-byte zero padding
// 16-byte configDigest
// 4-byte epoch
// 1-byte round
bytes16 configDigest = bytes16(r.rawReportContext << 88);
require(
r.hotVars.latestConfigDigest == configDigest,
"configDigest mismatch"
);
uint40 epochAndRound = uint40(uint256(r.rawReportContext));
// direct numerical comparison works here, because
//
// ((e,r) <= (e',r')) implies (epochAndRound <= epochAndRound')
//
// because alphabetic ordering implies e <= e', and if e = e', then r<=r',
// so e*256+r <= e'*256+r', because r, r' < 256
require(r.hotVars.latestEpochAndRound < epochAndRound, "stale report");
require(_rs.length > r.hotVars.threshold, "not enough signatures");
require(_rs.length <= maxNumOracles, "too many signatures");
require(_ss.length == _rs.length, "signatures out of registration");
require(r.observations.length <= maxNumOracles,
"num observations out of bounds");
require(r.observations.length > 2 * r.hotVars.threshold,
"too few values to trust median");
// Copy signature parities in bytes32 _rawVs to bytes r.v
r.vs = new bytes(_rs.length);
for (uint8 i = 0; i < _rs.length; i++) {
r.vs[i] = _rawVs[i];
}
// Copy observer identities in bytes32 rawObservers to bytes r.observers
r.observers = new bytes(r.observations.length);
bool[maxNumOracles] memory seen;
for (uint8 i = 0; i < r.observations.length; i++) {
uint8 observerIdx = uint8(rawObservers[i]);
require(!seen[observerIdx], "observer index repeated");
seen[observerIdx] = true;
r.observers[i] = rawObservers[i];
}
Oracle memory transmitter = s_oracles[msg.sender];
require( // Check that sender is authorized to report
transmitter.role == Role.Transmitter &&
msg.sender == s_transmitters[transmitter.index],
"unauthorized transmitter"
);
// record epochAndRound here, so that we don't have to carry the local
// variable in transmit. The change is reverted if something fails later.
r.hotVars.latestEpochAndRound = epochAndRound;
}
{ // Verify signatures attached to report
bytes32 h = keccak256(_report);
bool[maxNumOracles] memory signed;
Oracle memory o;
for (uint i = 0; i < _rs.length; i++) {
address signer = ecrecover(h, uint8(r.vs[i])+27, _rs[i], _ss[i]);
o = s_oracles[signer];
require(o.role == Role.Signer, "address not authorized to sign");
require(!signed[o.index], "non-unique signature");
signed[o.index] = true;
}
}
{ // Check the report contents, and record the result
for (uint i = 0; i < r.observations.length - 1; i++) {
bool inOrder = r.observations[i] <= r.observations[i+1];
require(inOrder, "observations not sorted");
}
int192 median = r.observations[r.observations.length/2];
require(minAnswer <= median && median <= maxAnswer, "median is out of min-max range");
r.hotVars.latestAggregatorRoundId++;
s_transmissions[r.hotVars.latestAggregatorRoundId] =
Transmission(median, uint64(block.timestamp));
emit NewTransmission(
r.hotVars.latestAggregatorRoundId,
median,
msg.sender,
r.observations,
r.observers,
r.rawReportContext
);
// Emit these for backwards compatability with offchain consumers
// that only support legacy events
emit NewRound(
r.hotVars.latestAggregatorRoundId,
address(0x0), // use zero address since we don't have anybody "starting" the round here
block.timestamp
);
emit AnswerUpdated(
median,
r.hotVars.latestAggregatorRoundId,
block.timestamp
);
validateAnswer(r.hotVars.latestAggregatorRoundId, median);
}
s_hotVars = r.hotVars;
assert(initialGas < maxUint32);
reimburseAndRewardOracles(uint32(initialGas), r.observers);
}
/*
* v2 Aggregator interface
*/
/**
* @notice median from the most recent report
*/
function latestAnswer()
public
override
view
virtual
returns (int256)
{
return s_transmissions[s_hotVars.latestAggregatorRoundId].answer;
}
/**
* @notice timestamp of block in which last report was transmitted
*/
function latestTimestamp()
public
override
view
virtual
returns (uint256)
{
return s_transmissions[s_hotVars.latestAggregatorRoundId].timestamp;
}
/**
* @notice Aggregator round (NOT OCR round) in which last report was transmitted
*/
function latestRound()
public
override
view
virtual
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
override
view
virtual
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
override
view
virtual
returns (uint256)
{
if (_roundId > 0xFFFFFFFF) { return 0; }
return s_transmissions[uint32(_roundId)].timestamp;
}
/*
* v3 Aggregator interface
*/
string constant private V3_NO_DATA_ERROR = "No data present";
/**
* @return answers are stored in fixed-point format, with this many digits of precision
*/
uint8 immutable public override decimals;
/**
* @notice aggregator contract version
*/
uint256 constant public override version = 4;
string internal s_description;
/**
* @notice human-readable description of observable this contract is reporting on
*/
function description()
public
override
view
virtual
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
override
view
virtual
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.timestamp,
transmission.timestamp,
_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
override
view
virtual
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.timestamp,
transmission.timestamp,
roundId
);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.1;
import "./SimpleWriteAccessController.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;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
interface AccessControllerInterface {
function hasAccess(address user, bytes calldata data) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
import "./AggregatorInterface.sol";
import "./AggregatorV3Interface.sol";
interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface
{
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
interface AggregatorValidatorInterface {
function validate(
uint256 previousRoundId,
int256 previousAnswer,
uint256 currentRoundId,
int256 currentAnswer
) external returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.1;
interface LinkTokenInterface {
function allowance(address owner, address spender) external view returns (uint256 remaining);
function approve(address spender, uint256 value) external returns (bool success);
function balanceOf(address owner) external view returns (uint256 balance);
function decimals() external view returns (uint8 decimalPlaces);
function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
function increaseApproval(address spender, uint256 subtractedValue) external;
function name() external view returns (string memory tokenName);
function symbol() external view returns (string memory tokenSymbol);
function totalSupply() external view returns (uint256 totalTokensIssued);
function transfer(address to, uint256 value) external returns (bool success);
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success);
function transferFrom(address from, address to, uint256 value) external returns (bool success);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
/**
* @title The Owned contract
* @notice A contract with helpers for basic contract ownership.
*/
contract Owned {
address payable public owner;
address private pendingOwner;
event OwnershipTransferRequested(
address indexed from,
address indexed to
);
event OwnershipTransferred(
address indexed from,
address indexed to
);
constructor() {
owner = msg.sender;
}
/**
* @dev Allows an owner to begin transferring ownership to a new address,
* pending.
*/
function transferOwnership(address _to)
external
onlyOwner()
{
pendingOwner = _to;
emit OwnershipTransferRequested(owner, _to);
}
/**
* @dev Allows an ownership transfer to be completed by the recipient.
*/
function acceptOwnership()
external
{
require(msg.sender == pendingOwner, "Must be proposed owner");
address oldOwner = owner;
owner = msg.sender;
pendingOwner = address(0);
emit OwnershipTransferred(oldOwner, msg.sender);
}
/**
* @dev Reverts if called by anyone other than the contract owner.
*/
modifier onlyOwner() {
require(msg.sender == owner, "Only callable by owner");
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
import "./AccessControllerInterface.sol";
import "./LinkTokenInterface.sol";
import "./Owned.sol";
/**
* @notice tracks administration of oracle-reward and gas-reimbursement parameters.
* @dev
* If you read or change this, be sure to read or adjust the comments. They
* track the units of the values under consideration, and are crucial to
* the readability of the operations it specifies.
* @notice
* Trust Model:
* Nothing in this contract prevents a billing admin from setting insane
* values for the billing parameters in setBilling. Oracles
* participating in this contract should regularly check that the
* parameters make sense. Similarly, the outstanding obligations of this
* contract to the oracles can exceed the funds held by the contract.
* Oracles participating in this contract should regularly check that it
* holds sufficient funds and stop interacting with it if funding runs
* out.
* This still leaves oracles with some risk due to TOCTOU issues.
* However, since the sums involved are pretty small (Ethereum
* transactions aren't that expensive in the end) and an oracle would
* likely stop participating in a contract it repeatedly lost money on,
* this risk is deemed acceptable. Oracles should also regularly
* withdraw any funds in the contract to prevent issues where the
* contract becomes underfunded at a later time, and different oracles
* are competing for the left-over funds.
* Finally, note that any change to the set of oracles or to the billing
* parameters will trigger payout of all oracles first (using the old
* parameters), a billing admin cannot take away funds that are already
* marked for payment.
*/
contract OffchainAggregatorBilling is Owned {
// Maximum number of oracles the offchain reporting protocol is designed for
uint256 constant internal maxNumOracles = 31;
// Parameters for oracle payments
struct Billing {
// Highest compensated gas price, in ETH-gwei uints
uint32 maximumGasPrice;
// If gas price is less (in ETH-gwei units), transmitter gets half the savings
uint32 reasonableGasPrice;
// Pay transmitter back this much LINK per unit eth spent on gas
// (1e-6LINK/ETH units)
uint32 microLinkPerEth;
// Fixed LINK reward for each observer, in LINK-gwei units
uint32 linkGweiPerObservation;
// Fixed reward for transmitter, in linkGweiPerObservation units
uint32 linkGweiPerTransmission;
}
Billing internal s_billing;
// We assume that the token contract is correct. This contract is not written
// to handle misbehaving ERC20 tokens!
LinkTokenInterface internal s_linkToken;
AccessControllerInterface internal s_billingAccessController;
// ith element is number of observation rewards due to ith process, plus one.
// This is expected to saturate after an oracle has submitted 65,535
// observations, or about 65535/(3*24*20) = 45 days, given a transmission
// every 3 minutes.
//
// This is always one greater than the actual value, so that when the value is
// reset to zero, we don't end up with a zero value in storage (which would
// result in a higher gas cost, the next time the value is incremented.)
// Calculations using this variable need to take that offset into account.
uint16[maxNumOracles] internal s_oracleObservationsCounts;
// Addresses at which oracles want to receive payments, by transmitter address
mapping (address /* transmitter */ => address /* payment address */)
internal
s_payees;
// Payee addresses which must be approved by the owner
mapping (address /* transmitter */ => address /* payment address */)
internal
s_proposedPayees;
// LINK-wei-denominated reimbursements for gas used by transmitters.
//
// This is always one greater than the actual value, so that when the value is
// reset to zero, we don't end up with a zero value in storage (which would
// result in a higher gas cost, the next time the value is incremented.)
// Calculations using this variable need to take that offset into account.
//
// Argument for overflow safety:
// We have the following maximum intermediate values:
// - 2**40 additions to this variable (epochAndRound is a uint40)
// - 2**32 gas price in ethgwei/gas
// - 1e9 ethwei/ethgwei
// - 2**32 gas since the block gas limit is at ~20 million
// - 2**32 (microlink/eth)
// And we have 2**40 * 2**32 * 1e9 * 2**32 * 2**32 < 2**166
// (we also divide in some places, but that only makes the value smaller)
// We can thus safely use uint256 intermediate values for the computation
// updating this variable.
uint256[maxNumOracles] internal s_gasReimbursementsLinkWei;
// Used for s_oracles[a].role, where a is an address, to track the purpose
// of the address, or to indicate that the address is unset.
enum Role {
// No oracle role has been set for address a
Unset,
// Signing address for the s_oracles[a].index'th oracle. I.e., report
// signatures from this oracle should ecrecover back to address a.
Signer,
// Transmission address for the s_oracles[a].index'th oracle. I.e., if a
// report is received by OffchainAggregator.transmit in which msg.sender is
// a, it is attributed to the s_oracles[a].index'th oracle.
Transmitter
}
struct Oracle {
uint8 index; // Index of oracle in s_signers/s_transmitters
Role role; // Role of the address which mapped to this struct
}
mapping (address /* signer OR transmitter address */ => Oracle)
internal s_oracles;
// s_signers contains the signing address of each oracle
address[] internal s_signers;
// s_transmitters contains the transmission address of each oracle,
// i.e. the address the oracle actually sends transactions to the contract from
address[] internal s_transmitters;
uint256 constant private maxUint16 = (1 << 16) - 1;
uint256 constant internal maxUint128 = (1 << 128) - 1;
constructor(
uint32 _maximumGasPrice,
uint32 _reasonableGasPrice,
uint32 _microLinkPerEth,
uint32 _linkGweiPerObservation,
uint32 _linkGweiPerTransmission,
LinkTokenInterface _link,
AccessControllerInterface _billingAccessController
)
{
setBillingInternal(_maximumGasPrice, _reasonableGasPrice, _microLinkPerEth,
_linkGweiPerObservation, _linkGweiPerTransmission);
s_linkToken = _link;
emit LinkTokenSet(LinkTokenInterface(address(0)), _link);
setBillingAccessControllerInternal(_billingAccessController);
uint16[maxNumOracles] memory counts; // See s_oracleObservationsCounts docstring
uint256[maxNumOracles] memory gas; // see s_gasReimbursementsLinkWei docstring
for (uint8 i = 0; i < maxNumOracles; i++) {
counts[i] = 1;
gas[i] = 1;
}
s_oracleObservationsCounts = counts;
s_gasReimbursementsLinkWei = gas;
}
/*
* @notice emitted when the LINK token contract is set
* @param _oldLinkToken the address of the old LINK token contract
* @param _newLinkToken the address of the new LINK token contract
*/
event LinkTokenSet(
LinkTokenInterface indexed _oldLinkToken,
LinkTokenInterface indexed _newLinkToken
);
/*
* @notice sets the LINK token contract used for paying oracles
* @param _linkToken the address of the LINK token contract
* @param _recipient remaining funds from the previous token contract are transfered
* here
* @dev this function will return early (without an error) without changing any state
* if _linkToken equals getLinkToken().
* @dev this will trigger a payout so that a malicious owner cannot take from oracles
* what is already owed to them.
* @dev we assume that the token contract is correct. This contract is not written
* to handle misbehaving ERC20 tokens!
*/
function setLinkToken(
LinkTokenInterface _linkToken,
address _recipient
) external
onlyOwner()
{
LinkTokenInterface oldLinkToken = s_linkToken;
if (_linkToken == oldLinkToken) {
// No change, nothing to be done
return;
}
// call balanceOf as a sanity check on whether we're talking to a token
// contract
_linkToken.balanceOf(address(this));
// we break CEI here, but that's okay because we're dealing with a correct
// token contract (by assumption).
payOracles();
uint256 remainingBalance = oldLinkToken.balanceOf(address(this));
require(oldLinkToken.transfer(_recipient, remainingBalance), "transfer remaining funds failed");
s_linkToken = _linkToken;
emit LinkTokenSet(oldLinkToken, _linkToken);
}
/*
* @notice gets the LINK token contract used for paying oracles
* @return linkToken the address of the LINK token contract
*/
function getLinkToken()
external
view
returns(LinkTokenInterface linkToken)
{
return s_linkToken;
}
/**
* @notice emitted when billing parameters are set
* @param maximumGasPrice highest gas price for which transmitter will be compensated
* @param reasonableGasPrice transmitter will receive reward for gas prices under this value
* @param microLinkPerEth reimbursement per ETH of gas cost, in 1e-6LINK units
* @param linkGweiPerObservation reward to oracle for contributing an observation to a successfully transmitted report, in 1e-9LINK units
* @param linkGweiPerTransmission reward to transmitter of a successful report, in 1e-9LINK units
*/
event BillingSet(
uint32 maximumGasPrice,
uint32 reasonableGasPrice,
uint32 microLinkPerEth,
uint32 linkGweiPerObservation,
uint32 linkGweiPerTransmission
);
function setBillingInternal(
uint32 _maximumGasPrice,
uint32 _reasonableGasPrice,
uint32 _microLinkPerEth,
uint32 _linkGweiPerObservation,
uint32 _linkGweiPerTransmission
)
internal
{
s_billing = Billing(_maximumGasPrice, _reasonableGasPrice, _microLinkPerEth,
_linkGweiPerObservation, _linkGweiPerTransmission);
emit BillingSet(_maximumGasPrice, _reasonableGasPrice, _microLinkPerEth,
_linkGweiPerObservation, _linkGweiPerTransmission);
}
/**
* @notice sets billing parameters
* @param _maximumGasPrice highest gas price for which transmitter will be compensated
* @param _reasonableGasPrice transmitter will receive reward for gas prices under this value
* @param _microLinkPerEth reimbursement per ETH of gas cost, in 1e-6LINK units
* @param _linkGweiPerObservation reward to oracle for contributing an observation to a successfully transmitted report, in 1e-9LINK units
* @param _linkGweiPerTransmission reward to transmitter of a successful report, in 1e-9LINK units
* @dev access control provided by billingAccessController
*/
function setBilling(
uint32 _maximumGasPrice,
uint32 _reasonableGasPrice,
uint32 _microLinkPerEth,
uint32 _linkGweiPerObservation,
uint32 _linkGweiPerTransmission
)
external
{
AccessControllerInterface access = s_billingAccessController;
require(msg.sender == owner || access.hasAccess(msg.sender, msg.data),
"Only owner&billingAdmin can call");
payOracles();
setBillingInternal(_maximumGasPrice, _reasonableGasPrice, _microLinkPerEth,
_linkGweiPerObservation, _linkGweiPerTransmission);
}
/**
* @notice gets billing parameters
* @param maximumGasPrice highest gas price for which transmitter will be compensated
* @param reasonableGasPrice transmitter will receive reward for gas prices under this value
* @param microLinkPerEth reimbursement per ETH of gas cost, in 1e-6LINK units
* @param linkGweiPerObservation reward to oracle for contributing an observation to a successfully transmitted report, in 1e-9LINK units
* @param linkGweiPerTransmission reward to transmitter of a successful report, in 1e-9LINK units
*/
function getBilling()
external
view
returns (
uint32 maximumGasPrice,
uint32 reasonableGasPrice,
uint32 microLinkPerEth,
uint32 linkGweiPerObservation,
uint32 linkGweiPerTransmission
)
{
Billing memory billing = s_billing;
return (
billing.maximumGasPrice,
billing.reasonableGasPrice,
billing.microLinkPerEth,
billing.linkGweiPerObservation,
billing.linkGweiPerTransmission
);
}
/**
* @notice emitted when a new access-control contract is set
* @param old the address prior to the current setting
* @param current the address of the new access-control contract
*/
event BillingAccessControllerSet(AccessControllerInterface old, AccessControllerInterface current);
function setBillingAccessControllerInternal(AccessControllerInterface _billingAccessController)
internal
{
AccessControllerInterface oldController = s_billingAccessController;
if (_billingAccessController != oldController) {
s_billingAccessController = _billingAccessController;
emit BillingAccessControllerSet(
oldController,
_billingAccessController
);
}
}
/**
* @notice sets billingAccessController
* @param _billingAccessController new billingAccessController contract address
* @dev only owner can call this
*/
function setBillingAccessController(AccessControllerInterface _billingAccessController)
external
onlyOwner
{
setBillingAccessControllerInternal(_billingAccessController);
}
/**
* @notice gets billingAccessController
* @return address of billingAccessController contract
*/
function billingAccessController()
external
view
returns (AccessControllerInterface)
{
return s_billingAccessController;
}
/**
* @notice withdraws an oracle's payment from the contract
* @param _transmitter the transmitter address of the oracle
* @dev must be called by oracle's payee address
*/
function withdrawPayment(address _transmitter)
external
{
require(msg.sender == s_payees[_transmitter], "Only payee can withdraw");
payOracle(_transmitter);
}
/**
* @notice query an oracle's payment amount
* @param _transmitter the transmitter address of the oracle
*/
function owedPayment(address _transmitter)
public
view
returns (uint256)
{
Oracle memory oracle = s_oracles[_transmitter];
if (oracle.role == Role.Unset) { return 0; }
Billing memory billing = s_billing;
uint256 linkWeiAmount =
uint256(s_oracleObservationsCounts[oracle.index] - 1) *
uint256(billing.linkGweiPerObservation) *
(1 gwei);
linkWeiAmount += s_gasReimbursementsLinkWei[oracle.index] - 1;
return linkWeiAmount;
}
/**
* @notice emitted when an oracle has been paid LINK
* @param transmitter address from which the oracle sends reports to the transmit method
* @param payee address to which the payment is sent
* @param amount amount of LINK sent
* @param linkToken address of the LINK token contract
*/
event OraclePaid(
address indexed transmitter,
address indexed payee,
uint256 amount,
LinkTokenInterface indexed linkToken
);
// payOracle pays out _transmitter's balance to the corresponding payee, and zeros it out
function payOracle(address _transmitter)
internal
{
Oracle memory oracle = s_oracles[_transmitter];
uint256 linkWeiAmount = owedPayment(_transmitter);
if (linkWeiAmount > 0) {
address payee = s_payees[_transmitter];
// Poses no re-entrancy issues, because LINK.transfer does not yield
// control flow.
require(s_linkToken.transfer(payee, linkWeiAmount), "insufficient funds");
s_oracleObservationsCounts[oracle.index] = 1; // "zero" the counts. see var's docstring
s_gasReimbursementsLinkWei[oracle.index] = 1; // "zero" the counts. see var's docstring
emit OraclePaid(_transmitter, payee, linkWeiAmount, s_linkToken);
}
}
// payOracles pays out all transmitters, and zeros out their balances.
//
// It's much more gas-efficient to do this as a single operation, to avoid
// hitting storage too much.
function payOracles()
internal
{
Billing memory billing = s_billing;
LinkTokenInterface linkToken = s_linkToken;
uint16[maxNumOracles] memory observationsCounts = s_oracleObservationsCounts;
uint256[maxNumOracles] memory gasReimbursementsLinkWei =
s_gasReimbursementsLinkWei;
address[] memory transmitters = s_transmitters;
for (uint transmitteridx = 0; transmitteridx < transmitters.length; transmitteridx++) {
uint256 reimbursementAmountLinkWei = gasReimbursementsLinkWei[transmitteridx] - 1;
uint256 obsCount = observationsCounts[transmitteridx] - 1;
uint256 linkWeiAmount =
obsCount * uint256(billing.linkGweiPerObservation) * (1 gwei) + reimbursementAmountLinkWei;
if (linkWeiAmount > 0) {
address payee = s_payees[transmitters[transmitteridx]];
// Poses no re-entrancy issues, because LINK.transfer does not yield
// control flow.
require(linkToken.transfer(payee, linkWeiAmount), "insufficient funds");
observationsCounts[transmitteridx] = 1; // "zero" the counts.
gasReimbursementsLinkWei[transmitteridx] = 1; // "zero" the counts.
emit OraclePaid(transmitters[transmitteridx], payee, linkWeiAmount, linkToken);
}
}
// "Zero" the accounting storage variables
s_oracleObservationsCounts = observationsCounts;
s_gasReimbursementsLinkWei = gasReimbursementsLinkWei;
}
function oracleRewards(
bytes memory observers,
uint16[maxNumOracles] memory observations
)
internal
pure
returns (uint16[maxNumOracles] memory)
{
// reward each observer-participant with the observer reward
for (uint obsIdx = 0; obsIdx < observers.length; obsIdx++) {
uint8 observer = uint8(observers[obsIdx]);
observations[observer] = saturatingAddUint16(observations[observer], 1);
}
return observations;
}
// This value needs to change if maxNumOracles is increased, or the accounting
// calculations at the bottom of reimburseAndRewardOracles change.
//
// To recalculate it, run the profiler as described in
// ../../profile/README.md, and add up the gas-usage values reported for the
// lines in reimburseAndRewardOracles following the "gasLeft = gasleft()"
// line. E.g., you will see output like this:
//
// 7 uint256 gasLeft = gasleft();
// 29 uint256 gasCostEthWei = transmitterGasCostEthWei(
// 9 uint256(initialGas),
// 3 gasPrice,
// 3 callDataGasCost,
// 3 gasLeft
// .
// .
// .
// 59 uint256 gasCostLinkWei = (gasCostEthWei * billing.microLinkPerEth)/ 1e6;
// .
// .
// .
// 5047 s_gasReimbursementsLinkWei[txOracle.index] =
// 856 s_gasReimbursementsLinkWei[txOracle.index] + gasCostLinkWei +
// 26 uint256(billing.linkGweiPerTransmission) * (1 gwei);
//
// If those were the only lines to be accounted for, you would add up
// 29+9+3+3+3+59+5047+856+26=6035.
uint256 internal constant accountingGasCost = 6035;
// Uncomment the following declaration to compute the remaining gas cost after
// above gasleft(). (This must exist in a base class to OffchainAggregator, so
// it can't go in TestOffchainAggregator.)
//
// uint256 public gasUsedInAccounting;
// Gas price at which the transmitter should be reimbursed, in ETH-gwei/gas
function impliedGasPrice(
uint256 txGasPrice, // ETH-gwei/gas units
uint256 reasonableGasPrice, // ETH-gwei/gas units
uint256 maximumGasPrice // ETH-gwei/gas units
)
internal
pure
returns (uint256)
{
// Reward the transmitter for choosing an efficient gas price: if they manage
// to come in lower than considered reasonable, give them half the savings.
//
// The following calculations are all in units of gwei/gas, i.e. 1e-9ETH/gas
uint256 gasPrice = txGasPrice;
if (txGasPrice < reasonableGasPrice) {
// Give transmitter half the savings for coming in under the reasonable gas price
gasPrice += (reasonableGasPrice - txGasPrice) / 2;
}
// Don't reimburse a gas price higher than maximumGasPrice
return min(gasPrice, maximumGasPrice);
}
// gas reimbursement due the transmitter, in ETH-wei
//
// If this function is changed, accountingGasCost needs to change, too. See
// its docstring
function transmitterGasCostEthWei(
uint256 initialGas,
uint256 gasPrice, // ETH-gwei/gas units
uint256 callDataCost, // gas units
uint256 gasLeft
)
internal
pure
returns (uint128 gasCostEthWei)
{
require(initialGas >= gasLeft, "gasLeft cannot exceed initialGas");
uint256 gasUsed = // gas units
initialGas - gasLeft + // observed gas usage
callDataCost + accountingGasCost; // estimated gas usage
// gasUsed is in gas units, gasPrice is in ETH-gwei/gas units; convert to ETH-wei
uint256 fullGasCostEthWei = gasUsed * gasPrice * (1 gwei);
assert(fullGasCostEthWei < maxUint128); // the entire ETH supply fits in a uint128...
return uint128(fullGasCostEthWei);
}
/**
* @notice withdraw any available funds left in the contract, up to _amount, after accounting for the funds due to participants in past reports
* @param _recipient address to send funds to
* @param _amount maximum amount to withdraw, denominated in LINK-wei.
* @dev access control provided by billingAccessController
*/
function withdrawFunds(address _recipient, uint256 _amount)
external
{
require(msg.sender == owner || s_billingAccessController.hasAccess(msg.sender, msg.data),
"Only owner&billingAdmin can call");
uint256 linkDue = totalLINKDue();
uint256 linkBalance = s_linkToken.balanceOf(address(this));
require(linkBalance >= linkDue, "insufficient balance");
require(s_linkToken.transfer(_recipient, min(linkBalance - linkDue, _amount)), "insufficient funds");
}
// Total LINK due to participants in past reports.
function totalLINKDue()
internal
view
returns (uint256 linkDue)
{
// Argument for overflow safety: We do all computations in
// uint256s. The inputs to linkDue are:
// - the <= 31 observation rewards each of which has less than
// 64 bits (32 bits for billing.linkGweiPerObservation, 32 bits
// for wei/gwei conversion). Hence 69 bits are sufficient for this part.
// - the <= 31 gas reimbursements, each of which consists of at most 166
// bits (see s_gasReimbursementsLinkWei docstring). Hence 171 bits are
// sufficient for this part
// In total, 172 bits are enough.
uint16[maxNumOracles] memory observationCounts = s_oracleObservationsCounts;
for (uint i = 0; i < maxNumOracles; i++) {
linkDue += observationCounts[i] - 1; // Stored value is one greater than actual value
}
Billing memory billing = s_billing;
// Convert linkGweiPerObservation to uint256, or this overflows!
linkDue *= uint256(billing.linkGweiPerObservation) * (1 gwei);
address[] memory transmitters = s_transmitters;
uint256[maxNumOracles] memory gasReimbursementsLinkWei =
s_gasReimbursementsLinkWei;
for (uint i = 0; i < transmitters.length; i++) {
linkDue += uint256(gasReimbursementsLinkWei[i]-1); // Stored value is one greater than actual value
}
}
/**
* @notice allows oracles to check that sufficient LINK balance is available
* @return availableBalance LINK available on this contract, after accounting for outstanding obligations. can become negative
*/
function linkAvailableForPayment()
external
view
returns (int256 availableBalance)
{
// there are at most one billion LINK, so this cast is safe
int256 balance = int256(s_linkToken.balanceOf(address(this)));
// according to the argument in the definition of totalLINKDue,
// totalLINKDue is never greater than 2**172, so this cast is safe
int256 due = int256(totalLINKDue());
// safe from overflow according to above sizes
return int256(balance) - int256(due);
}
/**
* @notice number of observations oracle is due to be reimbursed for
* @param _signerOrTransmitter address used by oracle for signing or transmitting reports
*/
function oracleObservationCount(address _signerOrTransmitter)
external
view
returns (uint16)
{
Oracle memory oracle = s_oracles[_signerOrTransmitter];
if (oracle.role == Role.Unset) { return 0; }
return s_oracleObservationsCounts[oracle.index] - 1;
}
function reimburseAndRewardOracles(
uint32 initialGas,
bytes memory observers
)
internal
{
Oracle memory txOracle = s_oracles[msg.sender];
Billing memory billing = s_billing;
// Reward oracles for providing observations. Oracles are not rewarded
// for providing signatures, because signing is essentially free.
s_oracleObservationsCounts =
oracleRewards(observers, s_oracleObservationsCounts);
// Reimburse transmitter of the report for gas usage
require(txOracle.role == Role.Transmitter,
"sent by undesignated transmitter"
);
uint256 gasPrice = impliedGasPrice(
tx.gasprice / (1 gwei), // convert to ETH-gwei units
billing.reasonableGasPrice,
billing.maximumGasPrice
);
// The following is only an upper bound, as it ignores the cheaper cost for
// 0 bytes. Safe from overflow, because calldata just isn't that long.
uint256 callDataGasCost = 16 * msg.data.length;
// If any changes are made to subsequent calculations, accountingGasCost
// needs to change, too.
uint256 gasLeft = gasleft();
uint256 gasCostEthWei = transmitterGasCostEthWei(
uint256(initialGas),
gasPrice,
callDataGasCost,
gasLeft
);
// microLinkPerEth is 1e-6LINK/ETH units, gasCostEthWei is 1e-18ETH units
// (ETH-wei), product is 1e-24LINK-wei units, dividing by 1e6 gives
// 1e-18LINK units, i.e. LINK-wei units
// Safe from over/underflow, since all components are non-negative,
// gasCostEthWei will always fit into uint128 and microLinkPerEth is a
// uint32 (128+32 < 256!).
uint256 gasCostLinkWei = (gasCostEthWei * billing.microLinkPerEth)/ 1e6;
// Safe from overflow, because gasCostLinkWei < 2**160 and
// billing.linkGweiPerTransmission * (1 gwei) < 2**64 and we increment
// s_gasReimbursementsLinkWei[txOracle.index] at most 2**40 times.
s_gasReimbursementsLinkWei[txOracle.index] =
s_gasReimbursementsLinkWei[txOracle.index] + gasCostLinkWei +
uint256(billing.linkGweiPerTransmission) * (1 gwei); // convert from linkGwei to linkWei
// Uncomment next line to compute the remaining gas cost after above gasleft().
// See OffchainAggregatorBilling.accountingGasCost docstring for more information.
//
// gasUsedInAccounting = gasLeft - gasleft();
}
/*
* Payee management
*/
/**
* @notice emitted when a transfer of an oracle's payee address has been initiated
* @param transmitter address from which the oracle sends reports to the transmit method
* @param current the payeee address for the oracle, prior to this setting
* @param proposed the proposed new payee address for the oracle
*/
event PayeeshipTransferRequested(
address indexed transmitter,
address indexed current,
address indexed proposed
);
/**
* @notice emitted when a transfer of an oracle's payee address has been completed
* @param transmitter address from which the oracle sends reports to the transmit method
* @param current the payeee address for the oracle, prior to this setting
*/
event PayeeshipTransferred(
address indexed transmitter,
address indexed previous,
address indexed current
);
/**
* @notice sets the payees for transmitting addresses
* @param _transmitters addresses oracles use to transmit the reports
* @param _payees addresses of payees corresponding to list of transmitters
* @dev must be called by owner
* @dev cannot be used to change payee addresses, only to initially populate them
*/
function setPayees(
address[] calldata _transmitters,
address[] calldata _payees
)
external
onlyOwner()
{
require(_transmitters.length == _payees.length, "transmitters.size != payees.size");
for (uint i = 0; i < _transmitters.length; i++) {
address transmitter = _transmitters[i];
address payee = _payees[i];
address currentPayee = s_payees[transmitter];
bool zeroedOut = currentPayee == address(0);
require(zeroedOut || currentPayee == payee, "payee already set");
s_payees[transmitter] = payee;
if (currentPayee != payee) {
emit PayeeshipTransferred(transmitter, currentPayee, payee);
}
}
}
/**
* @notice first step of payeeship transfer (safe transfer pattern)
* @param _transmitter transmitter address of oracle whose payee is changing
* @param _proposed new payee address
* @dev can only be called by payee address
*/
function transferPayeeship(
address _transmitter,
address _proposed
)
external
{
require(msg.sender == s_payees[_transmitter], "only current payee can update");
require(msg.sender != _proposed, "cannot transfer to self");
address previousProposed = s_proposedPayees[_transmitter];
s_proposedPayees[_transmitter] = _proposed;
if (previousProposed != _proposed) {
emit PayeeshipTransferRequested(_transmitter, msg.sender, _proposed);
}
}
/**
* @notice second step of payeeship transfer (safe transfer pattern)
* @param _transmitter transmitter address of oracle whose payee is changing
* @dev can only be called by proposed new payee address
*/
function acceptPayeeship(
address _transmitter
)
external
{
require(msg.sender == s_proposedPayees[_transmitter], "only proposed payees can accept");
address currentPayee = s_payees[_transmitter];
s_payees[_transmitter] = msg.sender;
s_proposedPayees[_transmitter] = address(0);
emit PayeeshipTransferred(_transmitter, currentPayee, msg.sender);
}
/*
* Helper functions
*/
function saturatingAddUint16(uint16 _x, uint16 _y)
internal
pure
returns (uint16)
{
return uint16(min(uint256(_x)+uint256(_y), maxUint16));
}
function min(uint256 a, uint256 b)
internal
pure
returns (uint256)
{
if (a < b) { return a; }
return b;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
abstract contract TypeAndVersionInterface{
function typeAndVersion()
external
pure
virtual
returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
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);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
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
);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
import "./Owned.sol";
import "./AccessControllerInterface.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, Owned {
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() {
addAccessInternal(_user);
}
function addAccessInternal(address _user) internal {
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");
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
import "./AccessControlledOffchainAggregator.sol";
import "./AccessControlTestHelper.sol";
contract TestOffchainAggregator is AccessControlledOffchainAggregator {
function testDecodeReport(
bytes memory report
) public pure returns (bytes32, bytes32, int192[] memory)
{
return decodeReport(report);
}
constructor(
uint32 _maximumGasPrice,
uint32 _reasonableGasPrice,
uint32 _microLinkPerEth,
uint32 _linkGweiPerObservation,
uint32 _linkGweiPerTransmission,
LinkTokenInterface _link,
int192 _minAnswer, int192 _maxAnswer,
AccessControllerInterface _billingAccessController,
AccessControllerInterface _requesterAdminAccessController
)
AccessControlledOffchainAggregator(_maximumGasPrice, _reasonableGasPrice, _microLinkPerEth,
_linkGweiPerObservation, _linkGweiPerTransmission, _link,
_minAnswer, _maxAnswer, _billingAccessController, _requesterAdminAccessController, 0, "TEST"
)
{}
function testPayee(
address _transmitter
)
external
view
returns (address)
{
return s_payees[_transmitter];
}
function getConfigDigest() public view returns (bytes16) {
return s_hotVars.latestConfigDigest;
}
function testSaturatingAddUint16(uint16 _x, uint16 _y)
external pure returns (uint16)
{
return saturatingAddUint16(_x, _y);
}
function testImpliedGasPrice(uint256 txGasPrice, uint256 reasonableGasPrice,
uint256 maximumGasPrice
) external pure returns (uint256) {
return impliedGasPrice(txGasPrice, reasonableGasPrice, maximumGasPrice);
}
function testTransmitterGasCostEthWei(uint256 initialGas, uint256 gasPrice,
uint256 callDataCost, uint256 gasLeft
) external pure returns (uint128) {
return transmitterGasCostEthWei(
initialGas, gasPrice, callDataCost, gasLeft
);
}
function testSetOracleObservationCount(address _oracle, uint16 _amount) external {
s_oracleObservationsCounts[s_oracles[_oracle].index] = _amount + 1;
}
function testTotalLinkDue()
external view returns (uint256 linkDue)
{
return totalLINKDue();
}
function billingData() external view returns (
uint16[maxNumOracles] memory observationsCounts,
uint256[maxNumOracles] memory gasReimbursements,
uint32 maximumGasPrice,
uint32 reasonableGasPrice,
uint32 microLinkPerEth,
uint32 linkGweiPerObservation,
uint32 linkGweiPerTransmission
) {
Billing memory b = s_billing;
return (s_oracleObservationsCounts, s_gasReimbursementsLinkWei,
b.maximumGasPrice, b.reasonableGasPrice, b.microLinkPerEth,
b.linkGweiPerObservation, b.linkGweiPerTransmission);
}
function testSetGasReimbursements(address _transmitterOrSigner, uint256 _amountLinkWei)
external
{
require(s_oracles[_transmitterOrSigner].role != Role.Unset, "address unknown");
s_gasReimbursementsLinkWei[s_oracles[_transmitterOrSigner].index] = _amountLinkWei + 1;
}
function testAccountingGasCost() public pure returns (uint256) {
return accountingGasCost;
}
function testBurnLINK(uint256 amount) public {
s_linkToken.transfer(address(1), amount);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.1;
import "./AccessControlledOffchainAggregator.sol";
contract AccessControlTestHelper {
event Dummy(); // Used to silence warning that these methods are pure
function readGetRoundData(address _aggregator, uint80 _roundID)
external
{
AccessControlledOffchainAggregator(_aggregator).getRoundData(_roundID);
emit Dummy();
}
function readLatestRoundData(address _aggregator)
external
{
AccessControlledOffchainAggregator(_aggregator).latestRoundData();
emit Dummy();
}
function readLatestAnswer(address _aggregator)
external
{
AccessControlledOffchainAggregator(_aggregator).latestAnswer();
emit Dummy();
}
function readLatestTimestamp(address _aggregator)
external
{
AccessControlledOffchainAggregator(_aggregator).latestTimestamp();
emit Dummy();
}
function readLatestRound(address _aggregator)
external
{
AccessControlledOffchainAggregator(_aggregator).latestRound();
emit Dummy();
}
function readGetAnswer(address _aggregator, uint256 _roundID)
external
{
AccessControlledOffchainAggregator(_aggregator).getAnswer(_roundID);
emit Dummy();
}
function readGetTimestamp(address _aggregator, uint256 _roundID)
external
{
AccessControlledOffchainAggregator(_aggregator).getTimestamp(_roundID);
emit Dummy();
}
function testLatestTransmissionDetails(address _aggregator) external view {
OffchainAggregator(_aggregator).latestTransmissionDetails();
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
import "./OffchainAggregator.sol";
// ExposedOffchainAggregator exposes certain internal OffchainAggregator
// methods/structures so that golang code can access them, and we get
// reliable type checking on their usage
contract ExposedOffchainAggregator is OffchainAggregator {
constructor()
OffchainAggregator(
0, 0, 0, 0, 0, LinkTokenInterface(address(0)), 0, 0, AccessControllerInterface(address(0)), AccessControllerInterface(address(0)), 0, ""
)
{}
function exposedConfigDigestFromConfigData(
address _contractAddress,
uint64 _configCount,
address[] calldata _signers,
address[] calldata _transmitters,
uint8 _threshold,
uint64 _encodedConfigVersion,
bytes calldata _encodedConfig
) external pure returns (bytes16) {
return configDigestFromConfigData(_contractAddress, _configCount,
_signers, _transmitters, _threshold, _encodedConfigVersion,
_encodedConfig);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
import "./AggregatorValidatorInterface.sol";
contract TestValidator is AggregatorValidatorInterface {
uint32 s_minGasUse;
uint256 s_latestRoundId;
event Validated(
uint256 previousRoundId,
int256 previousAnswer,
uint256 currentRoundId,
int256 currentAnswer,
uint256 initialGas
);
function validate(
uint256 previousRoundId,
int256 previousAnswer,
uint256 currentRoundId,
int256 currentAnswer
) external override returns (bool) {
uint256 initialGas = gasleft();
emit Validated(
previousRoundId,
previousAnswer,
currentRoundId,
currentAnswer,
initialGas
);
s_latestRoundId = currentRoundId;
uint256 minGasUse = s_minGasUse;
while (initialGas - gasleft() < minGasUse) {}
return true;
}
function setMinGasUse(uint32 minGasUse) external {
s_minGasUse = minGasUse;
}
function latestRoundId() external view returns (uint256) {
return s_latestRoundId;
}
}{
"optimizer": {
"enabled": true,
"runs": 20000
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"uint32","name":"_maximumGasPrice","type":"uint32"},{"internalType":"uint32","name":"_reasonableGasPrice","type":"uint32"},{"internalType":"uint32","name":"_microLinkPerEth","type":"uint32"},{"internalType":"uint32","name":"_linkGweiPerObservation","type":"uint32"},{"internalType":"uint32","name":"_linkGweiPerTransmission","type":"uint32"},{"internalType":"contract LinkTokenInterface","name":"_link","type":"address"},{"internalType":"int192","name":"_minAnswer","type":"int192"},{"internalType":"int192","name":"_maxAnswer","type":"int192"},{"internalType":"contract AccessControllerInterface","name":"_billingAccessController","type":"address"},{"internalType":"contract AccessControllerInterface","name":"_requesterAccessController","type":"address"},{"internalType":"uint8","name":"_decimals","type":"uint8"},{"internalType":"string","name":"description","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"}],"name":"AddedAccess","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"int256","name":"current","type":"int256"},{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"updatedAt","type":"uint256"}],"name":"AnswerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract AccessControllerInterface","name":"old","type":"address"},{"indexed":false,"internalType":"contract AccessControllerInterface","name":"current","type":"address"}],"name":"BillingAccessControllerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"maximumGasPrice","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"reasonableGasPrice","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"microLinkPerEth","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"linkGweiPerObservation","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"linkGweiPerTransmission","type":"uint32"}],"name":"BillingSet","type":"event"},{"anonymous":false,"inputs":[],"name":"CheckAccessDisabled","type":"event"},{"anonymous":false,"inputs":[],"name":"CheckAccessEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"threshold","type":"uint8"},{"indexed":false,"internalType":"uint64","name":"encodedConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"encoded","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract LinkTokenInterface","name":"_oldLinkToken","type":"address"},{"indexed":true,"internalType":"contract LinkTokenInterface","name":"_newLinkToken","type":"address"}],"name":"LinkTokenSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":true,"internalType":"address","name":"startedBy","type":"address"},{"indexed":false,"internalType":"uint256","name":"startedAt","type":"uint256"}],"name":"NewRound","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"aggregatorRoundId","type":"uint32"},{"indexed":false,"internalType":"int192","name":"answer","type":"int192"},{"indexed":false,"internalType":"address","name":"transmitter","type":"address"},{"indexed":false,"internalType":"int192[]","name":"observations","type":"int192[]"},{"indexed":false,"internalType":"bytes","name":"observers","type":"bytes"},{"indexed":false,"internalType":"bytes32","name":"rawReportContext","type":"bytes32"}],"name":"NewTransmission","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"payee","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"contract LinkTokenInterface","name":"linkToken","type":"address"}],"name":"OraclePaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"current","type":"address"},{"indexed":true,"internalType":"address","name":"proposed","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"previous","type":"address"},{"indexed":true,"internalType":"address","name":"current","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"}],"name":"RemovedAccess","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract AccessControllerInterface","name":"old","type":"address"},{"indexed":false,"internalType":"contract AccessControllerInterface","name":"current","type":"address"}],"name":"RequesterAccessControllerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requester","type":"address"},{"indexed":false,"internalType":"bytes16","name":"configDigest","type":"bytes16"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"},{"indexed":false,"internalType":"uint8","name":"round","type":"uint8"}],"name":"RoundRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract AggregatorValidatorInterface","name":"previousValidator","type":"address"},{"indexed":false,"internalType":"uint32","name":"previousGasLimit","type":"uint32"},{"indexed":true,"internalType":"contract AggregatorValidatorInterface","name":"currentValidator","type":"address"},{"indexed":false,"internalType":"uint32","name":"currentGasLimit","type":"uint32"}],"name":"ValidatorConfigSet","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"addAccess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"billingAccessController","outputs":[{"internalType":"contract AccessControllerInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"checkEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"description","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"disableAccessCheck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enableAccessCheck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_roundId","type":"uint256"}],"name":"getAnswer","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBilling","outputs":[{"internalType":"uint32","name":"maximumGasPrice","type":"uint32"},{"internalType":"uint32","name":"reasonableGasPrice","type":"uint32"},{"internalType":"uint32","name":"microLinkPerEth","type":"uint32"},{"internalType":"uint32","name":"linkGweiPerObservation","type":"uint32"},{"internalType":"uint32","name":"linkGweiPerTransmission","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkToken","outputs":[{"internalType":"contract LinkTokenInterface","name":"linkToken","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint80","name":"_roundId","type":"uint80"}],"name":"getRoundData","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":[{"internalType":"uint256","name":"_roundId","type":"uint256"}],"name":"getTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"bytes","name":"_calldata","type":"bytes"}],"name":"hasAccess","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestAnswer","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes16","name":"configDigest","type":"bytes16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestRound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[],"name":"latestTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestTransmissionDetails","outputs":[{"internalType":"bytes16","name":"configDigest","type":"bytes16"},{"internalType":"uint32","name":"epoch","type":"uint32"},{"internalType":"uint8","name":"round","type":"uint8"},{"internalType":"int192","name":"latestAnswer","type":"int192"},{"internalType":"uint64","name":"latestTimestamp","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"availableBalance","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxAnswer","outputs":[{"internalType":"int192","name":"","type":"int192"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minAnswer","outputs":[{"internalType":"int192","name":"","type":"int192"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_signerOrTransmitter","type":"address"}],"name":"oracleObservationCount","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_transmitter","type":"address"}],"name":"owedPayment","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"removeAccess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requestNewRound","outputs":[{"internalType":"uint80","name":"","type":"uint80"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requesterAccessController","outputs":[{"internalType":"contract AccessControllerInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_maximumGasPrice","type":"uint32"},{"internalType":"uint32","name":"_reasonableGasPrice","type":"uint32"},{"internalType":"uint32","name":"_microLinkPerEth","type":"uint32"},{"internalType":"uint32","name":"_linkGweiPerObservation","type":"uint32"},{"internalType":"uint32","name":"_linkGweiPerTransmission","type":"uint32"}],"name":"setBilling","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AccessControllerInterface","name":"_billingAccessController","type":"address"}],"name":"setBillingAccessController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_signers","type":"address[]"},{"internalType":"address[]","name":"_transmitters","type":"address[]"},{"internalType":"uint8","name":"_threshold","type":"uint8"},{"internalType":"uint64","name":"_encodedConfigVersion","type":"uint64"},{"internalType":"bytes","name":"_encoded","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract LinkTokenInterface","name":"_linkToken","type":"address"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"setLinkToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_transmitters","type":"address[]"},{"internalType":"address[]","name":"_payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AccessControllerInterface","name":"_requesterAccessController","type":"address"}],"name":"setRequesterAccessController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AggregatorValidatorInterface","name":"_newValidator","type":"address"},{"internalType":"uint32","name":"_newGasLimit","type":"uint32"}],"name":"setValidatorConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_transmitter","type":"address"},{"internalType":"address","name":"_proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_report","type":"bytes"},{"internalType":"bytes32[]","name":"_rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"_ss","type":"bytes32[]"},{"internalType":"bytes32","name":"_rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transmitters","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"validatorConfig","outputs":[{"internalType":"contract AggregatorValidatorInterface","name":"validator","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_transmitter","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60e06040523480156200001157600080fd5b50604051620065833803806200658383398181016040526101808110156200003857600080fd5b815160208301516040808501516060860151608087015160a088015160c089015160e08a01516101008b01516101208c01516101408d01516101608e0180519a519c9e9b9d999c989b979a969995989497939692959194939182019284640100000000821115620000a857600080fd5b908301906020820185811115620000be57600080fd5b8251640100000000811182820188101715620000d957600080fd5b82525081516020918201929091019080838360005b8381101562000108578181015183820152602001620000ee565b50505050905090810190601f168015620001365780820380516001836020036101000a031916815260200191505b506040525050600080546001600160a01b03191633179055508b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b89620001718787878787620002ef565b600380546001600160a01b0319166001600160a01b0384169081179091556040516000907f4966a50c93f855342ccf6c5c0d358b85b91335b2acedc7da0932f691f351711a908290a3620001c581620003e1565b620001cf62000678565b620001d962000678565b60005b601f8160ff16101562000229576001838260ff16601f8110620001fb57fe5b61ffff909216602092909202015260018260ff8316601f81106200021b57fe5b6020020152600101620001dc565b5062000239600583601f62000697565b5062000249600982601f62000734565b505050505060f887901b7fff000000000000000000000000000000000000000000000000000000000000001660c052505083516200029293506030925060208501915062000765565b506200029e836200045a565b620002ab60008062000532565b50505050601791820b820b604090811b60805290820b90910b901b60a05250506031805460ff1916600117905550620007fe9e505050505050505050505050505050565b6040805160a0808201835263ffffffff88811680845288821660208086018290528984168688018190528985166060808901829052958a1660809889018190526002805463ffffffff1916871763ffffffff60201b191664010000000087021763ffffffff60401b19166801000000000000000085021763ffffffff60601b19166c0100000000000000000000000084021763ffffffff60801b1916600160801b830217905589519586529285019390935283880152928201529283015291517fd0d9486a2c673e2a4b57fc82e4c8a556b3e2b82dd5db07e2c04a920ca0f469b6929181900390910190a15050505050565b6004546001600160a01b0390811690821681146200045657600480546001600160a01b0319166001600160a01b03848116918217909255604080519284168352602083019190915280517f793cb73064f3c8cde7e187ae515511e6e56d1ee89bf08b82fa60fb70f8d489129281900390910190a15b5050565b6000546001600160a01b03163314620004ba576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b602f546001600160a01b0390811690821681146200045657602f80546001600160a01b0319166001600160a01b03848116918217909255604080519284168352602083019190915280517f27b89aede8b560578baaa25ee5ce3852c5eecad1e114b941bbd89e1eb4bae6349281900390910190a15050565b6000546001600160a01b0316331462000592576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b60408051808201909152602e546001600160a01b03808216808452600160a01b90920463ffffffff1660208401528416141580620005e057508163ffffffff16816020015163ffffffff1614155b1562000673576040805180820182526001600160a01b0385811680835263ffffffff8681166020948501819052602e80546001600160a01b031916841763ffffffff60a01b1916600160a01b8302179055865187860151875193168352948201528451919493909216927fb04e3a37abe9c0fcdfebdeae019a8e2b12ddf53f5d55ffb0caccc1bedaca1541928290030190a35b505050565b604051806103e00160405280601f906020820280368337509192915050565b600283019183908215620007225791602002820160005b83821115620006f057835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620006ae565b8015620007205782816101000a81549061ffff0219169055600201602081600101049283019260010302620006f0565b505b5062000730929150620007e7565b5090565b82601f810192821562000722579160200282015b828111156200072257825182559160200191906001019062000748565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826200079d576000855562000722565b82601f10620007b857805160ff191683800117855562000722565b828001600101855582156200072257918201828111156200072257825182559160200191906001019062000748565b5b80821115620007305760008155600101620007e8565b60805160401c60a05160401c60c05160f81c615d456200083e60003980610fd6525080611e235280613b98525080610f355280613b6b5250615d456000f3fe608060405234801561001057600080fd5b506004361061030a5760003560e01c80638e0566de1161019c578063c1075329116100ee578063e76d516811610097578063f2fde38b11610071578063f2fde38b14610cb6578063fbffd2c114610cdc578063feaf968c14610d025761030a565b8063e76d516814610c4e578063eb45716314610c56578063eb5dcd6c14610c885761030a565b8063dc7f0124116100c8578063dc7f012414610b9f578063e4902f8214610ba7578063e5fe457714610be45761030a565b8063c107532914610a57578063c980753914610a83578063d09dc33914610b975761030a565b80639e3ceeab11610150578063b5ab58dc1161012a578063b5ab58dc146109d8578063b633620c146109f5578063bd82470614610a125761030a565b80639e3ceeab14610966578063a118f2491461098c578063b121e147146109b25761030a565b8063996e829811610181578063996e8298146108295780639a6fc8f5146108315780639c849b30146108a45761030a565b80638e0566de146107d257806398e5b12a146108025761030a565b80636b14daf81161026057806381411834116102095780638823da6c116101e35780638823da6c1461077e5780638ac28d5a146107a45780638da5cb5b146107ca5761030a565b806381411834146106cd57806381ff7048146107255780638205bf6a146107765761030a565b80637284e4161161023a5780637284e416146106b557806379ba5097146106bd5780638038e4a1146106c55761030a565b80636b14daf8146105bf57806370da2f671461068957806370efdf2d146106915761030a565b8063313ce567116102c257806354fd4d501161029c57806354fd4d5014610482578063585aa7de1461048a578063668a0f02146105b75761030a565b8063313ce5671461042e5780634fb174701461044c57806350d25bcd1461047a5761030a565b8063181f5a77116102f3578063181f5a771461035157806322adbc78146103ce57806329937268146103ed5761030a565b80630a7569831461030f5780630eafb25b14610319575b600080fd5b610317610d0a565b005b61033f6004803603602081101561032f57600080fd5b50356001600160a01b0316610dc8565b60408051918252519081900360200190f35b610359610f13565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561039357818101518382015260200161037b565b50505050905090810190601f1680156103c05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103d6610f33565b6040805160179290920b8252519081900360200190f35b6103f5610f57565b6040805163ffffffff96871681529486166020860152928516848401529084166060840152909216608082015290519081900360a00190f35b610436610fd4565b6040805160ff9092168252519081900360200190f35b6103176004803603604081101561046257600080fd5b506001600160a01b0381358116916020013516610ff8565b61033f6112dc565b61033f61137d565b610317600480360360a08110156104a057600080fd5b8101906020810181356401000000008111156104bb57600080fd5b8201836020820111156104cd57600080fd5b803590602001918460208302840111640100000000831117156104ef57600080fd5b91939092909160208101903564010000000081111561050d57600080fd5b82018360208201111561051f57600080fd5b8035906020019184602083028401116401000000008311171561054157600080fd5b9193909260ff8335169267ffffffffffffffff60208201351692919060608101906040013564010000000081111561057857600080fd5b82018360208201111561058a57600080fd5b803590602001918460018302840111640100000000831117156105ac57600080fd5b509092509050611382565b61033f611d5d565b610675600480360360408110156105d557600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561060057600080fd5b82018360208201111561061257600080fd5b8035906020019184600183028401116401000000008311171561063457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611df9945050505050565b604080519115158252519081900360200190f35b6103d6611e21565b610699611e45565b604080516001600160a01b039092168252519081900360200190f35b610359611e54565b610317611ef0565b610317611fbe565b6106d561207d565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156107115781810151838201526020016106f9565b505050509050019250505060405180910390f35b61072d6120df565b6040805163ffffffff94851681529290931660208301527fffffffffffffffffffffffffffffffff00000000000000000000000000000000168183015290519081900360600190f35b61033f612100565b6103176004803603602081101561079457600080fd5b50356001600160a01b031661219c565b610317600480360360208110156107ba57600080fd5b50356001600160a01b0316612293565b61069961230a565b6107da612319565b604080516001600160a01b03909316835263ffffffff90911660208301528051918290030190f35b61080a61235d565b6040805169ffffffffffffffffffff9092168252519081900360200190f35b6106996125b1565b61085a6004803603602081101561084757600080fd5b503569ffffffffffffffffffff166125c0565b604051808669ffffffffffffffffffff1681526020018581526020018481526020018381526020018269ffffffffffffffffffff1681526020019550505050505060405180910390f35b610317600480360360408110156108ba57600080fd5b8101906020810181356401000000008111156108d557600080fd5b8201836020820111156108e757600080fd5b8035906020019184602083028401116401000000008311171561090957600080fd5b91939092909160208101903564010000000081111561092757600080fd5b82018360208201111561093957600080fd5b8035906020019184602083028401116401000000008311171561095b57600080fd5b509092509050612675565b6103176004803603602081101561097c57600080fd5b50356001600160a01b03166128ae565b610317600480360360208110156109a257600080fd5b50356001600160a01b031661299c565b610317600480360360208110156109c857600080fd5b50356001600160a01b0316612a04565b61033f600480360360208110156109ee57600080fd5b5035612afd565b61033f60048036036020811015610a0b57600080fd5b5035612b9a565b610317600480360360a0811015610a2857600080fd5b5063ffffffff813581169160208101358216916040820135811691606081013582169160809091013516612c37565b61031760048036036040811015610a6d57600080fd5b506001600160a01b038135169060200135612d9d565b61031760048036036080811015610a9957600080fd5b810190602081018135640100000000811115610ab457600080fd5b820183602082011115610ac657600080fd5b80359060200191846001830284011164010000000083111715610ae857600080fd5b919390929091602081019035640100000000811115610b0657600080fd5b820183602082011115610b1857600080fd5b80359060200191846020830284011164010000000083111715610b3a57600080fd5b919390929091602081019035640100000000811115610b5857600080fd5b820183602082011115610b6a57600080fd5b80359060200191846020830284011164010000000083111715610b8c57600080fd5b9193509150356130c4565b61033f613fcd565b610675614077565b610bcd60048036036020811015610bbd57600080fd5b50356001600160a01b0316614080565b6040805161ffff9092168252519081900360200190f35b610bec61412d565b604080517fffffffffffffffffffffffffffffffff00000000000000000000000000000000909616865263ffffffff909416602086015260ff9092168484015260170b606084015267ffffffffffffffff166080830152519081900360a00190f35b61069961421c565b61031760048036036040811015610c6c57600080fd5b5080356001600160a01b0316906020013563ffffffff1661422b565b61031760048036036040811015610c9e57600080fd5b506001600160a01b03813581169160200135166143c0565b61031760048036036020811015610ccc57600080fd5b50356001600160a01b031661451b565b61031760048036036020811015610cf257600080fd5b50356001600160a01b03166145e3565b61085a61464b565b6000546001600160a01b03163314610d69576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b60315460ff1615610dc657603180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f3be8a977a014527b50ae38adda80b56911c267328965c98ddc385d248f53963890600090a15b565b6001600160a01b03811660009081526028602090815260408083208151808301909252805460ff808216845285948401916101009004166002811115610e0a57fe5b6002811115610e1557fe5b9052509050600081602001516002811115610e2c57fe5b1415610e3c576000915050610f0e565b6040805160a08101825260025463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c01000000000000000000000000810483166060830181905270010000000000000000000000000000000090910490921660808201528251909160009160019060059060ff16601f8110610ec757fe5b601091828204019190066002029054906101000a900461ffff160361ffff1602633b9aca0002905060016009846000015160ff16601f8110610f0557fe5b01540301925050505b919050565b6060604051806060016040528060288152602001615cc460289139905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040805160a08101825260025463ffffffff808216808452640100000000830482166020850181905268010000000000000000840483169585018690526c01000000000000000000000000840483166060860181905270010000000000000000000000000000000090940490921660809094018490529490939290565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000546001600160a01b03163314611057576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b6003546001600160a01b0390811690831681141561107557506112d8565b604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b1580156110d457600080fd5b505afa1580156110e8573d6000803e3d6000fd5b505050506040513d60208110156110fe57600080fd5b5061110990506146fe565b6000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561115857600080fd5b505afa15801561116c573d6000803e3d6000fd5b505050506040513d602081101561118257600080fd5b5051604080517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301526024820184905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b1580156111f357600080fd5b505af1158015611207573d6000803e3d6000fd5b505050506040513d602081101561121d57600080fd5b5051611270576040805162461bcd60e51b815260206004820152601f60248201527f7472616e736665722072656d61696e696e672066756e6473206661696c656400604482015290519081900360640190fd5b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0386811691821790925560405190918416907f4966a50c93f855342ccf6c5c0d358b85b91335b2acedc7da0932f691f351711a90600090a350505b5050565b600061131f336000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611df992505050565b611370576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b611378614aae565b905090565b600481565b868560ff8616601f8311156113de576040805162461bcd60e51b815260206004820152601060248201527f746f6f206d616e79207369676e65727300000000000000000000000000000000604482015290519081900360640190fd5b60008111611433576040805162461bcd60e51b815260206004820152601a60248201527f7468726573686f6c64206d75737420626520706f736974697665000000000000604482015290519081900360640190fd5b8183146114715760405162461bcd60e51b8152600401808060200182810382526024815260200180615cec6024913960400191505060405180910390fd5b8060030283116114c8576040805162461bcd60e51b815260206004820181905260248201527f6661756c74792d6f7261636c65207468726573686f6c6420746f6f2068696768604482015290519081900360640190fd5b6000546001600160a01b03163314611527576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b602954156116cb57602980547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101916000918390811061156457fe5b6000918252602082200154602a80546001600160a01b039092169350908490811061158b57fe5b6000918252602090912001546001600160a01b031690506115ab81614aea565b6001600160a01b0380831660009081526028602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009081169091559284168252902080549091169055602980548061160757fe5b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055019055602a80548061166a57fe5b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905501905550611527915050565b60005b8a811015611ad9576000602860008e8e858181106116e857fe5b602090810292909201356001600160a01b031683525081019190915260400160002054610100900460ff16600281111561171e57fe5b14611770576040805162461bcd60e51b815260206004820152601760248201527f7265706561746564207369676e65722061646472657373000000000000000000604482015290519081900360640190fd5b6040805180820190915260ff8216815260016020820152602860008e8e8581811061179757fe5b602090810292909201356001600160a01b031683525081810192909252604001600020825181547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff9091161780825591830151909182907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010083600281111561182257fe5b02179055506000915060079050818c8c8581811061183c57fe5b6001600160a01b03602091820293909301358316845283019390935260409091016000205416919091141590506118ba576040805162461bcd60e51b815260206004820152601160248201527f7061796565206d75737420626520736574000000000000000000000000000000604482015290519081900360640190fd5b6000602860008c8c858181106118cc57fe5b602090810292909201356001600160a01b031683525081019190915260400160002054610100900460ff16600281111561190257fe5b14611954576040805162461bcd60e51b815260206004820152601c60248201527f7265706561746564207472616e736d6974746572206164647265737300000000604482015290519081900360640190fd5b6040805180820190915260ff8216815260026020820152602860008c8c8581811061197b57fe5b602090810292909201356001600160a01b031683525081810192909252604001600020825181547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff9091161780825591830151909182907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100836002811115611a0657fe5b021790555090505060298c8c83818110611a1c57fe5b835460018101855560009485526020948590200180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b039590920293909301359390931692909217905550602a8a8a83818110611a7e57fe5b835460018181018655600095865260209586902090910180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03969093029490940135949094161790915550016116ce565b50602b805460ff89167501000000000000000000000000000000000000000000027fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff909116179055602d80544363ffffffff9081166401000000009081027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff84161780831660010183167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000909116179384905590910481169116611ba530828f8f8f8f8f8f8f8f614cf6565b602b60000160006101000a8154816fffffffffffffffffffffffffffffffff021916908360801c02179055506000602b60000160106101000a81548164ffffffffff021916908364ffffffffff1602179055507f25d719d88a4512dd76c7442b910a83360845505894eb444ef299409e180f8fb982828f8f8f8f8f8f8f8f604051808b63ffffffff1681526020018a67ffffffffffffffff16815260200180602001806020018760ff1681526020018667ffffffffffffffff1681526020018060200184810384528c8c82818152602001925060200280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910185810384528a8152602090810191508b908b0280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910185810383528681526020019050868680828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039f50909d5050505050505050505050505050a150505050505050505050505050565b6000611da0336000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611df992505050565b611df1576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b611378614e36565b6000611e058383614e5c565b80611e1857506001600160a01b03831632145b90505b92915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b602f546001600160a01b031690565b6060611e97336000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611df992505050565b611ee8576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b611378614e8c565b6001546001600160a01b03163314611f4f576040805162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015290519081900360640190fd5b60008054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000546001600160a01b0316331461201d576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b60315460ff16610dc657603180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517faebf329500988c6488a0074e5a0a9ff304561fc5c6fc877aeb1d59c8282c348090600090a1565b6060602a8054806020026020016040519081016040528092919081815260200182805480156120d557602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116120b7575b5050505050905090565b602d54602b5463ffffffff808316926401000000009004169060801b909192565b6000612143336000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611df992505050565b612194576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b611378614f37565b6000546001600160a01b031633146121fb576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b6001600160a01b03811660009081526032602052604090205460ff1615612290576001600160a01b03811660008181526032602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055815192835290517f3d68a6fce901d20453d1a7aa06bf3950302a735948037deb182a8db66df2a0d19281900390910190a15b50565b6001600160a01b03818116600090815260076020526040902054163314612301576040805162461bcd60e51b815260206004820152601760248201527f4f6e6c792070617965652063616e207769746864726177000000000000000000604482015290519081900360640190fd5b61229081614aea565b6000546001600160a01b031681565b60408051808201909152602e546001600160a01b0381168083527401000000000000000000000000000000000000000090910463ffffffff16602090920182905291565b600080546001600160a01b03163314806124575750602f54604080517f6b14daf800000000000000000000000000000000000000000000000000000000815233600482018181526024830193845236604484018190526001600160a01b0390951694636b14daf894929360009391929190606401848480828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016909201965060209550909350505081840390508186803b15801561242a57600080fd5b505afa15801561243e573d6000803e3d6000fd5b505050506040513d602081101561245457600080fd5b50515b6124a8576040805162461bcd60e51b815260206004820152601d60248201527f4f6e6c79206f776e6572267265717565737465722063616e2063616c6c000000604482015290519081900360640190fd5b6040805160808082018352602b549081901b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000016808352700100000000000000000000000000000000820464ffffffffff81166020808601919091527501000000000000000000000000000000000000000000840460ff9081168688015276010000000000000000000000000000000000000000000090940463ffffffff9081166060808801919091528751948552600884901c909116918401919091529216818501529251919233927f3ea16a923ff4b1df6526e854c9e3a995c43385d70e73359e10623c74f0b52037929181900390910190a2806060015160010163ffffffff1691505090565b6004546001600160a01b031690565b6000806000806000612609336000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611df992505050565b61265a576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b61266386614f92565b939a9299509097509550909350915050565b6000546001600160a01b031633146126d4576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b828114612728576040805162461bcd60e51b815260206004820181905260248201527f7472616e736d6974746572732e73697a6520213d207061796565732e73697a65604482015290519081900360640190fd5b60005b838110156128a757600085858381811061274157fe5b905060200201356001600160a01b03169050600084848481811061276157fe5b6001600160a01b0385811660009081526007602090815260409091205492029390930135831693509091169050801580806127ad5750826001600160a01b0316826001600160a01b0316145b6127fe576040805162461bcd60e51b815260206004820152601160248201527f706179656520616c726561647920736574000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03848116600090815260076020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168583169081179091559083161461289757826001600160a01b0316826001600160a01b0316856001600160a01b03167f78af32efdcad432315431e9b03d27e6cd98fb79c405fdc5af7c1714d9c0f75b360405160405180910390a45b50506001909201915061272b9050565b5050505050565b6000546001600160a01b0316331461290d576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b602f546001600160a01b0390811690821681146112d857602f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03848116918217909255604080519284168352602083019190915280517f27b89aede8b560578baaa25ee5ce3852c5eecad1e114b941bbd89e1eb4bae6349281900390910190a15050565b6000546001600160a01b031633146129fb576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b612290816150dd565b6001600160a01b03818116600090815260086020526040902054163314612a72576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792070726f706f736564207061796565732063616e2061636365707400604482015290519081900360640190fd5b6001600160a01b0381811660008181526007602090815260408083208054337fffffffffffffffffffffffff000000000000000000000000000000000000000080831682179093556008909452828520805490921690915590519416939092849290917f78af32efdcad432315431e9b03d27e6cd98fb79c405fdc5af7c1714d9c0f75b39190a45050565b6000612b40336000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611df992505050565b612b91576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b611e1b82615176565b6000612bdd336000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611df992505050565b612c2e576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b611e1b826151ac565b6004546000546001600160a01b039182169116331480612d2f5750604080517f6b14daf800000000000000000000000000000000000000000000000000000000815233600482018181526024830193845236604484018190526001600160a01b03861694636b14daf8946000939190606401848480828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016909201965060209550909350505081840390508186803b158015612d0257600080fd5b505afa158015612d16573d6000803e3d6000fd5b505050506040513d6020811015612d2c57600080fd5b50515b612d80576040805162461bcd60e51b815260206004820181905260248201527f4f6e6c79206f776e65722662696c6c696e6741646d696e2063616e2063616c6c604482015290519081900360640190fd5b612d886146fe565b612d958686868686615201565b505050505050565b6000546001600160a01b0316331480612e95575060048054604080517f6b14daf8000000000000000000000000000000000000000000000000000000008152339381018481526024820192835236604483018190526001600160a01b0390941694636b14daf8949093600093919291606401848480828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016909201965060209550909350505081840390508186803b158015612e6857600080fd5b505afa158015612e7c573d6000803e3d6000fd5b505050506040513d6020811015612e9257600080fd5b50515b612ee6576040805162461bcd60e51b815260206004820181905260248201527f4f6e6c79206f776e65722662696c6c696e6741646d696e2063616e2063616c6c604482015290519081900360640190fd5b6000612ef061537b565b600354604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290519293506000926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015612f5a57600080fd5b505afa158015612f6e573d6000803e3d6000fd5b505050506040513d6020811015612f8457600080fd5b5051905081811015612fdd576040805162461bcd60e51b815260206004820152601460248201527f696e73756666696369656e742062616c616e6365000000000000000000000000604482015290519081900360640190fd5b6003546001600160a01b031663a9059cbb85612ffb8585038761554b565b6040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561304157600080fd5b505af1158015613055573d6000803e3d6000fd5b505050506040513d602081101561306b57600080fd5b50516130be576040805162461bcd60e51b815260206004820152601260248201527f696e73756666696369656e742066756e64730000000000000000000000000000604482015290519081900360640190fd5b50505050565b60005a90506130d7888888888888615562565b361461312a576040805162461bcd60e51b815260206004820152601960248201527f7472616e736d6974206d65737361676520746f6f206c6f6e6700000000000000604482015290519081900360640190fd5b613132615b59565b6040805160808082018352602b549081901b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000168252700100000000000000000000000000000000810464ffffffffff1660208301527501000000000000000000000000000000000000000000810460ff169282019290925276010000000000000000000000000000000000000000000090910463ffffffff166060808301919091529082526000908a908a908110156131eb57600080fd5b81359160208101359181019060608101604082013564010000000081111561321257600080fd5b82018360208201111561322457600080fd5b8035906020019184602083028401116401000000008311171561324657600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050505060408801525050506080840182905283515190925060589190911b907fffffffffffffffffffffffffffffffff0000000000000000000000000000000080831691161461330d576040805162461bcd60e51b815260206004820152601560248201527f636f6e666967446967657374206d69736d617463680000000000000000000000604482015290519081900360640190fd5b608083015183516020015164ffffffffff808316911610613375576040805162461bcd60e51b815260206004820152600c60248201527f7374616c65207265706f72740000000000000000000000000000000000000000604482015290519081900360640190fd5b83516040015160ff1689116133d1576040805162461bcd60e51b815260206004820152601560248201527f6e6f7420656e6f756768207369676e6174757265730000000000000000000000604482015290519081900360640190fd5b601f891115613427576040805162461bcd60e51b815260206004820152601360248201527f746f6f206d616e79207369676e61747572657300000000000000000000000000604482015290519081900360640190fd5b86891461347b576040805162461bcd60e51b815260206004820152601e60248201527f7369676e617475726573206f7574206f6620726567697374726174696f6e0000604482015290519081900360640190fd5b601f84604001515111156134d6576040805162461bcd60e51b815260206004820152601e60248201527f6e756d206f62736572766174696f6e73206f7574206f6620626f756e64730000604482015290519081900360640190fd5b83600001516040015160020260ff168460400151511161353d576040805162461bcd60e51b815260206004820152601e60248201527f746f6f206665772076616c75657320746f207472757374206d656469616e0000604482015290519081900360640190fd5b8867ffffffffffffffff8111801561355457600080fd5b506040519080825280601f01601f19166020018201604052801561357f576020820181803683370190505b50606085015260005b60ff81168a11156135f057868160ff16602081106135a257fe5b1a60f81b85606001518260ff16815181106135b957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101613588565b5083604001515167ffffffffffffffff8111801561360d57600080fd5b506040519080825280601f01601f191660200182016040528015613638576020820181803683370190505b506020850152613646615b8d565b60005b8560400151518160ff16101561374c576000858260ff166020811061366a57fe5b1a90508281601f811061367957fe5b6020020151156136d0576040805162461bcd60e51b815260206004820152601760248201527f6f6273657276657220696e646578207265706561746564000000000000000000604482015290519081900360640190fd5b6001838260ff16601f81106136e157fe5b91151560209283029190910152869060ff84169081106136fd57fe5b1a60f81b87602001518360ff168151811061371457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050600101613649565b503360009081526028602090815260408083208151808301909252805460ff8082168452929391929184019161010090910416600281111561378a57fe5b600281111561379557fe5b90525090506002816020015160028111156137ac57fe5b1480156137e05750602a816000015160ff16815481106137c857fe5b6000918252602090912001546001600160a01b031633145b613831576040805162461bcd60e51b815260206004820152601860248201527f756e617574686f72697a6564207472616e736d69747465720000000000000000604482015290519081900360640190fd5b5050835164ffffffffff90911660209091015250506040516000908a908a9080838380828437604051920182900390912094506138729350615b8d92505050565b61387a615bac565b60005b89811015613a915760006001858760600151848151811061389a57fe5b60209101015160f81c601b018e8e868181106138b257fe5b905060200201358d8d878181106138c557fe5b9050602002013560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015613920573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101516001600160a01b03811660009081526028602090815290849020838501909452835460ff8082168552929650929450840191610100900416600281111561398d57fe5b600281111561399857fe5b90525092506001836020015160028111156139af57fe5b14613a01576040805162461bcd60e51b815260206004820152601e60248201527f61646472657373206e6f7420617574686f72697a656420746f207369676e0000604482015290519081900360640190fd5b8251849060ff16601f8110613a1257fe5b602002015115613a69576040805162461bcd60e51b815260206004820152601460248201527f6e6f6e2d756e69717565207369676e6174757265000000000000000000000000604482015290519081900360640190fd5b600184846000015160ff16601f8110613a7e57fe5b911515602090920201525060010161387d565b5050505060005b600182604001515103811015613b4257600082604001518260010181518110613abd57fe5b602002602001015160170b83604001518381518110613ad857fe5b602002602001015160170b1315905080613b39576040805162461bcd60e51b815260206004820152601760248201527f6f62736572766174696f6e73206e6f7420736f72746564000000000000000000604482015290519081900360640190fd5b50600101613a98565b50604081015180516000919060028104908110613b5b57fe5b602002602001015190508060170b7f000000000000000000000000000000000000000000000000000000000000000060170b13158015613bc157507f000000000000000000000000000000000000000000000000000000000000000060170b8160170b13155b613c12576040805162461bcd60e51b815260206004820152601e60248201527f6d656469616e206973206f7574206f66206d696e2d6d61782072616e67650000604482015290519081900360640190fd5b81516060908101805163ffffffff60019091018116909152604080518082018252601785810b80835267ffffffffffffffff42811660208086019182528a5189015188166000908152602c82528781209651875493519094167801000000000000000000000000000000000000000000000000029390950b77ffffffffffffffffffffffffffffffffffffffffffffffff9081167fffffffffffffffff0000000000000000000000000000000000000000000000009093169290921790911691909117909355875186015184890151848a01516080808c015188519586523386890181905291860181905260a0988601898152845199870199909952835194909916997ff6a97944f31ea060dfde0566e4167c1a1082551e64b60ecb14d599a9d023d451998c999298949793969095909492939185019260c086019289820192909102908190849084905b83811015613d75578181015183820152602001613d5d565b50505050905001838103825285818151815260200191508051906020019080838360005b83811015613db1578181015183820152602001613d99565b50505050905090810190601f168015613dde5780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390a281516060015160408051428152905160009263ffffffff16917f0109fc6f55cf40689f02fbaad7af7fe7bbac8a3d2186600afc7d3e10cac60271919081900360200190a381600001516060015163ffffffff168160170b7f0559884fd3a460db3073b7fc896cc77986f16e378210ded43186175bf646fc5f426040518082815260200191505060405180910390a3613e938260000151606001518260170b61557a565b5080518051602b8054602084015160408501516060909501517fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921660809490941c939093177fffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000064ffffffffff90941693909302929092177fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16750100000000000000000000000000000000000000000060ff90941693909302929092177fffffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffff1676010000000000000000000000000000000000000000000063ffffffff92831602179091558210613fb457fe5b613fc28282602001516156ba565b505050505050505050565b600354604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009283926001600160a01b03909116916370a0823191602480820192602092909190829003018186803b15801561403657600080fd5b505afa15801561404a573d6000803e3d6000fd5b505050506040513d602081101561406057600080fd5b50519050600061406e61537b565b90910391505090565b60315460ff1681565b6001600160a01b03811660009081526028602090815260408083208151808301909252805460ff8082168452859484019161010090041660028111156140c257fe5b60028111156140cd57fe5b90525090506000816020015160028111156140e457fe5b14156140f4576000915050610f0e565b60016005826000015160ff16601f811061410a57fe5b601091828204019190066002029054906101000a900461ffff1603915050919050565b600080808080333214614187576040805162461bcd60e51b815260206004820152601460248201527f4f6e6c792063616c6c61626c6520627920454f41000000000000000000000000604482015290519081900360640190fd5b5050602b5463ffffffff760100000000000000000000000000000000000000000000820481166000908152602c6020526040902054608083901b96700100000000000000000000000000000000909304600881901c909216955064ffffffffff9091169350601781900b92507801000000000000000000000000000000000000000000000000900467ffffffffffffffff1690565b6003546001600160a01b031690565b6000546001600160a01b0316331461428a576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b60408051808201909152602e546001600160a01b038082168084527401000000000000000000000000000000000000000090920463ffffffff16602084015284161415806142e857508163ffffffff16816020015163ffffffff1614155b156143bb576040805180820182526001600160a01b0385811680835263ffffffff8681166020948501819052602e80547fffffffffffffffffffffffff00000000000000000000000000000000000000001684177fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000008302179055865187860151875193168352948201528451919493909216927fb04e3a37abe9c0fcdfebdeae019a8e2b12ddf53f5d55ffb0caccc1bedaca1541928290030190a35b505050565b6001600160a01b0382811660009081526007602052604090205416331461442e576040805162461bcd60e51b815260206004820152601d60248201527f6f6e6c792063757272656e742070617965652063616e20757064617465000000604482015290519081900360640190fd5b336001600160a01b038216141561448c576040805162461bcd60e51b815260206004820152601760248201527f63616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015290519081900360640190fd5b6001600160a01b03808316600090815260086020526040902080548383167fffffffffffffffffffffffff0000000000000000000000000000000000000000821681179092559091169081146143bb576040516001600160a01b038084169133918616907f84f7c7c80bb8ed2279b4aab5f61cd05e6374073d38f46d7f32de8c30e9e3836790600090a4505050565b6000546001600160a01b0316331461457a576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000546001600160a01b03163314614642576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b61229081615907565b6000806000806000614694336000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611df992505050565b6146e5576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6146ed615996565b945094509450945094509091929394565b6040805160a08101825260025463ffffffff80821683526401000000008204811660208401526801000000000000000082048116838501526c0100000000000000000000000082048116606084015270010000000000000000000000000000000090910416608082015260035482516103e081019384905291926001600160a01b0390911691600091600590601f908285855b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411614791575050604080516103e0810191829052959650600095945060099350601f9250905082845b8154815260200190600101908083116147eb57505050505090506000602a80548060200260200160405190810160405280929190818152602001828054801561485d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161483f575b5050505050905060005b8151811015614a9257600060018483601f811061488057fe5b6020020151039050600060018684601f811061489857fe5b60200201510361ffff169050600082896060015163ffffffff168302633b9aca00020190506000811115614a87576000600760008787815181106148d857fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03169050886001600160a01b031663a9059cbb82846040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561496d57600080fd5b505af1158015614981573d6000803e3d6000fd5b505050506040513d602081101561499757600080fd5b50516149ea576040805162461bcd60e51b815260206004820152601260248201527f696e73756666696369656e742066756e64730000000000000000000000000000604482015290519081900360640190fd5b60018886601f81106149f857fe5b61ffff909216602092909202015260018786601f8110614a1457fe5b602002018181525050886001600160a01b0316816001600160a01b0316878781518110614a3d57fe5b60200260200101516001600160a01b03167fd0b1dac935d85bd54cf0a33b0d41d39f8cf53a968465fc7ea2377526b8ac712c856040518082815260200191505060405180910390a4505b505050600101614867565b50614aa0600584601f615bc3565b50612d95600983601f615c59565b602b54760100000000000000000000000000000000000000000000900463ffffffff166000908152602c6020526040902054601790810b900b90565b6001600160a01b03811660009081526028602090815260408083208151808301909252805460ff80821684529293919291840191610100909104166002811115614b3057fe5b6002811115614b3b57fe5b90525090506000614b4b83610dc8565b905080156143bb576001600160a01b0380841660009081526007602090815260408083205460035482517fa9059cbb000000000000000000000000000000000000000000000000000000008152918616600483018190526024830188905292519295169363a9059cbb9360448084019491939192918390030190829087803b158015614bd657600080fd5b505af1158015614bea573d6000803e3d6000fd5b505050506040513d6020811015614c0057600080fd5b5051614c53576040805162461bcd60e51b815260206004820152601260248201527f696e73756666696369656e742066756e64730000000000000000000000000000604482015290519081900360640190fd5b60016005846000015160ff16601f8110614c6957fe5b601091828204019190066002026101000a81548161ffff021916908361ffff16021790555060016009846000015160ff16601f8110614ca457fe5b01556003546040805184815290516001600160a01b039283169284811692908816917fd0b1dac935d85bd54cf0a33b0d41d39f8cf53a968465fc7ea2377526b8ac712c9181900360200190a450505050565b60008a8a8a8a8a8a8a8a8a8a604051602001808b6001600160a01b031681526020018a67ffffffffffffffff16815260200180602001806020018760ff1681526020018667ffffffffffffffff1681526020018060200184810384528c8c82818152602001925060200280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910185810384528a8152602090810191508b908b0280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910185810383528681526020019050868680828437600081840152601f19601f8201169050808301925050509d50505050505050505050505050506040516020818303038152906040528051906020012090509a9950505050505050505050565b602b54760100000000000000000000000000000000000000000000900463ffffffff1690565b6001600160a01b03821660009081526032602052604081205460ff1680611e1857505060315460ff161592915050565b60308054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156120d55780601f10614f0b576101008083540402835291602001916120d5565b820191906000526020600020905b815481529060010190602001808311614f1957509395945050505050565b602b54760100000000000000000000000000000000000000000000900463ffffffff166000908152602c60205260409020547801000000000000000000000000000000000000000000000000900467ffffffffffffffff1690565b600080600080600063ffffffff8669ffffffffffffffffffff1611156040518060400160405280600f81526020017f4e6f20646174612070726573656e7400000000000000000000000000000000008152509061506d5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561503257818101518382015260200161501a565b50505050905090810190601f16801561505f5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5050505063ffffffff83166000908152602c6020908152604091829020825180840190935254601781810b810b810b808552780100000000000000000000000000000000000000000000000090920467ffffffffffffffff1693909201839052949594900b939092508291508490565b6001600160a01b03811660009081526032602052604090205460ff16612290576001600160a01b03811660008181526032602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055815192835290517f87286ad1f399c8e82bf0c4ef4fcdc570ea2e1e92176e5c848b6413545b885db49281900390910190a150565b600063ffffffff82111561518c57506000610f0e565b5063ffffffff166000908152602c6020526040902054601790810b900b90565b600063ffffffff8211156151c257506000610f0e565b5063ffffffff166000908152602c60205260409020547801000000000000000000000000000000000000000000000000900467ffffffffffffffff1690565b6040805160a0808201835263ffffffff88811680845288821660208086018290528984168688018190528985166060808901829052958a166080988901819052600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001687177fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff166401000000008702177fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff16680100000000000000008502177fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff166c010000000000000000000000008402177fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff16700100000000000000000000000000000000830217905589519586529285019390935283880152928201529283015291517fd0d9486a2c673e2a4b57fc82e4c8a556b3e2b82dd5db07e2c04a920ca0f469b6929181900390910190a15050505050565b604080516103e0810191829052600091829190600590601f908285855b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116153985790505050505050905060005b601f8110156154085760018282601f81106153f157fe5b60200201510361ffff1692909201916001016153da565b506040805160a08101825260025463ffffffff8082168352640100000000820481166020808501919091526801000000000000000083048216848601526c0100000000000000000000000083048216606085018190527001000000000000000000000000000000009093049091166080840152602a805485518184028101840190965280865296909202633b9aca00029592936000939092918301828280156154da57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116154bc575b5050604080516103e0810191829052949550600094935060099250601f915082845b8154815260200190600101908083116154fc575050505050905060005b82518110156155435760018282601f811061553057fe5b6020020151039590950194600101615519565b505050505090565b60008183101561555c575081611e1b565b50919050565b602083810286019082020160e4019695505050505050565b60408051808201909152602e546001600160a01b0381168083527401000000000000000000000000000000000000000090910463ffffffff1660208301526155c257506112d8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830163ffffffff8181166000818152602c602090815260408083205487518884015183517fbeed9b510000000000000000000000000000000000000000000000000000000081526004810197909752601792830b90920b602487018190528b88166044880152606487018b9052925192966001600160a01b039091169563beed9b51959290911693608480830194919391928390030190829088803b15801561568b57600080fd5b5087f1935050505080156156b157506040513d60208110156156ac57600080fd5b505160015b612d95576128a7565b3360009081526028602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156156f757fe5b600281111561570257fe5b9052506040805160a08101825260025463ffffffff80821683526401000000008204811660208401526801000000000000000082048116838501526c0100000000000000000000000082048116606084015270010000000000000000000000000000000090910416608082015281516103e0810192839052929350916157d291859190600590601f90826000855b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116157905790505050505050615a1a565b6157e090600590601f615bc3565b506002826020015160028111156157f357fe5b14615845576040805162461bcd60e51b815260206004820181905260248201527f73656e7420627920756e64657369676e61746564207472616e736d6974746572604482015290519081900360640190fd5b600061586c633b9aca003a04836020015163ffffffff16846000015163ffffffff16615a8f565b90506010360260005a9050600061588b8863ffffffff16858585615ab5565b6fffffffffffffffffffffffffffffffff1690506000620f4240866040015163ffffffff168302816158b957fe5b049050856080015163ffffffff16633b9aca0002816009896000015160ff16601f81106158e257fe5b015401016009886000015160ff16601f81106158fa57fe5b0155505050505050505050565b6004546001600160a01b0390811690821681146112d857600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03848116918217909255604080519284168352602083019190915280517f793cb73064f3c8cde7e187ae515511e6e56d1ee89bf08b82fa60fb70f8d489129281900390910190a15050565b602b54760100000000000000000000000000000000000000000000900463ffffffff166000818152602c6020908152604091829020825180840190935254601781810b810b810b808552780100000000000000000000000000000000000000000000000090920467ffffffffffffffff1693909201839052929392900b9181908490565b615a22615b8d565b60005b8351811015615a87576000848281518110615a3c57fe5b016020015160f81c9050615a618482601f8110615a5557fe5b60200201516001615b41565b848260ff16601f8110615a7057fe5b61ffff909216602092909202015250600101615a25565b509092915050565b60008383811015615aa257600285850304015b615aac818461554b565b95945050505050565b600081851015615b0c576040805162461bcd60e51b815260206004820181905260248201527f6761734c6566742063616e6e6f742065786365656420696e697469616c476173604482015290519081900360640190fd5b818503830161179301633b9aca00858202026fffffffffffffffffffffffffffffffff8110615b3757fe5b9695505050505050565b6000611e188261ffff168461ffff160161ffff61554b565b6040518060a00160405280615b6c615c87565b81526060602082018190526040820181905280820152600060809091015290565b604051806103e00160405280601f906020820280368337509192915050565b604080518082019091526000808252602082015290565b600283019183908215615c495791602002820160005b83821115615c1957835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302615bd9565b8015615c475782816101000a81549061ffff0219169055600201602081600101049283019260010302615c19565b505b50615c55929150615cae565b5090565b82601f8101928215615c49579160200282015b82811115615c49578251825591602001919060010190615c6c565b60408051608081018252600080825260208201819052918101829052606081019190915290565b5b80821115615c555760008155600101615caf56fe416363657373436f6e74726f6c6c65644f6666636861696e41676772656761746f7220332e302e306f7261636c6520616464726573736573206f7574206f6620726567697374726174696f6ea2646970667358221220757bff216f6d81152fcaa510caac9632619adc3b29bcb61ba73c0af8d453fb2864736f6c6343000706003300000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000006f284c80000000000000000000000000000000000000000000000000000000000b688840000000000000000000000000000000000000000000000000000000004473318000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca00000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000002540be4000000000000000000000000009db83cef9f68b63989e4e82d65d549e7ff2acda9000000000000000000000000641b698ad1c6e503470520b0eecb472c0589dfe60000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000095a434e202f205553440000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061030a5760003560e01c80638e0566de1161019c578063c1075329116100ee578063e76d516811610097578063f2fde38b11610071578063f2fde38b14610cb6578063fbffd2c114610cdc578063feaf968c14610d025761030a565b8063e76d516814610c4e578063eb45716314610c56578063eb5dcd6c14610c885761030a565b8063dc7f0124116100c8578063dc7f012414610b9f578063e4902f8214610ba7578063e5fe457714610be45761030a565b8063c107532914610a57578063c980753914610a83578063d09dc33914610b975761030a565b80639e3ceeab11610150578063b5ab58dc1161012a578063b5ab58dc146109d8578063b633620c146109f5578063bd82470614610a125761030a565b80639e3ceeab14610966578063a118f2491461098c578063b121e147146109b25761030a565b8063996e829811610181578063996e8298146108295780639a6fc8f5146108315780639c849b30146108a45761030a565b80638e0566de146107d257806398e5b12a146108025761030a565b80636b14daf81161026057806381411834116102095780638823da6c116101e35780638823da6c1461077e5780638ac28d5a146107a45780638da5cb5b146107ca5761030a565b806381411834146106cd57806381ff7048146107255780638205bf6a146107765761030a565b80637284e4161161023a5780637284e416146106b557806379ba5097146106bd5780638038e4a1146106c55761030a565b80636b14daf8146105bf57806370da2f671461068957806370efdf2d146106915761030a565b8063313ce567116102c257806354fd4d501161029c57806354fd4d5014610482578063585aa7de1461048a578063668a0f02146105b75761030a565b8063313ce5671461042e5780634fb174701461044c57806350d25bcd1461047a5761030a565b8063181f5a77116102f3578063181f5a771461035157806322adbc78146103ce57806329937268146103ed5761030a565b80630a7569831461030f5780630eafb25b14610319575b600080fd5b610317610d0a565b005b61033f6004803603602081101561032f57600080fd5b50356001600160a01b0316610dc8565b60408051918252519081900360200190f35b610359610f13565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561039357818101518382015260200161037b565b50505050905090810190601f1680156103c05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103d6610f33565b6040805160179290920b8252519081900360200190f35b6103f5610f57565b6040805163ffffffff96871681529486166020860152928516848401529084166060840152909216608082015290519081900360a00190f35b610436610fd4565b6040805160ff9092168252519081900360200190f35b6103176004803603604081101561046257600080fd5b506001600160a01b0381358116916020013516610ff8565b61033f6112dc565b61033f61137d565b610317600480360360a08110156104a057600080fd5b8101906020810181356401000000008111156104bb57600080fd5b8201836020820111156104cd57600080fd5b803590602001918460208302840111640100000000831117156104ef57600080fd5b91939092909160208101903564010000000081111561050d57600080fd5b82018360208201111561051f57600080fd5b8035906020019184602083028401116401000000008311171561054157600080fd5b9193909260ff8335169267ffffffffffffffff60208201351692919060608101906040013564010000000081111561057857600080fd5b82018360208201111561058a57600080fd5b803590602001918460018302840111640100000000831117156105ac57600080fd5b509092509050611382565b61033f611d5d565b610675600480360360408110156105d557600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561060057600080fd5b82018360208201111561061257600080fd5b8035906020019184600183028401116401000000008311171561063457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611df9945050505050565b604080519115158252519081900360200190f35b6103d6611e21565b610699611e45565b604080516001600160a01b039092168252519081900360200190f35b610359611e54565b610317611ef0565b610317611fbe565b6106d561207d565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156107115781810151838201526020016106f9565b505050509050019250505060405180910390f35b61072d6120df565b6040805163ffffffff94851681529290931660208301527fffffffffffffffffffffffffffffffff00000000000000000000000000000000168183015290519081900360600190f35b61033f612100565b6103176004803603602081101561079457600080fd5b50356001600160a01b031661219c565b610317600480360360208110156107ba57600080fd5b50356001600160a01b0316612293565b61069961230a565b6107da612319565b604080516001600160a01b03909316835263ffffffff90911660208301528051918290030190f35b61080a61235d565b6040805169ffffffffffffffffffff9092168252519081900360200190f35b6106996125b1565b61085a6004803603602081101561084757600080fd5b503569ffffffffffffffffffff166125c0565b604051808669ffffffffffffffffffff1681526020018581526020018481526020018381526020018269ffffffffffffffffffff1681526020019550505050505060405180910390f35b610317600480360360408110156108ba57600080fd5b8101906020810181356401000000008111156108d557600080fd5b8201836020820111156108e757600080fd5b8035906020019184602083028401116401000000008311171561090957600080fd5b91939092909160208101903564010000000081111561092757600080fd5b82018360208201111561093957600080fd5b8035906020019184602083028401116401000000008311171561095b57600080fd5b509092509050612675565b6103176004803603602081101561097c57600080fd5b50356001600160a01b03166128ae565b610317600480360360208110156109a257600080fd5b50356001600160a01b031661299c565b610317600480360360208110156109c857600080fd5b50356001600160a01b0316612a04565b61033f600480360360208110156109ee57600080fd5b5035612afd565b61033f60048036036020811015610a0b57600080fd5b5035612b9a565b610317600480360360a0811015610a2857600080fd5b5063ffffffff813581169160208101358216916040820135811691606081013582169160809091013516612c37565b61031760048036036040811015610a6d57600080fd5b506001600160a01b038135169060200135612d9d565b61031760048036036080811015610a9957600080fd5b810190602081018135640100000000811115610ab457600080fd5b820183602082011115610ac657600080fd5b80359060200191846001830284011164010000000083111715610ae857600080fd5b919390929091602081019035640100000000811115610b0657600080fd5b820183602082011115610b1857600080fd5b80359060200191846020830284011164010000000083111715610b3a57600080fd5b919390929091602081019035640100000000811115610b5857600080fd5b820183602082011115610b6a57600080fd5b80359060200191846020830284011164010000000083111715610b8c57600080fd5b9193509150356130c4565b61033f613fcd565b610675614077565b610bcd60048036036020811015610bbd57600080fd5b50356001600160a01b0316614080565b6040805161ffff9092168252519081900360200190f35b610bec61412d565b604080517fffffffffffffffffffffffffffffffff00000000000000000000000000000000909616865263ffffffff909416602086015260ff9092168484015260170b606084015267ffffffffffffffff166080830152519081900360a00190f35b61069961421c565b61031760048036036040811015610c6c57600080fd5b5080356001600160a01b0316906020013563ffffffff1661422b565b61031760048036036040811015610c9e57600080fd5b506001600160a01b03813581169160200135166143c0565b61031760048036036020811015610ccc57600080fd5b50356001600160a01b031661451b565b61031760048036036020811015610cf257600080fd5b50356001600160a01b03166145e3565b61085a61464b565b6000546001600160a01b03163314610d69576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b60315460ff1615610dc657603180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f3be8a977a014527b50ae38adda80b56911c267328965c98ddc385d248f53963890600090a15b565b6001600160a01b03811660009081526028602090815260408083208151808301909252805460ff808216845285948401916101009004166002811115610e0a57fe5b6002811115610e1557fe5b9052509050600081602001516002811115610e2c57fe5b1415610e3c576000915050610f0e565b6040805160a08101825260025463ffffffff80821683526401000000008204811660208401526801000000000000000082048116938301939093526c01000000000000000000000000810483166060830181905270010000000000000000000000000000000090910490921660808201528251909160009160019060059060ff16601f8110610ec757fe5b601091828204019190066002029054906101000a900461ffff160361ffff1602633b9aca0002905060016009846000015160ff16601f8110610f0557fe5b01540301925050505b919050565b6060604051806060016040528060288152602001615cc460289139905090565b7f00000000000000000000000000000000000000000000000000000000000186a081565b6040805160a08101825260025463ffffffff808216808452640100000000830482166020850181905268010000000000000000840483169585018690526c01000000000000000000000000840483166060860181905270010000000000000000000000000000000090940490921660809094018490529490939290565b7f000000000000000000000000000000000000000000000000000000000000000881565b6000546001600160a01b03163314611057576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b6003546001600160a01b0390811690831681141561107557506112d8565b604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b1580156110d457600080fd5b505afa1580156110e8573d6000803e3d6000fd5b505050506040513d60208110156110fe57600080fd5b5061110990506146fe565b6000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561115857600080fd5b505afa15801561116c573d6000803e3d6000fd5b505050506040513d602081101561118257600080fd5b5051604080517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301526024820184905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b1580156111f357600080fd5b505af1158015611207573d6000803e3d6000fd5b505050506040513d602081101561121d57600080fd5b5051611270576040805162461bcd60e51b815260206004820152601f60248201527f7472616e736665722072656d61696e696e672066756e6473206661696c656400604482015290519081900360640190fd5b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0386811691821790925560405190918416907f4966a50c93f855342ccf6c5c0d358b85b91335b2acedc7da0932f691f351711a90600090a350505b5050565b600061131f336000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611df992505050565b611370576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b611378614aae565b905090565b600481565b868560ff8616601f8311156113de576040805162461bcd60e51b815260206004820152601060248201527f746f6f206d616e79207369676e65727300000000000000000000000000000000604482015290519081900360640190fd5b60008111611433576040805162461bcd60e51b815260206004820152601a60248201527f7468726573686f6c64206d75737420626520706f736974697665000000000000604482015290519081900360640190fd5b8183146114715760405162461bcd60e51b8152600401808060200182810382526024815260200180615cec6024913960400191505060405180910390fd5b8060030283116114c8576040805162461bcd60e51b815260206004820181905260248201527f6661756c74792d6f7261636c65207468726573686f6c6420746f6f2068696768604482015290519081900360640190fd5b6000546001600160a01b03163314611527576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b602954156116cb57602980547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101916000918390811061156457fe5b6000918252602082200154602a80546001600160a01b039092169350908490811061158b57fe5b6000918252602090912001546001600160a01b031690506115ab81614aea565b6001600160a01b0380831660009081526028602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009081169091559284168252902080549091169055602980548061160757fe5b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055019055602a80548061166a57fe5b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905501905550611527915050565b60005b8a811015611ad9576000602860008e8e858181106116e857fe5b602090810292909201356001600160a01b031683525081019190915260400160002054610100900460ff16600281111561171e57fe5b14611770576040805162461bcd60e51b815260206004820152601760248201527f7265706561746564207369676e65722061646472657373000000000000000000604482015290519081900360640190fd5b6040805180820190915260ff8216815260016020820152602860008e8e8581811061179757fe5b602090810292909201356001600160a01b031683525081810192909252604001600020825181547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff9091161780825591830151909182907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010083600281111561182257fe5b02179055506000915060079050818c8c8581811061183c57fe5b6001600160a01b03602091820293909301358316845283019390935260409091016000205416919091141590506118ba576040805162461bcd60e51b815260206004820152601160248201527f7061796565206d75737420626520736574000000000000000000000000000000604482015290519081900360640190fd5b6000602860008c8c858181106118cc57fe5b602090810292909201356001600160a01b031683525081019190915260400160002054610100900460ff16600281111561190257fe5b14611954576040805162461bcd60e51b815260206004820152601c60248201527f7265706561746564207472616e736d6974746572206164647265737300000000604482015290519081900360640190fd5b6040805180820190915260ff8216815260026020820152602860008c8c8581811061197b57fe5b602090810292909201356001600160a01b031683525081810192909252604001600020825181547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff9091161780825591830151909182907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100836002811115611a0657fe5b021790555090505060298c8c83818110611a1c57fe5b835460018101855560009485526020948590200180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b039590920293909301359390931692909217905550602a8a8a83818110611a7e57fe5b835460018181018655600095865260209586902090910180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03969093029490940135949094161790915550016116ce565b50602b805460ff89167501000000000000000000000000000000000000000000027fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff909116179055602d80544363ffffffff9081166401000000009081027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff84161780831660010183167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000909116179384905590910481169116611ba530828f8f8f8f8f8f8f8f614cf6565b602b60000160006101000a8154816fffffffffffffffffffffffffffffffff021916908360801c02179055506000602b60000160106101000a81548164ffffffffff021916908364ffffffffff1602179055507f25d719d88a4512dd76c7442b910a83360845505894eb444ef299409e180f8fb982828f8f8f8f8f8f8f8f604051808b63ffffffff1681526020018a67ffffffffffffffff16815260200180602001806020018760ff1681526020018667ffffffffffffffff1681526020018060200184810384528c8c82818152602001925060200280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910185810384528a8152602090810191508b908b0280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910185810383528681526020019050868680828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039f50909d5050505050505050505050505050a150505050505050505050505050565b6000611da0336000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611df992505050565b611df1576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b611378614e36565b6000611e058383614e5c565b80611e1857506001600160a01b03831632145b90505b92915050565b7f00000000000000000000000000000000000000000000000000000002540be40081565b602f546001600160a01b031690565b6060611e97336000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611df992505050565b611ee8576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b611378614e8c565b6001546001600160a01b03163314611f4f576040805162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015290519081900360640190fd5b60008054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000546001600160a01b0316331461201d576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b60315460ff16610dc657603180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517faebf329500988c6488a0074e5a0a9ff304561fc5c6fc877aeb1d59c8282c348090600090a1565b6060602a8054806020026020016040519081016040528092919081815260200182805480156120d557602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116120b7575b5050505050905090565b602d54602b5463ffffffff808316926401000000009004169060801b909192565b6000612143336000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611df992505050565b612194576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b611378614f37565b6000546001600160a01b031633146121fb576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b6001600160a01b03811660009081526032602052604090205460ff1615612290576001600160a01b03811660008181526032602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055815192835290517f3d68a6fce901d20453d1a7aa06bf3950302a735948037deb182a8db66df2a0d19281900390910190a15b50565b6001600160a01b03818116600090815260076020526040902054163314612301576040805162461bcd60e51b815260206004820152601760248201527f4f6e6c792070617965652063616e207769746864726177000000000000000000604482015290519081900360640190fd5b61229081614aea565b6000546001600160a01b031681565b60408051808201909152602e546001600160a01b0381168083527401000000000000000000000000000000000000000090910463ffffffff16602090920182905291565b600080546001600160a01b03163314806124575750602f54604080517f6b14daf800000000000000000000000000000000000000000000000000000000815233600482018181526024830193845236604484018190526001600160a01b0390951694636b14daf894929360009391929190606401848480828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016909201965060209550909350505081840390508186803b15801561242a57600080fd5b505afa15801561243e573d6000803e3d6000fd5b505050506040513d602081101561245457600080fd5b50515b6124a8576040805162461bcd60e51b815260206004820152601d60248201527f4f6e6c79206f776e6572267265717565737465722063616e2063616c6c000000604482015290519081900360640190fd5b6040805160808082018352602b549081901b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000016808352700100000000000000000000000000000000820464ffffffffff81166020808601919091527501000000000000000000000000000000000000000000840460ff9081168688015276010000000000000000000000000000000000000000000090940463ffffffff9081166060808801919091528751948552600884901c909116918401919091529216818501529251919233927f3ea16a923ff4b1df6526e854c9e3a995c43385d70e73359e10623c74f0b52037929181900390910190a2806060015160010163ffffffff1691505090565b6004546001600160a01b031690565b6000806000806000612609336000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611df992505050565b61265a576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b61266386614f92565b939a9299509097509550909350915050565b6000546001600160a01b031633146126d4576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b828114612728576040805162461bcd60e51b815260206004820181905260248201527f7472616e736d6974746572732e73697a6520213d207061796565732e73697a65604482015290519081900360640190fd5b60005b838110156128a757600085858381811061274157fe5b905060200201356001600160a01b03169050600084848481811061276157fe5b6001600160a01b0385811660009081526007602090815260409091205492029390930135831693509091169050801580806127ad5750826001600160a01b0316826001600160a01b0316145b6127fe576040805162461bcd60e51b815260206004820152601160248201527f706179656520616c726561647920736574000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03848116600090815260076020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168583169081179091559083161461289757826001600160a01b0316826001600160a01b0316856001600160a01b03167f78af32efdcad432315431e9b03d27e6cd98fb79c405fdc5af7c1714d9c0f75b360405160405180910390a45b50506001909201915061272b9050565b5050505050565b6000546001600160a01b0316331461290d576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b602f546001600160a01b0390811690821681146112d857602f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03848116918217909255604080519284168352602083019190915280517f27b89aede8b560578baaa25ee5ce3852c5eecad1e114b941bbd89e1eb4bae6349281900390910190a15050565b6000546001600160a01b031633146129fb576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b612290816150dd565b6001600160a01b03818116600090815260086020526040902054163314612a72576040805162461bcd60e51b815260206004820152601f60248201527f6f6e6c792070726f706f736564207061796565732063616e2061636365707400604482015290519081900360640190fd5b6001600160a01b0381811660008181526007602090815260408083208054337fffffffffffffffffffffffff000000000000000000000000000000000000000080831682179093556008909452828520805490921690915590519416939092849290917f78af32efdcad432315431e9b03d27e6cd98fb79c405fdc5af7c1714d9c0f75b39190a45050565b6000612b40336000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611df992505050565b612b91576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b611e1b82615176565b6000612bdd336000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611df992505050565b612c2e576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b611e1b826151ac565b6004546000546001600160a01b039182169116331480612d2f5750604080517f6b14daf800000000000000000000000000000000000000000000000000000000815233600482018181526024830193845236604484018190526001600160a01b03861694636b14daf8946000939190606401848480828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016909201965060209550909350505081840390508186803b158015612d0257600080fd5b505afa158015612d16573d6000803e3d6000fd5b505050506040513d6020811015612d2c57600080fd5b50515b612d80576040805162461bcd60e51b815260206004820181905260248201527f4f6e6c79206f776e65722662696c6c696e6741646d696e2063616e2063616c6c604482015290519081900360640190fd5b612d886146fe565b612d958686868686615201565b505050505050565b6000546001600160a01b0316331480612e95575060048054604080517f6b14daf8000000000000000000000000000000000000000000000000000000008152339381018481526024820192835236604483018190526001600160a01b0390941694636b14daf8949093600093919291606401848480828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016909201965060209550909350505081840390508186803b158015612e6857600080fd5b505afa158015612e7c573d6000803e3d6000fd5b505050506040513d6020811015612e9257600080fd5b50515b612ee6576040805162461bcd60e51b815260206004820181905260248201527f4f6e6c79206f776e65722662696c6c696e6741646d696e2063616e2063616c6c604482015290519081900360640190fd5b6000612ef061537b565b600354604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290519293506000926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015612f5a57600080fd5b505afa158015612f6e573d6000803e3d6000fd5b505050506040513d6020811015612f8457600080fd5b5051905081811015612fdd576040805162461bcd60e51b815260206004820152601460248201527f696e73756666696369656e742062616c616e6365000000000000000000000000604482015290519081900360640190fd5b6003546001600160a01b031663a9059cbb85612ffb8585038761554b565b6040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561304157600080fd5b505af1158015613055573d6000803e3d6000fd5b505050506040513d602081101561306b57600080fd5b50516130be576040805162461bcd60e51b815260206004820152601260248201527f696e73756666696369656e742066756e64730000000000000000000000000000604482015290519081900360640190fd5b50505050565b60005a90506130d7888888888888615562565b361461312a576040805162461bcd60e51b815260206004820152601960248201527f7472616e736d6974206d65737361676520746f6f206c6f6e6700000000000000604482015290519081900360640190fd5b613132615b59565b6040805160808082018352602b549081901b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000168252700100000000000000000000000000000000810464ffffffffff1660208301527501000000000000000000000000000000000000000000810460ff169282019290925276010000000000000000000000000000000000000000000090910463ffffffff166060808301919091529082526000908a908a908110156131eb57600080fd5b81359160208101359181019060608101604082013564010000000081111561321257600080fd5b82018360208201111561322457600080fd5b8035906020019184602083028401116401000000008311171561324657600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050505060408801525050506080840182905283515190925060589190911b907fffffffffffffffffffffffffffffffff0000000000000000000000000000000080831691161461330d576040805162461bcd60e51b815260206004820152601560248201527f636f6e666967446967657374206d69736d617463680000000000000000000000604482015290519081900360640190fd5b608083015183516020015164ffffffffff808316911610613375576040805162461bcd60e51b815260206004820152600c60248201527f7374616c65207265706f72740000000000000000000000000000000000000000604482015290519081900360640190fd5b83516040015160ff1689116133d1576040805162461bcd60e51b815260206004820152601560248201527f6e6f7420656e6f756768207369676e6174757265730000000000000000000000604482015290519081900360640190fd5b601f891115613427576040805162461bcd60e51b815260206004820152601360248201527f746f6f206d616e79207369676e61747572657300000000000000000000000000604482015290519081900360640190fd5b86891461347b576040805162461bcd60e51b815260206004820152601e60248201527f7369676e617475726573206f7574206f6620726567697374726174696f6e0000604482015290519081900360640190fd5b601f84604001515111156134d6576040805162461bcd60e51b815260206004820152601e60248201527f6e756d206f62736572766174696f6e73206f7574206f6620626f756e64730000604482015290519081900360640190fd5b83600001516040015160020260ff168460400151511161353d576040805162461bcd60e51b815260206004820152601e60248201527f746f6f206665772076616c75657320746f207472757374206d656469616e0000604482015290519081900360640190fd5b8867ffffffffffffffff8111801561355457600080fd5b506040519080825280601f01601f19166020018201604052801561357f576020820181803683370190505b50606085015260005b60ff81168a11156135f057868160ff16602081106135a257fe5b1a60f81b85606001518260ff16815181106135b957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101613588565b5083604001515167ffffffffffffffff8111801561360d57600080fd5b506040519080825280601f01601f191660200182016040528015613638576020820181803683370190505b506020850152613646615b8d565b60005b8560400151518160ff16101561374c576000858260ff166020811061366a57fe5b1a90508281601f811061367957fe5b6020020151156136d0576040805162461bcd60e51b815260206004820152601760248201527f6f6273657276657220696e646578207265706561746564000000000000000000604482015290519081900360640190fd5b6001838260ff16601f81106136e157fe5b91151560209283029190910152869060ff84169081106136fd57fe5b1a60f81b87602001518360ff168151811061371457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050600101613649565b503360009081526028602090815260408083208151808301909252805460ff8082168452929391929184019161010090910416600281111561378a57fe5b600281111561379557fe5b90525090506002816020015160028111156137ac57fe5b1480156137e05750602a816000015160ff16815481106137c857fe5b6000918252602090912001546001600160a01b031633145b613831576040805162461bcd60e51b815260206004820152601860248201527f756e617574686f72697a6564207472616e736d69747465720000000000000000604482015290519081900360640190fd5b5050835164ffffffffff90911660209091015250506040516000908a908a9080838380828437604051920182900390912094506138729350615b8d92505050565b61387a615bac565b60005b89811015613a915760006001858760600151848151811061389a57fe5b60209101015160f81c601b018e8e868181106138b257fe5b905060200201358d8d878181106138c557fe5b9050602002013560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015613920573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101516001600160a01b03811660009081526028602090815290849020838501909452835460ff8082168552929650929450840191610100900416600281111561398d57fe5b600281111561399857fe5b90525092506001836020015160028111156139af57fe5b14613a01576040805162461bcd60e51b815260206004820152601e60248201527f61646472657373206e6f7420617574686f72697a656420746f207369676e0000604482015290519081900360640190fd5b8251849060ff16601f8110613a1257fe5b602002015115613a69576040805162461bcd60e51b815260206004820152601460248201527f6e6f6e2d756e69717565207369676e6174757265000000000000000000000000604482015290519081900360640190fd5b600184846000015160ff16601f8110613a7e57fe5b911515602090920201525060010161387d565b5050505060005b600182604001515103811015613b4257600082604001518260010181518110613abd57fe5b602002602001015160170b83604001518381518110613ad857fe5b602002602001015160170b1315905080613b39576040805162461bcd60e51b815260206004820152601760248201527f6f62736572766174696f6e73206e6f7420736f72746564000000000000000000604482015290519081900360640190fd5b50600101613a98565b50604081015180516000919060028104908110613b5b57fe5b602002602001015190508060170b7f00000000000000000000000000000000000000000000000000000000000186a060170b13158015613bc157507f00000000000000000000000000000000000000000000000000000002540be40060170b8160170b13155b613c12576040805162461bcd60e51b815260206004820152601e60248201527f6d656469616e206973206f7574206f66206d696e2d6d61782072616e67650000604482015290519081900360640190fd5b81516060908101805163ffffffff60019091018116909152604080518082018252601785810b80835267ffffffffffffffff42811660208086019182528a5189015188166000908152602c82528781209651875493519094167801000000000000000000000000000000000000000000000000029390950b77ffffffffffffffffffffffffffffffffffffffffffffffff9081167fffffffffffffffff0000000000000000000000000000000000000000000000009093169290921790911691909117909355875186015184890151848a01516080808c015188519586523386890181905291860181905260a0988601898152845199870199909952835194909916997ff6a97944f31ea060dfde0566e4167c1a1082551e64b60ecb14d599a9d023d451998c999298949793969095909492939185019260c086019289820192909102908190849084905b83811015613d75578181015183820152602001613d5d565b50505050905001838103825285818151815260200191508051906020019080838360005b83811015613db1578181015183820152602001613d99565b50505050905090810190601f168015613dde5780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390a281516060015160408051428152905160009263ffffffff16917f0109fc6f55cf40689f02fbaad7af7fe7bbac8a3d2186600afc7d3e10cac60271919081900360200190a381600001516060015163ffffffff168160170b7f0559884fd3a460db3073b7fc896cc77986f16e378210ded43186175bf646fc5f426040518082815260200191505060405180910390a3613e938260000151606001518260170b61557a565b5080518051602b8054602084015160408501516060909501517fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921660809490941c939093177fffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000064ffffffffff90941693909302929092177fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16750100000000000000000000000000000000000000000060ff90941693909302929092177fffffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffff1676010000000000000000000000000000000000000000000063ffffffff92831602179091558210613fb457fe5b613fc28282602001516156ba565b505050505050505050565b600354604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009283926001600160a01b03909116916370a0823191602480820192602092909190829003018186803b15801561403657600080fd5b505afa15801561404a573d6000803e3d6000fd5b505050506040513d602081101561406057600080fd5b50519050600061406e61537b565b90910391505090565b60315460ff1681565b6001600160a01b03811660009081526028602090815260408083208151808301909252805460ff8082168452859484019161010090041660028111156140c257fe5b60028111156140cd57fe5b90525090506000816020015160028111156140e457fe5b14156140f4576000915050610f0e565b60016005826000015160ff16601f811061410a57fe5b601091828204019190066002029054906101000a900461ffff1603915050919050565b600080808080333214614187576040805162461bcd60e51b815260206004820152601460248201527f4f6e6c792063616c6c61626c6520627920454f41000000000000000000000000604482015290519081900360640190fd5b5050602b5463ffffffff760100000000000000000000000000000000000000000000820481166000908152602c6020526040902054608083901b96700100000000000000000000000000000000909304600881901c909216955064ffffffffff9091169350601781900b92507801000000000000000000000000000000000000000000000000900467ffffffffffffffff1690565b6003546001600160a01b031690565b6000546001600160a01b0316331461428a576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b60408051808201909152602e546001600160a01b038082168084527401000000000000000000000000000000000000000090920463ffffffff16602084015284161415806142e857508163ffffffff16816020015163ffffffff1614155b156143bb576040805180820182526001600160a01b0385811680835263ffffffff8681166020948501819052602e80547fffffffffffffffffffffffff00000000000000000000000000000000000000001684177fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000008302179055865187860151875193168352948201528451919493909216927fb04e3a37abe9c0fcdfebdeae019a8e2b12ddf53f5d55ffb0caccc1bedaca1541928290030190a35b505050565b6001600160a01b0382811660009081526007602052604090205416331461442e576040805162461bcd60e51b815260206004820152601d60248201527f6f6e6c792063757272656e742070617965652063616e20757064617465000000604482015290519081900360640190fd5b336001600160a01b038216141561448c576040805162461bcd60e51b815260206004820152601760248201527f63616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015290519081900360640190fd5b6001600160a01b03808316600090815260086020526040902080548383167fffffffffffffffffffffffff0000000000000000000000000000000000000000821681179092559091169081146143bb576040516001600160a01b038084169133918616907f84f7c7c80bb8ed2279b4aab5f61cd05e6374073d38f46d7f32de8c30e9e3836790600090a4505050565b6000546001600160a01b0316331461457a576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000546001600160a01b03163314614642576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b61229081615907565b6000806000806000614694336000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611df992505050565b6146e5576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6146ed615996565b945094509450945094509091929394565b6040805160a08101825260025463ffffffff80821683526401000000008204811660208401526801000000000000000082048116838501526c0100000000000000000000000082048116606084015270010000000000000000000000000000000090910416608082015260035482516103e081019384905291926001600160a01b0390911691600091600590601f908285855b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411614791575050604080516103e0810191829052959650600095945060099350601f9250905082845b8154815260200190600101908083116147eb57505050505090506000602a80548060200260200160405190810160405280929190818152602001828054801561485d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161483f575b5050505050905060005b8151811015614a9257600060018483601f811061488057fe5b6020020151039050600060018684601f811061489857fe5b60200201510361ffff169050600082896060015163ffffffff168302633b9aca00020190506000811115614a87576000600760008787815181106148d857fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03169050886001600160a01b031663a9059cbb82846040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561496d57600080fd5b505af1158015614981573d6000803e3d6000fd5b505050506040513d602081101561499757600080fd5b50516149ea576040805162461bcd60e51b815260206004820152601260248201527f696e73756666696369656e742066756e64730000000000000000000000000000604482015290519081900360640190fd5b60018886601f81106149f857fe5b61ffff909216602092909202015260018786601f8110614a1457fe5b602002018181525050886001600160a01b0316816001600160a01b0316878781518110614a3d57fe5b60200260200101516001600160a01b03167fd0b1dac935d85bd54cf0a33b0d41d39f8cf53a968465fc7ea2377526b8ac712c856040518082815260200191505060405180910390a4505b505050600101614867565b50614aa0600584601f615bc3565b50612d95600983601f615c59565b602b54760100000000000000000000000000000000000000000000900463ffffffff166000908152602c6020526040902054601790810b900b90565b6001600160a01b03811660009081526028602090815260408083208151808301909252805460ff80821684529293919291840191610100909104166002811115614b3057fe5b6002811115614b3b57fe5b90525090506000614b4b83610dc8565b905080156143bb576001600160a01b0380841660009081526007602090815260408083205460035482517fa9059cbb000000000000000000000000000000000000000000000000000000008152918616600483018190526024830188905292519295169363a9059cbb9360448084019491939192918390030190829087803b158015614bd657600080fd5b505af1158015614bea573d6000803e3d6000fd5b505050506040513d6020811015614c0057600080fd5b5051614c53576040805162461bcd60e51b815260206004820152601260248201527f696e73756666696369656e742066756e64730000000000000000000000000000604482015290519081900360640190fd5b60016005846000015160ff16601f8110614c6957fe5b601091828204019190066002026101000a81548161ffff021916908361ffff16021790555060016009846000015160ff16601f8110614ca457fe5b01556003546040805184815290516001600160a01b039283169284811692908816917fd0b1dac935d85bd54cf0a33b0d41d39f8cf53a968465fc7ea2377526b8ac712c9181900360200190a450505050565b60008a8a8a8a8a8a8a8a8a8a604051602001808b6001600160a01b031681526020018a67ffffffffffffffff16815260200180602001806020018760ff1681526020018667ffffffffffffffff1681526020018060200184810384528c8c82818152602001925060200280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910185810384528a8152602090810191508b908b0280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910185810383528681526020019050868680828437600081840152601f19601f8201169050808301925050509d50505050505050505050505050506040516020818303038152906040528051906020012090509a9950505050505050505050565b602b54760100000000000000000000000000000000000000000000900463ffffffff1690565b6001600160a01b03821660009081526032602052604081205460ff1680611e1857505060315460ff161592915050565b60308054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156120d55780601f10614f0b576101008083540402835291602001916120d5565b820191906000526020600020905b815481529060010190602001808311614f1957509395945050505050565b602b54760100000000000000000000000000000000000000000000900463ffffffff166000908152602c60205260409020547801000000000000000000000000000000000000000000000000900467ffffffffffffffff1690565b600080600080600063ffffffff8669ffffffffffffffffffff1611156040518060400160405280600f81526020017f4e6f20646174612070726573656e7400000000000000000000000000000000008152509061506d5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561503257818101518382015260200161501a565b50505050905090810190601f16801561505f5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5050505063ffffffff83166000908152602c6020908152604091829020825180840190935254601781810b810b810b808552780100000000000000000000000000000000000000000000000090920467ffffffffffffffff1693909201839052949594900b939092508291508490565b6001600160a01b03811660009081526032602052604090205460ff16612290576001600160a01b03811660008181526032602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055815192835290517f87286ad1f399c8e82bf0c4ef4fcdc570ea2e1e92176e5c848b6413545b885db49281900390910190a150565b600063ffffffff82111561518c57506000610f0e565b5063ffffffff166000908152602c6020526040902054601790810b900b90565b600063ffffffff8211156151c257506000610f0e565b5063ffffffff166000908152602c60205260409020547801000000000000000000000000000000000000000000000000900467ffffffffffffffff1690565b6040805160a0808201835263ffffffff88811680845288821660208086018290528984168688018190528985166060808901829052958a166080988901819052600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001687177fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff166401000000008702177fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff16680100000000000000008502177fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff166c010000000000000000000000008402177fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff16700100000000000000000000000000000000830217905589519586529285019390935283880152928201529283015291517fd0d9486a2c673e2a4b57fc82e4c8a556b3e2b82dd5db07e2c04a920ca0f469b6929181900390910190a15050505050565b604080516103e0810191829052600091829190600590601f908285855b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116153985790505050505050905060005b601f8110156154085760018282601f81106153f157fe5b60200201510361ffff1692909201916001016153da565b506040805160a08101825260025463ffffffff8082168352640100000000820481166020808501919091526801000000000000000083048216848601526c0100000000000000000000000083048216606085018190527001000000000000000000000000000000009093049091166080840152602a805485518184028101840190965280865296909202633b9aca00029592936000939092918301828280156154da57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116154bc575b5050604080516103e0810191829052949550600094935060099250601f915082845b8154815260200190600101908083116154fc575050505050905060005b82518110156155435760018282601f811061553057fe5b6020020151039590950194600101615519565b505050505090565b60008183101561555c575081611e1b565b50919050565b602083810286019082020160e4019695505050505050565b60408051808201909152602e546001600160a01b0381168083527401000000000000000000000000000000000000000090910463ffffffff1660208301526155c257506112d8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830163ffffffff8181166000818152602c602090815260408083205487518884015183517fbeed9b510000000000000000000000000000000000000000000000000000000081526004810197909752601792830b90920b602487018190528b88166044880152606487018b9052925192966001600160a01b039091169563beed9b51959290911693608480830194919391928390030190829088803b15801561568b57600080fd5b5087f1935050505080156156b157506040513d60208110156156ac57600080fd5b505160015b612d95576128a7565b3360009081526028602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156156f757fe5b600281111561570257fe5b9052506040805160a08101825260025463ffffffff80821683526401000000008204811660208401526801000000000000000082048116838501526c0100000000000000000000000082048116606084015270010000000000000000000000000000000090910416608082015281516103e0810192839052929350916157d291859190600590601f90826000855b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116157905790505050505050615a1a565b6157e090600590601f615bc3565b506002826020015160028111156157f357fe5b14615845576040805162461bcd60e51b815260206004820181905260248201527f73656e7420627920756e64657369676e61746564207472616e736d6974746572604482015290519081900360640190fd5b600061586c633b9aca003a04836020015163ffffffff16846000015163ffffffff16615a8f565b90506010360260005a9050600061588b8863ffffffff16858585615ab5565b6fffffffffffffffffffffffffffffffff1690506000620f4240866040015163ffffffff168302816158b957fe5b049050856080015163ffffffff16633b9aca0002816009896000015160ff16601f81106158e257fe5b015401016009886000015160ff16601f81106158fa57fe5b0155505050505050505050565b6004546001600160a01b0390811690821681146112d857600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03848116918217909255604080519284168352602083019190915280517f793cb73064f3c8cde7e187ae515511e6e56d1ee89bf08b82fa60fb70f8d489129281900390910190a15050565b602b54760100000000000000000000000000000000000000000000900463ffffffff166000818152602c6020908152604091829020825180840190935254601781810b810b810b808552780100000000000000000000000000000000000000000000000090920467ffffffffffffffff1693909201839052929392900b9181908490565b615a22615b8d565b60005b8351811015615a87576000848281518110615a3c57fe5b016020015160f81c9050615a618482601f8110615a5557fe5b60200201516001615b41565b848260ff16601f8110615a7057fe5b61ffff909216602092909202015250600101615a25565b509092915050565b60008383811015615aa257600285850304015b615aac818461554b565b95945050505050565b600081851015615b0c576040805162461bcd60e51b815260206004820181905260248201527f6761734c6566742063616e6e6f742065786365656420696e697469616c476173604482015290519081900360640190fd5b818503830161179301633b9aca00858202026fffffffffffffffffffffffffffffffff8110615b3757fe5b9695505050505050565b6000611e188261ffff168461ffff160161ffff61554b565b6040518060a00160405280615b6c615c87565b81526060602082018190526040820181905280820152600060809091015290565b604051806103e00160405280601f906020820280368337509192915050565b604080518082019091526000808252602082015290565b600283019183908215615c495791602002820160005b83821115615c1957835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302615bd9565b8015615c475782816101000a81549061ffff0219169055600201602081600101049283019260010302615c19565b505b50615c55929150615cae565b5090565b82601f8101928215615c49579160200282015b82811115615c49578251825591602001919060010190615c6c565b60408051608081018252600080825260208201819052918101829052606081019190915290565b5b80821115615c555760008155600101615caf56fe416363657373436f6e74726f6c6c65644f6666636861696e41676772656761746f7220332e302e306f7261636c6520616464726573736573206f7574206f6620726567697374726174696f6ea2646970667358221220757bff216f6d81152fcaa510caac9632619adc3b29bcb61ba73c0af8d453fb2864736f6c63430007060033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000006f284c80000000000000000000000000000000000000000000000000000000000b688840000000000000000000000000000000000000000000000000000000004473318000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca00000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000002540be4000000000000000000000000009db83cef9f68b63989e4e82d65d549e7ff2acda9000000000000000000000000641b698ad1c6e503470520b0eecb472c0589dfe60000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000095a434e202f205553440000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _maximumGasPrice (uint32): 2000
Arg [1] : _reasonableGasPrice (uint32): 100
Arg [2] : _microLinkPerEth (uint32): 116557000
Arg [3] : _linkGweiPerObservation (uint32): 11962500
Arg [4] : _linkGweiPerTransmission (uint32): 71775000
Arg [5] : _link (address): 0x514910771AF9Ca656af840dff83E8264EcF986CA
Arg [6] : _minAnswer (int192): 100000
Arg [7] : _maxAnswer (int192): 10000000000
Arg [8] : _billingAccessController (address): 0x9db83CEf9f68b63989E4E82D65D549e7fF2aCda9
Arg [9] : _requesterAccessController (address): 0x641B698aD1C6E503470520B0EeCb472c0589dfE6
Arg [10] : _decimals (uint8): 8
Arg [11] : description (string): ZCN / USD
-----Encoded View---------------
14 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000007d0
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000064
Arg [2] : 0000000000000000000000000000000000000000000000000000000006f284c8
Arg [3] : 0000000000000000000000000000000000000000000000000000000000b68884
Arg [4] : 0000000000000000000000000000000000000000000000000000000004473318
Arg [5] : 000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca
Arg [6] : 00000000000000000000000000000000000000000000000000000000000186a0
Arg [7] : 00000000000000000000000000000000000000000000000000000002540be400
Arg [8] : 0000000000000000000000009db83cef9f68b63989e4e82d65d549e7ff2acda9
Arg [9] : 000000000000000000000000641b698ad1c6e503470520b0eecb472c0589dfe6
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000008
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000180
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000009
Arg [13] : 5a434e202f205553440000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.