@@ -10,6 +10,8 @@ import { IModularCore } from "lib/modular-contracts/src/interface/IModularCore.s
10
10
import { LibClone } from "lib/solady/src/utils/LibClone.sol " ;
11
11
import { MockERC20 } from "./utils/MockERC20.sol " ;
12
12
import { MockTarget } from "./utils/MockTarget.sol " ;
13
+ import { MockTargetNonSpender } from "./utils/MockTargetNonSpender.sol " ;
14
+ import { MockSpender } from "./utils/MockSpender.sol " ;
13
15
14
16
contract UniversalBridgeTest is Test {
15
17
event TransactionInitiated (
@@ -25,6 +27,8 @@ contract UniversalBridgeTest is Test {
25
27
UniversalBridgeV1 internal bridge;
26
28
MockERC20 internal mockERC20;
27
29
MockTarget internal mockTarget;
30
+ MockTargetNonSpender internal mockTargetNonSpender;
31
+ MockSpender internal mockSpender;
28
32
29
33
address payable internal owner;
30
34
address payable internal protocolFeeRecipient;
@@ -63,6 +67,8 @@ contract UniversalBridgeTest is Test {
63
67
64
68
mockERC20 = new MockERC20 ("Token " , "TKN " );
65
69
mockTarget = new MockTarget ();
70
+ mockSpender = new MockSpender ();
71
+ mockTargetNonSpender = new MockTargetNonSpender (address (mockSpender));
66
72
67
73
// fund the sender
68
74
mockERC20.mint (sender, 1000 ether);
@@ -123,6 +129,42 @@ contract UniversalBridgeTest is Test {
123
129
assertEq (mockERC20.balanceOf (receiver), receiverBalanceBefore + sendValue);
124
130
}
125
131
132
+ function test_initiateTransaction_erc20_differentSpender () public {
133
+ bytes memory targetCalldata = _buildMockTargetCalldata (sender, receiver, address (mockERC20), sendValue, "" );
134
+
135
+ // approve amount to bridge contract
136
+ vm.prank (sender);
137
+ mockERC20.approve (address (bridge), sendValueWithFees);
138
+
139
+ bytes32 _transactionId = keccak256 ("transaction ID " );
140
+
141
+ // state/balances before sending transaction
142
+ uint256 protocolFeeRecipientBalanceBefore = mockERC20.balanceOf (protocolFeeRecipient);
143
+ uint256 developerBalanceBefore = mockERC20.balanceOf (developer);
144
+ uint256 senderBalanceBefore = mockERC20.balanceOf (sender);
145
+ uint256 receiverBalanceBefore = mockERC20.balanceOf (receiver);
146
+
147
+ // send transaction
148
+ vm.prank (sender);
149
+ bridge.initiateTransaction (
150
+ _transactionId,
151
+ address (mockERC20),
152
+ sendValue,
153
+ payable (address (mockTargetNonSpender)),
154
+ payable (address (mockSpender)),
155
+ developer,
156
+ developerFeeBps,
157
+ targetCalldata,
158
+ ""
159
+ );
160
+
161
+ // check balances after transaction
162
+ assertEq (mockERC20.balanceOf (protocolFeeRecipient), protocolFeeRecipientBalanceBefore + expectedProtocolFee);
163
+ assertEq (mockERC20.balanceOf (developer), developerBalanceBefore + expectedDeveloperFee);
164
+ assertEq (mockERC20.balanceOf (sender), senderBalanceBefore - sendValueWithFees);
165
+ assertEq (mockERC20.balanceOf (receiver), receiverBalanceBefore + sendValue);
166
+ }
167
+
126
168
function test_initiateTransaction_erc20_directTransfer () public {
127
169
// approve amount to bridge contract
128
170
vm.prank (sender);
@@ -146,7 +188,6 @@ contract UniversalBridgeTest is Test {
146
188
payable (address (0 )),
147
189
developer,
148
190
developerFeeBps,
149
- // true,
150
191
"" ,
151
192
""
152
193
);
@@ -196,6 +237,44 @@ contract UniversalBridgeTest is Test {
196
237
assertEq (receiver.balance, receiverBalanceBefore + sendValue);
197
238
}
198
239
240
+ function test_initiateTransaction_nativeToken_differentSpender () public {
241
+ bytes memory targetCalldata = _buildMockTargetCalldata (
242
+ sender,
243
+ receiver,
244
+ address (0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE ),
245
+ sendValue,
246
+ ""
247
+ );
248
+
249
+ bytes32 _transactionId = keccak256 ("transaction ID " );
250
+
251
+ // state/balances before sending transaction
252
+ uint256 protocolFeeRecipientBalanceBefore = protocolFeeRecipient.balance;
253
+ uint256 developerBalanceBefore = developer.balance;
254
+ uint256 senderBalanceBefore = sender.balance;
255
+ uint256 receiverBalanceBefore = receiver.balance;
256
+
257
+ // send transaction
258
+ vm.prank (sender);
259
+ bridge.initiateTransaction { value: sendValueWithFees }(
260
+ _transactionId,
261
+ address (0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE ),
262
+ sendValue,
263
+ payable (address (mockTargetNonSpender)),
264
+ payable (address (mockSpender)),
265
+ developer,
266
+ developerFeeBps,
267
+ targetCalldata,
268
+ ""
269
+ );
270
+
271
+ // check balances after transaction
272
+ assertEq (protocolFeeRecipient.balance, protocolFeeRecipientBalanceBefore + expectedProtocolFee);
273
+ assertEq (developer.balance, developerBalanceBefore + expectedDeveloperFee);
274
+ assertEq (sender.balance, senderBalanceBefore - sendValueWithFees);
275
+ assertEq (receiver.balance, receiverBalanceBefore + sendValue);
276
+ }
277
+
199
278
function test_initiateTransaction_nativeToken_directTransfer () public {
200
279
bytes memory targetCalldata = "" ;
201
280
0 commit comments