Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ValidatorProxy contract 🔀 (& Hardhat support for v0.8 contracts 👷‍♂️👀) #4265

Merged
merged 10 commits into from Apr 26, 2021

Conversation

alexroan
Copy link
Contributor

No description provided.

@alexroan alexroan added the making changes PR is not ready for review label Apr 22, 2021
@shortcut-integration
Copy link

This pull request has been linked to Clubhouse Story #7923: Create a ValidatorProxy contract.

@github-actions
Copy link
Contributor

I see that you haven't updated any CHANGELOG files. Would it make sense to do so?

evm-contracts/src/v0.8/dev/ValidatorProxy.sol Outdated Show resolved Hide resolved
evm-contracts/src/v0.8/dev/ValidatorProxy.sol Show resolved Hide resolved
evm-contracts/src/v0.8/dev/ValidatorProxy.sol Outdated Show resolved Hide resolved
evm-contracts/src/v0.8/dev/ValidatorProxy.sol Show resolved Hide resolved
evm-contracts/src/v0.8/dev/ValidatorProxy.sol Outdated Show resolved Hide resolved
@alexroan alexroan changed the title ValidatorProxy contract 🔀 ValidatorProxy contract 🔀 (& Hardhat support for v0.8 contracts 👀) Apr 23, 2021
@alexroan alexroan marked this pull request as ready for review April 26, 2021 14:46
@alexroan alexroan added ready for review PR is ready for code review and removed making changes PR is not ready for review labels Apr 26, 2021
@alexroan alexroan changed the title ValidatorProxy contract 🔀 (& Hardhat support for v0.8 contracts 👀) ValidatorProxy contract 🔀 (& Hardhat support for v0.8 contracts 👷‍♂️👀) Apr 26, 2021
@alexroan alexroan merged commit 819fa7d into develop Apr 26, 2021
@alexroan alexroan deleted the feature/ch7923 branch April 26, 2021 19:34
Copy link
Contributor

@kaleofduty kaleofduty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more feedback


/// @notice Uses a single storage slot to store the current address
struct ProxyConfiguration {
address target;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could make this AggregatorValidatorInterface target to save yourself some casts

Copy link
Contributor Author

@alexroan alexroan Apr 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't ideal because this struct is also used for the aggregator, which doesn't conform to that interface.

Since this is the case, I don't like the idea of using addresses for some state variables and AggregatorValidatorInterface for others.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about separate structs for separate purposes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could, but they are essentially the same thing, and it would make other state vars mismatch. So this:

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

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

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

  event AggregatorProposed(
    address indexed aggregator
  );
  event AggregatorUpgraded(
    address indexed previous,
    address indexed current
  );
  event ValidatorProposed(
    address indexed validator
  );
  event ValidatorUpgraded(
    address indexed previous,
    address 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
  );

becomes a bit messier:

  /// @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
  );

Since aggregators will be the address type anyway, it starts to get a bit messy. It's purely aesthetic, but I feel using address across the board and having a single struct is more elegant.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me the second looks cleaner plus you get more type safety.

// Configuration for the current validator
ProxyConfiguration private s_currentValidator;
// Proposed validator address
address private s_proposedValidator;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto, could be AggregatorValidatorInterface

address indexed current
);
event ValidatorProposed(
address indexed validator
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

address proposed = s_proposedAggregator;

// Perform the upgrade
require(current.hasNewProposal == true, "No proposal");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
require(current.hasNewProposal == true, "No proposal");
require(current.hasNewProposal, "No proposal");

current.target = proposed;
current.hasNewProposal = false;

s_currentAggregator = current;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer initializing a new struct here since it forces you to not forget any fields

Suggested change
s_currentAggregator = current;
s_currentAggregator = ProxyConfiguration({
target: proposed,
hasNewProposal: false
});

current.target = proposed;
current.hasNewProposal = false;

s_currentValidator = current;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto struct initializer

s_proposedAggregator = proposed;
// If proposed is zero address, hasNewProposal = false
s_currentAggregator.hasNewProposal = (proposed != address(0));
emit AggregatorProposed(proposed);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we usually try to filter duplicate logs

s_proposedValidator = proposed;
// If proposed is zero address, hasNewProposal = false
s_currentValidator.hasNewProposal = (proposed != address(0));
emit ValidatorProposed(proposed);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto duplicate logs

Comment on lines +59 to +60
s_currentAggregator.target = aggregator;
s_currentValidator.target = validator;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you initialize these using the full struct initializer syntax as well?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready for review PR is ready for code review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants