Skip to content

Commit a4d1830

Browse files
feat(tests/e2e): Multichain e2e test transfer back (#381)
Co-authored-by: Gjermund Garaba <[email protected]>
1 parent 537b47c commit a4d1830

File tree

2 files changed

+278
-6
lines changed

2 files changed

+278
-6
lines changed

.github/workflows/e2e.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ jobs:
9090
- TestWithCosmosRelayerTestSuite/TestICS20TimeoutPacket
9191
- TestWithCosmosRelayerTestSuite/Test_10_ICS20TimeoutPacket
9292
- TestWithMultichainTestSuite/TestDeploy_Groth16
93-
- TestWithMultichainTestSuite/TestTransferCosmosToEthToCosmos_Groth16
94-
- TestWithMultichainTestSuite/TestTransferEthToCosmosToCosmos_Groth16
93+
- TestWithMultichainTestSuite/TestTransferCosmosToEthToCosmosAndBack_Groth16
94+
- TestWithMultichainTestSuite/TestTransferEthToCosmosToCosmosAndBack_Groth16
9595
- TestWithSP1ICS07TendermintTestSuite/TestDeploy_Groth16
9696
- TestWithSP1ICS07TendermintTestSuite/TestDeploy_Plonk
9797
- TestWithSP1ICS07TendermintTestSuite/TestUpdateClient_Groth16

e2e/interchaintestv8/multichain_test.go

+276-4
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ func (s *MultichainTestSuite) TestDeploy_Groth16() {
646646
}))
647647
}
648648

649-
func (s *MultichainTestSuite) TestTransferCosmosToEthToCosmos_Groth16() {
649+
func (s *MultichainTestSuite) TestTransferCosmosToEthToCosmosAndBack_Groth16() {
650650
ctx := context.Background()
651651
proofType := operator.ProofTypeGroth16
652652

@@ -819,6 +819,7 @@ func (s *MultichainTestSuite) TestTransferCosmosToEthToCosmos_Groth16() {
819819
}))
820820
}))
821821

