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

Add transition period for continuity #18

Merged
merged 10 commits into from
Aug 27, 2024
Merged

Add transition period for continuity #18

merged 10 commits into from
Aug 27, 2024

Conversation

gershido
Copy link
Collaborator

Proposed elections flow:
Screenshot 2024-08-12 at 16 16 20

@spengrah
Copy link
Member

@gershido I haven't dug into the code in more detail than a cursory review, but overall this approach looks good to me. The diagram is helpful.

Only thing I'd consider is adding an option to set a new transition period as an arg in reelection.

@gershido gershido marked this pull request as ready for review August 13, 2024 14:33
@gershido gershido requested a review from spengrah August 13, 2024 14:33
@@ -20,15 +20,15 @@ contract DeployImplementationTest is DeployImplementation, Test {
// bytes32 public SALT;

uint256 public fork;
uint256 public BLOCK_NUMBER = 9_713_194; // the block number where hats module factory was deployed on Goerli;
uint256 public BLOCK_NUMBER = 6_488_268; // the block number where hats module factory was deployed on Goerli;
Copy link
Member

Choose a reason for hiding this comment

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

sepolia, i assume? If so, please change the comment

src/JokeraceEligibility.sol Outdated Show resolved Hide resolved
@gershido
Copy link
Collaborator Author

Added the following changes:

  • ElectionResultsPulled event. Currently there's no emitted event when the pullElectionResults is successfully called. Adding the event will help indexing the module.
  • Added a condition for the reelectionAllowed function, for the case in which we're in a transition period, the next contest was set but then for some reason was cancelled.

@gershido gershido requested a review from spengrah August 14, 2024 14:38
@@ -31,6 +31,8 @@ contract JokeraceEligibility is HatsEligibilityModule {

/// @notice Emitted when a reelection is set
event NewTerm(address NewContest, uint256 newTopK, uint256 newTermEnd, uint256 newTransitionPeriod);
/// @notice Emitted when election's results are pulled
event ElectionResultsPulled(address NewContest);
Copy link
Member

Choose a reason for hiding this comment

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

would like to see a test for this event

|| (
currentContest != address(0)
&& GovernorCountingSimple(payable(currentContest)).state() == Governor.ContestState.Canceled
) // or if we're in a transition period, and the next contest was canceled
Copy link
Member

Choose a reason for hiding this comment

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

Is there a test for this new logic? I might be missing it, but I don't see one

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Test added

@gershido
Copy link
Collaborator Author

Added:

  • New isTie param in the ElectionResultsPulled event, and emitting the event for the tie scenario also
  • Event tests

@gershido gershido requested a review from spengrah August 15, 2024 11:53
Copy link
Member

@spengrah spengrah left a comment

Choose a reason for hiding this comment

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

looks good! thanks for adding those tests

@gershido
Copy link
Collaborator Author

Following last week's discussion about the election flow, changed the implementation to allow setting up the next term even before the current term has ended. The main implication on the implementation side was that it requires to keep the full set of details for the next term (contest, term end, top K and transition period). Here are the main changes:

  • Terms are saved as indexed TermDetails structs. There's a currentTermIndex variable. The next term will be always saved in currentTermIndex + 1.
  • Name changes: reelection function changed to setNextTerm, pullElectionResults changed to startNextTerm
  • Mapping of eligible wearers was changed from eligibleWearesPerContest to eligibleWearersPerTerm

@gershido gershido requested a review from spengrah August 25, 2024 14:18
Copy link
Member

@spengrah spengrah left a comment

Choose a reason for hiding this comment

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

approving with several suggestions. otherwise, good to go!

/// @notice Emitted when a reelection is set
event NewTerm(address NewContest, uint256 newTopK, uint256 newTermEnd);
/// @notice Emitted when the next term is set
event NextTermSet(address NewContest, uint256 newTopK, uint256 newTermEnd, uint256 newTransitionPeriod);
Copy link
Member

Choose a reason for hiding this comment

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

style: camel case for newContest

/// @notice Term's ending time (a unix timestamp)
uint256 termEnd;
/// @notice Period of time after the term end when previous elected members are still considered eligible until a
/// new term begins.
Copy link
Member

Choose a reason for hiding this comment

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

style: join these two comment lines

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It's automatically formatted like that, the line_length in the foundry.toml file is set to 120.

Copy link
Member

Choose a reason for hiding this comment

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

Oh whoops, I misinterpreted github's ui 🫠

/// @notice Jokerace contest (election)
address contest;
/// @notice First K winners of the contest will be eligible
uint96 topK;
Copy link
Member

Choose a reason for hiding this comment

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

nice storage slot packing :)

function pullElectionResults() public returns (bool success) {
GovernorCountingSimple currentContest = GovernorCountingSimple(payable(underlyingContest));
function startNextTerm() public {
TermDetails memory nextTerm = terms[currentTermIndex + 1];
Copy link
Member

Choose a reason for hiding this comment

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

Since this function only needs topK and contest from the nextTerm object, it will be cheaper here to set nextTerm as a storage pointer rather than SLOADing the entire nextTerm object into memory

ie,

TermDetails stoarge nextTerm = terms[currentTermIndex + 1];

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Screenshot 2024-08-27 at 14 42 30

All the details from the nextTerm object are emitted in the event at the end of the function. A different approach would be to just include the next term's index instead of all the details. That's a bit less good for whoever listens to the event because it will require a call to the contract in order to get the details of this new term. What do you think?

Copy link
Member

Choose a reason for hiding this comment

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

ah good point, i missed the event params! Keep it as is, then.

address candidate = _getCandidate(currentContest, proposalsOfCurrentRank[proposalIndex]);
eligibleWearersPerContest[candidate][address(currentContest)] = true;
address candidate = _getCandidate(contest, proposalsOfCurrentRank[proposalIndex]);
eligibleWearersPerTerm[candidate][currentTermIndex + 1] = true;
Copy link
Member

Choose a reason for hiding this comment

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

this is the second SLOAD of currentTermIndex, so I'd suggest storing this in memory

}

/*//////////////////////////////////////////////////////////////
INTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////*/

function _currentTermEnded(uint256 currentTermEnd) internal view returns (bool allowed) {
Copy link
Member

Choose a reason for hiding this comment

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

Any reason these shouldn't be public functions? Might be nice for front ends to be able to easily get these sub-components of canStartNextTerm

Copy link
Collaborator Author

@gershido gershido Aug 27, 2024

Choose a reason for hiding this comment

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

Added two separate public functions: currentTermEnded and nextContestCompleted, that wrap the internal ones. The reason for the separate public functions is to make them input-less, while the internal ones receive input params to save fetches from storage (in the cases where the function that uses the internal function already fetched this param from storage for other purposes).

@gershido gershido merged commit 36634c9 into main Aug 27, 2024
3 checks passed
@gershido gershido deleted the add-grace-period branch August 27, 2024 19:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants