Skip to content

Commit

Permalink
Merge pull request #113 from ava-labs/test-case-send-specific-receipts
Browse files Browse the repository at this point in the history
Test send specific receipts (Part 2)
  • Loading branch information
gwen917 committed Nov 7, 2023
2 parents 0e8ef2d + e0a076f commit e8a3751
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 2 deletions.
1 change: 1 addition & 0 deletions tests/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ var _ = ginkgo.AfterSuite(testUtils.TearDownNetwork)
var _ = ginkgo.Describe("[Teleporter integration tests]", func() {
ginkgo.It("Send a message from Subnet A to Subnet B", BasicOneWaySendGinkgo)
ginkgo.It("Add additional fee amount", AddFeeAmountGinkgo)
ginkgo.It("Send specific receipts", SendSpecificReceiptsGinkgo)
})
131 changes: 131 additions & 0 deletions tests/send_specific_receipts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package tests

import (
"context"
"math/big"

"github.com/ava-labs/subnet-evm/accounts/abi/bind"
teleportermessenger "github.com/ava-labs/teleporter/abi-bindings/go/Teleporter/TeleporterMessenger"
"github.com/ava-labs/teleporter/tests/network"
"github.com/ava-labs/teleporter/tests/utils"
"github.com/ethereum/go-ethereum/common"
. "github.com/onsi/gomega"
)

func SendSpecificReceiptsGinkgo() {
SendSpecificReceipts(&network.LocalNetwork{})
}

func SendSpecificReceipts(network network.Network) {
subnets := network.GetSubnetsInfo()
subnetAInfo := subnets[0]
subnetBInfo := subnets[1]
teleporterContractAddress := network.GetTeleporterContractAddress()
fundedAddress, fundedKey := network.GetFundedAccountInfo()
ctx := context.Background()

subnetATeleporterMessenger, err := teleportermessenger.NewTeleporterMessenger(teleporterContractAddress, subnetAInfo.ChainRPCClient)
Expect(err).Should(BeNil())
subnetBTeleporterMessenger, err := teleportermessenger.NewTeleporterMessenger(teleporterContractAddress, subnetBInfo.ChainRPCClient)
Expect(err).Should(BeNil())

// Use mock token as the fee token
mockTokenAddress, mockToken := utils.DeployMockToken(context.Background(), fundedAddress, fundedKey, subnetAInfo)
utils.ExampleERC20Approve(ctx, mockToken, teleporterContractAddress, big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(10)), subnetAInfo)

relayerFeePerMessage := big.NewInt(5)
totalAccumulatedRelayerFee := big.NewInt(10)
// Send two messages from Subnet A to Subnet B
sendCrossChainMessageInput := teleportermessenger.TeleporterMessageInput{
DestinationChainID: subnetBInfo.BlockchainID,
DestinationAddress: fundedAddress,
FeeInfo: teleportermessenger.TeleporterFeeInfo{
ContractAddress: mockTokenAddress,
Amount: relayerFeePerMessage,
},
RequiredGasLimit: big.NewInt(1),
AllowedRelayerAddresses: []common.Address{},
Message: []byte{1, 2, 3, 4},
}

// Send first message from Subnet A to Subnet B with fee amount 5
sendCrossChainMsgReceipt, messageID1 := utils.SendCrossChainMessageAndWaitForAcceptance(
ctx, subnetAInfo, subnetBInfo, sendCrossChainMessageInput, fundedAddress, fundedKey, subnetATeleporterMessenger)

// Relay message from SubnetA to SubnetB
network.RelayMessage(ctx, sendCrossChainMsgReceipt.BlockHash, sendCrossChainMsgReceipt.BlockNumber, subnetAInfo, subnetBInfo)
// Check messge delivered
delivered, err := subnetBTeleporterMessenger.MessageReceived(&bind.CallOpts{}, subnetAInfo.BlockchainID, messageID1)
Expect(err).Should(BeNil())
Expect(delivered).Should(BeTrue())

// Send second message from Subnet A to Subnet B with fee amount 5
sendCrossChainMsgReceipt, messageID2 := utils.SendCrossChainMessageAndWaitForAcceptance(
ctx, subnetAInfo, subnetBInfo, sendCrossChainMessageInput, fundedAddress, fundedKey, subnetATeleporterMessenger)

// Relay message from SubnetA to SubnetB
network.RelayMessage(ctx, sendCrossChainMsgReceipt.BlockHash, sendCrossChainMsgReceipt.BlockNumber, subnetAInfo, subnetBInfo)
// Check delivered
delivered, err = subnetBTeleporterMessenger.MessageReceived(&bind.CallOpts{}, subnetAInfo.BlockchainID, messageID2)
Expect(err).Should(BeNil())
Expect(delivered).Should(BeTrue())

// Relayer send specific receipts to get reward of relaying two messages
receipt, messageID := utils.SendSpecifiedReceiptsAndWaitForAcceptance(
ctx,
subnetAInfo.BlockchainID,
subnetBInfo,
[]*big.Int{messageID1, messageID2},
teleportermessenger.TeleporterFeeInfo{
ContractAddress: mockTokenAddress,
Amount: big.NewInt(0),
},
[]common.Address{},
fundedAddress,
fundedKey,
subnetBTeleporterMessenger,
)

