Skip to content

Commit 6b61e28

Browse files
committed
fix tests
Signed-off-by: Ihor Farion <ihor@umaproject.org>
1 parent 45fc706 commit 6b61e28

1 file changed

Lines changed: 50 additions & 28 deletions

File tree

test/evm/foundry/local/ArbitraryEVMFlowExecutor.t.sol

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ contract ArbitraryEVMFlowExecutorTest is Test {
107107
});
108108
}
109109

110-
// ----- Branch 1: action fails -> initialToken returned, finalToken rewritten to initialToken -----
110+
// ----- Action fails -> initialToken returned, finalToken rewritten to initialToken -----
111111
function testActionFails_FallsBackToInitialToken() public {
112112
tokenIn.mint(address(harness), 1000e6);
113113

@@ -127,8 +127,7 @@ contract ArbitraryEVMFlowExecutorTest is Test {
127127
assertEq(tokenIn.balanceOf(address(multicallHandler)), 0, "handler drained");
128128
}
129129

130-
// ----- Branch 2: same input/output token, action consumes more than it returns -----
131-
// Pre-fix this case incorrectly reported finalAmount = 0.
130+
// ----- Same input/output token, action consumes more than it returns (net loss) -----
132131
function testSameToken_PartialConsumption() public {
133132
tokenIn.mint(address(harness), 1000e6);
134133
tokenIn.mint(address(swap), 1000e6); // pre-fund swap with output liquidity
@@ -145,13 +144,14 @@ contract ArbitraryEVMFlowExecutorTest is Test {
145144
CommonFlowParams memory out = harness.executeFlow(p);
146145

147146
assertEq(out.finalToken, address(tokenIn), "finalToken unchanged");
148-
assertEq(out.amountInEVM, 400e6, "finalAmount = amountInEVM - (X - Y) = 500 - 100 = 400");
147+
// finalAmount = amountInEVM + eBI - sBI = 500 + 900 - 1000 = 400.
148+
assertEq(out.amountInEVM, 400e6, "credits net delta against amountInEVM");
149149
// Harness: 1000 - 500 transfer + 400 drain back = 900.
150150
assertEq(tokenIn.balanceOf(address(harness)), 900e6);
151151
assertEq(tokenIn.balanceOf(address(multicallHandler)), 0);
152152
}
153153

154-
// ----- Branch 1 (no-op): same token, empty calls -> full amountInEVM returned -----
154+
// ----- Same token, empty calls -> full amountInEVM returned -----
155155
function testSameToken_NoCalls() public {
156156
tokenIn.mint(address(harness), 1000e6);
157157

@@ -165,9 +165,8 @@ contract ArbitraryEVMFlowExecutorTest is Test {
165165
assertEq(tokenIn.balanceOf(address(harness)), 1000e6, "harness balance unchanged");
166166
}
167167

168-
// ----- Edge case: same token, profitable (Y > X) ----
169-
// The `<=` in branch 1 swallows the surplus; documents current behaviour.
170-
function testSameToken_Profitable_SurplusStaysInContract() public {
168+
// ----- Same token, profitable (Y > X) -> surplus is credited to finalAmount -----
169+
function testSameToken_Profitable_SurplusIsCredited() public {
171170
tokenIn.mint(address(harness), 1000e6);
172171
tokenIn.mint(address(swap), 1000e6);
173172

@@ -183,13 +182,12 @@ contract ArbitraryEVMFlowExecutorTest is Test {
183182
CommonFlowParams memory out = harness.executeFlow(p);
184183

185184
assertEq(out.finalToken, address(tokenIn));
186-
// Branch 1 triggers (initialBalance > initialAmountSnapshot via `<=`); reports the original input.
187-
assertEq(out.amountInEVM, 500e6, "branch 1 reports amountInEVM, ignoring surplus");
188-
// Harness physically holds 1000 - 500 + 600 = 1100. Surplus of 100 is held but unreported.
189-
assertEq(tokenIn.balanceOf(address(harness)), 1100e6, "surplus is retained in the contract");
185+
// finalAmount = amountInEVM + eBI - sBI = 500 + 1100 - 1000 = 600.
186+
assertEq(out.amountInEVM, 600e6, "surplus is credited via balance delta");
187+
assertEq(tokenIn.balanceOf(address(harness)), 1100e6, "harness physically holds the surplus");
190188
}
191189

192-
// ----- Branch 3: different tokens, normal swap -----
190+
// ----- Different tokens, normal swap -----
193191
function testDifferentTokens_NormalSwap() public {
194192
tokenIn.mint(address(harness), 1000e6);
195193
tokenOut.mint(address(swap), 1000e6);
@@ -210,10 +208,8 @@ contract ArbitraryEVMFlowExecutorTest is Test {
210208
assertEq(tokenOut.balanceOf(address(harness)), 400e6, "tokenOut received");
211209
}
212210

213-
// ----- Pre-existing handler dust in initialToken must not orphan the swap output -----
214-
// Pre-fix: initialBalance from dust drain triggered the "swap didn't happen" branch,
215-
// rewriting finalToken to initialToken and stranding the actual finalToken output in the executor.
216-
function testDifferentTokens_HandlerDustInInitialToken_DoesNotOrphanSwapOutput() public {
211+
// ----- Pre-existing handler dust in initialToken is drained upfront and not credited to the flow -----
212+
function testDifferentTokens_HandlerDustInInitialToken_IsDrainedUpfront() public {
217213
tokenIn.mint(address(harness), 1000e6);
218214
tokenIn.mint(address(multicallHandler), 500e6); // pre-existing dust on handler
219215
tokenOut.mint(address(swap), 1000e6);
@@ -228,17 +224,43 @@ contract ArbitraryEVMFlowExecutorTest is Test {
228224
EVMFlowParams memory p = _params(address(tokenIn), address(tokenOut), 500e6, abi.encode(calls));
229225
CommonFlowParams memory out = harness.executeFlow(p);
230226

231-
assertEq(out.finalToken, address(tokenOut), "finalToken must remain tokenOut despite handler dust");
232-
assertEq(out.amountInEVM, 400e6, "credits actual swap output, not stale initialAmountSnapshot");
233-
// Harness physically holds 1000 - 500 transferred + 500 dust returned = 1000 tokenIn,
234-
// plus the 400 tokenOut from the swap. The dust stays on the executor but is not credited to the user.
235-
assertEq(tokenIn.balanceOf(address(harness)), 1000e6, "handler dust drained back to executor");
236-
assertEq(tokenOut.balanceOf(address(harness)), 400e6, "swap output preserved");
237-
assertEq(tokenIn.balanceOf(address(multicallHandler)), 0, "handler fully drained");
227+
assertEq(out.finalToken, address(tokenOut));
228+
assertEq(out.amountInEVM, 400e6, "credits finalToken balance delta only");
229+
// _drainMulticallHandlerDust pulled 500 tokenIn back to the harness before the snapshot,
230+
// so sBI captured it and the swap delta is unaffected by the dust.
231+
assertEq(tokenIn.balanceOf(address(harness)), 1000e6);
232+
assertEq(tokenOut.balanceOf(address(harness)), 400e6);
233+
assertEq(tokenIn.balanceOf(address(multicallHandler)), 0);
234+
assertEq(tokenOut.balanceOf(address(multicallHandler)), 0);
235+
}
236+
237+
// ----- Pre-existing handler dust in finalToken is drained upfront and not credited to the flow -----
238+
function testDifferentTokens_HandlerDustInFinalToken_IsDrainedUpfront() public {
239+
tokenIn.mint(address(harness), 1000e6);
240+
tokenOut.mint(address(multicallHandler), 250e6); // pre-existing finalToken dust on handler
241+
tokenOut.mint(address(swap), 1000e6);
242+
243+
ArbitraryEVMFlowExecutor.CompressedCall[] memory calls = _buildSwapCalls(
244+
address(tokenIn),
245+
address(tokenOut),
246+
500e6,
247+
400e6
248+
);
249+
250+
EVMFlowParams memory p = _params(address(tokenIn), address(tokenOut), 500e6, abi.encode(calls));
251+
CommonFlowParams memory out = harness.executeFlow(p);
252+
253+
assertEq(out.finalToken, address(tokenOut));
254+
// Without the upfront drain, sBF would have started at 250 and the swap's 400 output
255+
// would still pass eBF > sBF. Verifying 400e6 here also confirms the dust wasn't double-credited.
256+
assertEq(out.amountInEVM, 400e6, "finalAmount = eBF - sBF, dust excluded by upfront drain");
257+
// Harness keeps the drained dust (250) + swap output (400) = 650 tokenOut.
258+
assertEq(tokenOut.balanceOf(address(harness)), 650e6);
259+
assertEq(tokenIn.balanceOf(address(multicallHandler)), 0);
238260
assertEq(tokenOut.balanceOf(address(multicallHandler)), 0);
239261
}
240262

241-
// ----- Branch 3 (partial consumption): different tokens, leftover initialToken returned -----
263+
// ----- Different tokens, partial consumption: leftover initialToken returned by handler's tail drain -----
242264
function testDifferentTokens_PartialConsumption_LeftoverInitialTokenReturned() public {
243265
tokenIn.mint(address(harness), 1000e6);
244266
tokenOut.mint(address(swap), 1000e6);
@@ -255,9 +277,9 @@ contract ArbitraryEVMFlowExecutorTest is Test {
255277
CommonFlowParams memory out = harness.executeFlow(p);
256278

257279
assertEq(out.finalToken, address(tokenOut));
258-
assertEq(out.amountInEVM, 400e6, "credits finalToken received");
259-
// The 200 of unspent initialToken at handler is drained by MulticallHandler's tail drain.
260-
assertEq(tokenIn.balanceOf(address(harness)), 700e6, "1000 - 500 transferred + 200 leftover returned");
280+
assertEq(out.amountInEVM, 400e6, "finalAmount = eBF - sBF (finalToken delta)");
281+
// The 200 of unspent initialToken left at handler is returned by handleV3AcrossMessage's tail drain.
282+
assertEq(tokenIn.balanceOf(address(harness)), 700e6);
261283
assertEq(tokenOut.balanceOf(address(harness)), 400e6);
262284
assertEq(tokenIn.balanceOf(address(multicallHandler)), 0);
263285
}

0 commit comments

Comments
 (0)