-
Notifications
You must be signed in to change notification settings - Fork 12k
Governor #2672
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
Merged
Merged
Governor #2672
Changes from all commits
Commits
Show all changes
202 commits
Select commit
Hold shift + click to select a range
a0fd692
starting work on the Timer contract
Amxx 41367cf
Timers: solidity version
Amxx e7bd166
Rebase onto master
Amxx 5facd4c
support locking timers
Amxx e0311c6
rafactor TimelockController to use Timers
Amxx 18d0d94
renaming timers internal functions
Amxx 4494cc8
add ERC20SnapshotEveryBlock
Amxx 53edd89
add changelog entry
Amxx 10a5b63
testing for ERC20SnapshotEveryBlock
Amxx 512324a
improve snapshoting
Amxx 3f317cd
split Timelock into module (inheritable) and controller (standalone)
Amxx e87de1e
start work on a Comp extension to ERC20
Amxx a235d0c
delegation query cleanup
Amxx 4c17b9a
minor cleanup of comp test
Amxx d4b655c
Merge branch 'feature/ERC20SnapshotBlockNumber' into feature/erc20/comp
Amxx 46aa3cc
remove autodelegation
Amxx fabd802
fix/improve testing for ERC20Comp
Amxx ba43a54
rename ERC20Comp to ERC20Votes
Amxx c9a321d
gas optimization + comp compatibility and tests
Amxx 74812f9
function ordering
Amxx 9e49d5e
minor refactor
Amxx fc83c27
minor gas reduction
Amxx 0678a9f
improve testing
Amxx 321bdf3
remove ERC20SnapsotEveryBlock for now
Amxx 6aa3372
Merge branch 'master' into feature/timers
Amxx 60a28fc
use low level errors in timers
Amxx cbc9b49
overload modifier to keep revert messages in TimelockController
Amxx 95e3d41
Merge branch 'feature/erc20/comp' into feature/governance
Amxx d6efa11
initial governor code
Amxx 009612b
make getVote public
Amxx 837d519
update governor interface
Amxx e1dec20
Merge branch 'master' into feature/governance
Amxx 6fc519e
Fix Changelog
Amxx 13aab40
using uint256 for proposalId
Amxx e2420b2
add some initial governor testing
Amxx 01f38d5
remove Timers abstract contract in favor of the Time library
Amxx dbd5032
reenable internal timelock
Amxx ee5b5ac
rename function in the Time library
Amxx 07eb7c6
revert to 0.8.3
Amxx b984baf
remove timelock changes from this PR
Amxx e0d77d8
merge GovernorCore into Governor
Amxx 8acc1cc
cleanup governance
Amxx f39699f
reduce distance to GovernorAlpha/Bravo events
Amxx c37403b
add timelock() view function in IGovernorWithTimelock
Amxx 0c78480
add description to proposal + make params memory instead of calldata …
Amxx 62c2662
support cancel in timelock
Amxx 46d059d
make execute functions payable
Amxx 0733c67
add comp timelock support(wip)
Amxx 31a1bc2
fix module name
Amxx 3cad527
disable execute function with wrong signature
Amxx 8f68441
fix the signature issue with comp timelock
Amxx e73357f
test comptimelock module for governor
Amxx bb21719
add check
Amxx 2050af7
working on governor testing
Amxx a2501f6
improve test coverage
Amxx 33d0016
improve revert reasons
Amxx 5291af5
add a blockNumber argument to the quorum() function
Amxx f9b5d78
improve governanor coverage
Amxx 2cbb385
complete coverage of governor core and extensions
Amxx 630152e
fix lint
Amxx ae7edba
fix lint
Amxx 81604cc
governor documentation
Amxx 9ac4a1a
fix doc links
Amxx 7e35f9a
remove viewProposalStatus in favor of state
Amxx b0cbd58
improve governor alpha compatibility
Amxx b5fa119
improve soldity style
Amxx 7d8d4c5
check that old timelock has pending admin before updating
Amxx 73adefa
clarify setup of governor with openzeppelin timelock
Amxx ea82e23
improve governor module inheritance and refactor voting arguments
Amxx 46851fa
put voting into modules
Amxx 699f37e
add a proposalScore accessor
Amxx f841315
Merge branch 'master' into feature/governance
Amxx 783bdec
fix governor tests
Amxx 1d71b99
coverage testing of ScoreVoting
Amxx d7f4028
fix lint
Amxx 85f44ca
renaming governor extensions
Amxx a04eff5
mocks with timelock should not have a receive function
Amxx 8668af3
remove extra modules (keept in separate branch)
Amxx d238096
documentation of governor's modules
Amxx cbda273
prevent queueing duplicated sub-calls
Amxx 982d6d1
documentation for the governor
Amxx a30e280
documentation for the governor
Amxx 895a6f0
minor improvement to utils/Time readability
Amxx b7b9f5e
fix linting
Amxx 577be2c
Improve gas efficiency of the voting system
Amxx a8247d9
fix error message testing
Amxx dfe20d2
add a proposalVotes accessor
Amxx 31a9b42
documentation for proposalVotes
Amxx acbb608
Add compound licence
Amxx d0e8456
Move ProposalState enum definition to IGovernor
Amxx 1a48129
Address comments on the PR
Amxx 63c4e05
fix naming mistake
Amxx d30c56c
fix cancel condition
Amxx c17daf0
addressing many issues from the PR
Amxx 5da0219
minor renaming in GovernorVotingSimple
Amxx a299185
fix old natspec comments
Amxx 29c98f2
Merge branch 'master' into feature/governance
Amxx ac618df
update vote modules according to recent ERC20Votes changes
Amxx 909faf0
improve testing
Amxx 37bbbcb
remove dead code
Amxx 48e7ae1
Merge branch 'master' into feature/governance
Amxx 26bdaa9
apply prettifier to the governance contract
Amxx c582c24
turing ternary operator into if/elseif/else for clarity
Amxx 4b687af
run lint:fix with updated dependencies
Amxx 3e4d388
making governor events comp compliant
Amxx f63d273
expand proposalCreated event testing
Amxx a99c8de
store timers in uint64
Amxx 2e1db61
fixe my mess (from changing deadline types to uint64)
Amxx cc42201
fix lint
Amxx 5d4b90c
Working on a comp compatibility layer for the governor
Amxx 32a7cf3
working on comp compatiblity
Amxx 05154ba
fix cancelled & executed status in comp compatibility
Amxx bb5aa87
skip tests if optimization is not enabled
Amxx c5d6eb4
lint:fix
Amxx 83279db
documentation of GovernorCompound
Amxx b68740b
enable all testing + allowUnlimitedContractSize if optimisations are …
Amxx 1b16e0a
renaming struct to improve compound compliance
Amxx 5b89af0
documentation of the GovernorCompound compatibility layer
Amxx 5d82a7e
make revert reason match contract names
Amxx e70dd54
revert change made by early version of the linter
Amxx 3791bb9
store proposal in core interface of comp compatibility layer
Amxx 7f75429
fix contract inheritance to enforce existance of an ordering
Amxx a9e98e1
fix lint (again)
Amxx c39a4c7
reorganise proposals() view function to improve contract size
Amxx 25db6ea
fix lint yet again
Amxx 2413e55
Merge branch 'master' into feature/governance
Amxx 77ea9f5
use proposal description for salt
Amxx f7e7cb4
remove ProposalSalt event made superfluous by the use of description …
Amxx 1c643b8
Merge branch 'master' into feature/governance
Amxx 61f27da
Governor is now scheduled for 4.3
Amxx 498187b
add the proposalThreshold access restriction mechanism, with default …
Amxx 745d20e
make BALLOT_TYPEHASH public
Amxx 9b6dd41
IGovernorTimelock is IGovernor
Amxx 8e3cd7a
deep refactor of IGovernor vs Governor
Amxx 481a279
add erc165 introspection
Amxx 872b1b1
moving more things to IGOvernor
Amxx c0c9584
fix contract ordering, and improve the detector script
Amxx a220cbd
ERC165 testing of governor core
Amxx 1961a74
fix lint
Amxx 867ba31
test GOvernorTimelock interface
Amxx a221e69
interface IGovernorTimelock
Amxx 5de73c5
fix lint
Amxx e22a1ea
replace salt with descriptionHash
Amxx 90050fc
replace salt with descriptionHash in tests
Amxx 4cf2ed6
Merge branch 'master' into feature/governance
Amxx 655f96b
rename governor contracts
Amxx f07cd19
revert changes caused by an old version of prettier
Amxx 4e6a7b2
add quorum ratio to GovernorWithERC20Votes
Amxx 949d11d
quorum is strict, so it is safe to set it to 0, at least 1 vote is st…
Amxx b214fa0
fix lint
Amxx 2468cf6
prevent seting the quorum ratio over the maximum
Amxx 37ad037
use an internal virtual function _executor() instead of a virtual mod…
Amxx 0c0896d
fix lint yet again
Amxx 8a583aa
refactor token modules
Amxx 3675fb4
update tests according to the module renaming
Amxx 5771e5b
expand testing to block number based timers
Amxx ad52976
addressing many comments from the PR & improving compatibility of cor…
Amxx 2eecef8
Rename modules: Voting → Counting & Weight → Votes
Amxx f52e732
fix lint
Amxx 2e1a8ab
remove @notice entires in favor of extended contract description
Amxx eff08aa
fix event link
frangio a277991
fix links
frangio 962fee7
fix abi of proposals(uint256) in the compatibility layer
Amxx f49b2e6
Merge branch 'feature/governance' of github.com:Amxx/openzeppelin-con…
Amxx c096ff2
match governor structure declaration
Amxx c3c9387
knock knock. who's there ? its the linter yet again
Amxx 0a0a08f
address review comments on GovernorTimelockController
Amxx 4be97fc
address review comments on GovernorTimelockCompound
Amxx cf6cd37
make timelock modules hook into the execution module using an interna…
Amxx 3ebb685
fix lint
Amxx 47d608e
imporve state checkers now that the core execution is used
Amxx a59801f
variable naming
Amxx b26b1ab
add checks for revert reason bubbling in execute
Amxx 887c2d3
extend testing of proposal execution with value
Amxx 7c8cb01
minor refactor of governor testing
Amxx e2d6c1e
extend security of the updateTimelock process with Compound timelock
Amxx d862d2b
change argument types to use contract object for tokens and timelocks
Amxx fc7ad04
fix documentation links
Amxx bb5be03
Update contracts/governance/compatibility/GovernorCompatibilityBravo.sol
Amxx ec283a8
Update contracts/governance/extensions/GovernorCountingSimple.sol
Amxx c34d946
rename GovernorTimelockController → GovernorTimelockControl
Amxx 49fce6a
fix recuring typo
Amxx 3a89fd8
fix lint
Amxx ddc0d3d
strict inaquality prevent openning proposal to the wide public
Amxx 26c5ffb
Merge branch 'master' into feature/governance
Amxx be72915
rename GovernorVotesQuorumFractional → GovernorVotesQuorumFraction
Amxx f421783
fix lint
Amxx 5651a98
add test where timelock proposal is executed by another actor
Amxx d41de3d
add testing for proposalDelay
Amxx 66d0fe7
expand governor testing
Amxx 409a1d6
address some issues from the PR
Amxx f0eb4f1
add COUNTING_MODE
frangio 669bc0e
fix lint
Amxx 814c210
fix lint and update readme
Amxx 76cda5f
remove opinionated restrictions to transfer timelock
frangio 24d3ca1
update prettier-plugin-solidity
frangio 66f66e9
remove commented functions
frangio ed3f574
Merge branch 'master' into feature/governance
frangio cd578cf
add changelog entry
frangio df41439
update lockfile
frangio 20beb65
Merge branch 'master' into feature/governance
frangio 42cc0db
Merge branch 'master' into feature/governance
frangio File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,357 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
import "../utils/cryptography/ECDSA.sol"; | ||
import "../utils/cryptography/draft-EIP712.sol"; | ||
import "../utils/introspection/ERC165.sol"; | ||
import "../utils/math/SafeCast.sol"; | ||
import "../utils/Address.sol"; | ||
import "../utils/Context.sol"; | ||
import "../utils/Timers.sol"; | ||
import "./IGovernor.sol"; | ||
|
||
/** | ||
* @dev Core of the governance system, designed to be extended though various modules. | ||
* | ||
* This contract is abstract and requiers several function to be implemented in various modules: | ||
* | ||
* - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote} | ||
* - A voting module must implement {getVotes} | ||
* - Additionanly, the {votingPeriod} must also be implemented | ||
* | ||
* _Available since v4.3._ | ||
*/ | ||
abstract contract Governor is Context, ERC165, EIP712, IGovernor { | ||
using SafeCast for uint256; | ||
using Timers for Timers.BlockNumber; | ||
|
||
bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,uint8 support)"); | ||
|
||
struct ProposalCore { | ||
Timers.BlockNumber voteStart; | ||
Timers.BlockNumber voteEnd; | ||
bool executed; | ||
bool canceled; | ||
} | ||
|
||
string private _name; | ||
|
||
mapping(uint256 => ProposalCore) private _proposals; | ||
|
||
/** | ||
* @dev Restrict access to governor executing address. Some module might override the _executor function to make | ||
* sure this modifier is consistant with the execution model. | ||
*/ | ||
modifier onlyGovernance() { | ||
require(_msgSender() == _executor(), "Governor: onlyGovernance"); | ||
_; | ||
} | ||
|
||
/** | ||
* @dev Sets the value for {name} and {version} | ||
*/ | ||
constructor(string memory name_) EIP712(name_, version()) { | ||
_name = name_; | ||
} | ||
|
||
/** | ||
* @dev See {IERC165-supportsInterface}. | ||
*/ | ||
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) { | ||
return interfaceId == type(IGovernor).interfaceId || super.supportsInterface(interfaceId); | ||
} | ||
|
||
/** | ||
* @dev See {IGovernor-name}. | ||
*/ | ||
function name() public view virtual override returns (string memory) { | ||
return _name; | ||
} | ||
|
||
/** | ||
* @dev See {IGovernor-version}. | ||
*/ | ||
function version() public view virtual override returns (string memory) { | ||
return "1"; | ||
} | ||
|
||
/** | ||
* @dev See {IGovernor-hashProposal}. | ||
Amxx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* | ||
* The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array | ||
* and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id | ||
* can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in | ||
* advance, before the proposal is submitted. | ||
* | ||
* Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the | ||
* same proposal (with same operation and same description) will have the same id if submitted on multiple governors | ||
* accross multiple networks. This also means that in order to execute the same operation twice (on the same | ||
* governor) the proposer will have to change the description in order to avoid proposal id conflicts. | ||
*/ | ||
function hashProposal( | ||
address[] memory targets, | ||
uint256[] memory values, | ||
bytes[] memory calldatas, | ||
bytes32 descriptionHash | ||
) public pure virtual override returns (uint256) { | ||
return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash))); | ||
} | ||
|
||
/** | ||
* @dev See {IGovernor-state}. | ||
*/ | ||
function state(uint256 proposalId) public view virtual override returns (ProposalState) { | ||
ProposalCore memory proposal = _proposals[proposalId]; | ||
|
||
if (proposal.executed) { | ||
return ProposalState.Executed; | ||
} else if (proposal.canceled) { | ||
return ProposalState.Canceled; | ||
} else if (proposal.voteStart.isPending()) { | ||
return ProposalState.Pending; | ||
} else if (proposal.voteEnd.isPending()) { | ||
return ProposalState.Active; | ||
} else if (proposal.voteEnd.isExpired()) { | ||
return | ||
_quorumReached(proposalId) && _voteSucceeded(proposalId) | ||
? ProposalState.Succeeded | ||
: ProposalState.Defeated; | ||
} else { | ||
revert("Governor: unknown proposal id"); | ||
} | ||
} | ||
|
||
/** | ||
* @dev See {IGovernor-proposalSnapshot}. | ||
*/ | ||
function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) { | ||
return _proposals[proposalId].voteStart.getDeadline(); | ||
} | ||
|
||
/** | ||
* @dev See {IGovernor-proposalDeadline}. | ||
*/ | ||
function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) { | ||
return _proposals[proposalId].voteEnd.getDeadline(); | ||
} | ||
|
||
/** | ||
* @dev See {IGovernor-votingDelay} | ||
*/ | ||
function votingDelay() public view virtual override returns (uint256); | ||
|
||
/** | ||
* @dev See {IGovernor-votingPeriod} | ||
*/ | ||
function votingPeriod() public view virtual override returns (uint256); | ||
|
||
/** | ||
* @dev See {IGovernor-quorum} | ||
Amxx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
*/ | ||
function quorum(uint256 blockNumber) public view virtual override returns (uint256); | ||
|
||
/** | ||
* @dev See {IGovernor-getVotes} | ||
*/ | ||
function getVotes(address account, uint256 blockNumber) public view virtual override returns (uint256); | ||
|
||
/** | ||
* @dev Amount of votes already casted passes the threshold limit. | ||
*/ | ||
function _quorumReached(uint256 proposalId) internal view virtual returns (bool); | ||
|
||
/** | ||
* @dev Is the proposal successful or not. | ||
*/ | ||
function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool); | ||
|
||
/** | ||
* @dev Register a vote with a given support and voting weight. | ||
* | ||
* Note: Support is generic and can represent various things depending on the voting system used. | ||
*/ | ||
function _countVote( | ||
uint256 proposalId, | ||
address account, | ||
uint8 support, | ||
uint256 weight | ||
) internal virtual; | ||
|
||
/** | ||
* @dev See {IGovernor-propose}. | ||
*/ | ||
function propose( | ||
address[] memory targets, | ||
uint256[] memory values, | ||
bytes[] memory calldatas, | ||
string memory description | ||
) public virtual override returns (uint256) { | ||
uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description))); | ||
|
||
require(targets.length == values.length, "Governor: invalid proposal length"); | ||
require(targets.length == calldatas.length, "Governor: invalid proposal length"); | ||
require(targets.length > 0, "Governor: empty proposal"); | ||
|
||
ProposalCore storage proposal = _proposals[proposalId]; | ||
require(proposal.voteStart.isUnset(), "Governor: proposal already exists"); | ||
|
||
uint64 snapshot = block.number.toUint64() + votingDelay().toUint64(); | ||
uint64 deadline = snapshot + votingPeriod().toUint64(); | ||
|
||
proposal.voteStart.setDeadline(snapshot); | ||
proposal.voteEnd.setDeadline(deadline); | ||
|
||
emit ProposalCreated( | ||
proposalId, | ||
_msgSender(), | ||
targets, | ||
values, | ||
new string[](targets.length), | ||
calldatas, | ||
snapshot, | ||
deadline, | ||
description | ||
); | ||
|
||
return proposalId; | ||
} | ||
|
||
/** | ||
* @dev See {IGovernor-execute}. | ||
*/ | ||
function execute( | ||
address[] memory targets, | ||
uint256[] memory values, | ||
bytes[] memory calldatas, | ||
bytes32 descriptionHash | ||
) public payable virtual override returns (uint256) { | ||
uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash); | ||
|
||
ProposalState status = state(proposalId); | ||
require( | ||
status == ProposalState.Succeeded || status == ProposalState.Queued, | ||
"Governor: proposal not successful" | ||
); | ||
_proposals[proposalId].executed = true; | ||
|
||
emit ProposalExecuted(proposalId); | ||
|
||
_execute(proposalId, targets, values, calldatas, descriptionHash); | ||
|
||
return proposalId; | ||
} | ||
|
||
/** | ||
* @dev Internal execution mechanism. Can be overriden to implement different execution mechanism | ||
*/ | ||
function _execute( | ||
uint256, /* proposalId */ | ||
address[] memory targets, | ||
uint256[] memory values, | ||
bytes[] memory calldatas, | ||
bytes32 /*descriptionHash*/ | ||
) internal virtual { | ||
string memory errorMessage = "Governor: call reverted without message"; | ||
for (uint256 i = 0; i < targets.length; ++i) { | ||
(bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]); | ||
Address.verifyCallResult(success, returndata, errorMessage); | ||
} | ||
} | ||
|
||
/** | ||
* @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as | ||
* canceled to allow distinguishing it from executed proposals. | ||
* | ||
* Emits a {IGovernor-ProposalCanceled} event. | ||
*/ | ||
function _cancel( | ||
address[] memory targets, | ||
uint256[] memory values, | ||
bytes[] memory calldatas, | ||
bytes32 descriptionHash | ||
) internal virtual returns (uint256) { | ||
uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash); | ||
ProposalState status = state(proposalId); | ||
|
||
require( | ||
status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed, | ||
"Governor: proposal not active" | ||
); | ||
_proposals[proposalId].canceled = true; | ||
|
||
emit ProposalCanceled(proposalId); | ||
Amxx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
return proposalId; | ||
} | ||
|
||
/** | ||
* @dev See {IGovernor-castVote}. | ||
*/ | ||
function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) { | ||
address voter = _msgSender(); | ||
return _castVote(proposalId, voter, support, ""); | ||
} | ||
|
||
/** | ||
* @dev See {IGovernor-castVoteWithReason}. | ||
*/ | ||
function castVoteWithReason( | ||
uint256 proposalId, | ||
uint8 support, | ||
string calldata reason | ||
) public virtual override returns (uint256) { | ||
address voter = _msgSender(); | ||
return _castVote(proposalId, voter, support, reason); | ||
} | ||
|
||
/** | ||
* @dev See {IGovernor-castVoteBySig}. | ||
*/ | ||
function castVoteBySig( | ||
uint256 proposalId, | ||
uint8 support, | ||
uint8 v, | ||
bytes32 r, | ||
bytes32 s | ||
) public virtual override returns (uint256) { | ||
address voter = ECDSA.recover( | ||
_hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))), | ||
v, | ||
r, | ||
s | ||
); | ||
return _castVote(proposalId, voter, support, ""); | ||
} | ||
|
||
/** | ||
* @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been casted yet, retrieve | ||
* voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. | ||
* | ||
* Emits a {IGovernor-VoteCast} event. | ||
*/ | ||
function _castVote( | ||
uint256 proposalId, | ||
address account, | ||
uint8 support, | ||
string memory reason | ||
) internal virtual returns (uint256) { | ||
ProposalCore storage proposal = _proposals[proposalId]; | ||
require(state(proposalId) == ProposalState.Active, "Governor: vote not currently active"); | ||
|
||
uint256 weight = getVotes(account, proposal.voteStart.getDeadline()); | ||
_countVote(proposalId, account, support, weight); | ||
|
||
emit VoteCast(account, proposalId, support, weight, reason); | ||
|
||
return weight; | ||
} | ||
|
||
/** | ||
* @dev Address through which the governor executes action. Will be overloaded by module that execute actions | ||
* through another contract such as a timelock. | ||
*/ | ||
function _executor() internal view virtual returns (address) { | ||
return address(this); | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.