// Relay message from Subnet B to Subnet A
network.RelayMessage(ctx, receipt.BlockHash, receipt.BlockNumber, subnetBInfo, subnetAInfo)
// Check delivered
delivered, err = subnetATeleporterMessenger.MessageReceived(&bind.CallOpts{}, subnetBInfo.BlockchainID, messageID)
Expect(err).Should(BeNil())
Expect(delivered).Should(BeTrue())

// Check the reward amount. The reward amount should be 10
amount, err := subnetATeleporterMessenger.CheckRelayerRewardAmount(&bind.CallOpts{}, fundedAddress, mockTokenAddress)
Expect(err).Should(BeNil())
Expect(amount).Should(Equal(totalAccumulatedRelayerFee))

// Send message from Subnet B to Subnet A to trigger the "regular" method of delivering receipts.
// The next message from B->A will contain the same receipts that were manually sent in the above steps,
// but they should not be processed again on Subnet A.
sendCrossChainMessageInput = teleportermessenger.TeleporterMessageInput{
DestinationChainID: subnetAInfo.BlockchainID,
DestinationAddress: fundedAddress,
FeeInfo: teleportermessenger.TeleporterFeeInfo{
ContractAddress: mockTokenAddress,
Amount: big.NewInt(0),
},
RequiredGasLimit: big.NewInt(1),
AllowedRelayerAddresses: []common.Address{},
Message: []byte{1, 2, 3, 4},
}

// This message will also have the same receipt as the previous message
receipt, messageID = utils.SendCrossChainMessageAndWaitForAcceptance(
ctx, subnetBInfo, subnetAInfo, sendCrossChainMessageInput, fundedAddress, fundedKey, subnetBTeleporterMessenger)

// Relay message from Subnet B to Subnet A
network.RelayMessage(ctx, receipt.BlockHash, receipt.BlockNumber, subnetBInfo, subnetAInfo)
// Check delivered
delivered, err = subnetATeleporterMessenger.MessageReceived(&bind.CallOpts{}, subnetBInfo.BlockchainID, messageID)
Expect(err).Should(BeNil())
Expect(delivered).Should(BeTrue())

// Check the reward amount remains the same
amount, err = subnetATeleporterMessenger.CheckRelayerRewardAmount(&bind.CallOpts{}, fundedAddress, mockTokenAddress)
Expect(err).Should(BeNil())
Expect(amount).Should(Equal(totalAccumulatedRelayerFee))
}
37 changes: 35 additions & 2 deletions tests/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"strconv"
"strings"

"github.com/ava-labs/avalanchego/ids"
avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp"
"github.com/ava-labs/subnet-evm/accounts/abi/bind"
"github.com/ava-labs/subnet-evm/core/types"
Expand Down Expand Up @@ -127,6 +128,38 @@ func SendAddFeeAmountAndWaitForAcceptance(
return receipt
}

func SendSpecifiedReceiptsAndWaitForAcceptance(
ctx context.Context,
originChainID ids.ID,
source SubnetTestInfo,
messageIDs []*big.Int,
feeInfo teleportermessenger.TeleporterFeeInfo,
allowedRelayerAddresses []common.Address,
fundedAddress common.Address,
fundedKey *ecdsa.PrivateKey,
transactor *teleportermessenger.TeleporterMessenger,
) (*types.Receipt, *big.Int) {
opts := CreateTransactorOpts(ctx, source, fundedAddress, fundedKey)

txn, err := transactor.SendSpecifiedReceipts(opts, originChainID, messageIDs, feeInfo, allowedRelayerAddresses)
Expect(err).Should(BeNil())

receipt, err := bind.WaitMined(ctx, source.ChainRPCClient, txn)
Expect(err).Should(BeNil())
Expect(receipt.Status).Should(Equal(types.ReceiptStatusSuccessful))

// Check the transaction logs for the SendCrossChainMessage event emitted by the Teleporter contract
event, err := GetSendEventFromLogs(receipt.Logs, transactor)
Expect(err).Should(BeNil())
Expect(event.DestinationChainID[:]).Should(Equal(originChainID[:]))

log.Info("Sending SendSpecifiedReceipts transaction",
"originChainID", originChainID,
"txHash", txn.Hash())

return receipt, event.Message.MessageID
}

func HttpToWebsocketURI(uri string, blockchainID string) string {
return fmt.Sprintf("ws://%s/ext/bc/%s/ws", strings.TrimPrefix(uri, "http://"), blockchainID)
}
Expand Down Expand Up @@ -263,7 +296,7 @@ func CreateNativeTransferTransaction(
recipient common.Address,
amount *big.Int,
) *types.Transaction {
gasFeeCap, gasTipCap, nonce := calculateTxParams(ctx, network.ChainRPCClient, fundedAddress)
gasFeeCap, gasTipCap, nonce := calculateTxParams(ctx, network.ChainRPCClient, fromAddress)

tx := types.NewTx(&types.DynamicFeeTx{
ChainID: network.ChainIDInt,
Expand All @@ -275,7 +308,7 @@ func CreateNativeTransferTransaction(
Value: amount,
})

return signTransaction(tx, fundedKey, network.ChainIDInt)
return signTransaction(tx, fromKey, network.ChainIDInt)
}

//
Expand Down

0 comments on commit e8a3751

Please sign in to comment.