@@ -11,6 +11,7 @@ import "../src/interfaces/IManagerBase.sol";
1111import "../src/interfaces/IRateLimiterEvents.sol " ;
1212import "../src/NttManager/TransceiverRegistry.sol " ;
1313import "../src/libraries/PausableUpgradeable.sol " ;
14+ import "../src/libraries/TransceiverHelpers.sol " ;
1415import {Utils} from "./libraries/Utils.sol " ;
1516
1617import "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol " ;
@@ -787,6 +788,120 @@ contract TestNttManager is Test, IRateLimiterEvents {
787788 e2.receiveMessage (encodedEm);
788789 }
789790
791+ function test_transfersOnForkedChains () public {
792+ uint256 evmChainId = block .chainid ;
793+
794+ address user_A = address (0x123 );
795+ address user_B = address (0x456 );
796+
797+ DummyToken token = DummyToken (nttManager.token ());
798+
799+ uint8 decimals = token.decimals ();
800+
801+ nttManager.setPeer (
802+ TransceiverHelpersLib.SENDING_CHAIN_ID,
803+ toWormholeFormat (address (nttManagerOther)),
804+ 9 ,
805+ type (uint64 ).max
806+ );
807+ nttManager.setOutboundLimit (0 );
808+
809+ token.mintDummy (address (user_A), 5 * 10 ** decimals);
810+
811+ vm.startPrank (user_A);
812+
813+ token.approve (address (nttManager), 3 * 10 ** decimals);
814+
815+ uint64 sequence = nttManager.transfer (
816+ 1 * 10 ** decimals,
817+ TransceiverHelpersLib.SENDING_CHAIN_ID,
818+ toWormholeFormat (user_B),
819+ toWormholeFormat (user_A),
820+ true ,
821+ new bytes (1 )
822+ );
823+
824+ vm.warp (vm.getBlockTimestamp () + 1 days);
825+
826+ vm.chainId (chainId);
827+
828+ // Queued outbound transfers can't be completed
829+ vm.expectRevert (abi.encodeWithSelector (InvalidFork.selector , evmChainId, chainId));
830+ nttManager.completeOutboundQueuedTransfer (sequence);
831+
832+ // Queued outbound transfers can't be cancelled
833+ vm.expectRevert (abi.encodeWithSelector (InvalidFork.selector , evmChainId, chainId));
834+ nttManager.cancelOutboundQueuedTransfer (sequence);
835+
836+ // Outbound transfers fail when queued
837+ vm.expectRevert (abi.encodeWithSelector (InvalidFork.selector , evmChainId, chainId));
838+ nttManager.transfer (
839+ 1 * 10 ** decimals,
840+ TransceiverHelpersLib.SENDING_CHAIN_ID,
841+ toWormholeFormat (user_B),
842+ toWormholeFormat (user_A),
843+ true ,
844+ new bytes (1 )
845+ );
846+ vm.stopPrank ();
847+
848+ nttManager.setOutboundLimit (packTrimmedAmount (type (uint64 ).max, 8 ).untrim (decimals));
849+ // Outbound transfers fail when not queued
850+ vm.prank (user_A);
851+ vm.expectRevert (abi.encodeWithSelector (InvalidFork.selector , evmChainId, chainId));
852+ nttManager.transfer (
853+ 1 * 10 ** decimals,
854+ TransceiverHelpersLib.SENDING_CHAIN_ID,
855+ toWormholeFormat (user_B),
856+ toWormholeFormat (user_A),
857+ false ,
858+ new bytes (1 )
859+ );
860+
861+ // INBOUND
862+
863+ bytes memory tokenTransferMessage = TransceiverStructs.encodeNativeTokenTransfer (
864+ TransceiverStructs.NativeTokenTransfer ({
865+ amount: packTrimmedAmount (100 , 8 ),
866+ sourceToken: toWormholeFormat (address (token)),
867+ to: toWormholeFormat (user_B),
868+ toChain: chainId
869+ })
870+ );
871+
872+ bytes memory transceiverMessage;
873+ TransceiverStructs.NttManagerMessage memory nttManagerMessage;
874+ (nttManagerMessage, transceiverMessage) = TransceiverHelpersLib
875+ .buildTransceiverMessageWithNttManagerPayload (
876+ 0 ,
877+ toWormholeFormat (address (0x1 )),
878+ toWormholeFormat (address (nttManagerOther)),
879+ toWormholeFormat (address (nttManager)),
880+ tokenTransferMessage
881+ );
882+
883+ // Inbound transfers can't be completed
884+ vm.expectRevert (abi.encodeWithSelector (InvalidFork.selector , evmChainId, chainId));
885+ dummyTransceiver.receiveMessage (transceiverMessage);
886+
887+ // Inbound queued transfers can't be completed
888+ nttManager.setInboundLimit (0 , TransceiverHelpersLib.SENDING_CHAIN_ID);
889+
890+ vm.chainId (evmChainId);
891+
892+ bytes32 hash = TransceiverStructs.nttManagerMessageDigest (
893+ TransceiverHelpersLib.SENDING_CHAIN_ID, nttManagerMessage
894+ );
895+ dummyTransceiver.receiveMessage (transceiverMessage);
896+
897+ vm.chainId (chainId);
898+
899+ vm.warp (vm.getBlockTimestamp () + 1 days);
900+
901+ vm.expectRevert (abi.encodeWithSelector (InvalidFork.selector , evmChainId, chainId));
902+ nttManager.completeInboundQueuedTransfer (hash);
903+ }
904+
790905 // TODO:
791906 // currently there is no way to test the threshold logic and the duplicate
792907 // protection logic without setting up the business logic as well.
0 commit comments