Skip to content

Commit fb906e1

Browse files
authored
Budget: optimize existence check (#123)
* Budget: check spender address for allowande existence and test prohibited values * forge snapshot
1 parent 1ddadaa commit fb906e1

3 files changed

Lines changed: 148 additions & 84 deletions

File tree

.gas-snapshot

Lines changed: 76 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -11,71 +11,81 @@ ForwarderLibTest:testForwardTargetRevert() (gas: 113884)
1111
ForwarderLibTest:testHitsTarget():(address) (gas: 109476)
1212
ForwarderLibTest:testLowLevelForward() (gas: 84355)
1313
ForwarderLibTest:testRevertsOnRepeatedSalt() (gas: 8937393460516731420)
14-
LlamaPayStreamsTest:testCanCancelStream() (gas: 2442679)
15-
LlamaPayStreamsTest:testCanChangePrepayBuffer() (gas: 2613650)
16-
LlamaPayStreamsTest:testCanModifyStream() (gas: 2560107)
17-
LlamaPayStreamsTest:testCanPauseStream() (gas: 2442678)
18-
LlamaPayStreamsTest:testCantCancelStreamIfNotAdmin() (gas: 2409958)
19-
LlamaPayStreamsTest:testCantCreateStreamIfNotAdmin() (gas: 2170790)
20-
LlamaPayStreamsTest:testCantModifyStreamIfNotAdmin() (gas: 2411611)
21-
LlamaPayStreamsTest:testCantPauseStreamIfNotAdmin() (gas: 2409934)
22-
LlamaPayStreamsTest:testCreateMultipleStreams() (gas: 2513223)
23-
LlamaPayStreamsTest:testCreateStream():(address,address,uint256) (gas: 2403399)
14+
LlamaPayStreamsTest:testCanCancelStream() (gas: 2440569)
15+
LlamaPayStreamsTest:testCanChangePrepayBuffer() (gas: 2611430)
16+
LlamaPayStreamsTest:testCanModifyStream() (gas: 2557975)
17+
LlamaPayStreamsTest:testCanPauseStream() (gas: 2440568)
18+
LlamaPayStreamsTest:testCantCancelStreamIfNotAdmin() (gas: 2407870)
19+
LlamaPayStreamsTest:testCantCreateStreamIfNotAdmin() (gas: 2168746)
20+
LlamaPayStreamsTest:testCantModifyStreamIfNotAdmin() (gas: 2409523)
21+
LlamaPayStreamsTest:testCantPauseStreamIfNotAdmin() (gas: 2407846)
22+
LlamaPayStreamsTest:testCreateMultipleStreams() (gas: 2511113)
23+
LlamaPayStreamsTest:testCreateStream():(address,address,uint256) (gas: 2401333)
2424
LlamaPayStreamsTest:testInitialState() (gas: 24728)
25-
EtherBudgetTest:testAllowanceChain() (gas: 564704)
26-
EtherBudgetTest:testAllowanceIsKeptTrackOfOnMulti() (gas: 327583)
27-
EtherBudgetTest:testAllowanceIsKeptTrackOfOnSingle() (gas: 283801)
28-
EtherBudgetTest:testAllowanceSpenderWithRoleFlags() (gas: 241886)
29-
EtherBudgetTest:testCanDebitAllowance() (gas: 249109)
30-
EtherBudgetTest:testCanDebitOnChains() (gas: 519641)
31-
EtherBudgetTest:testCannotCreateNonRecurrentAllowanceNotInTheFuture() (gas: 39307)
32-
EtherBudgetTest:testCannotReinit() (gas: 21818)
33-
EtherBudgetTest:testCantExecuteIfNotAuthorized() (gas: 136496)
34-
EtherBudgetTest:testCantExecuteInexistentAllowance() (gas: 18937)
35-
EtherBudgetTest:testCantExecuteMultiIfNotAuthorized() (gas: 138517)
36-
EtherBudgetTest:testCreateAllowance():(uint256) (gas: 136514)
37-
EtherBudgetTest:testCreateNonRecurrentAllowance():(uint256,uint40) (gas: 125470)
38-
EtherBudgetTest:testCreateSuballowance():(uint256,uint256) (gas: 316302)
39-
EtherBudgetTest:testCreateSuballowanceWithInheritedRecurrency() (gas: 285722)
40-
EtherBudgetTest:testDisablingAllowanceBreaksChain() (gas: 574859)
41-
EtherBudgetTest:testInheritOffsetValueIsIgnored() (gas: 225118)
42-
EtherBudgetTest:testInitialState() (gas: 19859)
43-
EtherBudgetTest:testInvalidSpenderReverts() (gas: 37493)
44-
EtherBudgetTest:testInvalidTimeshiftsRevert() (gas: 29110)
45-
EtherBudgetTest:testMultipleAllowances() (gas: 423365)
46-
EtherBudgetTest:testNonAdminCannotUpdateAllowanceParams() (gas: 337042)
47-
EtherBudgetTest:testNonRecurrentAllowanceDoesntResetAndExpires() (gas: 199536)
48-
EtherBudgetTest:testNotOwnerCannotCreateTopLevelAllowance() (gas: 23603)
49-
EtherBudgetTest:testOnlyParentAdminCanDisableAllowance() (gas: 571803)
50-
EtherBudgetTest:testRevertOnBadInputToMultiPayment() (gas: 138220)
51-
EtherBudgetTest:testUpdateAllowanceParams() (gas: 153345)
52-
TokenBudgetTest:testAllowanceChain() (gas: 564704)
53-
TokenBudgetTest:testAllowanceIsKeptTrackOfOnMulti() (gas: 303504)
54-
TokenBudgetTest:testAllowanceIsKeptTrackOfOnSingle() (gas: 279603)
55-
TokenBudgetTest:testAllowanceSpenderWithRoleFlags() (gas: 241620)
56-
TokenBudgetTest:testCanDebitAllowance() (gas: 245800)
57-
TokenBudgetTest:testCanDebitOnChains() (gas: 488490)
58-
TokenBudgetTest:testCannotCreateNonRecurrentAllowanceNotInTheFuture() (gas: 39307)
59-
TokenBudgetTest:testCannotReinit() (gas: 21806)
60-
TokenBudgetTest:testCantExecuteIfNotAuthorized() (gas: 136496)
61-
TokenBudgetTest:testCantExecuteInexistentAllowance() (gas: 18937)
62-
TokenBudgetTest:testCantExecuteMultiIfNotAuthorized() (gas: 138517)
63-
TokenBudgetTest:testCreateAllowance():(uint256) (gas: 136514)
64-
TokenBudgetTest:testCreateNonRecurrentAllowance():(uint256,uint40) (gas: 125470)
65-
TokenBudgetTest:testCreateSuballowance():(uint256,uint256) (gas: 316302)
66-
TokenBudgetTest:testCreateSuballowanceWithInheritedRecurrency() (gas: 285722)
67-
TokenBudgetTest:testDisablingAllowanceBreaksChain() (gas: 574859)
68-
TokenBudgetTest:testInheritOffsetValueIsIgnored() (gas: 225118)
69-
TokenBudgetTest:testInitialState() (gas: 19859)
70-
TokenBudgetTest:testInvalidSpenderReverts() (gas: 37493)
71-
TokenBudgetTest:testInvalidTimeshiftsRevert() (gas: 29110)
72-
TokenBudgetTest:testMultipleAllowances() (gas: 417201)
73-
TokenBudgetTest:testNonAdminCannotUpdateAllowanceParams() (gas: 337042)
74-
TokenBudgetTest:testNonRecurrentAllowanceDoesntResetAndExpires() (gas: 199270)
75-
TokenBudgetTest:testNotOwnerCannotCreateTopLevelAllowance() (gas: 23603)
76-
TokenBudgetTest:testOnlyParentAdminCanDisableAllowance() (gas: 571803)
77-
TokenBudgetTest:testRevertOnBadInputToMultiPayment() (gas: 138220)
78-
TokenBudgetTest:testUpdateAllowanceParams() (gas: 153345)
25+
EtherBudgetTest:testAllowanceChain() (gas: 644074)
26+
EtherBudgetTest:testAllowanceIsKeptTrackOfOnMulti() (gas: 327578)
27+
EtherBudgetTest:testAllowanceIsKeptTrackOfOnSingle() (gas: 285660)
28+
EtherBudgetTest:testAllowanceSpenderWithRoleFlags() (gas: 241924)
29+
EtherBudgetTest:testCanDebitAllowance() (gas: 249125)
30+
EtherBudgetTest:testCanDebitOnChains() (gas: 519667)
31+
EtherBudgetTest:testCannotCreateNonRecurrentAllowanceNotInTheFuture() (gas: 39406)
32+
EtherBudgetTest:testCannotReinit() (gas: 23903)
33+
EtherBudgetTest:testCantCreateAllowanceWithInvalidTimeshift() (gas: 31257)
34+
EtherBudgetTest:testCantCreateAllowanceWithZeroSpender() (gas: 19348)
35+
EtherBudgetTest:testCantCreateAllowanceWithZeroToken() (gas: 19366)
36+
EtherBudgetTest:testCantExecuteIfNotAuthorized() (gas: 136600)
37+
EtherBudgetTest:testCantExecuteInexistentAllowance() (gas: 21073)
38+
EtherBudgetTest:testCantExecuteMultiIfNotAuthorized() (gas: 138555)
39+
EtherBudgetTest:testCantSetAllowanceAmountToZeroIfNotInherited() (gas: 249523)
40+
EtherBudgetTest:testCantSetAllowanceAmountToZeroIfTopLevel() (gas: 139829)
41+
EtherBudgetTest:testCantUpdateSpenderToZeroAddress() (gas: 138905)
42+
EtherBudgetTest:testCreateAllowance():(uint256) (gas: 136574)
43+
EtherBudgetTest:testCreateNonRecurrentAllowance():(uint256,uint40) (gas: 125508)
44+
EtherBudgetTest:testCreateSuballowance():(uint256,uint256) (gas: 349634)
45+
EtherBudgetTest:testCreateSuballowanceWithInheritedRecurrency() (gas: 338970)
46+
EtherBudgetTest:testDisablingAllowanceBreaksChain() (gas: 654251)
47+
EtherBudgetTest:testInheritOffsetValueIsIgnored() (gas: 225216)
48+
EtherBudgetTest:testInitialState() (gas: 19814)
49+
EtherBudgetTest:testInvalidSpenderReverts() (gas: 39732)
50+
EtherBudgetTest:testMultipleAllowances() (gas: 425941)
51+
EtherBudgetTest:testNonAdminCannotUpdateAllowanceParams() (gas: 370244)
52+
EtherBudgetTest:testNonRecurrentAllowanceDoesntResetAndExpires() (gas: 199529)
53+
EtherBudgetTest:testNotOwnerCannotCreateTopLevelAllowance() (gas: 23642)
54+
EtherBudgetTest:testOnlyParentAdminCanDisableAllowance() (gas: 651120)
55+
EtherBudgetTest:testRevertOnBadInputToMultiPayment() (gas: 138236)
56+
EtherBudgetTest:testUpdateAllowanceParams() (gas: 153428)
57+
TokenBudgetTest:testAllowanceChain() (gas: 645004)
58+
TokenBudgetTest:testAllowanceIsKeptTrackOfOnMulti() (gas: 303499)
59+
TokenBudgetTest:testAllowanceIsKeptTrackOfOnSingle() (gas: 286204)
60+
TokenBudgetTest:testAllowanceSpenderWithRoleFlags() (gas: 241658)
61+
TokenBudgetTest:testCanDebitAllowance() (gas: 245816)
62+
TokenBudgetTest:testCanDebitOnChains() (gas: 488516)
63+
TokenBudgetTest:testCannotCreateNonRecurrentAllowanceNotInTheFuture() (gas: 39406)
64+
TokenBudgetTest:testCannotReinit() (gas: 23891)
65+
TokenBudgetTest:testCantCreateAllowanceWithInvalidTimeshift() (gas: 31257)
66+
TokenBudgetTest:testCantCreateAllowanceWithZeroSpender() (gas: 19348)
67+
TokenBudgetTest:testCantCreateAllowanceWithZeroToken() (gas: 19366)
68+
TokenBudgetTest:testCantExecuteIfNotAuthorized() (gas: 136600)
69+
TokenBudgetTest:testCantExecuteInexistentAllowance() (gas: 21073)
70+
TokenBudgetTest:testCantExecuteMultiIfNotAuthorized() (gas: 138555)
71+
TokenBudgetTest:testCantSetAllowanceAmountToZeroIfNotInherited() (gas: 249523)
72+
TokenBudgetTest:testCantSetAllowanceAmountToZeroIfTopLevel() (gas: 139829)
73+
TokenBudgetTest:testCantUpdateSpenderToZeroAddress() (gas: 138905)
74+
TokenBudgetTest:testCreateAllowance():(uint256) (gas: 136574)
75+
TokenBudgetTest:testCreateNonRecurrentAllowance():(uint256,uint40) (gas: 125508)
76+
TokenBudgetTest:testCreateSuballowance():(uint256,uint256) (gas: 350948)
77+
TokenBudgetTest:testCreateSuballowanceWithInheritedRecurrency() (gas: 340285)
78+
TokenBudgetTest:testDisablingAllowanceBreaksChain() (gas: 655181)
79+
TokenBudgetTest:testInheritOffsetValueIsIgnored() (gas: 225216)
80+
TokenBudgetTest:testInitialState() (gas: 19814)
81+
TokenBudgetTest:testInvalidSpenderReverts() (gas: 39732)
82+
TokenBudgetTest:testMultipleAllowances() (gas: 426100)
83+
TokenBudgetTest:testNonAdminCannotUpdateAllowanceParams() (gas: 371558)
84+
TokenBudgetTest:testNonRecurrentAllowanceDoesntResetAndExpires() (gas: 199263)
85+
TokenBudgetTest:testNotOwnerCannotCreateTopLevelAllowance() (gas: 23642)
86+
TokenBudgetTest:testOnlyParentAdminCanDisableAllowance() (gas: 652050)
87+
TokenBudgetTest:testRevertOnBadInputToMultiPayment() (gas: 138236)
88+
TokenBudgetTest:testUpdateAllowanceParams() (gas: 153428)
7989
TimeShiftLibEncodingTest:testDecodingGas() (gas: 442)
8090
TimeShiftLibEncodingTest:testEncodingGas() (gas: 588)
8191
TimeShiftLibEncodingTest:testRoundtrips() (gas: 3318)
@@ -145,8 +155,8 @@ RolesAuthTest:testExplicitAddrIsAuthorized() (gas: 9214)
145155
RolesAuthTest:testRoleFlags(uint8) (runs: 256, μ: 43839, ~: 43839)
146156
RolesAuthTest:testRoleFlagsEdgeCases() (gas: 48435)
147157
RolesAuthTest:testRolesIsSaved() (gas: 13272)
148-
FirmFactoryIntegrationTest:testBudgetStreaming() (gas: 3512367)
149-
FirmFactoryIntegrationTest:testExecutingPaymentsFromBudget() (gas: 1197370)
158+
FirmFactoryIntegrationTest:testBudgetStreaming() (gas: 3512355)
159+
FirmFactoryIntegrationTest:testExecutingPaymentsFromBudget() (gas: 1197380)
150160
FirmFactoryIntegrationTest:testFactoryGas() (gas: 637637)
151161
FirmFactoryIntegrationTest:testInitialState() (gas: 647821)
152162
FirmFactoryIntegrationTest:testModuleUpgrades() (gas: 1363377)

src/budget/Budget.sol

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,10 @@ contract Budget is FirmBase, SafeModule, RolesAuth {
133133
) public returns (uint256 allowanceId) {
134134
uint40 nextResetTime;
135135

136+
if (spender == address(0) || token == address(0)) {
137+
revert BadInput();
138+
}
139+
136140
if (parentAllowanceId == NO_PARENT_ID) {
137141
// Top-level allowances can only be created by the Safe
138142
if (_msgSender() != address(safe())) {
@@ -237,6 +241,10 @@ contract Budget is FirmBase, SafeModule, RolesAuth {
237241
* @param spender New spender account for the allowance
238242
*/
239243
function setAllowanceSpender(uint256 allowanceId, address spender) external {
244+
if (spender == address(0)) {
245+
revert BadInput();
246+
}
247+
240248
_validateAuthorizedAddress(spender);
241249

242250
Allowance storage allowance = _getAllowanceAndValidateAdmin(allowanceId);
@@ -439,12 +447,12 @@ contract Budget is FirmBase, SafeModule, RolesAuth {
439447
}
440448
}
441449

442-
function _getAllowance(uint256 allowanceId) internal view returns (Allowance storage) {
443-
if (allowanceId == NO_PARENT_ID || allowanceId > allowancesCount) {
450+
function _getAllowance(uint256 allowanceId) internal view returns (Allowance storage allowance) {
451+
allowance = allowances[allowanceId];
452+
453+
if (allowance.spender == address(0)) {
444454
revert UnexistentAllowance(allowanceId);
445455
}
446-
447-
return allowances[allowanceId];
448456
}
449457

450458
function isAdminOnAllowance(uint256 allowanceId, address actor) public view returns (bool) {

src/budget/test/Budget.t.sol

Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ abstract contract BudgetTest is FirmTest {
1616
SafeStub safe;
1717
RolesStub roles;
1818
Budget budget;
19-
address token;
19+
address token; // set in deriving contracts
2020

2121
address SPENDER = account("spender");
2222
address RECEIVER = account("receiver");
@@ -25,7 +25,7 @@ abstract contract BudgetTest is FirmTest {
2525
function setUp() public virtual {
2626
safe = new SafeStub();
2727
roles = new RolesStub();
28-
budget = Budget(createProxy(new Budget(), abi.encodeCall(Budget.initialize, (safe, roles, address(0)))));
28+
budget = Budget(createProxy(new Budget(), abi.encodeCall(Budget.initialize, (safe, roles, token))));
2929
}
3030

3131
function testInitialState() public {
@@ -35,7 +35,7 @@ abstract contract BudgetTest is FirmTest {
3535

3636
function testCannotReinit() public {
3737
vm.expectRevert(abi.encodeWithSelector(SafeAware.AlreadyInitialized.selector));
38-
budget.initialize(safe, roles, address(0));
38+
budget.initialize(safe, roles, token);
3939
}
4040

4141
function testCreateAllowance() public returns (uint256 allowanceId) {
@@ -81,16 +81,59 @@ abstract contract BudgetTest is FirmTest {
8181
assertEq(spender, RECEIVER);
8282
}
8383

84+
function testCantUpdateSpenderToZeroAddress() public {
85+
uint256 allowanceId = testCreateAllowance();
86+
87+
vm.startPrank(address(safe));
88+
vm.expectRevert(abi.encodeWithSelector(Budget.BadInput.selector));
89+
budget.setAllowanceSpender(allowanceId, address(0));
90+
}
91+
92+
function testCantSetAllowanceAmountToZeroIfTopLevel() public {
93+
uint256 allowanceId = testCreateAllowance();
94+
95+
vm.prank(address(safe));
96+
vm.expectRevert(abi.encodeWithSelector(Budget.InheritedAmountNotAllowed.selector));
97+
budget.setAllowanceAmount(allowanceId, 0);
98+
}
99+
100+
function testCantSetAllowanceAmountToZeroIfNotInherited() public {
101+
uint256 allowanceId = testCreateAllowance();
102+
vm.prank(address(SPENDER));
103+
uint256 childAllowanceId = budget.createAllowance(
104+
allowanceId, SPENDER, token, 10, TimeShift(TimeShiftLib.TimeUnit.Daily, 0).encode(), ""
105+
);
106+
vm.prank(address(SPENDER));
107+
vm.expectRevert(abi.encodeWithSelector(Budget.InheritedAmountNotAllowed.selector));
108+
budget.setAllowanceAmount(childAllowanceId, 0);
109+
}
110+
84111
function testNotOwnerCannotCreateTopLevelAllowance() public {
85112
vm.expectRevert(abi.encodeWithSelector(Budget.UnauthorizedNotAllowanceAdmin.selector, 0));
86113
createDailyAllowance(SPENDER, 0);
87114
}
88115

89-
function testInvalidTimeshiftsRevert() public {
116+
function testCantCreateAllowanceWithZeroToken() public {
117+
vm.prank(address(safe));
118+
vm.expectRevert(abi.encodeWithSelector(Budget.BadInput.selector));
119+
budget.createAllowance(
120+
NO_PARENT_ID, SPENDER, address(0), 10, TimeShift(TimeShiftLib.TimeUnit.Daily, 0).encode(), ""
121+
);
122+
}
123+
124+
function testCantCreateAllowanceWithZeroSpender() public {
125+
vm.prank(address(safe));
126+
vm.expectRevert(abi.encodeWithSelector(Budget.BadInput.selector));
127+
budget.createAllowance(
128+
NO_PARENT_ID, address(0), token, 10, TimeShift(TimeShiftLib.TimeUnit.Daily, 0).encode(), ""
129+
);
130+
}
131+
132+
function testCantCreateAllowanceWithInvalidTimeshift() public {
90133
vm.prank(address(safe));
91134
vm.expectRevert(abi.encodeWithSelector(TimeShiftLib.InvalidTimeShift.selector));
92135
budget.createAllowance(
93-
NO_PARENT_ID, SPENDER, address(0), 10, TimeShift(TimeShiftLib.TimeUnit.Inherit, 0).encode(), ""
136+
NO_PARENT_ID, SPENDER, token, 10, TimeShift(TimeShiftLib.TimeUnit.Inherit, 0).encode(), ""
94137
);
95138
}
96139

@@ -108,7 +151,7 @@ abstract contract BudgetTest is FirmTest {
108151
vm.prank(address(safe));
109152
vm.expectRevert(abi.encodeWithSelector(RolesAuth.UnexistentRole.selector, badRoleId));
110153
budget.createAllowance(
111-
NO_PARENT_ID, roleFlag(badRoleId), address(0), 10, TimeShift(TimeShiftLib.TimeUnit.Daily, 0).encode(), ""
154+
NO_PARENT_ID, roleFlag(badRoleId), token, 10, TimeShift(TimeShiftLib.TimeUnit.Daily, 0).encode(), ""
112155
);
113156
}
114157

@@ -187,11 +230,11 @@ abstract contract BudgetTest is FirmTest {
187230

188231
vm.prank(address(safe));
189232
topLevelAllowance = budget.createAllowance(
190-
NO_PARENT_ID, SPENDER, address(0), 10, TimeShift(TimeShiftLib.TimeUnit.Monthly, 0).encode(), ""
233+
NO_PARENT_ID, SPENDER, token, 10, TimeShift(TimeShiftLib.TimeUnit.Monthly, 0).encode(), ""
191234
);
192235
vm.prank(SPENDER);
193236
subAllowance = budget.createAllowance(
194-
topLevelAllowance, SOMEONE_ELSE, address(0), 5, TimeShift(TimeShiftLib.TimeUnit.Daily, 0).encode(), ""
237+
topLevelAllowance, SOMEONE_ELSE, token, 5, TimeShift(TimeShiftLib.TimeUnit.Daily, 0).encode(), ""
195238
);
196239

197240
assertExecutePayment(SOMEONE_ELSE, subAllowance, RECEIVER, 5, initialTime + 1 days);
@@ -233,11 +276,11 @@ abstract contract BudgetTest is FirmTest {
233276

234277
vm.prank(address(safe));
235278
uint256 topLevelAllowance = budget.createAllowance(
236-
NO_PARENT_ID, SPENDER, address(0), 10, TimeShift(TimeShiftLib.TimeUnit.Daily, 0).encode(), ""
279+
NO_PARENT_ID, SPENDER, token, 10, TimeShift(TimeShiftLib.TimeUnit.Daily, 0).encode(), ""
237280
);
238281
vm.prank(SPENDER);
239282
uint256 subAllowance = budget.createAllowance(
240-
topLevelAllowance, SOMEONE_ELSE, address(0), 5, TimeShift(TimeShiftLib.TimeUnit.Inherit, 0).encode(), ""
283+
topLevelAllowance, SOMEONE_ELSE, token, 5, TimeShift(TimeShiftLib.TimeUnit.Inherit, 0).encode(), ""
241284
);
242285

243286
assertExecutePayment(SOMEONE_ELSE, subAllowance, RECEIVER, 5, initialTime + 1 days);
@@ -249,17 +292,17 @@ abstract contract BudgetTest is FirmTest {
249292

250293
vm.prank(address(safe));
251294
uint256 allowance1 = budget.createAllowance(
252-
NO_PARENT_ID, SPENDER, address(0), 10, TimeShift(TimeShiftLib.TimeUnit.Monthly, 0).encode(), ""
295+
NO_PARENT_ID, SPENDER, token, 10, TimeShift(TimeShiftLib.TimeUnit.Monthly, 0).encode(), ""
253296
);
254297
vm.startPrank(SPENDER);
255298
uint256 allowance2 = budget.createAllowance(
256-
allowance1, SPENDER, address(0), 5, TimeShift(TimeShiftLib.TimeUnit.Inherit, 0).encode(), ""
299+
allowance1, SPENDER, token, 5, TimeShift(TimeShiftLib.TimeUnit.Inherit, 0).encode(), ""
257300
);
258301
uint256 allowance3 = budget.createAllowance(
259-
allowance2, SPENDER, address(0), 2, TimeShift(TimeShiftLib.TimeUnit.Daily, 0).encode(), ""
302+
allowance2, SPENDER, token, 2, TimeShift(TimeShiftLib.TimeUnit.Daily, 0).encode(), ""
260303
);
261304
uint256 allowance4 = budget.createAllowance(
262-
allowance3, SPENDER, address(0), 1, TimeShift(TimeShiftLib.TimeUnit.Inherit, 0).encode(), ""
305+
allowance3, SPENDER, token, 1, TimeShift(TimeShiftLib.TimeUnit.Inherit, 0).encode(), ""
263306
);
264307
vm.stopPrank();
265308

@@ -522,10 +565,13 @@ abstract contract BudgetTest is FirmTest {
522565
initialSpent = 0;
523566
}
524567

568+
uint256 balanceBefore = token == NATIVE_ASSET ? to.balance : ERC20Token(token_).balanceOf(to);
525569
vm.prank(actor);
526570
vm.expectEmit(true, true, true, true);
527571
emit PaymentExecuted(allowanceId, actor, token_, to, amount, expectedNextResetTime, "");
528572
budget.executePayment(allowanceId, to, amount, "");
573+
uint256 balanceAfter = token == NATIVE_ASSET ? to.balance : ERC20Token(token_).balanceOf(to);
574+
assertEq(balanceAfter - balanceBefore, amount);
529575

530576
(,, uint256 spent,, uint40 nextResetTime,,,) = budget.allowances(allowanceId);
531577

0 commit comments

Comments
 (0)