Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
geoff-vball committed Sep 26, 2023
1 parent 36465ed commit 2b80900
Show file tree
Hide file tree
Showing 4 changed files with 240 additions and 17 deletions.
3 changes: 2 additions & 1 deletion contracts/remappings.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
@subnet-evm-contracts=../subnet-evm/contracts/contracts
@openzeppelin/=lib/openzeppelin-contracts/
@openzeppelin/=lib/openzeppelin-contracts/
@ds-test/=lib/forge-std/lib/ds-test/src/
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,16 @@ contract NativeTokenMinter is ITeleporterReceiver, INativeTokenMinter, Reentranc
// Lock tokens in this bridge instance. Supports "fee/burn on transfer" ERC20 token
// implementations by only bridging the actual balance increase reflected by the call
// to transferFrom.
uint256 adjustedAmount = SafeERC20TransferFrom.safeTransferFrom(
IERC20(feeTokenContractAddress),
feeAmount
);

// Ensure that the adjusted amount is greater than the fee to be paid.
if (adjustedAmount <= feeAmount) {
revert InsufficientAdjustedAmount(adjustedAmount, feeAmount);
if (feeAmount > 0) {
uint256 adjustedAmount = SafeERC20TransferFrom.safeTransferFrom(
IERC20(feeTokenContractAddress),
feeAmount
);

// Ensure that the adjusted amount is greater than the fee to be paid.
if (adjustedAmount <= feeAmount) {
revert InsufficientAdjustedAmount(adjustedAmount, feeAmount);
}
}

// Burn native token by sending to BLACKHOLE_ADDRESS
Expand Down
233 changes: 226 additions & 7 deletions tests/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,10 +314,7 @@ var _ = ginkgo.BeforeSuite(func() {
"--constructor-args", teleporterContractAddress.Hex(), hexutil.Encode(chainBIDInt.Bytes()))

cmd.Dir = "./contracts"
fmt.Println(cmd.Args)
// time.Sleep(10000 * time.Second)
output, err := cmd.Output()
fmt.Println(output)
err := cmd.Run()
Expect(err).Should(BeNil())
}
{
Expand All @@ -329,10 +326,9 @@ var _ = ginkgo.BeforeSuite(func() {
"--private-key", hexutil.Encode(nativeTokenBridgeDeployerPK.D.Bytes()),
"--constructor-args", teleporterContractAddress.Hex(), hexutil.Encode(chainAIDInt.Bytes()))


cmd.Dir = "./contracts"
output, err := cmd.Output()
fmt.Println(output)
err := cmd.Run()
Expect(err).Should(BeNil())
}
log.Info("Finished deploying Bridge contracts")
Expand Down Expand Up @@ -605,3 +601,226 @@ var _ = ginkgo.Describe("[Teleporter one way send]", ginkgo.Ordered, func() {
})

})

