Skip to content

Commit b82f64e

Browse files
committed
Address code review changes from @cairoeth
1 parent 2f0f94d commit b82f64e

3 files changed

+77
-4
lines changed

src/ProposalTypesConfigurator.sol

+13-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {IProposalTypesConfigurator} from "src/interfaces/IProposalTypesConfigura
55
import {IAgoraGovernor} from "src/interfaces/IAgoraGovernor.sol";
66

77
/**
8-
* Contract that stores proposalTypes for Governor.
8+
* Contract that stores proposalTypes for the Agora Governor.
99
*/
1010
contract ProposalTypesConfigurator is IProposalTypesConfigurator {
1111
/*//////////////////////////////////////////////////////////////
@@ -85,6 +85,10 @@ contract ProposalTypesConfigurator is IProposalTypesConfigurator {
8585
_setScopeForProposalType(proposalTypeId, txTypeHash, encodedLimit, parameters, comparators);
8686
}
8787

88+
/**
89+
* @notice Sets the scope for a given proposal type.
90+
* @param proposalTypeId Id of the proposal type.
91+
*/
8892
function _setScopeForProposalType(
8993
uint8 proposalTypeId,
9094
bytes32 txTypeHash,
@@ -154,11 +158,16 @@ contract ProposalTypesConfigurator is IProposalTypesConfigurator {
154158
_updateScopeForProposalType(proposalTypeId, scope);
155159
}
156160

161+
/**
162+
* @notice Adds an additional scope for a given proposal type.
163+
* @param proposalTypeId Id of the proposal type
164+
* @param scope An object that contains the scope for a transaction type hash
165+
*/
157166
function _updateScopeForProposalType(uint8 proposalTypeId, Scope calldata scope) internal {
158-
if (_proposalTypesExists[proposalTypeId]) revert InvalidProposalType();
167+
if (!_proposalTypesExists[proposalTypeId]) revert InvalidProposalType();
159168
scopes[proposalTypeId].push(scope);
160169

161-
require(scopeExists[proposalTypeId][scope.txTypeHash]); // Do not allow multiple scopes for a single transaction type
170+
if (scopeExists[proposalTypeId][scope.txTypeHash]) revert NoDuplicateTxTypes(); // Do not allow multiple scopes for a single transaction type
162171
scopeExists[proposalTypeId][scope.txTypeHash] = true;
163172
}
164173

@@ -170,7 +179,7 @@ contract ProposalTypesConfigurator is IProposalTypesConfigurator {
170179
function getLimit(uint8 proposalTypeId, bytes32 txTypeHash) public view returns (bytes memory encodedLimits) {
171180
if (!_proposalTypesExists[proposalTypeId]) revert InvalidProposalType();
172181

173-
require(scopeExists[proposalTypeId][txTypeHash]);
182+
if (!scopeExists[proposalTypeId][txTypeHash]) revert InvalidScope();
174183
Scope[] memory validScopes = scopes[proposalTypeId];
175184

176185
for (uint8 i = 0; i < validScopes.length; i++) {

src/interfaces/IProposalTypesConfigurator.sol

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ interface IProposalTypesConfigurator {
1111
error InvalidProposalType();
1212
error InvalidParameterConditions();
1313
error NoDuplicateTxTypes();
14+
error InvalidScope();
1415
error NotAdminOrTimelock();
1516
error NotAdmin();
1617
error AlreadyInit();

test/ProposalTypesConfigurator.t.sol

+63
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,69 @@ contract SetProposalType is ProposalTypesConfiguratorTest {
194194
}
195195
}
196196

197+
contract UpdateScopeForProposalType is ProposalTypesConfiguratorTest {
198+
function testFuzz_UpdateScopeForProposalType(uint256 _actorSeed) public {
199+
vm.prank(_adminOrTimelock(_actorSeed));
200+
vm.expectEmit();
201+
bytes32[] memory transactions = new bytes32[](1);
202+
emit ProposalTypeSet(0, 4_000, 6_000, "New Default", transactions);
203+
proposalTypesConfigurator.setProposalType(0, 4_000, 6_000, "New Default", address(0), transactions);
204+
205+
vm.startPrank(admin);
206+
bytes32 txTypeHash1 = keccak256("transfer(address,address,uint)");
207+
bytes memory txEncoded1 = abi.encode("transfer(address,address,uint)", 0xdeadbeef, 0xdeadbeef, 10);
208+
209+
bytes32 txTypeHash2 = keccak256("initialize(address,address)");
210+
bytes memory txEncoded2 = abi.encode("initialize(address,address)", 0xdeadbeef, 0xdeadbeef);
211+
bytes[] memory parameters = new bytes[](1);
212+
IProposalTypesConfigurator.Comparators[] memory comparators = new IProposalTypesConfigurator.Comparators[](1);
213+
214+
proposalTypesConfigurator.setScopeForProposalType(0, txTypeHash1, txEncoded1, parameters, comparators);
215+
216+
IProposalTypesConfigurator.Scope memory scope = IProposalTypesConfigurator.Scope(txTypeHash2, txEncoded2, new bytes[](1), new IProposalTypesConfigurator.Comparators[](1));
217+
proposalTypesConfigurator.updateScopeForProposalType(0, scope);
218+
vm.stopPrank();
219+
220+
bytes memory limit1 = proposalTypesConfigurator.getLimit(0, txTypeHash1);
221+
bytes memory limit2 = proposalTypesConfigurator.getLimit(0, txTypeHash2);
222+
assertEq(limit1, txEncoded1);
223+
assertEq(limit2, txEncoded2);
224+
}
225+
226+
function testRevert_updateScopeForProposalType_InvalidProposalType() public {
227+
vm.startPrank(admin);
228+
bytes32 txTypeHash = keccak256("transfer(address,address,uint)");
229+
bytes memory txEncoded = abi.encode("transfer(address,address,uint)", 0xdeadbeef, 0xdeadbeef, 10);
230+
231+
vm.expectRevert(IProposalTypesConfigurator.InvalidProposalType.selector);
232+
IProposalTypesConfigurator.Scope memory scope = IProposalTypesConfigurator.Scope(txTypeHash, txEncoded, new bytes[](1), new IProposalTypesConfigurator.Comparators[](1));
233+
proposalTypesConfigurator.updateScopeForProposalType(3, scope);
234+
vm.stopPrank();
235+
}
236+
237+
function testRevert_updateScopeForProposalType_NoDuplicateTxTypes() public {
238+
vm.startPrank(admin);
239+
bytes32 txTypeHash = keccak256("transfer(address,address,uint)");
240+
bytes memory txEncoded = abi.encode("transfer(address,address,uint)", 0xdeadbeef, 0xdeadbeef, 10);
241+
242+
proposalTypesConfigurator.setScopeForProposalType(
243+
0, txTypeHash, txEncoded, new bytes[](1), new IProposalTypesConfigurator.Comparators[](1)
244+
);
245+
246+
vm.expectRevert(IProposalTypesConfigurator.NoDuplicateTxTypes.selector);
247+
IProposalTypesConfigurator.Scope memory scope = IProposalTypesConfigurator.Scope(txTypeHash, txEncoded, new bytes[](1), new IProposalTypesConfigurator.Comparators[](1));
248+
proposalTypesConfigurator.updateScopeForProposalType(0, scope);
249+
vm.stopPrank();
250+
}
251+
}
252+
253+
contract getLimit is ProposalTypesConfiguratorTest {
254+
function testRevert_getLimit_InvalidProposalType() public {
255+
vm.expectRevert(IProposalTypesConfigurator.InvalidProposalType.selector);
256+
proposalTypesConfigurator.getLimit(3, keccak256("foobar(address,address)"));
257+
}
258+
}
259+
197260
contract GovernorMock {
198261
address immutable adminAddress;
199262
address immutable timelockAddress;

0 commit comments

Comments
 (0)