|
@@ -106,8 +106,9 @@ abstract contract GovernorTimelockControl is IGovernorTimelock, Governor {
|
|
|
}
|
|
|
|
|
|
uint256 delay = _timelock.getMinDelay();
|
|
|
- _timelockIds[proposalId] = _timelock.hashOperationBatch(targets, values, calldatas, 0, descriptionHash);
|
|
|
- _timelock.scheduleBatch(targets, values, calldatas, 0, descriptionHash, delay);
|
|
|
+ bytes32 salt = _timelockSalt(descriptionHash);
|
|
|
+ _timelockIds[proposalId] = _timelock.hashOperationBatch(targets, values, calldatas, 0, salt);
|
|
|
+ _timelock.scheduleBatch(targets, values, calldatas, 0, salt, delay);
|
|
|
|
|
|
emit ProposalQueued(proposalId, block.timestamp + delay);
|
|
|
|
|
@@ -125,7 +126,7 @@ abstract contract GovernorTimelockControl is IGovernorTimelock, Governor {
|
|
|
bytes32 descriptionHash
|
|
|
) internal virtual override {
|
|
|
// execute
|
|
|
- _timelock.executeBatch{value: msg.value}(targets, values, calldatas, 0, descriptionHash);
|
|
|
+ _timelock.executeBatch{value: msg.value}(targets, values, calldatas, 0, _timelockSalt(descriptionHash));
|
|
|
// cleanup for refund
|
|
|
delete _timelockIds[proposalId];
|
|
|
}
|
|
@@ -177,4 +178,14 @@ abstract contract GovernorTimelockControl is IGovernorTimelock, Governor {
|
|
|
emit TimelockChange(address(_timelock), address(newTimelock));
|
|
|
_timelock = newTimelock;
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @dev Computes the {TimelockController} operation salt.
|
|
|
+ *
|
|
|
+ * It is computed with the governor address itself to avoid collisions across governor instances using the
|
|
|
+ * same timelock.
|
|
|
+ */
|
|
|
+ function _timelockSalt(bytes32 descriptionHash) private view returns (bytes32) {
|
|
|
+ return bytes20(address(this)) ^ descriptionHash;
|
|
|
+ }
|
|
|
}
|