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

Governor #2672

Merged
merged 202 commits into from
Jul 16, 2021
Merged
Show file tree
Hide file tree
Changes from 81 commits
Commits
Show all changes
202 commits
Select commit Hold shift + click to select a range
a0fd692
starting work on the Timer contract
Amxx Jan 4, 2021
41367cf
Timers: solidity version
Amxx Jan 4, 2021
e7bd166
Rebase onto master
Amxx Feb 23, 2021
5facd4c
support locking timers
Amxx Mar 4, 2021
e0311c6
rafactor TimelockController to use Timers
Amxx Mar 4, 2021
18d0d94
renaming timers internal functions
Amxx Mar 4, 2021
4494cc8
add ERC20SnapshotEveryBlock
Amxx Mar 12, 2021
53edd89
add changelog entry
Amxx Mar 12, 2021
10a5b63
testing for ERC20SnapshotEveryBlock
Amxx Mar 23, 2021
512324a
improve snapshoting
Amxx Mar 24, 2021
3f317cd
split Timelock into module (inheritable) and controller (standalone)
Amxx Mar 25, 2021
e87de1e
start work on a Comp extension to ERC20
Amxx Apr 18, 2021
a235d0c
delegation query cleanup
Amxx Apr 18, 2021
4c17b9a
minor cleanup of comp test
Amxx Apr 19, 2021
d4b655c
Merge branch 'feature/ERC20SnapshotBlockNumber' into feature/erc20/comp
Amxx Apr 19, 2021
46aa3cc
remove autodelegation
Amxx Apr 20, 2021
fabd802
fix/improve testing for ERC20Comp
Amxx Apr 20, 2021
ba43a54
rename ERC20Comp to ERC20Votes
Amxx Apr 20, 2021
c9a321d
gas optimization + comp compatibility and tests
Amxx Apr 28, 2021
74812f9
function ordering
Amxx Apr 28, 2021
9e49d5e
minor refactor
Amxx Apr 28, 2021
fc83c27
minor gas reduction
Amxx Apr 28, 2021
0678a9f
improve testing
Amxx Apr 28, 2021
321bdf3
remove ERC20SnapsotEveryBlock for now
Amxx Apr 28, 2021
6aa3372
Merge branch 'master' into feature/timers
Amxx May 3, 2021
60a28fc
use low level errors in timers
Amxx May 3, 2021
cbc9b49
overload modifier to keep revert messages in TimelockController
Amxx May 3, 2021
95e3d41
Merge branch 'feature/erc20/comp' into feature/governance
Amxx May 3, 2021
d6efa11
initial governor code
Amxx May 3, 2021
009612b
make getVote public
Amxx May 10, 2021
837d519
update governor interface
Amxx May 14, 2021
e1dec20
Merge branch 'master' into feature/governance
Amxx May 14, 2021
6fc519e
Fix Changelog
Amxx May 14, 2021
13aab40
using uint256 for proposalId
Amxx May 14, 2021
e2420b2
add some initial governor testing
Amxx May 14, 2021
01f38d5
remove Timers abstract contract in favor of the Time library
Amxx May 14, 2021
dbd5032
reenable internal timelock
Amxx May 14, 2021
ee5b5ac
rename function in the Time library
Amxx May 14, 2021
07eb7c6
revert to 0.8.3
Amxx May 15, 2021
b984baf
remove timelock changes from this PR
Amxx May 18, 2021
e0d77d8
merge GovernorCore into Governor
Amxx May 18, 2021
8acc1cc
cleanup governance
Amxx May 19, 2021
f39699f
reduce distance to GovernorAlpha/Bravo events
Amxx May 19, 2021
c37403b
add timelock() view function in IGovernorWithTimelock
Amxx May 19, 2021
0c78480
add description to proposal + make params memory instead of calldata …
Amxx May 20, 2021
62c2662
support cancel in timelock
Amxx May 20, 2021
46d059d
make execute functions payable
Amxx May 20, 2021
0733c67
add comp timelock support(wip)
Amxx May 20, 2021
31a1bc2
fix module name
Amxx May 20, 2021
3cad527
disable execute function with wrong signature
Amxx May 20, 2021
8f68441
fix the signature issue with comp timelock
Amxx May 20, 2021
e73357f
test comptimelock module for governor
Amxx May 21, 2021
bb21719
add check
Amxx May 21, 2021
2050af7
working on governor testing
Amxx May 21, 2021
a2501f6
improve test coverage
Amxx May 21, 2021
33d0016
improve revert reasons
Amxx May 21, 2021
5291af5
add a blockNumber argument to the quorum() function
Amxx May 22, 2021
f9b5d78
improve governanor coverage
Amxx May 25, 2021
2cbb385
complete coverage of governor core and extensions
Amxx May 25, 2021
630152e
fix lint
Amxx May 25, 2021
ae7edba
fix lint
Amxx May 25, 2021
81604cc
governor documentation
Amxx May 26, 2021
9ac4a1a
fix doc links
Amxx May 26, 2021
7e35f9a
remove viewProposalStatus in favor of state
Amxx May 26, 2021
b0cbd58
improve governor alpha compatibility
Amxx May 27, 2021
b5fa119
improve soldity style
Amxx May 27, 2021
7d8d4c5
check that old timelock has pending admin before updating
Amxx May 27, 2021
73adefa
clarify setup of governor with openzeppelin timelock
Amxx May 27, 2021
ea82e23
improve governor module inheritance and refactor voting arguments
Amxx May 28, 2021
46851fa
put voting into modules
Amxx May 28, 2021
699f37e
add a proposalScore accessor
Amxx May 28, 2021
f841315
Merge branch 'master' into feature/governance
Amxx May 28, 2021
783bdec
fix governor tests
Amxx May 28, 2021
1d71b99
coverage testing of ScoreVoting
Amxx May 28, 2021
d7f4028
fix lint
Amxx May 28, 2021
85f44ca
renaming governor extensions
Amxx May 28, 2021
a04eff5
mocks with timelock should not have a receive function
Amxx May 28, 2021
8668af3
remove extra modules (keept in separate branch)
Amxx May 31, 2021
d238096
documentation of governor's modules
Amxx May 31, 2021
cbda273
prevent queueing duplicated sub-calls
Amxx May 31, 2021
982d6d1
documentation for the governor
Amxx Jun 1, 2021
a30e280
documentation for the governor
Amxx Jun 1, 2021
895a6f0
minor improvement to utils/Time readability
Amxx Jun 1, 2021
b7b9f5e
fix linting
Amxx Jun 1, 2021
577be2c
Improve gas efficiency of the voting system
Amxx Jun 2, 2021
a8247d9
fix error message testing
Amxx Jun 2, 2021
dfe20d2
add a proposalVotes accessor
Amxx Jun 2, 2021
31a9b42
documentation for proposalVotes
Amxx Jun 2, 2021
acbb608
Add compound licence
Amxx Jun 3, 2021
d0e8456
Move ProposalState enum definition to IGovernor
Amxx Jun 3, 2021
1a48129
Address comments on the PR
Amxx Jun 3, 2021
63c4e05
fix naming mistake
Amxx Jun 3, 2021
d30c56c
fix cancel condition
Amxx Jun 3, 2021
c17daf0
addressing many issues from the PR
Amxx Jun 3, 2021
5da0219
minor renaming in GovernorVotingSimple
Amxx Jun 3, 2021
a299185
fix old natspec comments
Amxx Jun 4, 2021
29c98f2
Merge branch 'master' into feature/governance
Amxx Jun 4, 2021
ac618df
update vote modules according to recent ERC20Votes changes
Amxx Jun 4, 2021
909faf0
improve testing
Amxx Jun 7, 2021
37bbbcb
remove dead code
Amxx Jun 7, 2021
48e7ae1
Merge branch 'master' into feature/governance
Amxx Jun 7, 2021
26bdaa9
apply prettifier to the governance contract
Amxx Jun 7, 2021
c582c24
turing ternary operator into if/elseif/else for clarity
Amxx Jun 7, 2021
4b687af
run lint:fix with updated dependencies
Amxx Jun 7, 2021
3e4d388
making governor events comp compliant
Amxx Jun 10, 2021
f63d273
expand proposalCreated event testing
Amxx Jun 10, 2021
a99c8de
store timers in uint64
Amxx Jun 11, 2021
2e1db61
fixe my mess (from changing deadline types to uint64)
Amxx Jun 11, 2021
cc42201
fix lint
Amxx Jun 11, 2021
5d4b90c
Working on a comp compatibility layer for the governor
Amxx Jun 11, 2021
32a7cf3
working on comp compatiblity
Amxx Jun 14, 2021
05154ba
fix cancelled & executed status in comp compatibility
Amxx Jun 14, 2021
bb5aa87
skip tests if optimization is not enabled
Amxx Jun 14, 2021
c5d6eb4
lint:fix
Amxx Jun 14, 2021
83279db
documentation of GovernorCompound
Amxx Jun 14, 2021
b68740b
enable all testing + allowUnlimitedContractSize if optimisations are …
Amxx Jun 14, 2021
1b16e0a
renaming struct to improve compound compliance
Amxx Jun 16, 2021
5b89af0
documentation of the GovernorCompound compatibility layer
Amxx Jun 16, 2021
5d82a7e
make revert reason match contract names
Amxx Jun 16, 2021
e70dd54
revert change made by early version of the linter
Amxx Jun 17, 2021
3791bb9
store proposal in core interface of comp compatibility layer
Amxx Jun 17, 2021
7f75429
fix contract inheritance to enforce existance of an ordering
Amxx Jun 17, 2021
a9e98e1
fix lint (again)
Amxx Jun 18, 2021
c39a4c7
reorganise proposals() view function to improve contract size
Amxx Jun 18, 2021
25db6ea
fix lint yet again
Amxx Jun 18, 2021
2413e55
Merge branch 'master' into feature/governance
Amxx Jun 18, 2021
77ea9f5
use proposal description for salt
Amxx Jun 22, 2021
f7e7cb4
remove ProposalSalt event made superfluous by the use of description …
Amxx Jun 22, 2021
1c643b8
Merge branch 'master' into feature/governance
Amxx Jun 23, 2021
61f27da
Governor is now scheduled for 4.3
Amxx Jun 23, 2021
498187b
add the proposalThreshold access restriction mechanism, with default …
Amxx Jun 24, 2021
745d20e
make BALLOT_TYPEHASH public
Amxx Jun 25, 2021
9b6dd41
IGovernorTimelock is IGovernor
Amxx Jun 25, 2021
8e3cd7a
deep refactor of IGovernor vs Governor
Amxx Jun 26, 2021
481a279
add erc165 introspection
Amxx Jun 26, 2021
872b1b1
moving more things to IGOvernor
Amxx Jun 26, 2021
c0c9584
fix contract ordering, and improve the detector script
Amxx Jun 26, 2021
a220cbd
ERC165 testing of governor core
Amxx Jun 29, 2021
1961a74
fix lint
Amxx Jun 29, 2021
867ba31
test GOvernorTimelock interface
Amxx Jun 29, 2021
a221e69
interface IGovernorTimelock
Amxx Jun 29, 2021
5de73c5
fix lint
Amxx Jun 29, 2021
e22a1ea
replace salt with descriptionHash
Amxx Jun 30, 2021
90050fc
replace salt with descriptionHash in tests
Amxx Jun 30, 2021
4cf2ed6
Merge branch 'master' into feature/governance
Amxx Jun 30, 2021
655f96b
rename governor contracts
Amxx Jul 1, 2021
f07cd19
revert changes caused by an old version of prettier
Amxx Jul 2, 2021
4e6a7b2
add quorum ratio to GovernorWithERC20Votes
Amxx Jul 2, 2021
949d11d
quorum is strict, so it is safe to set it to 0, at least 1 vote is st…
Amxx Jul 2, 2021
b214fa0
fix lint
Amxx Jul 2, 2021
2468cf6
prevent seting the quorum ratio over the maximum
Amxx Jul 2, 2021
37ad037
use an internal virtual function _executor() instead of a virtual mod…
Amxx Jul 2, 2021
0c0896d
fix lint yet again
Amxx Jul 2, 2021
8a583aa
refactor token modules
Amxx Jul 2, 2021
3675fb4
update tests according to the module renaming
Amxx Jul 2, 2021
5771e5b
expand testing to block number based timers
Amxx Jul 5, 2021
ad52976
addressing many comments from the PR & improving compatibility of cor…
Amxx Jul 6, 2021
2eecef8
Rename modules: Voting → Counting & Weight → Votes
Amxx Jul 6, 2021
f52e732
fix lint
Amxx Jul 6, 2021
2e1a8ab
remove @notice entires in favor of extended contract description
Amxx Jul 6, 2021
eff08aa
fix event link
frangio Jul 6, 2021
a277991
fix links
frangio Jul 6, 2021
962fee7
fix abi of proposals(uint256) in the compatibility layer
Amxx Jul 7, 2021
f49b2e6
Merge branch 'feature/governance' of github.com:Amxx/openzeppelin-con…
Amxx Jul 7, 2021
c096ff2
match governor structure declaration
Amxx Jul 7, 2021
c3c9387
knock knock. who's there ? its the linter yet again
Amxx Jul 7, 2021
0a0a08f
address review comments on GovernorTimelockController
Amxx Jul 7, 2021
4be97fc
address review comments on GovernorTimelockCompound
Amxx Jul 7, 2021
cf6cd37
make timelock modules hook into the execution module using an interna…
Amxx Jul 7, 2021
3ebb685
fix lint
Amxx Jul 7, 2021
47d608e
imporve state checkers now that the core execution is used
Amxx Jul 7, 2021
a59801f
variable naming
Amxx Jul 7, 2021
b26b1ab
add checks for revert reason bubbling in execute
Amxx Jul 7, 2021
887c2d3
extend testing of proposal execution with value
Amxx Jul 7, 2021
7c8cb01
minor refactor of governor testing
Amxx Jul 7, 2021
e2d6c1e
extend security of the updateTimelock process with Compound timelock
Amxx Jul 7, 2021
d862d2b
change argument types to use contract object for tokens and timelocks
Amxx Jul 7, 2021
fc7ad04
fix documentation links
Amxx Jul 7, 2021
bb5be03
Update contracts/governance/compatibility/GovernorCompatibilityBravo.sol
Amxx Jul 9, 2021
ec283a8
Update contracts/governance/extensions/GovernorCountingSimple.sol
Amxx Jul 9, 2021
c34d946
rename GovernorTimelockController → GovernorTimelockControl
Amxx Jul 9, 2021
49fce6a
fix recuring typo
Amxx Jul 9, 2021
3a89fd8
fix lint
Amxx Jul 9, 2021
ddc0d3d
strict inaquality prevent openning proposal to the wide public
Amxx Jul 9, 2021
26c5ffb
Merge branch 'master' into feature/governance
Amxx Jul 9, 2021
be72915
rename GovernorVotesQuorumFractional → GovernorVotesQuorumFraction
Amxx Jul 9, 2021
f421783
fix lint
Amxx Jul 9, 2021
5651a98
add test where timelock proposal is executed by another actor
Amxx Jul 9, 2021
d41de3d
add testing for proposalDelay
Amxx Jul 9, 2021
66d0fe7
expand governor testing
Amxx Jul 9, 2021
409a1d6
address some issues from the PR
Amxx Jul 9, 2021
f0eb4f1
add COUNTING_MODE
frangio Jul 16, 2021
669bc0e
fix lint
Amxx Jul 16, 2021
814c210
fix lint and update readme
Amxx Jul 16, 2021
76cda5f
remove opinionated restrictions to transfer timelock
frangio Jul 16, 2021
24d3ca1
update prettier-plugin-solidity
frangio Jul 16, 2021
66f66e9
remove commented functions
frangio Jul 16, 2021
ed3f574
Merge branch 'master' into feature/governance
frangio Jul 16, 2021
cd578cf
add changelog entry
frangio Jul 16, 2021
df41439
update lockfile
frangio Jul 16, 2021
20beb65
Merge branch 'master' into feature/governance
frangio Jul 16, 2021
42cc0db
Merge branch 'master' into feature/governance
frangio Jul 16, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
314 changes: 314 additions & 0 deletions contracts/governance/Governor.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,314 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../utils/cryptography/ECDSA.sol";
import "../utils/cryptography/draft-EIP712.sol";
import "../utils/Address.sol";
import "../utils/Context.sol";
import "../utils/Time.sol";
import "./IGovernor.sol";

