Skip to content
This repository has been archived by the owner on Nov 27, 2024. It is now read-only.

Commit

Permalink
fix: time period checks (#72)
Browse files Browse the repository at this point in the history
**Motivation:**

There were some issues with our current time period checks. We need to
fix them such that there's no overlapping time periods or gaps in time
periods. And it should also respect the underlying approval and
disapproval periods in the Llama framework.

**Modifications:**

* All time period checks start from the beginning and now progress
forward.
* Fix `getPastVotes` to use `delayPeriodEndTime` instead of
`action.creationTime - 1` (Since voting period starts at
`delayPeriodEndTime + 1`).
* Fix `getPastTotalSupply` to use `delayPeriodEndTime` instead of
`action.creationTime - 1` (Since voting period starts at
`delayPeriodEndTime + 1`).
* Fix where castingPeriodEndTime was being calculated wrong (due to
forgetting to include voting delay in the calculation)

**Result:**

No time period related issues. Closes #32
  • Loading branch information
0xrajath authored Dec 16, 2023
1 parent e7c747a commit dd2b930
Show file tree
Hide file tree
Showing 4 changed files with 363 additions and 296 deletions.
89 changes: 48 additions & 41 deletions src/token-voting/LlamaTokenCaster.sol
Original file line number Diff line number Diff line change
Expand Up @@ -317,19 +317,22 @@ contract LlamaTokenCaster is Initializable {

actionInfo.strategy.checkIfApprovalEnabled(actionInfo, address(this), role); // Reverts if not allowed.
if (casts[actionInfo.id].approvalSubmitted) revert AlreadySubmittedApproval();
// check to make sure the casting period has ended
uint256 approvalPeriod = actionInfo.strategy.approvalPeriod();
(, uint16 castingPeriodPct,) = periodPctsCheckpoint.getAtProbablyRecentTimestamp(action.creationTime - 1);
if (block.timestamp < action.creationTime + (approvalPeriod * castingPeriodPct) / ONE_HUNDRED_IN_BPS) {
revert CannotSubmitYet();
}

if (block.timestamp > action.creationTime + approvalPeriod) revert SubmissionPeriodOver();

// Reverts if clock or CLOCK_MODE() has changed
tokenAdapter.checkIfInconsistentClock();

uint256 totalSupply = tokenAdapter.getPastTotalSupply(tokenAdapter.timestampToTimepoint(action.creationTime) - 1);
// Checks to ensure it's the submission period.
(uint16 delayPeriodPct, uint16 castingPeriodPct,) =
periodPctsCheckpoint.getAtProbablyRecentTimestamp(action.creationTime - 1);
uint256 approvalPeriod = actionInfo.strategy.approvalPeriod();
uint256 delayPeriodEndTime = action.creationTime + ((approvalPeriod * delayPeriodPct) / ONE_HUNDRED_IN_BPS);
uint256 castingPeriodEndTime = delayPeriodEndTime + ((approvalPeriod * castingPeriodPct) / ONE_HUNDRED_IN_BPS);
if (block.timestamp <= castingPeriodEndTime) revert CannotSubmitYet();
// Doing (action.creationTime + approvalPeriod) vs (castingPeriodEndTime + ((approvalPeriod * submissionPeriodPct) /
// ONE_HUNDRED_IN_BPS)) to prevent any off-by-one errors due to precision loss.
// Llama approval period is inclusive of approval end time.
if (block.timestamp > action.creationTime + approvalPeriod) revert SubmissionPeriodOver();

uint256 totalSupply = tokenAdapter.getPastTotalSupply(tokenAdapter.timestampToTimepoint(delayPeriodEndTime));
uint96 votesFor = casts[actionInfo.id].votesFor;
uint96 votesAgainst = casts[actionInfo.id].votesAgainst;
uint96 votesAbstain = casts[actionInfo.id].votesAbstain;
Expand All @@ -351,19 +354,23 @@ contract LlamaTokenCaster is Initializable {

actionInfo.strategy.checkIfDisapprovalEnabled(actionInfo, address(this), role); // Reverts if not allowed.
if (casts[actionInfo.id].disapprovalSubmitted) revert AlreadySubmittedDisapproval();
// Reverts if clock or CLOCK_MODE() has changed
tokenAdapter.checkIfInconsistentClock();

// Checks to ensure it's the submission period.
(uint16 delayPeriodPct, uint16 castingPeriodPct,) =
periodPctsCheckpoint.getAtProbablyRecentTimestamp(action.creationTime - 1);
uint256 queuingPeriod = actionInfo.strategy.queuingPeriod();
(,, uint16 submissionPeriodPct) = periodPctsCheckpoint.getAtProbablyRecentTimestamp(action.creationTime - 1);
// check to make sure the current timestamp is within the submitDisapprovalBuffer 9period
if (block.timestamp < action.minExecutionTime - (queuingPeriod * submissionPeriodPct) / ONE_HUNDRED_IN_BPS) {
revert CannotSubmitYet();
}
uint256 delayPeriodEndTime =
(action.minExecutionTime - queuingPeriod) + ((queuingPeriod * delayPeriodPct) / ONE_HUNDRED_IN_BPS);
uint256 castingPeriodEndTime = delayPeriodEndTime + ((queuingPeriod * castingPeriodPct) / ONE_HUNDRED_IN_BPS);
// Doing (castingPeriodEndTime) vs (action.minExecutionTime - ((queuingPeriod * submissionPeriodPct) /
// ONE_HUNDRED_IN_BPS)) to prevent any off-by-one errors due to precision loss.
if (block.timestamp <= castingPeriodEndTime) revert CannotSubmitYet();
// Llama disapproval period is exclusive of min execution time.
if (block.timestamp >= action.minExecutionTime) revert SubmissionPeriodOver();

// Reverts if clock or CLOCK_MODE() has changed
tokenAdapter.checkIfInconsistentClock();

uint256 totalSupply = tokenAdapter.getPastTotalSupply(tokenAdapter.timestampToTimepoint(action.creationTime) - 1);
uint256 totalSupply = tokenAdapter.getPastTotalSupply(tokenAdapter.timestampToTimepoint(delayPeriodEndTime));
uint96 vetoesFor = casts[actionInfo.id].vetoesFor;
uint96 vetoesAgainst = casts[actionInfo.id].vetoesAgainst;
uint96 vetoesAbstain = casts[actionInfo.id].vetoesAbstain;
Expand Down Expand Up @@ -491,26 +498,26 @@ contract LlamaTokenCaster is Initializable {
actionInfo.strategy.checkIfApprovalEnabled(actionInfo, address(this), role); // Reverts if not allowed.
if (llamaCore.getActionState(actionInfo) != uint8(ActionState.Active)) revert ActionNotActive();
if (casts[actionInfo.id].castVote[caster]) revert AlreadyCastedVote();
_preCastAssertions(support);

// Checks to ensure it's the casting period.
(uint16 delayPeriodPct, uint16 castingPeriodPct,) =
periodPctsCheckpoint.getAtProbablyRecentTimestamp(action.creationTime - 1);
uint256 approvalPeriod = actionInfo.strategy.approvalPeriod();
uint256 delayPeriodTimestamp = action.creationTime + (approvalPeriod * delayPeriodPct) / ONE_HUNDRED_IN_BPS;
if (block.timestamp < delayPeriodTimestamp) revert VotingDelayNotOver();
if (block.timestamp > action.creationTime + (approvalPeriod * castingPeriodPct) / ONE_HUNDRED_IN_BPS) {
revert CastingPeriodOver();
}
uint256 delayPeriodEndTime = action.creationTime + ((approvalPeriod * delayPeriodPct) / ONE_HUNDRED_IN_BPS);
uint256 castingPeriodEndTime = delayPeriodEndTime + ((approvalPeriod * castingPeriodPct) / ONE_HUNDRED_IN_BPS);
if (block.timestamp <= delayPeriodEndTime) revert VotingDelayNotOver();
if (block.timestamp > castingPeriodEndTime) revert CastingPeriodOver();

uint96 weight = LlamaUtils.toUint96(
tokenAdapter.getPastVotes(caster, tokenAdapter.timestampToTimepoint(delayPeriodTimestamp) - 1)
);
_preCastAssertions(support);
uint96 weight =
LlamaUtils.toUint96(tokenAdapter.getPastVotes(caster, tokenAdapter.timestampToTimepoint(delayPeriodEndTime)));

if (support == uint8(VoteType.Against)) casts[actionInfo.id].votesAgainst += weight;
else if (support == uint8(VoteType.For)) casts[actionInfo.id].votesFor += weight;
else if (support == uint8(VoteType.Abstain)) casts[actionInfo.id].votesAbstain += weight;
casts[actionInfo.id].castVote[caster] = true;
emit VoteCast(actionInfo.id, caster, support, weight, reason);

emit VoteCast(actionInfo.id, caster, support, weight, reason);
return weight;
}

Expand All @@ -524,27 +531,27 @@ contract LlamaTokenCaster is Initializable {
actionInfo.strategy.checkIfDisapprovalEnabled(actionInfo, address(this), role); // Reverts if not allowed.
if (llamaCore.getActionState(actionInfo) != uint8(ActionState.Queued)) revert ActionNotQueued();
if (casts[actionInfo.id].castVeto[caster]) revert AlreadyCastedVeto();
(uint16 delayPeriodPct,, uint16 submissionPeriodPct) =
_preCastAssertions(support);

// Checks to ensure it's the casting period.
(uint16 delayPeriodPct, uint16 castingPeriodPct,) =
periodPctsCheckpoint.getAtProbablyRecentTimestamp(action.creationTime - 1);
uint256 queuingPeriod = actionInfo.strategy.queuingPeriod();
uint256 delayPeriodTimestamp =
action.minExecutionTime - queuingPeriod + (queuingPeriod * delayPeriodPct) / ONE_HUNDRED_IN_BPS;
if (block.timestamp < delayPeriodTimestamp) revert VotingDelayNotOver();
if (block.timestamp > action.minExecutionTime - (queuingPeriod * submissionPeriodPct) / ONE_HUNDRED_IN_BPS) {
revert CastingPeriodOver();
}
uint256 delayPeriodEndTime =
(action.minExecutionTime - queuingPeriod) + ((queuingPeriod * delayPeriodPct) / ONE_HUNDRED_IN_BPS);
uint256 castingPeriodEndTime = delayPeriodEndTime + ((queuingPeriod * castingPeriodPct) / ONE_HUNDRED_IN_BPS);
if (block.timestamp <= delayPeriodEndTime) revert VotingDelayNotOver();
if (block.timestamp > castingPeriodEndTime) revert CastingPeriodOver();

uint96 weight = LlamaUtils.toUint96(
tokenAdapter.getPastVotes(caster, tokenAdapter.timestampToTimepoint(delayPeriodTimestamp) - 1)
);
_preCastAssertions(support);
uint96 weight =
LlamaUtils.toUint96(tokenAdapter.getPastVotes(caster, tokenAdapter.timestampToTimepoint(delayPeriodEndTime)));

if (support == uint8(VoteType.Against)) casts[actionInfo.id].vetoesAgainst += weight;
else if (support == uint8(VoteType.For)) casts[actionInfo.id].vetoesFor += weight;
else if (support == uint8(VoteType.Abstain)) casts[actionInfo.id].vetoesAbstain += weight;
casts[actionInfo.id].castVeto[caster] = true;
emit VetoCast(actionInfo.id, caster, support, weight, reason);

emit VetoCast(actionInfo.id, caster, support, weight, reason);
return weight;
}

Expand Down
Loading

0 comments on commit dd2b930

Please sign in to comment.