this is the execute()
function from openzeppelin Governor
contract.
function execute( address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash ) public payable virtual returns (uint256) {
uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
_validateStateBitmap( proposalId, _encodeStateBitmap(ProposalState.Succeeded) | _encodeStateBitmap(ProposalState.Queued) );
// mark as executed before calls to avoid reentrancy
_proposals[proposalId].executed = true;
// before execute: register governance call in queue.
if (_executor() != address(this)) {
for (uint256 i = 0; i < targets.length; ++i) {
if (targets[i] == address(this)) {
_governanceCall.pushBack( keccak256(calldatas[i]) );
}
}
}
_executeOperations(proposalId, targets, values, calldatas, descriptionHash);
// after execute: cleanup governance call queue.
if (_executor() != address(this) && !_governanceCall.empty()) {
_governanceCall.clear();
}
emit ProposalExecuted(proposalId);
return proposalId;
}
the part that confuses me is before and after _executeOperations()
logic:
// before execute: register governance call in queue.
if (_executor() != address(this)) {
for (uint256 i = 0; i < targets.length; ++i) {
if (targets[i] == address(this)) {
_governanceCall.pushBack( keccak256(calldatas[i]) );
}
}
}
_executeOperations(proposalId, targets, values, calldatas, descriptionHash);
// after execute: cleanup governance call queue.
if (_executor() != address(this) && !_governanceCall.empty()) {
_governanceCall.clear();
}
i really want to know why we should store the calldata at end of the queue(DoubleEndedQueue.Bytes32Deque
) and then clear it. basically why should the execute()
function contain such logic? what is it for?