/**
* @dev TODO
*
* _Available since v4.2._
*/
abstract contract Governor is IGovernor, EIP712, Context {
using Time for Time.Timer;

bytes32 private constant _BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,uint8 support)");

struct Proposal {
Time.Timer timer;
uint256 snapshot;
bool canceled;
}

string private _name;
string private _version;

mapping (uint256 => Proposal) private _proposals;
mapping (uint256 => mapping (address => bool)) private _votes;

/**
* @dev Sets the value for {name} and {version}
*/
constructor(string memory name_, string memory version_)
EIP712(name_, version_)
Amxx marked this conversation as resolved.
Show resolved Hide resolved
{
_name = name_;
Amxx marked this conversation as resolved.
Show resolved Hide resolved
_version = version_;
}

/**
* @dev See {IGovernor-name}.
*/
function name() external view virtual override returns (string memory) {
return _name;
}

/**
* @dev See {IGovernor-version}.
*/
function version() external view virtual override returns (string memory) {
return _version;
}

/**
* @dev See {IGovernor-version}.
*/
function state(uint256 proposalId) public view virtual override returns (ProposalState) {
Proposal memory proposal = _proposals[proposalId];

if (proposal.timer.isUnset()) {
// There is no ProposalState for unset proposals
revert("Governor::state: invalid proposal id");
} else if (block.number <= proposal.snapshot) {
return ProposalState.Pending;
} else if (proposal.timer.isPending()) {
return ProposalState.Active;
} else if (proposal.timer.isExpired()) {
return (proposalWeight(proposalId) >= quorum(proposal.snapshot) && _voteSuccess(proposalId))
? ProposalState.Succeeded
: ProposalState.Defeated;
} else if (proposal.canceled) {
return ProposalState.Canceled;
} else {
return ProposalState.Executed;
}
}

