Contract 0x44750a79ae69D5E9bC1651E099DFFE1fb8611AbA

 
 
Txn Hash
Method
Block
From
To
Value
0xfdcbbbf18730b92057be40202c7e1888394d8a8713ec9f9eb773fb2367e78ba3Transfer Ownersh...135452382021-11-03 17:36:36392 days 2 hrs ago0x4cadde3de133ccb22718ff3ac3b54b86760895dd IN  0x44750a79ae69d5e9bc1651e099dffe1fb8611aba0 Ether0.01012232 211.66661248
0xf6ace20384dc2e2c3f6924caa7afb72ed1b5ccc8f8d03e3eeb9f53f9e82804ac0x60806040135135972021-10-29 18:21:12397 days 1 hr ago0x4cadde3de133ccb22718ff3ac3b54b86760895dd IN  Contract Creation0 Ether0.16256804 221
[ Download CSV Export 
View more zero value Internal Transactions in Advanced View mode
Loading

Similar Match Source Code
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0x264BDDFD9D93D48d759FBDB0670bE1C6fDd50236

Contract Name:
ValidatorProxy

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license
File 1 of 5 : ConfirmedOwner.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/**
 * @title The ConfirmedOwner contract
 * @notice A contract with helpers for basic contract ownership.
 */
contract ConfirmedOwner {

  address private s_owner;
  address private s_pendingOwner;

  event OwnershipTransferRequested(
    address indexed from,
    address indexed to
  );
  event OwnershipTransferred(
    address indexed from,
    address indexed to
  );

  constructor(address newOwner) {
    s_owner = newOwner;
  }

  /**
   * @notice Allows an owner to begin transferring ownership to a new address,
   * pending.
   */
  function transferOwnership(
    address to
  )
    external
    onlyOwner()
  {
    require(to != msg.sender, "Cannot transfer to self");

    s_pendingOwner = to;

    emit OwnershipTransferRequested(s_owner, to);
  }

  /**
   * @notice Allows an ownership transfer to be completed by the recipient.
   */
  function acceptOwnership()
    external
  {
    require(msg.sender == s_pendingOwner, "Must be proposed owner");

    address oldOwner = s_owner;
    s_owner = msg.sender;
    s_pendingOwner = address(0);

    emit OwnershipTransferred(oldOwner, msg.sender);
  }

  /**
   * @notice Get the current owner
   */
  function owner()
    public
    view
    returns (
      address
    )
  {
    return s_owner;
  }

  /**
   * @notice Reverts if called by anyone other than the contract owner.
   */
  modifier onlyOwner() {
    require(msg.sender == s_owner, "Only callable by owner");
    _;
  }

}

File 2 of 5 : ValidatorProxy.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./ConfirmedOwner.sol";
import "../interfaces/AggregatorValidatorInterface.sol";
import "../interfaces/TypeAndVersionInterface.sol";

contract ValidatorProxy is AggregatorValidatorInterface, TypeAndVersionInterface, ConfirmedOwner {

  /// @notice Uses a single storage slot to store the current address
  struct AggregatorConfiguration {
    address target;
    bool hasNewProposal;
  }

  struct ValidatorConfiguration {
    AggregatorValidatorInterface target;
    bool hasNewProposal;
  }

  // Configuration for the current aggregator
  AggregatorConfiguration private s_currentAggregator;
  // Proposed aggregator address
  address private s_proposedAggregator;

  // Configuration for the current validator
  ValidatorConfiguration private s_currentValidator;
  // Proposed validator address
  AggregatorValidatorInterface private s_proposedValidator;

  event AggregatorProposed(
    address indexed aggregator
  );
  event AggregatorUpgraded(
    address indexed previous,
    address indexed current
  );
  event ValidatorProposed(
    AggregatorValidatorInterface indexed validator
  );
  event ValidatorUpgraded(
    AggregatorValidatorInterface indexed previous,
    AggregatorValidatorInterface indexed current
  );
  /// @notice The proposed aggregator called validate, but the call was not passed on to any validators
  event ProposedAggregatorValidateCall(
    address indexed proposed,
    uint256 previousRoundId,
    int256 previousAnswer,
    uint256 currentRoundId,
    int256 currentAnswer
  );

  /**
   * @notice Construct the ValidatorProxy with an aggregator and a validator
   * @param aggregator address
   * @param validator address
   */
  constructor(
    address aggregator,
    AggregatorValidatorInterface validator
  )
    ConfirmedOwner(msg.sender)
  {
    s_currentAggregator = AggregatorConfiguration({
      target: aggregator,
      hasNewProposal: false
    });
    s_currentValidator = ValidatorConfiguration({
      target: validator,
      hasNewProposal: false
    });
  }

  /**
   * @notice Validate a transmission
   * @dev Must be called by either the `s_currentAggregator.target`, or the `s_proposedAggregator`.
   * If called by the `s_currentAggregator.target` this function passes the call on to the `s_currentValidator.target`
   * and the `s_proposedValidator`, if it is set.
   * If called by the `s_proposedAggregator` this function emits a `ProposedAggregatorValidateCall` to signal that
   * the call was received.
   * @dev To guard against external `validate` calls reverting, we use raw calls here.
   * We favour `call` over try-catch to ensure that failures are avoided even if the validator address is incorrectly
   * set as a non-contract address.
   * @dev If the `aggregator` and `validator` are the same contract or collude, this could exhibit reentrancy behavior.
   * However, since that contract would have to be explicitly written for reentrancy and that the `owner` would have
   * to configure this contract to use that malicious contract, we refrain from using mutex or check here.
   * @dev This does not perform any checks on any roundId, so it is possible that a validator receive different reports
   * for the same roundId at different points in time. Validator implementations should be aware of this.
   * @param previousRoundId uint256
   * @param previousAnswer int256
   * @param currentRoundId uint256
   * @param currentAnswer int256
   * @return bool
   */
  function validate(
    uint256 previousRoundId,
    int256 previousAnswer,
    uint256 currentRoundId,
    int256 currentAnswer
  )
    external
    override
    returns (
      bool
    )
  {
    address currentAggregator = s_currentAggregator.target;
    if (msg.sender != currentAggregator) {
      address proposedAggregator = s_proposedAggregator;
      require(msg.sender == proposedAggregator, "Not a configured aggregator");
      // If the aggregator is still in proposed state, emit an event and don't push to any validator.
      // This is to confirm that `validate` is being called prior to upgrade.
      emit ProposedAggregatorValidateCall(
        proposedAggregator,
        previousRoundId,
        previousAnswer,
        currentRoundId,
        currentAnswer
      );
      return true;
    }

    // Send the validate call to the current validator
    ValidatorConfiguration memory currentValidator = s_currentValidator;
    address currentValidatorAddress = address(currentValidator.target);
    require(currentValidatorAddress != address(0), "No validator set");
    currentValidatorAddress.call(
      abi.encodeWithSelector(
        AggregatorValidatorInterface.validate.selector,
        previousRoundId,
        previousAnswer,
        currentRoundId,
        currentAnswer
      )
    );
    // If there is a new proposed validator, send the validate call to that validator also
    if (currentValidator.hasNewProposal) {
      address(s_proposedValidator).call(
        abi.encodeWithSelector(
          AggregatorValidatorInterface.validate.selector,
          previousRoundId,
          previousAnswer,
          currentRoundId,
          currentAnswer
        )
      );
    }
    return true;
  }

  /** AGGREGATOR CONFIGURATION FUNCTIONS **/

  /**
   * @notice Propose an aggregator
   * @dev A zero address can be used to unset the proposed aggregator. Only owner can call.
   * @param proposed address
   */
  function proposeNewAggregator(
    address proposed
  )
    external
    onlyOwner()
  {
    require(s_proposedAggregator != proposed && s_currentAggregator.target != proposed, "Invalid proposal");
    s_proposedAggregator = proposed;
    // If proposed is zero address, hasNewProposal = false
    s_currentAggregator.hasNewProposal = (proposed != address(0));
    emit AggregatorProposed(proposed);
  }

  /**
   * @notice Upgrade the aggregator by setting the current aggregator as the proposed aggregator.
   * @dev Must have a proposed aggregator. Only owner can call.
   */
  function upgradeAggregator()
    external
    onlyOwner()
  {
    // Get configuration in memory
    AggregatorConfiguration memory current = s_currentAggregator;
    address previous = current.target;
    address proposed = s_proposedAggregator;

    // Perform the upgrade
    require(current.hasNewProposal, "No proposal");
    s_currentAggregator = AggregatorConfiguration({
      target: proposed,
      hasNewProposal: false
    });
    delete s_proposedAggregator;

    emit AggregatorUpgraded(previous, proposed);
  }

  /**
   * @notice Get aggregator details
   * @return current address
   * @return hasProposal bool
   * @return proposed address
   */
  function getAggregators()
    external
    view
    returns(
      address current,
      bool hasProposal,
      address proposed
    )
  {
    current = s_currentAggregator.target;
    hasProposal = s_currentAggregator.hasNewProposal;
    proposed = s_proposedAggregator;
  }

  /** VALIDATOR CONFIGURATION FUNCTIONS **/

  /**
   * @notice Propose an validator
   * @dev A zero address can be used to unset the proposed validator. Only owner can call.
   * @param proposed address
   */
  function proposeNewValidator(
    AggregatorValidatorInterface proposed
  )
    external
    onlyOwner()
  {
    require(s_proposedValidator != proposed && s_currentValidator.target != proposed, "Invalid proposal");
    s_proposedValidator = proposed;
    // If proposed is zero address, hasNewProposal = false
    s_currentValidator.hasNewProposal = (address(proposed) != address(0));
    emit ValidatorProposed(proposed);
  }

  /**
   * @notice Upgrade the validator by setting the current validator as the proposed validator.
   * @dev Must have a proposed validator. Only owner can call.
   */
  function upgradeValidator()
    external
    onlyOwner()
  {
    // Get configuration in memory
    ValidatorConfiguration memory current = s_currentValidator;
    AggregatorValidatorInterface previous = current.target;
    AggregatorValidatorInterface proposed = s_proposedValidator;

    // Perform the upgrade
    require(current.hasNewProposal, "No proposal");
    s_currentValidator = ValidatorConfiguration({
      target: proposed,
      hasNewProposal: false
    });
    delete s_proposedValidator;

    emit ValidatorUpgraded(previous, proposed);
  }

  /**
   * @notice Get validator details
   * @return current address
   * @return hasProposal bool
   * @return proposed address
   */
  function getValidators()
    external
    view
    returns(
      AggregatorValidatorInterface current,
      bool hasProposal,
      AggregatorValidatorInterface proposed
    )
  {
    current = s_currentValidator.target;
    hasProposal = s_currentValidator.hasNewProposal;
    proposed = s_proposedValidator;
  }

  /**
   * @notice The type and version of this contract
   * @return Type and version string
   */
  function typeAndVersion()
    external
    pure
    virtual
    override
    returns (
      string memory
    )
  {
    return "ValidatorProxy 1.0.0";
  }

}

File 3 of 5 : AggregatorValidatorInterface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface AggregatorValidatorInterface {
  function validate(
    uint256 previousRoundId,
    int256 previousAnswer,
    uint256 currentRoundId,
    int256 currentAnswer
  )
    external
    returns (
      bool
    );
}

File 4 of 5 : TypeAndVersionInterface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

abstract contract TypeAndVersionInterface{
  function typeAndVersion()
    external
    pure
    virtual
    returns (
      string memory
    );
}

File 5 of 5 : MockAggregatorValidator.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "../interfaces/AggregatorValidatorInterface.sol";

contract MockAggregatorValidator is AggregatorValidatorInterface {
  
  uint8 immutable id;

  constructor(uint8 id_) {
    id = id_;
  }

  event ValidateCalled(
    uint8 id,
    uint256 previousRoundId,
    int256 previousAnswer,
    uint256 currentRoundId,
    int256 currentAnswer
  );
  
  function validate(
    uint256 previousRoundId,
    int256 previousAnswer,
    uint256 currentRoundId,
    int256 currentAnswer
  )
    external
    override
    returns (
      bool
    )
  {
    emit ValidateCalled(id, previousRoundId, previousAnswer, currentRoundId, currentAnswer);
    return true;
  }

}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"aggregator","type":"address"},{"internalType":"contract AggregatorValidatorInterface","name":"validator","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"aggregator","type":"address"}],"name":"AggregatorProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previous","type":"address"},{"indexed":true,"internalType":"address","name":"current","type":"address"}],"name":"AggregatorUpgraded","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":"proposed","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousRoundId","type":"uint256"},{"indexed":false,"internalType":"int256","name":"previousAnswer","type":"int256"},{"indexed":false,"internalType":"uint256","name":"currentRoundId","type":"uint256"},{"indexed":false,"internalType":"int256","name":"currentAnswer","type":"int256"}],"name":"ProposedAggregatorValidateCall","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract AggregatorValidatorInterface","name":"validator","type":"address"}],"name":"ValidatorProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract AggregatorValidatorInterface","name":"previous","type":"address"},{"indexed":true,"internalType":"contract AggregatorValidatorInterface","name":"current","type":"address"}],"name":"ValidatorUpgraded","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAggregators","outputs":[{"internalType":"address","name":"current","type":"address"},{"internalType":"bool","name":"hasProposal","type":"bool"},{"internalType":"address","name":"proposed","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getValidators","outputs":[{"internalType":"contract AggregatorValidatorInterface","name":"current","type":"address"},{"internalType":"bool","name":"hasProposal","type":"bool"},{"internalType":"contract AggregatorValidatorInterface","name":"proposed","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proposed","type":"address"}],"name":"proposeNewAggregator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AggregatorValidatorInterface","name":"proposed","type":"address"}],"name":"proposeNewValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"upgradeAggregator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upgradeValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"previousRoundId","type":"uint256"},{"internalType":"int256","name":"previousAnswer","type":"int256"},{"internalType":"uint256","name":"currentRoundId","type":"uint256"},{"internalType":"int256","name":"currentAnswer","type":"int256"}],"name":"validate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b50604051610c64380380610c6483398101604081905261002f91610098565b600080546001600160a01b031916331781556040805180820182526001600160a01b039485168082526020918201849052600280546001600160a81b031990811690921790558251808401909352939094168082529301526004805490911690911790556100e9565b600080604083850312156100aa578182fd5b82516100b5816100d1565b60208401519092506100c6816100d1565b809150509250929050565b6001600160a01b03811681146100e657600080fd5b50565b610b6c806100f86000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80638da5cb5b116100715780638da5cb5b1461015b57806394ce943b14610176578063b7ab4db514610189578063beed9b51146101ac578063c97f7856146101cf578063f2fde38b146101d757600080fd5b8063181f5a77146100ae57806359112a4e146100ed5780637903677f1461010257806379ba50971461010a5780637ee7f7d114610112575b600080fd5b6040805180820182526014815273056616c696461746f7250726f787920312e302e360641b602082015290516100e49190610a8b565b60405180910390f35b6101006100fb366004610a1b565b6101ea565b005b6101006102e9565b6101006103f4565b6002546003546001600160a01b0380831692600160a01b900460ff1691165b604080516001600160a01b03948516815292151560208401529216918101919091526060016100e4565b6000546040516001600160a01b0390911681526020016100e4565b610100610184366004610a1b565b61049e565b6004546005546001600160a01b0380831692600160a01b900460ff169116610131565b6101bf6101ba366004610a3e565b610593565b60405190151581526020016100e4565b61010061083c565b6101006101e5366004610a1b565b610947565b6000546001600160a01b0316331461021d5760405162461bcd60e51b815260040161021490610abe565b60405180910390fd5b6003546001600160a01b0382811691161480159061024957506002546001600160a01b03828116911614155b6102885760405162461bcd60e51b815260206004820152601060248201526f125b9d985b1a59081c1c9bdc1bdcd85b60821b6044820152606401610214565b600380546001600160a01b0319166001600160a01b0383169081179091556002805460ff60a01b1916821515600160a01b021790556040517f5f9c9d260db95e6065c958ac4462171e7a8e70c0c5a7e1864ec8e425c3348de790600090a250565b6000546001600160a01b031633146103135760405162461bcd60e51b815260040161021490610abe565b604080518082019091526004546001600160a01b03808216808452600160a01b90920460ff16151560208401819052600554909116906103835760405162461bcd60e51b815260206004820152600b60248201526a139bc81c1c9bdc1bdcd85b60aa1b6044820152606401610214565b6040805180820182526001600160a01b0380841680835260006020909301839052600480546001600160a81b03191682179055600580546001600160a01b03191690559251908516917fb78a7598213b871cdb0b5cf984a129fa34c321bfd3b74073ba5147e0e3f1c33c91a3505050565b6001546001600160a01b031633146104475760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b6044820152606401610214565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000546001600160a01b031633146104c85760405162461bcd60e51b815260040161021490610abe565b6005546001600160a01b038281169116148015906104f457506004546001600160a01b03828116911614155b6105335760405162461bcd60e51b815260206004820152601060248201526f125b9d985b1a59081c1c9bdc1bdcd85b60821b6044820152606401610214565b600580546001600160a01b0319166001600160a01b0383169081179091556004805460ff60a01b1916821515600160a01b021790556040517e2d79d30d9a290b4aa306dc3542d81c243b1f679b4083044b9723d2378600be90600090a250565b6002546000906001600160a01b0316338114610662576003546001600160a01b03163381146106045760405162461bcd60e51b815260206004820152601b60248201527f4e6f74206120636f6e666967757265642061676772656761746f7200000000006044820152606401610214565b6040805188815260208101889052908101869052606081018590526001600160a01b038216907f5a76b3e9adddfd8f853f50a26cb51f7e4cfef4fbaf1d49df7da37b90119aba789060800160405180910390a2600192505050610834565b604080518082019091526004546001600160a01b038116808352600160a01b90910460ff1615156020830152806106ce5760405162461bcd60e51b815260206004820152601060248201526f139bc81d985b1a59185d1bdc881cd95d60821b6044820152606401610214565b60408051602481018a9052604481018990526064810188905260848082018890528251808303909101815260a490910182526020810180516001600160e01b031663beed9b5160e01b17905290516001600160a01b0383169161073091610a6f565b6000604051808303816000865af19150503d806000811461076d576040519150601f19603f3d011682016040523d82523d6000602084013e610772565b606091505b50505081602001511561082c5760055460408051602481018b9052604481018a90526064810189905260848082018990528251808303909101815260a490910182526020810180516001600160e01b031663beed9b5160e01b17905290516001600160a01b03909216916107e69190610a6f565b6000604051808303816000865af19150503d8060008114610823576040519150601f19603f3d011682016040523d82523d6000602084013e610828565b606091505b5050505b600193505050505b949350505050565b6000546001600160a01b031633146108665760405162461bcd60e51b815260040161021490610abe565b604080518082019091526002546001600160a01b03808216808452600160a01b90920460ff16151560208401819052600354909116906108d65760405162461bcd60e51b815260206004820152600b60248201526a139bc81c1c9bdc1bdcd85b60aa1b6044820152606401610214565b6040805180820182526001600160a01b0380841680835260006020909301839052600280546001600160a81b03191682179055600380546001600160a01b03191690559251908516917f7005ddb42f7ac176ef55c6adb46b53f52e2832c77e915dad61a643841466ea2191a3505050565b6000546001600160a01b031633146109715760405162461bcd60e51b815260040161021490610abe565b6001600160a01b0381163314156109ca5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610214565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610a2c578081fd5b8135610a3781610b1e565b9392505050565b60008060008060808587031215610a53578283fd5b5050823594602084013594506040840135936060013592509050565b60008251610a81818460208701610aee565b9190910192915050565b6020815260008251806020840152610aaa816040850160208701610aee565b601f01601f19169190910160400192915050565b60208082526016908201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b604082015260600190565b60005b83811015610b09578181015183820152602001610af1565b83811115610b18576000848401525b50505050565b6001600160a01b0381168114610b3357600080fd5b5056fea2646970667358221220667756bba087de6ff4730b3a7600fcf70e66602c0f0f6a70f02472b4302ce54f64736f6c6343000804003300000000000000000000000037bc7498f4ff12c19678ee8fe19d713b87f6a9e60000000000000000000000000000000000000000000000000000000000000000

Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.

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.