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