// Ginkgo describe node that acts as a container for the teleporter e2e tests. This test suite
// will run through the following steps in order:
// 1.
var _ = ginkgo.Describe("[Native Token Bridge one way send]", ginkgo.Ordered, func() {
// Send a transaction to Subnet A to issue a Warp Message from the Teleporter contract to Subnet B
ginkgo.It("Send Message from A to B", ginkgo.Label("NativeTokenBridge", "SendNativeTokenBridge"), func() {
ctx := context.Background()

cmd := exec.CommandContext(
ctx,
"cast",
"send",
nativeTokenBridgeContractAddress.Hex(),
"bridgeTokens(address,address,uint256)",
fundedAddress.Hex(),
fundedAddress.Hex(), // TODO use different address
"0x00",
"--rpc-url", chainARPCURI,
"--private-key", hexutil.Encode(nativeTokenBridgeDeployerPK.D.Bytes()))

err := cmd.Run()
Expect(err).Should(BeNil())

// Sleep to ensure the new block is published to the subscriber
time.Sleep(5 * time.Second)

})

// ginkgo.It("Relay message to destination", ginkgo.Label("Teleporter", "RelayMessage"), func() {
// ctx := context.Background()

// // Get the latest block from Subnet A, and retrieve the warp message from the logs
// log.Info("Waiting for new block confirmation")
// newHeadA := <-newHeadsA
// blockHashA := newHeadA.Hash()

// log.Info("Fetching relevant warp logs from the newly produced block")
// logs, err := chainARPCClient.FilterLogs(ctx, interfaces.FilterQuery{
// BlockHash: &blockHashA,
// Addresses: []common.Address{warp.Module.Address},
// })
// Expect(err).Should(BeNil())
// Expect(len(logs)).Should(Equal(1))

// // Check for relevant warp log from subscription and ensure that it matches
// // the log extracted from the last block.
// txLog := logs[0]
// log.Info("Parsing logData as unsigned warp message")
// unsignedMsg, err := avalancheWarp.ParseUnsignedMessage(txLog.Data)
// Expect(err).Should(BeNil())

// // Set local variables for the duration of the test
// unsignedWarpMessageID := unsignedMsg.ID()
// unsignedWarpMsg := unsignedMsg
// log.Info("Parsed unsignedWarpMsg", "unsignedWarpMessageID", unsignedWarpMessageID, "unsignedWarpMessage", unsignedWarpMsg)

// // Loop over each client on chain A to ensure they all have time to accept the block.
// // Note: if we did not confirm this here, the next stage could be racy since it assumes every node
// // has accepted the block.
// for i, uri := range chainANodeURIs {
// chainAWSURI := httpToWebsocketURI(uri, blockchainIDA.String())
// log.Info("Creating ethclient for blockchainA", "wsURI", chainAWSURI)
// client, err := ethclient.Dial(chainAWSURI)
// Expect(err).Should(BeNil())

// // Loop until each node has advanced to >= the height of the block that emitted the warp log
// for {
// block, err := client.BlockByNumber(ctx, nil)
// Expect(err).Should(BeNil())
// if block.NumberU64() >= newHeadA.Number.Uint64() {
// log.Info("client accepted the block containing SendWarpMessage", "client", i, "height", block.NumberU64())
// break
// }
// }
// }

// // Get the aggregate signature for the Warp message
// log.Info("Fetching aggregate signature from the source chain validators")
// warpClient, err := warpBackend.NewWarpClient(chainANodeURIs[0], blockchainIDA.String())
// Expect(err).Should(BeNil())
// signedWarpMessageBytes, err := warpClient.GetAggregateSignature(ctx, unsignedWarpMessageID, params.WarpQuorumDenominator)
// Expect(err).Should(BeNil())

// // Construct the transaction to send the Warp message to the destination chain
// log.Info("Constructing transaction for the destination chain")
// signedMessage, err := avalancheWarp.ParseMessage(signedWarpMessageBytes)
// Expect(err).Should(BeNil())

// numSigners, err := signedMessage.Signature.NumSigners()
// Expect(err).Should(BeNil())

// gasLimit, err := teleporter.CalculateReceiveMessageGasLimit(numSigners, teleporterMessage.RequiredGasLimit)
// Expect(err).Should(BeNil())

// callData, err := teleporter.EVMTeleporterContractABI.Pack("receiveCrossChainMessage", fundedAddress)
// Expect(err).Should(BeNil())

// baseFee, err := chainBRPCClient.EstimateBaseFee(ctx)
// Expect(err).Should(BeNil())

// gasTipCap, err := chainBRPCClient.SuggestGasTipCap(ctx)
// Expect(err).Should(BeNil())

// nonce, err := chainBRPCClient.NonceAt(ctx, fundedAddress, nil)
// Expect(err).Should(BeNil())

// gasFeeCap := baseFee.Mul(baseFee, big.NewInt(2))
// gasFeeCap.Add(gasFeeCap, big.NewInt(2500000000))
// destinationTx := predicateutils.NewPredicateTx(
// chainBIDInt,
// nonce,
// &teleporterContractAddress,
// gasLimit,
// gasFeeCap,
// gasTipCap,
// big.NewInt(0),
// callData,
// types.AccessList{},
// warp.ContractAddress,
// signedMessage.Bytes(),
// )

// // Sign and send the transaction on the destination chain
// signer := types.LatestSignerForChainID(chainBIDInt)
// signedTxB, err := types.SignTx(destinationTx, signer, fundedKey)
// Expect(err).Should(BeNil())

// log.Info("Subscribing to new heads on destination chain")
// subB, err := chainBWSClient.SubscribeNewHead(ctx, newHeadsB)
// Expect(err).Should(BeNil())
// defer subB.Unsubscribe()

// log.Info("Sending transaction to destination chain")
// err = chainBRPCClient.SendTransaction(context.Background(), signedTxB)
// Expect(err).Should(BeNil())

// // Sleep to ensure the new block is published to the subscriber
// time.Sleep(5 * time.Second)
// receipt, err := chainBRPCClient.TransactionReceipt(ctx, signedTxB.Hash())
// Expect(err).Should(BeNil())
// Expect(receipt.Status).Should(Equal(types.ReceiptStatusSuccessful))
// })

// ginkgo.It("Receive message on Subnet B", ginkgo.Label("Teleporter", "ReceiveTeleporter"), func() {
// ctx := context.Background()

// // Get the latest block from Subnet B
// log.Info("Waiting for new block confirmation")
// newHeadB := <-newHeadsB
// log.Info("Received new head", "height", newHeadB.Number.Uint64())
// blockHashB := newHeadB.Hash()
// block, err := chainBRPCClient.BlockByHash(ctx, blockHashB)
// Expect(err).Should(BeNil())
// log.Info(
// "Got block",
// "blockHash", blockHashB,
// "blockNumber", block.NumberU64(),
// "transactions", block.Transactions(),
// "numTransactions", len(block.Transactions()),
// "block", block,
// )
// accessLists := block.Transactions()[0].AccessList()
// Expect(len(accessLists)).Should(Equal(1))
// Expect(accessLists[0].Address).Should(Equal(warp.Module.Address))

// // Check the transaction storage key has warp message we're expecting
// storageKeyHashes := accessLists[0].StorageKeys
// packedPredicate := predicateutils.HashSliceToBytes(storageKeyHashes)
// predicateBytes, err := predicateutils.UnpackPredicate(packedPredicate)
// Expect(err).Should(BeNil())
// receivedWarpMessage, err = avalancheWarp.ParseMessage(predicateBytes)
// Expect(err).Should(BeNil())

// // Check that the transaction has successful receipt status
// txHash := block.Transactions()[0].Hash()
// receipt, err := chainBRPCClient.TransactionReceipt(ctx, txHash)
// Expect(err).Should(BeNil())
// Expect(receipt.Status).Should(Equal(types.ReceiptStatusSuccessful))

// log.Info("Finished sending warp message, closing down output channel")

// })

// ginkgo.It("Validate Received Warp Message Values", ginkgo.Label("Teleporter", "VerifyWarp"), func() {
// Expect(receivedWarpMessage.SourceChainID).Should(Equal(blockchainIDA))
// addressedPayload, err := warpPayload.ParseAddressedPayload(receivedWarpMessage.Payload)
// Expect(err).Should(BeNil())

// receivedDestinationID, err := ids.ToID(addressedPayload.DestinationChainID.Bytes())
// Expect(err).Should(BeNil())
// Expect(receivedDestinationID).Should(Equal(blockchainIDB))
// Expect(addressedPayload.DestinationAddress).Should(Equal(teleporterContractAddress))
// Expect(addressedPayload.Payload).Should(Equal(payload))

// // Check that the teleporter message is correct
// receivedTeleporterMessage, err := teleporter.UnpackTeleporterMessage(addressedPayload.Payload)
// Expect(err).Should(BeNil())
// Expect(*receivedTeleporterMessage).Should(Equal(teleporterMessage))

// teleporterMessageID = receivedTeleporterMessage.MessageID
// })

// ginkgo.It("Check Teleporter Message Received", ginkgo.Label("Teleporter", "TeleporterMessageReceived"), func() {
// data, err := teleporter.PackMessageReceivedMessage(teleporter.MessageReceivedInput{
// OriginChainID: blockchainIDA,
// MessageID: teleporterMessageID,
// })
// Expect(err).Should(BeNil())
// callMessage := interfaces.CallMsg{
// To: &teleporterContractAddress,
// Data: data,
// }
// result, err := chainBRPCClient.CallContract(context.Background(), callMessage, nil)
// Expect(err).Should(BeNil())

// // check the contract call result
// delivered, err := teleporter.UnpackMessageReceivedResult(result)
// Expect(err).Should(BeNil())
// Expect(delivered).Should(BeTrue())
// })

})
3 changes: 2 additions & 1 deletion tests/warp-genesis.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"contractNativeMinterConfig": {
"blockTimestamp": 0,
"adminAddresses": [
"0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC"
"0x1337cfd2dCff6270615B90938aCB1efE79801704",
"0xAcB633F5B00099c7ec187eB00156c5cd9D854b5B"
]
}
},
Expand Down

0 comments on commit 2b80900

Please sign in to comment.