Refactor Governor proposal struct for efficient access (#4495)

Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
pull/4512/head
Vladislav Volosnikov 2 years ago committed by GitHub
parent b81bec4552
commit 54a235f895
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 51
      contracts/governance/Governor.sol

@ -40,22 +40,13 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
uint32 voteDuration; uint32 voteDuration;
bool executed; bool executed;
bool canceled; bool canceled;
}
struct ProposalExtra {
uint48 eta; uint48 eta;
} }
// Each object in this should fit into a single slot so it can be cached efficiently
struct ProposalFull {
ProposalCore core;
ProposalExtra extra;
}
bytes32 private constant _ALL_PROPOSAL_STATES_BITMAP = bytes32((2 ** (uint8(type(ProposalState).max) + 1)) - 1); bytes32 private constant _ALL_PROPOSAL_STATES_BITMAP = bytes32((2 ** (uint8(type(ProposalState).max) + 1)) - 1);
string private _name; string private _name;
mapping(uint256 => ProposalFull) private _proposals; mapping(uint256 => ProposalCore) private _proposals;
// This queue keeps track of the governor operating on itself. Calls to functions protected by the // This queue keeps track of the governor operating on itself. Calls to functions protected by the
// {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute}, // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},
@ -144,13 +135,16 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
* @dev See {IGovernor-state}. * @dev See {IGovernor-state}.
*/ */
function state(uint256 proposalId) public view virtual override returns (ProposalState) { function state(uint256 proposalId) public view virtual override returns (ProposalState) {
// ProposalCore is just one slot. We can load it from storage to memory with a single sload and use memory // ProposalCore is just one slot. We can load it from storage to stack with a single sload
// object as a cache. This avoid duplicating expensive sloads. ProposalCore storage proposal = _proposals[proposalId];
ProposalCore memory core = _proposals[proposalId].core; bool proposalExecuted = proposal.executed;
bool proposalCanceled = proposal.canceled;
if (core.executed) { if (proposalExecuted) {
return ProposalState.Executed; return ProposalState.Executed;
} else if (core.canceled) { }
if (proposalCanceled) {
return ProposalState.Canceled; return ProposalState.Canceled;
} }
@ -190,28 +184,28 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
* @dev See {IGovernor-proposalSnapshot}. * @dev See {IGovernor-proposalSnapshot}.
*/ */
function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) { function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {
return _proposals[proposalId].core.voteStart; return _proposals[proposalId].voteStart;
} }
/** /**
* @dev See {IGovernor-proposalDeadline}. * @dev See {IGovernor-proposalDeadline}.
*/ */
function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) { function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {
return _proposals[proposalId].core.voteStart + _proposals[proposalId].core.voteDuration; return _proposals[proposalId].voteStart + _proposals[proposalId].voteDuration;
} }
/** /**
* @dev See {IGovernor-proposalProposer}. * @dev See {IGovernor-proposalProposer}.
*/ */
function proposalProposer(uint256 proposalId) public view virtual override returns (address) { function proposalProposer(uint256 proposalId) public view virtual override returns (address) {
return _proposals[proposalId].core.proposer; return _proposals[proposalId].proposer;
} }
/** /**
* @dev See {IGovernor-proposalEta}. * @dev See {IGovernor-proposalEta}.
*/ */
function proposalEta(uint256 proposalId) public view virtual override returns (uint256) { function proposalEta(uint256 proposalId) public view virtual override returns (uint256) {
return _proposals[proposalId].extra.eta; return _proposals[proposalId].eta;
} }
/** /**
@ -311,20 +305,17 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
if (targets.length != values.length || targets.length != calldatas.length || targets.length == 0) { if (targets.length != values.length || targets.length != calldatas.length || targets.length == 0) {
revert GovernorInvalidProposalLength(targets.length, calldatas.length, values.length); revert GovernorInvalidProposalLength(targets.length, calldatas.length, values.length);
} }
if (_proposals[proposalId].core.voteStart != 0) { if (_proposals[proposalId].voteStart != 0) {
revert GovernorUnexpectedProposalState(proposalId, state(proposalId), bytes32(0)); revert GovernorUnexpectedProposalState(proposalId, state(proposalId), bytes32(0));
} }
uint256 snapshot = clock() + votingDelay(); uint256 snapshot = clock() + votingDelay();
uint256 duration = votingPeriod(); uint256 duration = votingPeriod();
_proposals[proposalId].core = ProposalCore({ ProposalCore storage proposal = _proposals[proposalId];
proposer: proposer, proposal.proposer = proposer;
voteStart: SafeCast.toUint48(snapshot), proposal.voteStart = SafeCast.toUint48(snapshot);
voteDuration: SafeCast.toUint32(duration), proposal.voteDuration = SafeCast.toUint32(duration);
executed: false,
canceled: false
});
emit ProposalCreated( emit ProposalCreated(
proposalId, proposalId,
@ -357,7 +348,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
uint48 eta = _queueOperations(proposalId, targets, values, calldatas, descriptionHash); uint48 eta = _queueOperations(proposalId, targets, values, calldatas, descriptionHash);
if (eta != 0) { if (eta != 0) {
_proposals[proposalId].extra.eta = eta; _proposals[proposalId].eta = eta;
emit ProposalQueued(proposalId, eta); emit ProposalQueued(proposalId, eta);
} else { } else {
revert GovernorQueueNotImplemented(); revert GovernorQueueNotImplemented();
@ -406,7 +397,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
); );
// mark as executed before calls to avoid reentrancy // mark as executed before calls to avoid reentrancy
_proposals[proposalId].core.executed = true; _proposals[proposalId].executed = true;
// before execute: register governance call in queue. // before execute: register governance call in queue.
if (_executor() != address(this)) { if (_executor() != address(this)) {
@ -494,7 +485,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
_encodeStateBitmap(ProposalState.Executed) _encodeStateBitmap(ProposalState.Executed)
); );
_proposals[proposalId].core.canceled = true; _proposals[proposalId].canceled = true;
emit ProposalCanceled(proposalId); emit ProposalCanceled(proposalId);
return proposalId; return proposalId;

Loading…
Cancel
Save