{"sources":{"EACAggregatorProxy.sol":{"content":"pragma solidity 0.6.6;\n\n\n/**\n * @title The Owned contract\n * @notice A contract with helpers for basic contract ownership.\n */\ncontract Owned {\n\n  address payable public owner;\n  address private pendingOwner;\n\n  event OwnershipTransferRequested(\n    address indexed from,\n    address indexed to\n  );\n  event OwnershipTransferred(\n    address indexed from,\n    address indexed to\n  );\n\n  constructor() public {\n    owner = msg.sender;\n  }\n\n  /**\n   * @dev Allows an owner to begin transferring ownership to a new address,\n   * pending.\n   */\n  function transferOwnership(address _to)\n    external\n    onlyOwner()\n  {\n    pendingOwner = _to;\n\n    emit OwnershipTransferRequested(owner, _to);\n  }\n\n  /**\n   * @dev Allows an ownership transfer to be completed by the recipient.\n   */\n  function acceptOwnership()\n    external\n  {\n    require(msg.sender == pendingOwner, \"Must be proposed owner\");\n\n    address oldOwner = owner;\n    owner = msg.sender;\n    pendingOwner = address(0);\n\n    emit OwnershipTransferred(oldOwner, msg.sender);\n  }\n\n  /**\n   * @dev Reverts if called by anyone other than the contract owner.\n   */\n  modifier onlyOwner() {\n    require(msg.sender == owner, \"Only callable by owner\");\n    _;\n  }\n\n}\n\ninterface AggregatorInterface {\n  function latestAnswer() external view returns (int256);\n  function latestTimestamp() external view returns (uint256);\n  function latestRound() external view returns (uint256);\n  function getAnswer(uint256 roundId) external view returns (int256);\n  function getTimestamp(uint256 roundId) external view returns (uint256);\n\n  event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);\n  event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);\n}\n\ninterface AggregatorV3Interface {\n\n  function decimals() external view returns (uint8);\n  function description() external view returns (string memory);\n  function version() external view returns (uint256);\n\n  // getRoundData and latestRoundData should both raise \"No data present\"\n  // if they do not have data to report, instead of returning unset values\n  // which could be misinterpreted as actual reported values.\n  function getRoundData(uint80 _roundId)\n    external\n    view\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    );\n  function latestRoundData()\n    external\n    view\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    );\n\n}\n\ninterface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface\n{\n}\n\n/**\n * @title A trusted proxy for updating where current answers are read from\n * @notice This contract provides a consistent address for the\n * CurrentAnwerInterface but delegates where it reads from to the owner, who is\n * trusted to update it.\n */\ncontract AggregatorProxy is AggregatorV2V3Interface, Owned {\n\n  struct Phase {\n    uint16 id;\n    AggregatorV2V3Interface aggregator;\n  }\n  Phase private currentPhase;\n  AggregatorV2V3Interface public proposedAggregator;\n  mapping(uint16 => AggregatorV2V3Interface) public phaseAggregators;\n\n  uint256 constant private PHASE_OFFSET = 64;\n  uint256 constant private PHASE_SIZE = 16;\n  uint256 constant private MAX_ID = 2**(PHASE_OFFSET+PHASE_SIZE) - 1;\n\n  constructor(address _aggregator) public Owned() {\n    setAggregator(_aggregator);\n  }\n\n  /**\n   * @notice Reads the current answer from aggregator delegated to.\n   *\n   * @dev #[deprecated] Use latestRoundData instead. This does not error if no\n   * answer has been reached, it will simply return 0. Either wait to point to\n   * an already answered Aggregator or use the recommended latestRoundData\n   * instead which includes better verification information.\n   */\n  function latestAnswer()\n    public\n    view\n    virtual\n    override\n    returns (int256 answer)\n  {\n    return currentPhase.aggregator.latestAnswer();\n  }\n\n  /**\n   * @notice Reads the last updated height from aggregator delegated to.\n   *\n   * @dev #[deprecated] Use latestRoundData instead. This does not error if no\n   * answer has been reached, it will simply return 0. Either wait to point to\n   * an already answered Aggregator or use the recommended latestRoundData\n   * instead which includes better verification information.\n   */\n  function latestTimestamp()\n    public\n    view\n    virtual\n    override\n    returns (uint256 updatedAt)\n  {\n    return currentPhase.aggregator.latestTimestamp();\n  }\n\n  /**\n   * @notice get past rounds answers\n   * @param _roundId the answer number to retrieve the answer for\n   *\n   * @dev #[deprecated] Use getRoundData instead. This does not error if no\n   * answer has been reached, it will simply return 0. Either wait to point to\n   * an already answered Aggregator or use the recommended getRoundData\n   * instead which includes better verification information.\n   */\n  function getAnswer(uint256 _roundId)\n    public\n    view\n    virtual\n    override\n    returns (int256 answer)\n  {\n    if (_roundId > MAX_ID) return 0;\n\n    (uint16 phaseId, uint64 aggregatorRoundId) = parseIds(_roundId);\n    AggregatorV2V3Interface aggregator = phaseAggregators[phaseId];\n    if (address(aggregator) == address(0)) return 0;\n\n    return aggregator.getAnswer(aggregatorRoundId);\n  }\n\n  /**\n   * @notice get block timestamp when an answer was last updated\n   * @param _roundId the answer number to retrieve the updated timestamp for\n   *\n   * @dev #[deprecated] Use getRoundData instead. This does not error if no\n   * answer has been reached, it will simply return 0. Either wait to point to\n   * an already answered Aggregator or use the recommended getRoundData\n   * instead which includes better verification information.\n   */\n  function getTimestamp(uint256 _roundId)\n    public\n    view\n    virtual\n    override\n    returns (uint256 updatedAt)\n  {\n    if (_roundId > MAX_ID) return 0;\n\n    (uint16 phaseId, uint64 aggregatorRoundId) = parseIds(_roundId);\n    AggregatorV2V3Interface aggregator = phaseAggregators[phaseId];\n    if (address(aggregator) == address(0)) return 0;\n\n    return aggregator.getTimestamp(aggregatorRoundId);\n  }\n\n  /**\n   * @notice get the latest completed round where the answer was updated. This\n   * ID includes the proxy's phase, to make sure round IDs increase even when\n   * switching to a newly deployed aggregator.\n   *\n   * @dev #[deprecated] Use latestRoundData instead. This does not error if no\n   * answer has been reached, it will simply return 0. Either wait to point to\n   * an already answered Aggregator or use the recommended latestRoundData\n   * instead which includes better verification information.\n   */\n  function latestRound()\n    public\n    view\n    virtual\n    override\n    returns (uint256 roundId)\n  {\n    Phase memory phase = currentPhase; // cache storage reads\n    return addPhase(phase.id, uint64(phase.aggregator.latestRound()));\n  }\n\n  /**\n   * @notice get data about a round. Consumers are encouraged to check\n   * that they're receiving fresh data by inspecting the updatedAt and\n   * answeredInRound return values.\n   * Note that different underlying implementations of AggregatorV3Interface\n   * have slightly different semantics for some of the return values. Consumers\n   * should determine what implementations they expect to receive\n   * data from and validate that they can properly handle return data from all\n   * of them.\n   * @param _roundId the requested round ID as presented through the proxy, this\n   * is made up of the aggregator's round ID with the phase ID encoded in the\n   * two highest order bytes\n   * @return roundId is the round ID from the aggregator for which the data was\n   * retrieved combined with an phase to ensure that round IDs get larger as\n   * time moves forward.\n   * @return answer is the answer for the given round\n   * @return startedAt is the timestamp when the round was started.\n   * (Only some AggregatorV3Interface implementations return meaningful values)\n   * @return updatedAt is the timestamp when the round last was updated (i.e.\n   * answer was last computed)\n   * @return answeredInRound is the round ID of the round in which the answer\n   * was computed.\n   * (Only some AggregatorV3Interface implementations return meaningful values)\n   * @dev Note that answer and updatedAt may change between queries.\n   */\n  function getRoundData(uint80 _roundId)\n    public\n    view\n    virtual\n    override\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    )\n  {\n    (uint16 phaseId, uint64 aggregatorRoundId) = parseIds(_roundId);\n\n    (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 ansIn\n    ) = phaseAggregators[phaseId].getRoundData(aggregatorRoundId);\n\n    return addPhaseIds(roundId, answer, startedAt, updatedAt, ansIn, phaseId);\n  }\n\n  /**\n   * @notice get data about the latest round. Consumers are encouraged to check\n   * that they're receiving fresh data by inspecting the updatedAt and\n   * answeredInRound return values.\n   * Note that different underlying implementations of AggregatorV3Interface\n   * have slightly different semantics for some of the return values. Consumers\n   * should determine what implementations they expect to receive\n   * data from and validate that they can properly handle return data from all\n   * of them.\n   * @return roundId is the round ID from the aggregator for which the data was\n   * retrieved combined with an phase to ensure that round IDs get larger as\n   * time moves forward.\n   * @return answer is the answer for the given round\n   * @return startedAt is the timestamp when the round was started.\n   * (Only some AggregatorV3Interface implementations return meaningful values)\n   * @return updatedAt is the timestamp when the round last was updated (i.e.\n   * answer was last computed)\n   * @return answeredInRound is the round ID of the round in which the answer\n   * was computed.\n   * (Only some AggregatorV3Interface implementations return meaningful values)\n   * @dev Note that answer and updatedAt may change between queries.\n   */\n  function latestRoundData()\n    public\n    view\n    virtual\n    override\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    )\n  {\n    Phase memory current = currentPhase; // cache storage reads\n\n    (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 ansIn\n    ) = current.aggregator.latestRoundData();\n\n    return addPhaseIds(roundId, answer, startedAt, updatedAt, ansIn, current.id);\n  }\n\n  /**\n   * @notice Used if an aggregator contract has been proposed.\n   * @param _roundId the round ID to retrieve the round data for\n   * @return roundId is the round ID for which data was retrieved\n   * @return answer is the answer for the given round\n   * @return startedAt is the timestamp when the round was started.\n   * (Only some AggregatorV3Interface implementations return meaningful values)\n   * @return updatedAt is the timestamp when the round last was updated (i.e.\n   * answer was last computed)\n   * @return answeredInRound is the round ID of the round in which the answer\n   * was computed.\n  */\n  function proposedGetRoundData(uint80 _roundId)\n    public\n    view\n    virtual\n    hasProposal()\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    )\n  {\n    return proposedAggregator.getRoundData(_roundId);\n  }\n\n  /**\n   * @notice Used if an aggregator contract has been proposed.\n   * @return roundId is the round ID for which data was retrieved\n   * @return answer is the answer for the given round\n   * @return startedAt is the timestamp when the round was started.\n   * (Only some AggregatorV3Interface implementations return meaningful values)\n   * @return updatedAt is the timestamp when the round last was updated (i.e.\n   * answer was last computed)\n   * @return answeredInRound is the round ID of the round in which the answer\n   * was computed.\n  */\n  function proposedLatestRoundData()\n    public\n    view\n    virtual\n    hasProposal()\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    )\n  {\n    return proposedAggregator.latestRoundData();\n  }\n\n  /**\n   * @notice returns the current phase's aggregator address.\n   */\n  function aggregator()\n    external\n    view\n    returns (address)\n  {\n    return address(currentPhase.aggregator);\n  }\n\n  /**\n   * @notice returns the current phase's ID.\n   */\n  function phaseId()\n    external\n    view\n    returns (uint16)\n  {\n    return currentPhase.id;\n  }\n\n  /**\n   * @notice represents the number of decimals the aggregator responses represent.\n   */\n  function decimals()\n    external\n    view\n    override\n    returns (uint8)\n  {\n    return currentPhase.aggregator.decimals();\n  }\n\n  /**\n   * @notice the version number representing the type of aggregator the proxy\n   * points to.\n   */\n  function version()\n    external\n    view\n    override\n    returns (uint256)\n  {\n    return currentPhase.aggregator.version();\n  }\n\n  /**\n   * @notice returns the description of the aggregator the proxy points to.\n   */\n  function description()\n    external\n    view\n    override\n    returns (string memory)\n  {\n    return currentPhase.aggregator.description();\n  }\n\n  /**\n   * @notice Allows the owner to propose a new address for the aggregator\n   * @param _aggregator The new address for the aggregator contract\n   */\n  function proposeAggregator(address _aggregator)\n    external\n    onlyOwner()\n  {\n    proposedAggregator = AggregatorV2V3Interface(_aggregator);\n  }\n\n  /**\n   * @notice Allows the owner to confirm and change the address\n   * to the proposed aggregator\n   * @dev Reverts if the given address doesn't match what was previously\n   * proposed\n   * @param _aggregator The new address for the aggregator contract\n   */\n  function confirmAggregator(address _aggregator)\n    external\n    onlyOwner()\n  {\n    require(_aggregator == address(proposedAggregator), \"Invalid proposed aggregator\");\n    delete proposedAggregator;\n    setAggregator(_aggregator);\n  }\n\n\n  /*\n   * Internal\n   */\n\n  function setAggregator(address _aggregator)\n    internal\n  {\n    uint16 id = currentPhase.id + 1;\n    currentPhase = Phase(id, AggregatorV2V3Interface(_aggregator));\n    phaseAggregators[id] = AggregatorV2V3Interface(_aggregator);\n  }\n\n  function addPhase(\n    uint16 _phase,\n    uint64 _originalId\n  )\n    internal\n    view\n    returns (uint80)\n  {\n    return uint80(uint256(_phase) << PHASE_OFFSET | _originalId);\n  }\n\n  function parseIds(\n    uint256 _roundId\n  )\n    internal\n    view\n    returns (uint16, uint64)\n  {\n    uint16 phaseId = uint16(_roundId >> PHASE_OFFSET);\n    uint64 aggregatorRoundId = uint64(_roundId);\n\n    return (phaseId, aggregatorRoundId);\n  }\n\n  function addPhaseIds(\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound,\n      uint16 phaseId\n  )\n    internal\n    view\n    returns (uint80, int256, uint256, uint256, uint80)\n  {\n    return (\n      addPhase(phaseId, uint64(roundId)),\n      answer,\n      startedAt,\n      updatedAt,\n      addPhase(phaseId, uint64(answeredInRound))\n    );\n  }\n\n  /*\n   * Modifiers\n   */\n\n  modifier hasProposal() {\n    require(address(proposedAggregator) != address(0), \"No proposed aggregator present\");\n    _;\n  }\n\n}\n\ninterface AccessControllerInterface {\n  function hasAccess(address user, bytes calldata data) external view returns (bool);\n}\n\n/**\n * @title External Access Controlled Aggregator Proxy\n * @notice A trusted proxy for updating where current answers are read from\n * @notice This contract provides a consistent address for the\n * Aggregator and AggregatorV3Interface but delegates where it reads from to the owner, who is\n * trusted to update it.\n * @notice Only access enabled addresses are allowed to access getters for\n * aggregated answers and round information.\n */\ncontract EACAggregatorProxy is AggregatorProxy {\n\n  AccessControllerInterface public accessController;\n\n  constructor(\n    address _aggregator,\n    address _accessController\n  )\n    public\n    AggregatorProxy(_aggregator)\n  {\n    setController(_accessController);\n  }\n\n  /**\n   * @notice Allows the owner to update the accessController contract address.\n   * @param _accessController The new address for the accessController contract\n   */\n  function setController(address _accessController)\n    public\n    onlyOwner()\n  {\n    accessController = AccessControllerInterface(_accessController);\n  }\n\n  /**\n   * @notice Reads the current answer from aggregator delegated to.\n   * @dev overridden function to add the checkAccess() modifier\n   *\n   * @dev #[deprecated] Use latestRoundData instead. This does not error if no\n   * answer has been reached, it will simply return 0. Either wait to point to\n   * an already answered Aggregator or use the recommended latestRoundData\n   * instead which includes better verification information.\n   */\n  function latestAnswer()\n    public\n    view\n    override\n    checkAccess()\n    returns (int256)\n  {\n    return super.latestAnswer();\n  }\n\n  /**\n   * @notice get the latest completed round where the answer was updated. This\n   * ID includes the proxy's phase, to make sure round IDs increase even when\n   * switching to a newly deployed aggregator.\n   *\n   * @dev #[deprecated] Use latestRoundData instead. This does not error if no\n   * answer has been reached, it will simply return 0. Either wait to point to\n   * an already answered Aggregator or use the recommended latestRoundData\n   * instead which includes better verification information.\n   */\n  function latestTimestamp()\n    public\n    view\n    override\n    checkAccess()\n    returns (uint256)\n  {\n    return super.latestTimestamp();\n  }\n\n  /**\n   * @notice get past rounds answers\n   * @param _roundId the answer number to retrieve the answer for\n   * @dev overridden function to add the checkAccess() modifier\n   *\n   * @dev #[deprecated] Use getRoundData instead. This does not error if no\n   * answer has been reached, it will simply return 0. Either wait to point to\n   * an already answered Aggregator or use the recommended getRoundData\n   * instead which includes better verification information.\n   */\n  function getAnswer(uint256 _roundId)\n    public\n    view\n    override\n    checkAccess()\n    returns (int256)\n  {\n    return super.getAnswer(_roundId);\n  }\n\n  /**\n   * @notice get block timestamp when an answer was last updated\n   * @param _roundId the answer number to retrieve the updated timestamp for\n   * @dev overridden function to add the checkAccess() modifier\n   *\n   * @dev #[deprecated] Use getRoundData instead. This does not error if no\n   * answer has been reached, it will simply return 0. Either wait to point to\n   * an already answered Aggregator or use the recommended getRoundData\n   * instead which includes better verification information.\n   */\n  function getTimestamp(uint256 _roundId)\n    public\n    view\n    override\n    checkAccess()\n    returns (uint256)\n  {\n    return super.getTimestamp(_roundId);\n  }\n\n  /**\n   * @notice get the latest completed round where the answer was updated\n   * @dev overridden function to add the checkAccess() modifier\n   *\n   * @dev #[deprecated] Use latestRoundData instead. This does not error if no\n   * answer has been reached, it will simply return 0. Either wait to point to\n   * an already answered Aggregator or use the recommended latestRoundData\n   * instead which includes better verification information.\n   */\n  function latestRound()\n    public\n    view\n    override\n    checkAccess()\n    returns (uint256)\n  {\n    return super.latestRound();\n  }\n\n  /**\n   * @notice get data about a round. Consumers are encouraged to check\n   * that they're receiving fresh data by inspecting the updatedAt and\n   * answeredInRound return values.\n   * Note that different underlying implementations of AggregatorV3Interface\n   * have slightly different semantics for some of the return values. Consumers\n   * should determine what implementations they expect to receive\n   * data from and validate that they can properly handle return data from all\n   * of them.\n   * @param _roundId the round ID to retrieve the round data for\n   * @return roundId is the round ID from the aggregator for which the data was\n   * retrieved combined with a phase to ensure that round IDs get larger as\n   * time moves forward.\n   * @return answer is the answer for the given round\n   * @return startedAt is the timestamp when the round was started.\n   * (Only some AggregatorV3Interface implementations return meaningful values)\n   * @return updatedAt is the timestamp when the round last was updated (i.e.\n   * answer was last computed)\n   * @return answeredInRound is the round ID of the round in which the answer\n   * was computed.\n   * (Only some AggregatorV3Interface implementations return meaningful values)\n   * @dev Note that answer and updatedAt may change between queries.\n   */\n  function getRoundData(uint80 _roundId)\n    public\n    view\n    checkAccess()\n    override\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    )\n  {\n    return super.getRoundData(_roundId);\n  }\n\n  /**\n   * @notice get data about the latest round. Consumers are encouraged to check\n   * that they're receiving fresh data by inspecting the updatedAt and\n   * answeredInRound return values.\n   * Note that different underlying implementations of AggregatorV3Interface\n   * have slightly different semantics for some of the return values. Consumers\n   * should determine what implementations they expect to receive\n   * data from and validate that they can properly handle return data from all\n   * of them.\n   * @return roundId is the round ID from the aggregator for which the data was\n   * retrieved combined with a phase to ensure that round IDs get larger as\n   * time moves forward.\n   * @return answer is the answer for the given round\n   * @return startedAt is the timestamp when the round was started.\n   * (Only some AggregatorV3Interface implementations return meaningful values)\n   * @return updatedAt is the timestamp when the round last was updated (i.e.\n   * answer was last computed)\n   * @return answeredInRound is the round ID of the round in which the answer\n   * was computed.\n   * (Only some AggregatorV3Interface implementations return meaningful values)\n   * @dev Note that answer and updatedAt may change between queries.\n   */\n  function latestRoundData()\n    public\n    view\n    checkAccess()\n    override\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    )\n  {\n    return super.latestRoundData();\n  }\n\n  /**\n   * @notice Used if an aggregator contract has been proposed.\n   * @param _roundId the round ID to retrieve the round data for\n   * @return roundId is the round ID for which data was retrieved\n   * @return answer is the answer for the given round\n   * @return startedAt is the timestamp when the round was started.\n   * (Only some AggregatorV3Interface implementations return meaningful values)\n   * @return updatedAt is the timestamp when the round last was updated (i.e.\n   * answer was last computed)\n   * @return answeredInRound is the round ID of the round in which the answer\n   * was computed.\n  */\n  function proposedGetRoundData(uint80 _roundId)\n    public\n    view\n    checkAccess()\n    hasProposal()\n    override\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    )\n  {\n    return super.proposedGetRoundData(_roundId);\n  }\n\n  /**\n   * @notice Used if an aggregator contract has been proposed.\n   * @return roundId is the round ID for which data was retrieved\n   * @return answer is the answer for the given round\n   * @return startedAt is the timestamp when the round was started.\n   * (Only some AggregatorV3Interface implementations return meaningful values)\n   * @return updatedAt is the timestamp when the round last was updated (i.e.\n   * answer was last computed)\n   * @return answeredInRound is the round ID of the round in which the answer\n   * was computed.\n  */\n  function proposedLatestRoundData()\n    public\n    view\n    checkAccess()\n    hasProposal()\n    override\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    )\n  {\n    return super.proposedLatestRoundData();\n  }\n\n  /**\n   * @dev reverts if the caller does not have access by the accessController\n   * contract or is the contract itself.\n   */\n  modifier checkAccess() {\n    AccessControllerInterface ac = accessController;\n    require(address(ac) == address(0) || ac.hasAccess(msg.sender, msg.data), \"No access\");\n    _;\n  }\n}"}},"matchId":"2398528","creationMatch":"match","runtimeMatch":"match","verifiedAt":"2024-08-08T15:19:12Z","match":"match","chainId":"1","address":"0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419"}