/**
* @dev See {IGovernor-proposalDeadline}.
*/
function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {
return _proposals[proposalId].timer.getDeadline();
}

/**
* @dev See {IGovernor-proposalSnapshot}.
*/
function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {
return _proposals[proposalId].snapshot;
}

/**
* @dev See {IGovernor-hasVoted}.
*/
function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {
return _votes[proposalId][account];
}

/**
* @dev See {IGovernor-hashProposal}.
*/
function hashProposal(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 salt
)
public view virtual override returns (uint256 proposalId)
{
return uint256(keccak256(abi.encode(targets, values, calldatas, salt)));
}


/**
* @dev See {IGovernor-propose}.
*/
function propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 salt,
string memory description
)
public virtual override returns (uint256 proposalId)
{
uint256 snapshot;
uint256 deadline;
(proposalId, snapshot, deadline) = _propose(targets, values, calldatas, salt);
emit ProposalCreated(proposalId, _msgSender(), targets, values, calldatas, salt, snapshot, deadline, description);
}

/**
* @dev See {IGovernor-execute}.
*/
function execute(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 salt
)
public payable virtual override returns (uint256 proposalId)
{
proposalId = _execute(targets, values, calldatas, salt);
Amxx marked this conversation as resolved.
Show resolved Hide resolved
emit ProposalExecuted(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-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 propose mechanism: Hashes proposal and sets snapshot and deadline. Revert if proposal is already
* registered.
*
* Note: does not emit any events. Events are part of the public function so they can be customized.
*/
function _propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 salt
)
internal virtual returns (uint256 proposalId, uint256 snapshot, uint256 deadline)
{
proposalId = hashProposal(targets, values, calldatas, salt);

require(targets.length == values.length, "Governance: invalid proposal length");
require(targets.length == calldatas.length, "Governance: invalid proposal length");
require(targets.length > 0, "Governance: empty proposal");

Proposal storage proposal = _proposals[proposalId];
require(proposal.timer.isUnset(), "Governance: proposal already exists");

snapshot = block.number + votingDelay();
deadline = block.timestamp + votingDuration();

proposal.snapshot = snapshot;
proposal.timer.setDeadline(deadline);
}

/**
* @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 salt
)
internal virtual returns (uint256 proposalId)
{
proposalId = hashProposal(targets, values, calldatas, salt);
_proposals[proposalId].timer.lock();
_proposals[proposalId].canceled = true;
emit ProposalCanceled(proposalId);
Amxx marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* @dev Internal execute mechanism: verifies that a proposal is successfull, lock the timelock to prevent
* re-execution, and calls the {_calls} internal function.
*
* Note: does not emit any events. Events are part of the public function so they can be customized. In particular
Amxx marked this conversation as resolved.
Show resolved Hide resolved
* some modules can use this mechanism to queue timelocked proposals.
*/
function _execute(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 salt
)
internal virtual returns (uint256 proposalId)
{
proposalId = hashProposal(targets, values, calldatas, salt);

Proposal storage proposal = _proposals[proposalId];
require(proposal.timer.isExpired(), "Governance: proposal not ready");
require(proposalWeight(proposalId) >= quorum(proposal.snapshot), "Governance: quorum not reached");
require(_voteSuccess(proposalId), "Governance: required score not reached");
Amxx marked this conversation as resolved.
Show resolved Hide resolved
proposal.timer.lock();
Amxx marked this conversation as resolved.
Show resolved Hide resolved

_calls(proposalId, targets, values, calldatas, salt);
}

/**
* @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 {IGovernor-_pushVote} internal function.
*
* Emits a {IGovernor-VoteCast} event.
*/
function _castVote(
uint256 proposalId,
address account,
uint8 support
)
internal virtual returns (uint256 weight)
{
Proposal storage proposal = _proposals[proposalId];
require(proposal.timer.isPending(), "Governance: vote not currently active");

require(!_votes[proposalId][account], "Governance: vote already casted");
_votes[proposalId][account] = true;

weight = getVotes(account, proposal.snapshot);
_pushVote(proposalId, support, weight);

emit VoteCast(account, proposalId, support, weight);
}

/**
* @dev Internal mechnism to execute multiple calls. Relies on {_call} for individual calls. Can be overriden to
* customized the operation to performed by {_execute} when an proposal is successfull.
*/
function _calls(
uint256 /*proposalId*/,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 /*salt*/
)
internal virtual
{
for (uint256 i = 0; i < targets.length; ++i) {
_call(targets[i], values[i], calldatas[i]);
}
}

/**
* @dev Internal mechnism to execute a single call. Can be overriden to customized the operation to performed by
* {_execute} when an proposal is successfull.
*/
function _call(
address target,
uint256 value,
bytes memory data
)
internal virtual
{
if (data.length == 0) {
Address.sendValue(payable(target), value);
} else {
Address.functionCallWithValue(target, data, value);
frangio marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Loading