Commit c2f0632a authored by Adrian Sutton's avatar Adrian Sutton

op-e2e: Add helper method to send L2 transactions

parent 52698092
...@@ -155,25 +155,12 @@ func TestSystemE2E(t *testing.T) { ...@@ -155,25 +155,12 @@ func TestSystemE2E(t *testing.T) {
require.Equal(t, mintAmount, diff, "Did not get expected balance change") require.Equal(t, mintAmount, diff, "Did not get expected balance change")
// Submit TX to L2 sequencer node // Submit TX to L2 sequencer node
toAddr := common.Address{0xff, 0xff} receipt := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) {
tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{ opts.Value = big.NewInt(1_000_000_000)
ChainID: cfg.L2ChainIDBig(), opts.Nonce = 1 // Already have deposit
Nonce: 1, // Already have deposit opts.ToAddr = &common.Address{0xff, 0xff}
To: &toAddr, opts.VerifyOnClients(l2Verif)
Value: big.NewInt(1_000_000_000),
GasTipCap: big.NewInt(10),
GasFeeCap: big.NewInt(200),
Gas: 21000,
}) })
err = l2Seq.SendTransaction(context.Background(), tx)
require.Nil(t, err, "Sending L2 tx to sequencer")
_, err = waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "Waiting for L2 tx on sequencer")
receipt, err := waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "Waiting for L2 tx on verifier")
require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status, "TX should have succeeded")
// Verify blocks match after batch submission on verifiers and sequencers // Verify blocks match after batch submission on verifiers and sequencers
verifBlock, err := l2Verif.BlockByNumber(context.Background(), receipt.BlockNumber) verifBlock, err := l2Verif.BlockByNumber(context.Background(), receipt.BlockNumber)
...@@ -413,22 +400,10 @@ func TestMissingBatchE2E(t *testing.T) { ...@@ -413,22 +400,10 @@ func TestMissingBatchE2E(t *testing.T) {
ethPrivKey := cfg.Secrets.Alice ethPrivKey := cfg.Secrets.Alice
// Submit TX to L2 sequencer node // Submit TX to L2 sequencer node
toAddr := common.Address{0xff, 0xff} receipt := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) {
tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{ opts.ToAddr = &common.Address{0xff, 0xff}
ChainID: cfg.L2ChainIDBig(), opts.Value = big.NewInt(1_000_000_000)
Nonce: 0,
To: &toAddr,
Value: big.NewInt(1_000_000_000),
GasTipCap: big.NewInt(10),
GasFeeCap: big.NewInt(200),
Gas: 21000,
}) })
err = l2Seq.SendTransaction(context.Background(), tx)
require.Nil(t, err, "Sending L2 tx to sequencer")
// Let it show up on the unsafe chain
receipt, err := waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "Waiting for L2 tx on sequencer")
// Wait until the block it was first included in shows up in the safe chain on the verifier // Wait until the block it was first included in shows up in the safe chain on the verifier
_, err = waitForBlock(receipt.BlockNumber, l2Verif, time.Duration((sys.RollupConfig.SeqWindowSize+4)*cfg.DeployConfig.L1BlockTime)*time.Second) _, err = waitForBlock(receipt.BlockNumber, l2Verif, time.Duration((sys.RollupConfig.SeqWindowSize+4)*cfg.DeployConfig.L1BlockTime)*time.Second)
...@@ -437,7 +412,7 @@ func TestMissingBatchE2E(t *testing.T) { ...@@ -437,7 +412,7 @@ func TestMissingBatchE2E(t *testing.T) {
// Assert that the transaction is not found on the verifier // Assert that the transaction is not found on the verifier
ctx, cancel := context.WithTimeout(context.Background(), time.Second) ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel() defer cancel()
_, err = l2Verif.TransactionReceipt(ctx, tx.Hash()) _, err = l2Verif.TransactionReceipt(ctx, receipt.TxHash)
require.Equal(t, ethereum.NotFound, err, "Found transaction in verifier when it should not have been included") require.Equal(t, ethereum.NotFound, err, "Found transaction in verifier when it should not have been included")
// Wait a short time for the L2 reorg to occur on the sequencer as well. // Wait a short time for the L2 reorg to occur on the sequencer as well.
...@@ -570,35 +545,20 @@ func TestSystemMockP2P(t *testing.T) { ...@@ -570,35 +545,20 @@ func TestSystemMockP2P(t *testing.T) {
ethPrivKey := cfg.Secrets.Alice ethPrivKey := cfg.Secrets.Alice
// Submit TX to L2 sequencer node // Submit TX to L2 sequencer node
toAddr := common.Address{0xff, 0xff} receiptSeq := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) {
tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{ opts.ToAddr = &common.Address{0xff, 0xff}
ChainID: cfg.L2ChainIDBig(), opts.Value = big.NewInt(1_000_000_000)
Nonce: 0,
To: &toAddr,
Value: big.NewInt(1_000_000_000),
GasTipCap: big.NewInt(10),
GasFeeCap: big.NewInt(200),
Gas: 21000,
})
err = l2Seq.SendTransaction(context.Background(), tx)
require.Nil(t, err, "Sending L2 tx to sequencer")
// Wait for tx to be mined on the L2 sequencer chain // Wait until the block it was first included in shows up in the safe chain on the verifier
receiptSeq, err := waitForTransaction(tx.Hash(), l2Seq, 5*time.Minute) opts.VerifyOnClients(l2Verif)
require.Nil(t, err, "Waiting for L2 tx on sequencer") })
// Wait until the block it was first included in shows up in the safe chain on the verifier
receiptVerif, err := waitForTransaction(tx.Hash(), l2Verif, 5*time.Minute)
require.Nil(t, err, "Waiting for L2 tx on verifier")
require.Equal(t, receiptSeq, receiptVerif)
// Verify that everything that was received was published // Verify that everything that was received was published
require.GreaterOrEqual(t, len(published), len(received)) require.GreaterOrEqual(t, len(published), len(received))
require.ElementsMatch(t, received, published[:len(received)]) require.ElementsMatch(t, received, published[:len(received)])
// Verify that the tx was received via p2p // Verify that the tx was received via p2p
require.Contains(t, received, receiptVerif.BlockHash) require.Contains(t, received, receiptSeq.BlockHash)
} }
// TestSystemRPCAltSync sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that // TestSystemRPCAltSync sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that
...@@ -655,31 +615,16 @@ func TestSystemRPCAltSync(t *testing.T) { ...@@ -655,31 +615,16 @@ func TestSystemRPCAltSync(t *testing.T) {
ethPrivKey := cfg.Secrets.Alice ethPrivKey := cfg.Secrets.Alice
// Submit a TX to L2 sequencer node // Submit a TX to L2 sequencer node
toAddr := common.Address{0xff, 0xff} receiptSeq := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) {
tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{ opts.ToAddr = &common.Address{0xff, 0xff}
ChainID: cfg.L2ChainIDBig(), opts.Value = big.NewInt(1_000_000_000)
Nonce: 0,
To: &toAddr,
Value: big.NewInt(1_000_000_000),
GasTipCap: big.NewInt(10),
GasFeeCap: big.NewInt(200),
Gas: 21000,
})
err = l2Seq.SendTransaction(context.Background(), tx)
require.Nil(t, err, "Sending L2 tx to sequencer")
// Wait for tx to be mined on the L2 sequencer chain
receiptSeq, err := waitForTransaction(tx.Hash(), l2Seq, 6*time.Duration(sys.RollupConfig.BlockTime)*time.Second)
require.Nil(t, err, "Waiting for L2 tx on sequencer")
// Wait for alt RPC sync to pick up the blocks on the sequencer chain // Wait for alt RPC sync to pick up the blocks on the sequencer chain
receiptVerif, err := waitForTransaction(tx.Hash(), l2Verif, 12*time.Duration(sys.RollupConfig.BlockTime)*time.Second) opts.VerifyOnClients(l2Verif)
require.Nil(t, err, "Waiting for L2 tx on verifier") })
require.Equal(t, receiptSeq, receiptVerif)
// Verify that the tx was received via RPC sync (P2P is disabled) // Verify that the tx was received via RPC sync (P2P is disabled)
require.Contains(t, received, eth.BlockID{Hash: receiptVerif.BlockHash, Number: receiptVerif.BlockNumber.Uint64()}.String()) require.Contains(t, received, eth.BlockID{Hash: receiptSeq.BlockHash, Number: receiptSeq.BlockNumber.Uint64()}.String())
// Verify that everything that was received was published // Verify that everything that was received was published
require.GreaterOrEqual(t, len(published), len(received)) require.GreaterOrEqual(t, len(published), len(received))
...@@ -744,22 +689,10 @@ func TestSystemP2PAltSync(t *testing.T) { ...@@ -744,22 +689,10 @@ func TestSystemP2PAltSync(t *testing.T) {
ethPrivKey := cfg.Secrets.Alice ethPrivKey := cfg.Secrets.Alice
// Submit a TX to L2 sequencer node // Submit a TX to L2 sequencer node
toAddr := common.Address{0xff, 0xff} receiptSeq := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) {
tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{ opts.ToAddr = &common.Address{0xff, 0xff}
ChainID: cfg.L2ChainIDBig(), opts.Value = big.NewInt(1_000_000_000)
Nonce: 0,
To: &toAddr,
Value: big.NewInt(1_000_000_000),
GasTipCap: big.NewInt(10),
GasFeeCap: big.NewInt(200),
Gas: 21000,
}) })
err = l2Seq.SendTransaction(context.Background(), tx)
require.Nil(t, err, "Sending L2 tx to sequencer")
// Wait for tx to be mined on the L2 sequencer chain
receiptSeq, err := waitForTransaction(tx.Hash(), l2Seq, 6*time.Duration(sys.RollupConfig.BlockTime)*time.Second)
require.Nil(t, err, "Waiting for L2 tx on sequencer")
// Gossip is able to respond to IWANT messages for the duration of heartbeat_time * message_window = 0.5 * 12 = 6 // Gossip is able to respond to IWANT messages for the duration of heartbeat_time * message_window = 0.5 * 12 = 6
// Wait till we pass that, and then we'll have missed some blocks that cannot be retrieved in any way from gossip // Wait till we pass that, and then we'll have missed some blocks that cannot be retrieved in any way from gossip
...@@ -823,7 +756,7 @@ func TestSystemP2PAltSync(t *testing.T) { ...@@ -823,7 +756,7 @@ func TestSystemP2PAltSync(t *testing.T) {
l2Verif := ethclient.NewClient(rpc) l2Verif := ethclient.NewClient(rpc)
// It may take a while to sync, but eventually we should see the sequenced data show up // It may take a while to sync, but eventually we should see the sequenced data show up
receiptVerif, err := waitForTransaction(tx.Hash(), l2Verif, 100*time.Duration(sys.RollupConfig.BlockTime)*time.Second) receiptVerif, err := waitForTransaction(receiptSeq.TxHash, l2Verif, 100*time.Duration(sys.RollupConfig.BlockTime)*time.Second)
require.Nil(t, err, "Waiting for L2 tx on verifier") require.Nil(t, err, "Waiting for L2 tx on verifier")
require.Equal(t, receiptSeq, receiptVerif) require.Equal(t, receiptSeq, receiptVerif)
...@@ -916,35 +849,13 @@ func TestSystemDenseTopology(t *testing.T) { ...@@ -916,35 +849,13 @@ func TestSystemDenseTopology(t *testing.T) {
ethPrivKey := cfg.Secrets.Alice ethPrivKey := cfg.Secrets.Alice
// Submit TX to L2 sequencer node // Submit TX to L2 sequencer node
toAddr := common.Address{0xff, 0xff} receiptSeq := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) {
tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{ opts.ToAddr = &common.Address{0xff, 0xff}
ChainID: cfg.L2ChainIDBig(), opts.Value = big.NewInt(1_000_000_000)
Nonce: 0,
To: &toAddr,
Value: big.NewInt(1_000_000_000),
GasTipCap: big.NewInt(10),
GasFeeCap: big.NewInt(200),
Gas: 21000,
})
err = l2Seq.SendTransaction(context.Background(), tx)
require.NoError(t, err, "Sending L2 tx to sequencer")
// Wait for tx to be mined on the L2 sequencer chain
receiptSeq, err := waitForTransaction(tx.Hash(), l2Seq, 10*time.Duration(sys.RollupConfig.BlockTime)*time.Second)
require.NoError(t, err, "Waiting for L2 tx on sequencer")
// Wait until the block it was first included in shows up in the safe chain on the verifier
receiptVerif, err := waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(sys.RollupConfig.BlockTime)*time.Second)
require.NoError(t, err, "Waiting for L2 tx on verifier")
require.Equal(t, receiptSeq, receiptVerif)
receiptVerif, err = waitForTransaction(tx.Hash(), l2Verif2, 10*time.Duration(sys.RollupConfig.BlockTime)*time.Second)
require.NoError(t, err, "Waiting for L2 tx on verifier2")
require.Equal(t, receiptSeq, receiptVerif)
receiptVerif, err = waitForTransaction(tx.Hash(), l2Verif3, 10*time.Duration(sys.RollupConfig.BlockTime)*time.Second) // Wait until the block it was first included in shows up in the safe chain on the verifiers
require.NoError(t, err, "Waiting for L2 tx on verifier3") opts.VerifyOnClients(l2Verif, l2Verif2, l2Verif3)
require.Equal(t, receiptSeq, receiptVerif) })
// Verify that everything that was received was published // Verify that everything that was received was published
require.GreaterOrEqual(t, len(published), len(received1)) require.GreaterOrEqual(t, len(published), len(received1))
...@@ -955,9 +866,9 @@ func TestSystemDenseTopology(t *testing.T) { ...@@ -955,9 +866,9 @@ func TestSystemDenseTopology(t *testing.T) {
require.ElementsMatch(t, published, received3[:len(published)]) require.ElementsMatch(t, published, received3[:len(published)])
// Verify that the tx was received via p2p // Verify that the tx was received via p2p
require.Contains(t, received1, receiptVerif.BlockHash) require.Contains(t, received1, receiptSeq.BlockHash)
require.Contains(t, received2, receiptVerif.BlockHash) require.Contains(t, received2, receiptSeq.BlockHash)
require.Contains(t, received3, receiptVerif.BlockHash) require.Contains(t, received3, receiptSeq.BlockHash)
} }
func TestL1InfoContract(t *testing.T) { func TestL1InfoContract(t *testing.T) {
...@@ -1325,30 +1236,16 @@ func TestFees(t *testing.T) { ...@@ -1325,30 +1236,16 @@ func TestFees(t *testing.T) {
startBalance, err := l2Verif.BalanceAt(ctx, fromAddr, nil) startBalance, err := l2Verif.BalanceAt(ctx, fromAddr, nil)
require.Nil(t, err) require.Nil(t, err)
toAddr := common.Address{0xff, 0xff}
transferAmount := big.NewInt(1_000_000_000) transferAmount := big.NewInt(1_000_000_000)
gasTip := big.NewInt(10) gasTip := big.NewInt(10)
tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{ receipt := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) {
ChainID: cfg.L2ChainIDBig(), opts.ToAddr = &common.Address{0xff, 0xff}
Nonce: 0, opts.Value = transferAmount
To: &toAddr, opts.GasTipCap = gasTip
Value: transferAmount, opts.Gas = 21000
GasTipCap: gasTip, opts.GasFeeCap = big.NewInt(200)
GasFeeCap: big.NewInt(200), opts.VerifyOnClients(l2Verif)
Gas: 21000,
}) })
sender, err := types.LatestSignerForChainID(cfg.L2ChainIDBig()).Sender(tx)
require.NoError(t, err)
t.Logf("waiting for tx %s from %s to %s", tx.Hash(), sender, tx.To())
err = l2Seq.SendTransaction(context.Background(), tx)
require.Nil(t, err, "Sending L2 tx to sequencer")
_, err = waitForTransaction(tx.Hash(), l2Seq, 4*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "Waiting for L2 tx on sequencer")
receipt, err := waitForTransaction(tx.Hash(), l2Verif, 4*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "Waiting for L2 tx on verifier")
require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status, "TX should have succeeded")
ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)
defer cancel() defer cancel()
...@@ -1397,6 +1294,8 @@ func TestFees(t *testing.T) { ...@@ -1397,6 +1294,8 @@ func TestFees(t *testing.T) {
require.Equal(t, baseFee, baseFeeRecipientDiff, "base fee fee mismatch") require.Equal(t, baseFee, baseFeeRecipientDiff, "base fee fee mismatch")
// Tally L1 Fee // Tally L1 Fee
tx, _, err := l2Seq.TransactionByHash(ctx, receipt.TxHash)
require.NoError(t, err, "Should be able to get transaction")
bytes, err := tx.MarshalBinary() bytes, err := tx.MarshalBinary()
require.Nil(t, err) require.Nil(t, err)
l1GasUsed := calcL1GasUsed(bytes, overhead) l1GasUsed := calcL1GasUsed(bytes, overhead)
...@@ -1483,23 +1382,12 @@ func TestStopStartBatcher(t *testing.T) { ...@@ -1483,23 +1382,12 @@ func TestStopStartBatcher(t *testing.T) {
nonce := uint64(0) nonce := uint64(0)
sendTx := func() *types.Receipt { sendTx := func() *types.Receipt {
// Submit TX to L2 sequencer node // Submit TX to L2 sequencer node
tx := types.MustSignNewTx(cfg.Secrets.Alice, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{ receipt := SendL2Tx(t, cfg, l2Seq, cfg.Secrets.Alice, func(opts *TxOpts) {
ChainID: cfg.L2ChainIDBig(), opts.ToAddr = &common.Address{0xff, 0xff}
Nonce: nonce, opts.Value = big.NewInt(1_000_000_000)
To: &common.Address{0xff, 0xff}, opts.Nonce = nonce
Value: big.NewInt(1_000_000_000),
GasTipCap: big.NewInt(10),
GasFeeCap: big.NewInt(200),
Gas: 21000,
}) })
nonce++ nonce++
err = l2Seq.SendTransaction(context.Background(), tx)
require.Nil(t, err, "Sending L2 tx to sequencer")
// Let it show up on the unsafe chain
receipt, err := waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "Waiting for L2 tx on sequencer")
return receipt return receipt
} }
// send a transaction // send a transaction
......
package op_e2e package op_e2e
import ( import (
"context"
"crypto/ecdsa"
"math/big" "math/big"
"testing" "testing"
"time" "time"
...@@ -15,6 +17,10 @@ import ( ...@@ -15,6 +17,10 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
// SendDepositTx creates and sends a deposit transaction.
// The L1 transaction, including sender, is configured by the l1Opts param.
// The L2 transaction options can be configured by modifying the DepositTxOps value supplied to applyL2Opts
// Will verify that the transaction is included with the expected status on L1 and L2
func SendDepositTx(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, l2Client *ethclient.Client, l1Opts *bind.TransactOpts, applyL2Opts DepositTxOptsFn) { func SendDepositTx(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, l2Client *ethclient.Client, l1Opts *bind.TransactOpts, applyL2Opts DepositTxOptsFn) {
l2Opts := defaultDepositTxOpts(l1Opts) l2Opts := defaultDepositTxOpts(l1Opts)
applyL2Opts(l2Opts) applyL2Opts(l2Opts)
...@@ -27,14 +33,14 @@ func SendDepositTx(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, l ...@@ -27,14 +33,14 @@ func SendDepositTx(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, l
require.Nil(t, err, "with deposit tx") require.Nil(t, err, "with deposit tx")
// Wait for transaction on L1 // Wait for transaction on L1
receipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) receipt, err := waitForTransaction(tx.Hash(), l1Client, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "Waiting for deposit tx on L1") require.Nil(t, err, "Waiting for deposit tx on L1")
// Wait for transaction to be included on L2 // Wait for transaction to be included on L2
reconstructedDep, err := derive.UnmarshalDepositLogEvent(receipt.Logs[0]) reconstructedDep, err := derive.UnmarshalDepositLogEvent(receipt.Logs[0])
require.NoError(t, err, "Could not reconstruct L2 Deposit") require.NoError(t, err, "Could not reconstruct L2 Deposit")
tx = types.NewTx(reconstructedDep) tx = types.NewTx(reconstructedDep)
receipt, err = waitForTransaction(tx.Hash(), l2Client, 6*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) receipt, err = waitForTransaction(tx.Hash(), l2Client, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, l2Opts.ExpectedStatus, receipt.Status) require.Equal(t, l2Opts.ExpectedStatus, receipt.Status)
} }
...@@ -60,3 +66,70 @@ func defaultDepositTxOpts(opts *bind.TransactOpts) *DepositTxOpts { ...@@ -60,3 +66,70 @@ func defaultDepositTxOpts(opts *bind.TransactOpts) *DepositTxOpts {
ExpectedStatus: types.ReceiptStatusSuccessful, ExpectedStatus: types.ReceiptStatusSuccessful,
} }
} }
// SendL2Tx creates and sends a transaction.
// The supplied privKey is used to specify the account to send from and the transaction is sent to the supplied l2Client
// Transaction options and expected status can be configured in the applyTxOpts function by modifying the supplied TxOpts
// Will verify that the transaction is included with the expected status on l2Client and any clients added to TxOpts.VerifyClients
func SendL2Tx(t *testing.T, cfg SystemConfig, l2Client *ethclient.Client, privKey *ecdsa.PrivateKey, applyTxOpts TxOptsFn) *types.Receipt {
opts := defaultTxOpts()
applyTxOpts(opts)
tx := types.MustSignNewTx(privKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{
ChainID: cfg.L2ChainIDBig(),
Nonce: opts.Nonce, // Already have deposit
To: opts.ToAddr,
Value: opts.Value,
GasTipCap: opts.GasTipCap,
GasFeeCap: opts.GasFeeCap,
Gas: opts.Gas,
})
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
err := l2Client.SendTransaction(ctx, tx)
require.Nil(t, err, "Sending L2 tx")
receipt, err := waitForTransaction(tx.Hash(), l2Client, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second)
require.Nil(t, err, "Waiting for L2 tx")
require.Equal(t, opts.ExpectedStatus, receipt.Status, "TX should have expected status")
for i, client := range opts.VerifyClients {
t.Logf("Waiting for tx %v on verification client %d", tx.Hash(), i)
receiptVerif, err := waitForTransaction(tx.Hash(), client, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second)
require.Nilf(t, err, "Waiting for L2 tx on verification client %d", i)
require.Equalf(t, receipt, receiptVerif, "Receipts should be the same on sequencer and verification client %d", i)
}
return receipt
}
type TxOptsFn func(opts *TxOpts)
type TxOpts struct {
ToAddr *common.Address
Nonce uint64
Value *big.Int
Gas uint64
GasTipCap *big.Int
GasFeeCap *big.Int
Data []byte
ExpectedStatus uint64
VerifyClients []*ethclient.Client
}
// VerifyOnClients adds additional l2 clients that should sync the block the tx is included in
// Checks that the receipt received from these clients is equal to the receipt received from the sequencer
func (o *TxOpts) VerifyOnClients(clients ...*ethclient.Client) {
o.VerifyClients = append(o.VerifyClients, clients...)
}
func defaultTxOpts() *TxOpts {
return &TxOpts{
ToAddr: nil,
Nonce: 0,
Value: common.Big0,
GasTipCap: big.NewInt(10),
GasFeeCap: big.NewInt(200),
Gas: 21_000,
Data: nil,
ExpectedStatus: types.ReceiptStatusSuccessful,
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment