@@ -28,6 +28,7 @@ import {IEverclearAdapter, IEverclear, IEverclearSpoke} from "../../contracts/in
2828import {Quote} from "../../contracts/interfaces/ITokenBridge.sol " ;
2929import {TokenMessage} from "../../contracts/token/libs/TokenMessage.sol " ;
3030import {IWETH} from "contracts/token/interfaces/IWETH.sol " ;
31+ import {LinearFee} from "../../contracts/token/fees/LinearFee.sol " ;
3132
3233import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol " ;
3334/**
@@ -400,6 +401,56 @@ contract EverclearTokenBridgeTest is Test {
400401 assertEq (sig, feeSignature);
401402 }
402403
404+ function testTransferRemoteWithFeeRecipient () public {
405+ // Create a LinearFee contract as the fee recipient
406+ // LinearFee(token, maxFee, halfAmount, owner)
407+ address feeCollector = makeAddr ("feeCollector " );
408+ LinearFee feeContract = new LinearFee (
409+ address (token),
410+ 1e6 , // maxFee
411+ TRANSFER_AMT / 2 , // halfAmount
412+ feeCollector
413+ );
414+
415+ // Set fee recipient to the LinearFee contract
416+ vm.prank (OWNER);
417+ bridge.setFeeRecipient (address (feeContract));
418+
419+ uint256 initialAliceBalance = token.balanceOf (ALICE);
420+ uint256 initialFeeContractBalance = token.balanceOf (
421+ address (feeContract)
422+ );
423+ uint256 initialBridgeBalance = token.balanceOf (address (bridge));
424+
425+ // Get the expected fee from the feeContract
426+ uint256 expectedFeeRecipientFee = feeContract
427+ .quoteTransferRemote (DESTINATION, RECIPIENT, TRANSFER_AMT)[0 ].amount;
428+
429+ vm.prank (ALICE);
430+ bridge.transferRemote (DESTINATION, RECIPIENT, TRANSFER_AMT);
431+
432+ // Check Alice paid the transfer amount + external fee + fee recipient fee
433+ assertEq (
434+ token.balanceOf (ALICE),
435+ initialAliceBalance -
436+ TRANSFER_AMT -
437+ FEE_AMOUNT -
438+ expectedFeeRecipientFee
439+ );
440+
441+ // Check fee contract received the fee recipient fee (this tests the fix!)
442+ assertEq (
443+ token.balanceOf (address (feeContract)),
444+ initialFeeContractBalance + expectedFeeRecipientFee
445+ );
446+
447+ // Check bridge only holds the transfer amount + external fee, not the fee recipient fee
448+ assertEq (
449+ token.balanceOf (address (bridge)),
450+ initialBridgeBalance + TRANSFER_AMT + FEE_AMOUNT
451+ );
452+ }
453+
403454 function testTransferRemoteOutputAssetNotSet () public {
404455 vm.expectRevert ("ETB: Output asset not set " );
405456 vm.prank (ALICE);
@@ -797,10 +848,9 @@ contract EverclearTokenBridgeForkTest is BaseEverclearTokenBridgeForkTest {
797848contract MockEverclearEthBridge is EverclearEthBridge {
798849 constructor (
799850 IWETH _weth ,
800- uint256 _scale ,
801851 address _mailbox ,
802852 IEverclearAdapter _everclearAdapter
803- ) EverclearEthBridge (_weth, _scale, _mailbox, _everclearAdapter) {}
853+ ) EverclearEthBridge (_weth, _mailbox, _everclearAdapter) {}
804854
805855 bytes public lastIntent;
806856 function _createIntent (
@@ -835,7 +885,6 @@ contract EverclearEthBridgeForkTest is BaseEverclearTokenBridgeForkTest {
835885 // Deploy ETH bridge implementation
836886 MockEverclearEthBridge implementation = new MockEverclearEthBridge (
837887 IWETH (ARBITRUM_WETH),
838- 1 ,
839888 address (0x979Ca5202784112f4738403dBec5D0F3B9daabB9 ), // Mailbox
840889 everclearAdapter
841890 );
@@ -927,7 +976,6 @@ contract EverclearEthBridgeForkTest is BaseEverclearTokenBridgeForkTest {
927976 function testEthBridgeConstructor () public {
928977 EverclearEthBridge newBridge = new EverclearEthBridge (
929978 IWETH (ARBITRUM_WETH),
930- 1 ,
931979 address (0x979Ca5202784112f4738403dBec5D0F3B9daabB9 ), // Mailbox
932980 everclearAdapter
933981 );
0 commit comments