|
|
|
@ -40,22 +40,13 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 |
|
|
|
|
uint32 voteDuration; |
|
|
|
|
bool executed; |
|
|
|
|
bool canceled; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct ProposalExtra { |
|
|
|
|
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); |
|
|
|
|
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 |
|
|
|
|
// {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}. |
|
|
|
|
*/ |
|
|
|
|
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 |
|
|
|
|
// object as a cache. This avoid duplicating expensive sloads. |
|
|
|
|
ProposalCore memory core = _proposals[proposalId].core; |
|
|
|
|
// ProposalCore is just one slot. We can load it from storage to stack with a single sload |
|
|
|
|
ProposalCore storage proposal = _proposals[proposalId]; |
|
|
|
|
bool proposalExecuted = proposal.executed; |
|
|
|
|
bool proposalCanceled = proposal.canceled; |
|
|
|
|
|
|
|
|
|
if (core.executed) { |
|
|
|
|
if (proposalExecuted) { |
|
|
|
|
return ProposalState.Executed; |
|
|
|
|
} else if (core.canceled) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (proposalCanceled) { |
|
|
|
|
return ProposalState.Canceled; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -190,28 +184,28 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 |
|
|
|
|
* @dev See {IGovernor-proposalSnapshot}. |
|
|
|
|
*/ |
|
|
|
|
function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) { |
|
|
|
|
return _proposals[proposalId].core.voteStart; |
|
|
|
|
return _proposals[proposalId].voteStart; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @dev See {IGovernor-proposalDeadline}. |
|
|
|
|
*/ |
|
|
|
|
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}. |
|
|
|
|
*/ |
|
|
|
|
function proposalProposer(uint256 proposalId) public view virtual override returns (address) { |
|
|
|
|
return _proposals[proposalId].core.proposer; |
|
|
|
|
return _proposals[proposalId].proposer; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @dev See {IGovernor-proposalEta}. |
|
|
|
|
*/ |
|
|
|
|
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) { |
|
|
|
|
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)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint256 snapshot = clock() + votingDelay(); |
|
|
|
|
uint256 duration = votingPeriod(); |
|
|
|
|
|
|
|
|
|
_proposals[proposalId].core = ProposalCore({ |
|
|
|
|
proposer: proposer, |
|
|
|
|
voteStart: SafeCast.toUint48(snapshot), |
|
|
|
|
voteDuration: SafeCast.toUint32(duration), |
|
|
|
|
executed: false, |
|
|
|
|
canceled: false |
|
|
|
|
}); |
|
|
|
|
ProposalCore storage proposal = _proposals[proposalId]; |
|
|
|
|
proposal.proposer = proposer; |
|
|
|
|
proposal.voteStart = SafeCast.toUint48(snapshot); |
|
|
|
|
proposal.voteDuration = SafeCast.toUint32(duration); |
|
|
|
|
|
|
|
|
|
emit ProposalCreated( |
|
|
|
|
proposalId, |
|
|
|
@ -357,7 +348,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 |
|
|
|
|
uint48 eta = _queueOperations(proposalId, targets, values, calldatas, descriptionHash); |
|
|
|
|
|
|
|
|
|
if (eta != 0) { |
|
|
|
|
_proposals[proposalId].extra.eta = eta; |
|
|
|
|
_proposals[proposalId].eta = eta; |
|
|
|
|
emit ProposalQueued(proposalId, eta); |
|
|
|
|
} else { |
|
|
|
|
revert GovernorQueueNotImplemented(); |
|
|
|
@ -406,7 +397,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
// mark as executed before calls to avoid reentrancy |
|
|
|
|
_proposals[proposalId].core.executed = true; |
|
|
|
|
_proposals[proposalId].executed = true; |
|
|
|
|
|
|
|
|
|
// before execute: register governance call in queue. |
|
|
|
|
if (_executor() != address(this)) { |
|
|
|
@ -494,7 +485,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 |
|
|
|
|
_encodeStateBitmap(ProposalState.Executed) |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
_proposals[proposalId].core.canceled = true; |
|
|
|
|
_proposals[proposalId].canceled = true; |
|
|
|
|
emit ProposalCanceled(proposalId); |
|
|
|
|
|
|
|
|
|
return proposalId; |
|
|
|
|