822+
var finalDenom transfertypes.Denom
822823
s.Require().True(s.Run("Receive packet on SimdB", func() {
823824
var relayTxBodyBz []byte
824825
s.Require().True(s.Run("Retrieve relay tx", func() {
@@ -840,7 +841,7 @@ func (s *MultichainTestSuite) TestTransferCosmosToEthToCosmos_Groth16() {
840841
}))
841842

842843
s.Require().True(s.Run("Verify balances on Cosmos chain", func() {
843-
finalDenom := transfertypes.NewDenom(
844+
finalDenom = transfertypes.NewDenom(
844845
simdA.Config().Denom,
845846
transfertypes.NewHop(transfertypes.PortID, testvalues.FirstWasmClientID),
846847
transfertypes.NewHop(transfertypes.PortID, testvalues.FirstUniversalClientID),
@@ -857,9 +858,146 @@ func (s *MultichainTestSuite) TestTransferCosmosToEthToCosmos_Groth16() {
857858
s.Require().Equal(finalDenom.IBCDenom(), resp.Balance.Denom)
858859
}))
859860
}))
861+
862+
// Transfer back (unwind)
863+
s.Require().True(s.Run("Transfer tokens from SimdB to Ethereum", func() {
864+
timeout := uint64(time.Now().Add(30 * time.Minute).Unix())
865+
transferPayload := transfertypes.FungibleTokenPacketData{
866+
Denom: finalDenom.Path(), // XXX: IBCDenom()?
867+
Amount: transferAmount.String(),
868+
Sender: simdBUser.FormattedAddress(),
869+
Receiver: strings.ToLower(ethereumUserAddress.Hex()),
870+
Memo: "",
871+
}
872+
873+
encodedPayload, err := transfertypes.EncodeABIFungibleTokenPacketData(&transferPayload)
874+
s.Require().NoError(err)
875+
876+
payload := channeltypesv2.Payload{
877+
SourcePort: transfertypes.PortID,
878+
DestinationPort: transfertypes.PortID,
879+
Version: transfertypes.V1,
880+
Encoding: transfertypes.EncodingABI,
881+
Value: encodedPayload,
882+
}
883+
884+
resp, err := s.BroadcastMessages(ctx, simdB, simdBUser, 200_000, &channeltypesv2.MsgSendPacket{
885+
SourceClient: testvalues.FirstWasmClientID,
886+
TimeoutTimestamp: timeout,
887+
Payloads: []channeltypesv2.Payload{
888+
payload,
889+
},
890+
Signer: simdBUser.FormattedAddress(),
891+
})
892+
s.Require().NoError(err)
893+
s.Require().NotEmpty(resp.TxHash)
894+
895+
simdBSendTxHash, err := hex.DecodeString(resp.TxHash)
896+
s.Require().NoError(err)
897+
898+
s.Require().True(s.Run("Receive packet on Ethereum", func() {
899+
var relayTxBodyBz []byte
900+
s.Require().True(s.Run("Retrieve relay tx", func() {
901+
resp, err := s.RelayerClient.RelayByTx(context.Background(), &relayertypes.RelayByTxRequest{
902+
SrcChain: simdB.Config().ChainID,
903+
DstChain: eth.ChainID.String(),
904+
SourceTxIds: [][]byte{simdBSendTxHash},
905+
TargetClientId: testvalues.SecondUniversalClientID,
906+
})
907+
s.Require().NoError(err)
908+
s.Require().NotEmpty(resp.Tx)
909+
s.Require().Equal(ics26Address.String(), resp.Address)
910+
911+
relayTxBodyBz = resp.Tx
912+
}))
913+
914+
s.Require().True(s.Run("Submit relay tx", func() {
915+
receipt, err := eth.BroadcastTx(ctx, s.EthRelayerSubmitter, 5_000_000, ics26Address, relayTxBodyBz)
916+
s.Require().NoError(err)
917+
s.Require().Equal(ethtypes.ReceiptStatusSuccessful, receipt.Status, fmt.Sprintf("Tx failed: %+v", receipt))
918+
}))
919+
920+
s.True(s.Run("Verify balances on Ethereum", func() {
921+
userBalance, err := ibcERC20.BalanceOf(nil, ethereumUserAddress)
922+
s.Require().NoError(err)
923+
s.Require().Equal(transferAmount, userBalance)
924+
925+
// ICS20 contract balance on Ethereum
926+
ics20TransferBalance, err := ibcERC20.BalanceOf(nil, ics20Address)
927+
s.Require().NoError(err)
928+
s.Require().Zero(ics20TransferBalance.Int64())
929+
}))
930+
}))
931+
}))
932+
933+
s.Require().True(s.Run("Approve the ICS20Transfer.sol contract to spend the erc20 tokens", func() {
934+
tx, err := ibcERC20.Approve(s.GetTransactOpts(s.key, eth), ics20Address, transferAmount)
935+
s.Require().NoError(err)
936+
937+
receipt, err := eth.GetTxReciept(ctx, tx.Hash())
938+
s.Require().NoError(err)
939+
s.Require().Equal(ethtypes.ReceiptStatusSuccessful, receipt.Status)
940+
941+
allowance, err := ibcERC20.Allowance(nil, ethereumUserAddress, ics20Address)
942+
s.Require().NoError(err)
943+
s.Require().Equal(transferAmount, allowance)
944+
}))
945+
946+
s.Require().True(s.Run("Transfer tokens from Ethereum to SimdA", func() {
947+
timeout := uint64(time.Now().Add(30 * time.Minute).Unix())
948+
msgSendPacket := ics20transfer.IICS20TransferMsgsSendTransferMsg{
949+
Denom: ibcERC20Address,
950+
Amount: transferAmount,
951+
Receiver: simdAUser.FormattedAddress(),
952+
SourceClient: testvalues.FirstUniversalClientID,
953+
DestPort: transfertypes.PortID,
954+
TimeoutTimestamp: timeout,
955+
Memo: "",
956+
}
957+
958+
tx, err := s.ics20Contract.SendTransfer(s.GetTransactOpts(s.key, eth), msgSendPacket)
959+
s.Require().NoError(err)
960+
961+
receipt, err := eth.GetTxReciept(ctx, tx.Hash())
962+
s.Require().NoError(err)
963+
s.Require().Equal(ethtypes.ReceiptStatusSuccessful, receipt.Status)
964+
965+
ethSendTxHash = tx.Hash().Bytes()
966+
}))
967+
968+
s.Require().True(s.Run("Receive packet on SimdA", func() {
969+
var relayTxBodyBz []byte
970+
s.Require().True(s.Run("Retrieve relay tx", func() {
971+
resp, err := s.RelayerClient.RelayByTx(context.Background(), &relayertypes.RelayByTxRequest{
972+
SrcChain: eth.ChainID.String(),
973+
DstChain: simdA.Config().ChainID,
974+
SourceTxIds: [][]byte{ethSendTxHash},
975+
TargetClientId: testvalues.FirstWasmClientID,
976+
})
977+
s.Require().NoError(err)
978+
s.Require().NotEmpty(resp.Tx)
979+
s.Require().Empty(resp.Address)
980+
981+
relayTxBodyBz = resp.Tx
982+
}))
983+
984+
s.Require().True(s.Run("Broadcast relay tx", func() {
985+
_ = s.BroadcastSdkTxBody(ctx, simdA, s.SimdARelayerSubmitter, 2_000_000, relayTxBodyBz)
986+
}))
987+
988+
s.Require().True(s.Run("Verify balances on Cosmos chain", func() {
989+
resp, err := e2esuite.GRPCQuery[banktypes.QueryBalanceResponse](ctx, simdA, &banktypes.QueryBalanceRequest{
990+
Address: simdAUser.FormattedAddress(),
991+
Denom: simdA.Config().Denom,
992+
})
993+
s.Require().NoError(err)
994+
s.Require().NotNil(resp.Balance)
995+
s.Require().Equal(testvalues.InitialBalance, resp.Balance.Amount.Int64())
996+
}))
997+
}))
860998
}
861999

862-
func (s *MultichainTestSuite) TestTransferEthToCosmosToCosmos_Groth16() {
1000+
func (s *MultichainTestSuite) TestTransferEthToCosmosToCosmosAndBack_Groth16() {
8631001
ctx := context.Background()
8641002
proofType := operator.ProofTypeGroth16
8651003

@@ -1006,6 +1144,7 @@ func (s *MultichainTestSuite) TestTransferEthToCosmosToCosmos_Groth16() {
10061144
s.Require().NoError(err)
10071145
}))
10081146

1147+
var finalDenom transfertypes.Denom
10091148
s.Require().True(s.Run("Receive packet on SimdB", func() {
10101149
var txBodyBz []byte
10111150
s.Require().True(s.Run("Retrieve relay tx to SimdB", func() {
@@ -1028,7 +1167,7 @@ func (s *MultichainTestSuite) TestTransferEthToCosmosToCosmos_Groth16() {
10281167
}))
10291168

10301169
s.Require().True(s.Run("Verify balances on Cosmos chain", func() {
1031-
finalDenom := transfertypes.NewDenom(
1170+
finalDenom = transfertypes.NewDenom(
10321171
s.contractAddresses.Erc20,
10331172
transfertypes.NewHop(transfertypes.PortID, ibctesting.SecondClientID),
10341173
transfertypes.NewHop(transfertypes.PortID, testvalues.FirstWasmClientID),
@@ -1045,4 +1184,137 @@ func (s *MultichainTestSuite) TestTransferEthToCosmosToCosmos_Groth16() {
10451184
s.Require().Equal(finalDenom.IBCDenom(), resp.Balance.Denom)
10461185
}))
10471186
}))
1187+
1188+
// Transfer back (unwind)
1189+
var simdBTransferTxHash []byte
1190+
s.Require().True(s.Run("Transfer tokens from SimdB to SimdA", func() {
1191+
timeout := uint64(time.Now().Add(30 * time.Minute).Unix())
1192+
transferPayload := transfertypes.FungibleTokenPacketData{
1193+
Denom: finalDenom.Path(), // XXX: IBCDenom()?
1194+
Amount: transferAmount.String(),
1195+
Sender: simdBUser.FormattedAddress(),
1196+
Receiver: simdAUser.FormattedAddress(),
1197+
Memo: "",
1198+
}
1199+
encodedPayload, err := transfertypes.EncodeABIFungibleTokenPacketData(&transferPayload)
1200+
s.Require().NoError(err)
1201+
1202+
payload := channeltypesv2.Payload{
1203+
SourcePort: transfertypes.PortID,
1204+
DestinationPort: transfertypes.PortID,
1205+
Version: transfertypes.V1,
1206+
Encoding: transfertypes.EncodingABI,
1207+
Value: encodedPayload,
1208+
}
1209+
1210+
resp, err := s.BroadcastMessages(ctx, simdB, simdBUser, 2_000_000, &channeltypesv2.MsgSendPacket{
1211+
SourceClient: ibctesting.SecondClientID,
1212+
TimeoutTimestamp: timeout,
1213+
Payloads: []channeltypesv2.Payload{payload},
1214+
Signer: simdBUser.FormattedAddress(),
1215+
})
1216+
s.Require().NoError(err)
1217+
s.Require().NotEmpty(resp.TxHash)
1218+
1219+
simdBTransferTxHash, err = hex.DecodeString(resp.TxHash)
1220+
s.Require().NoError(err)
1221+
}))
1222+
1223+
s.Require().True(s.Run("Receive packet on SimdA", func() {
1224+
var relayTxBodyBz []byte
1225+
s.Require().True(s.Run("Retrieve relay tx", func() {
1226+
resp, err := s.RelayerClient.RelayByTx(context.Background(), &relayertypes.RelayByTxRequest{
1227+
SrcChain: simdB.Config().ChainID,
1228+
DstChain: simdA.Config().ChainID,
1229+
SourceTxIds: [][]byte{simdBTransferTxHash},
1230+
TargetClientId: ibctesting.SecondClientID,
1231+
})
1232+
s.Require().NoError(err)
1233+
s.Require().NotEmpty(resp.Tx)
1234+
s.Require().Empty(resp.Address)
1235+
1236+
relayTxBodyBz = resp.Tx
1237+
}))
1238+
1239+
s.Require().True(s.Run("Broadcast relay tx on SimdA", func() {
1240+
_ = s.BroadcastSdkTxBody(ctx, simdA, s.SimdARelayerSubmitter, 2_000_000, relayTxBodyBz)
1241+
}))
1242+
1243+
s.Require().True(s.Run("Verify balances on SimdA", func() {
1244+
denomOnSimdA := transfertypes.NewDenom(s.contractAddresses.Erc20, transfertypes.NewHop(transfertypes.PortID, testvalues.FirstWasmClientID))
1245+
resp, err := e2esuite.GRPCQuery[banktypes.QueryBalanceResponse](ctx, simdA, &banktypes.QueryBalanceRequest{
1246+
Address: simdAUser.FormattedAddress(),
1247+
Denom: denomOnSimdA.IBCDenom(),
1248+
})
1249+
s.Require().NoError(err)
1250+
s.Require().NotNil(resp.Balance)
1251+
s.Require().Equal(transferAmount, resp.Balance.Amount.BigInt())
1252+
s.Require().Equal(denomOnSimdA.IBCDenom(), resp.Balance.Denom)
1253+
}))
1254+
}))
1255+
1256+
s.Require().True(s.Run("Transfer tokens from SimdA to Ethereum", func() {
1257+
timeout := uint64(time.Now().Add(30 * time.Minute).Unix())
1258+
denomOnSimdA := transfertypes.NewDenom(s.contractAddresses.Erc20, transfertypes.NewHop(transfertypes.PortID, testvalues.FirstWasmClientID))
1259+
transferPayload := transfertypes.FungibleTokenPacketData{
1260+
Denom: denomOnSimdA.Path(),
1261+
Amount: transferAmount.String(),
1262+
Sender: simdAUser.FormattedAddress(),
1263+
Receiver: strings.ToLower(ethereumUserAddress.Hex()),
1264+
Memo: "",
1265+
}
1266+
encodedPayload, err := transfertypes.EncodeABIFungibleTokenPacketData(&transferPayload)
1267+
s.Require().NoError(err)
1268+
1269+
payload := channeltypesv2.Payload{
1270+
SourcePort: transfertypes.PortID,
1271+
DestinationPort: transfertypes.PortID,
1272+
Version: transfertypes.V1,
1273+
Encoding: transfertypes.EncodingABI,
1274+
Value: encodedPayload,
1275+
}
1276+
1277+
resp, err := s.BroadcastMessages(ctx, simdA, simdAUser, 2_000_000, &channeltypesv2.MsgSendPacket{
1278+
SourceClient: testvalues.FirstWasmClientID,
1279+
TimeoutTimestamp: timeout,
1280+
Payloads: []channeltypesv2.Payload{payload},
1281+
Signer: simdAUser.FormattedAddress(),
1282+
})
1283+
s.Require().NoError(err)
1284+
s.Require().NotEmpty(resp.TxHash)
1285+
1286+
simdASendTxHash, err = hex.DecodeString(resp.TxHash)
1287+
s.Require().NoError(err)
1288+
1289+
s.Require().True(s.Run("Receive packet on Ethereum", func() {
1290+
ics26Address := ethcommon.HexToAddress(s.contractAddresses.Ics26Router)
1291+
1292+
var relayTxBodyBz []byte
1293+
s.Require().True(s.Run("Retrieve relay tx", func() {
1294+
resp, err := s.RelayerClient.RelayByTx(context.Background(), &relayertypes.RelayByTxRequest{
1295+
SrcChain: simdA.Config().ChainID,
1296+
DstChain: eth.ChainID.String(),
1297+
SourceTxIds: [][]byte{simdASendTxHash},
1298+
TargetClientId: testvalues.FirstUniversalClientID,
1299+
})
1300+
s.Require().NoError(err)
1301+
s.Require().NotEmpty(resp.Tx)
1302+
s.Require().Equal(ics26Address.String(), resp.Address)
1303+
1304+
relayTxBodyBz = resp.Tx
1305+
}))
1306+
1307+
s.Require().True(s.Run("Submit relay tx", func() {
1308+
receipt, err := eth.BroadcastTx(ctx, s.EthRelayerSubmitter, 5_000_000, ics26Address, relayTxBodyBz)
1309+
s.Require().NoError(err)
1310+
s.Require().Equal(ethtypes.ReceiptStatusSuccessful, receipt.Status, fmt.Sprintf("Tx failed: %+v", receipt))
1311+
}))
1312+
1313+
s.True(s.Run("Verify balances on Ethereum", func() {
1314+
userBalance, err := s.erc20Contract.BalanceOf(nil, ethereumUserAddress)
1315+
s.Require().NoError(err)
1316+
s.Require().Equal(testvalues.StartingERC20Balance, userBalance)
1317+
}))
1318+
}))
1319+
}))
10481320
}

0 commit comments

Comments
 (0)