@@ -9,14 +9,19 @@ import (
9
9
10
10
"github.com/ethereum/go-ethereum/accounts/abi/bind"
11
11
"github.com/ethereum/go-ethereum/common"
12
+ gethtypes "github.com/ethereum/go-ethereum/core/types"
13
+ "github.com/ethereum/go-ethereum/crypto"
12
14
"github.com/stretchr/testify/require"
13
15
"golang.org/x/exp/maps"
14
16
15
- "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3 "
17
+ chainsel "github.com/smartcontractkit/chain-selectors "
16
18
19
+ "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3"
20
+ "github.com/smartcontractkit/chainlink-common/pkg/merklemulti"
17
21
"github.com/smartcontractkit/chainlink/deployment"
18
22
"github.com/smartcontractkit/chainlink/deployment/ccip/changeset"
19
23
"github.com/smartcontractkit/chainlink/integration-tests/testsetups"
24
+ "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
20
25
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp"
21
26
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp"
22
27
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router"
@@ -63,21 +68,20 @@ func Test_CCIPBatching(t *testing.T) {
63
68
sourceChain1 : 1 ,
64
69
sourceChain2 : 1 ,
65
70
}
66
- endSeqNum = map [uint64 ]ccipocr3.SeqNum {
67
- sourceChain1 : ccipocr3 .SeqNum (numMessages ),
68
- sourceChain2 : ccipocr3 .SeqNum (numMessages ),
69
- }
70
71
)
71
72
72
73
t .Run ("batch data only messages from single source" , func (t * testing.T ) {
74
+ var (
75
+ sourceChain = sourceChain1
76
+ )
73
77
err := sendMessages (
74
78
ctx ,
75
79
t ,
76
- e .Env .Chains [sourceChain1 ],
77
- e .Env .Chains [sourceChain1 ].DeployerKey ,
78
- state .Chains [sourceChain1 ].OnRamp ,
79
- state .Chains [sourceChain1 ].Router ,
80
- state .Chains [sourceChain1 ].Multicall3 ,
80
+ e .Env .Chains [sourceChain ],
81
+ e .Env .Chains [sourceChain ].DeployerKey ,
82
+ state .Chains [sourceChain ].OnRamp ,
83
+ state .Chains [sourceChain ].Router ,
84
+ state .Chains [sourceChain ].Multicall3 ,
81
85
destChain ,
82
86
numMessages ,
83
87
common .LeftPadBytes (state .Chains [destChain ].Receiver .Address ().Bytes (), 32 ),
@@ -86,30 +90,29 @@ func Test_CCIPBatching(t *testing.T) {
86
90
87
91
_ , err = changeset .ConfirmCommitWithExpectedSeqNumRange (
88
92
t ,
89
- e .Env .Chains [sourceChain1 ],
93
+ e .Env .Chains [sourceChain ],
90
94
e .Env .Chains [destChain ],
91
95
state .Chains [destChain ].OffRamp ,
92
96
nil ,
93
- ccipocr3 .NewSeqNumRange (startSeqNum [sourceChain1 ], endSeqNum [ sourceChain1 ] ),
97
+ ccipocr3 .NewSeqNumRange (startSeqNum [sourceChain ], startSeqNum [ sourceChain ] + numMessages - 1 ),
94
98
)
95
- require .NoErrorf (t , err , "failed to confirm commit from chain %d" , sourceChain1 )
99
+ require .NoErrorf (t , err , "failed to confirm commit from chain %d" , sourceChain )
96
100
97
101
states , err := changeset .ConfirmExecWithSeqNrs (
98
102
t ,
99
- e .Env .Chains [sourceChain1 ],
103
+ e .Env .Chains [sourceChain ],
100
104
e .Env .Chains [destChain ],
101
105
state .Chains [destChain ].OffRamp ,
102
106
nil ,
103
- genSeqNrRange (startSeqNum [sourceChain1 ], endSeqNum [ sourceChain1 ] ),
107
+ genSeqNrRange (startSeqNum [sourceChain ], startSeqNum [ sourceChain ] + numMessages - 1 ),
104
108
)
105
109
require .NoError (t , err )
106
110
// assert that all states are successful
107
111
for _ , state := range states {
108
112
require .Equal (t , changeset .EXECUTION_STATE_SUCCESS , state )
109
113
}
110
114
111
- startSeqNum [sourceChain1 ] = endSeqNum [sourceChain1 ] + 1
112
- endSeqNum [sourceChain1 ] = startSeqNum [sourceChain1 ] + ccipocr3 .SeqNum (numMessages ) - 1
115
+ startSeqNum [sourceChain ] = startSeqNum [sourceChain ] + numMessages
113
116
})
114
117
115
118
t .Run ("batch data only messages from multiple sources" , func (t * testing.T ) {
@@ -158,7 +161,7 @@ func Test_CCIPBatching(t *testing.T) {
158
161
srcChain ,
159
162
destChain ,
160
163
startSeqNum [srcChain ],
161
- endSeqNum [srcChain ],
164
+ startSeqNum [srcChain ]+ ccipocr3 . SeqNum ( numMessages ) - 1 ,
162
165
& wg ,
163
166
outputErrs ,
164
167
)
@@ -198,7 +201,7 @@ func Test_CCIPBatching(t *testing.T) {
198
201
state ,
199
202
srcChain ,
200
203
destChain ,
201
- genSeqNrRange (startSeqNum [srcChain ], endSeqNum [srcChain ]),
204
+ genSeqNrRange (startSeqNum [srcChain ], startSeqNum [srcChain ]+ ccipocr3 . SeqNum ( numMessages ) - 1 ),
202
205
& wg ,
203
206
execErrs ,
204
207
)
@@ -226,6 +229,77 @@ func Test_CCIPBatching(t *testing.T) {
226
229
require .Equal (t , changeset .EXECUTION_STATE_SUCCESS , state )
227
230
}
228
231
}
232
+
233
+ // update the start and end seq nums
234
+ for _ , srcChain := range sourceChains {
235
+ startSeqNum [srcChain ] = startSeqNum [srcChain ] + numMessages
236
+ }
237
+ })
238
+
239
+ t .Run ("max evm batch size" , func (t * testing.T ) {
240
+ var (
241
+ sourceChain = sourceChain1
242
+ otherSender = mustNewTransactor (t , e .Env .Chains [sourceChain ])
243
+ transactors = []* bind.TransactOpts {
244
+ e .Env .Chains [sourceChain ].DeployerKey ,
245
+ otherSender ,
246
+ }
247
+ errs = make (chan error , len (transactors ))
248
+ )
249
+
250
+ // transfer some eth to the other sender from the DeployerKey
251
+ sendEth (
252
+ ctx ,
253
+ t ,
254
+ e .Env .Chains [sourceChain ],
255
+ e .Env .Chains [sourceChain ].DeployerKey ,
256
+ otherSender .From ,
257
+ assets .Ether (20 ).ToInt (),
258
+ )
259
+
260
+ for _ , transactor := range transactors {
261
+ go func () {
262
+ err := sendMessages (
263
+ ctx ,
264
+ t ,
265
+ e .Env .Chains [sourceChain ],
266
+ transactor ,
267
+ state .Chains [sourceChain ].OnRamp ,
268
+ state .Chains [sourceChain ].Router ,
269
+ state .Chains [sourceChain ].Multicall3 ,
270
+ destChain ,
271
+ merklemulti .MaxNumberTreeLeaves / 2 ,
272
+ common .LeftPadBytes (state .Chains [destChain ].Receiver .Address ().Bytes (), 32 ),
273
+ )
274
+ t .Log ("sendMessages error:" , err , ", writing to channel" )
275
+ errs <- err
276
+ t .Log ("sent error to channel" )
277
+ }()
278
+ }
279
+
280
+ var i = 0
281
+ for i < len (transactors ) {
282
+ select {
283
+ case err := <- errs :
284
+ require .NoError (t , err )
285
+ i ++
286
+ case <- ctx .Done ():
287
+ require .FailNow (t , "didn't get all errors before test context was done" )
288
+ }
289
+ }
290
+
291
+ _ , err = changeset .ConfirmCommitWithExpectedSeqNumRange (
292
+ t ,
293
+ e .Env .Chains [sourceChain ],
294
+ e .Env .Chains [destChain ],
295
+ state .Chains [destChain ].OffRamp ,
296
+ nil , // startBlock
297
+ ccipocr3 .NewSeqNumRange (
298
+ startSeqNum [sourceChain ],
299
+ startSeqNum [sourceChain ]+ ccipocr3 .SeqNum (merklemulti .MaxNumberTreeLeaves )- 1 ,
300
+ ),
301
+ )
302
+ require .NoErrorf (t , err , "failed to confirm commit from chain %d" , sourceChain )
229
303
})
230
304
}
231
305
@@ -333,6 +407,7 @@ func sendMessages(
333
407
}
334
408
335
409
// Send the tx with the messages through the multicall
410
+ t .Logf ("Sending %d messages with total value %s" , numMessages , totalValue .String ())
336
411
tx , err := sourceMulticall3 .Aggregate3Value (
337
412
& bind.TransactOpts {
338
413
From : sourceTransactOpts .From ,
@@ -414,3 +489,51 @@ func genSeqNrRange(start, end ccipocr3.SeqNum) []uint64 {
414
489
}
415
490
return seqNrs
416
491
}
492
+
493
+ func mustNewTransactor (t * testing.T , chain deployment.Chain ) * bind.TransactOpts {
494
+ chainID , err := chainsel .GetChainIDFromSelector (chain .Selector )
495
+ require .NoError (t , err )
496
+ chainIDBig , ok := new (big.Int ).SetString (chainID , 10 )
497
+ require .True (t , ok , "evm chainID must be integral" )
498
+ key , err := crypto .GenerateKey ()
499
+ require .NoError (t , err )
500
+ transactor , err := bind .NewKeyedTransactorWithChainID (key , chainIDBig )
501
+ require .NoError (t , err )
502
+ return transactor
503
+ }
504
+
505
+ func sendEth (
506
+ ctx context.Context ,
507
+ t * testing.T ,
508
+ chain deployment.Chain ,
509
+ from * bind.TransactOpts ,
510
+ to common.Address ,
511
+ value * big.Int ,
512
+ ) {
513
+ balance , err := chain .Client .BalanceAt (ctx , from .From , nil )
514
+ require .NoError (t , err )
515
+ if balance .Cmp (value ) < 0 {
516
+ t .Fatalf ("insufficient balance: %s < %s" , balance .String (), value .String ())
517
+ }
518
+ t .Logf ("balance of from account %s: %s" , from .From .String (), balance .String ())
519
+
520
+ nonce , err := chain .Client .PendingNonceAt (ctx , from .From )
521
+ require .NoError (t , err )
522
+ gp , err := chain .Client .SuggestGasPrice (ctx )
523
+ require .NoError (t , err )
524
+ tx := gethtypes .NewTx (& gethtypes.LegacyTx {
525
+ Nonce : nonce ,
526
+ GasPrice : gp ,
527
+ Gas : 21_000 ,
528
+ To : & to ,
529
+ Value : value ,
530
+ Data : nil ,
531
+ })
532
+ signedTx , err := from .Signer (from .From , tx )
533
+ require .NoError (t , err )
534
+ err = chain .Client .SendTransaction (ctx , signedTx )
535
+ require .NoError (t , err )
536
+ t .Log ("sent funding tx:" , signedTx .Hash ().Hex ())
537
+ _ , err = deployment .ConfirmIfNoError (chain , signedTx , err )
538
+ require .NoError (t , err )
539
+ }
0 commit comments