Skip to content

Commit 447fed2

Browse files
authored
feat: include L1 message with insufficient balance (#462)
* feat: include L1 message with insufficient balance * fix tests * add comment * bump version
1 parent e5dfc75 commit 447fed2

File tree

3 files changed

+65
-20
lines changed

3 files changed

+65
-20
lines changed

core/state_transition.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,10 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
374374
st.gas -= gas
375375

376376
// Check clause 6
377-
if msg.Value().Sign() > 0 && !st.evm.Context.CanTransfer(st.state, msg.From(), msg.Value()) {
377+
// Note: If this is an L1MessageTx, we will not return a top-level ErrInsufficientFundsForTransfer.
378+
// Instead, we return ErrInsufficientBalance from within st.evm.Call. This means that such transactions
379+
// will revert but they can be included in a valid block. This is necessary for supporting enforced txs.
380+
if msg.Value().Sign() > 0 && !st.evm.Context.CanTransfer(st.state, msg.From(), msg.Value()) && !msg.IsL1MessageTx() {
378381
return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From().Hex())
379382
}
380383

miner/scroll_worker_test.go

Lines changed: 60 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ func TestL1MsgCorrectOrder(t *testing.T) {
515515
}
516516
}
517517

518-
func l1MessageTest(t *testing.T, msgs []types.L1MessageTx, withL2Tx bool, callback func(i int, block *types.Block, db ethdb.Database, w *worker) bool) {
518+
func l1MessageTest(t *testing.T, msgs []types.L1MessageTx, withL2Tx bool, callback func(i int, block *types.Block, db ethdb.Database, w *worker, bc *core.BlockChain) bool) {
519519
var (
520520
engine consensus.Engine
521521
chainConfig *params.ChainConfig
@@ -558,7 +558,7 @@ func l1MessageTest(t *testing.T, msgs []types.L1MessageTx, withL2Tx bool, callba
558558
w.start()
559559

560560
// call once before first block
561-
callback(0, nil, db, w)
561+
callback(0, nil, db, w, chain)
562562

563563
// timeout for all blocks
564564
globalTimeout := time.After(3 * time.Second)
@@ -574,7 +574,7 @@ func l1MessageTest(t *testing.T, msgs []types.L1MessageTx, withL2Tx bool, callba
574574
case ev := <-sub.Chan():
575575
block := ev.Data.(core.NewMinedBlockEvent).Block
576576

577-
if done := callback(ii, block, db, w); done {
577+
if done := callback(ii, block, db, w, chain); done {
578578
return
579579
}
580580

@@ -594,7 +594,7 @@ func TestL1SingleMessageOverGasLimit(t *testing.T) {
594594
{QueueIndex: 2, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{3}}, // different sender
595595
}
596596

597-
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker) bool {
597+
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker, bc *core.BlockChain) bool {
598598
switch blockNum {
599599
case 0:
600600
return false
@@ -630,7 +630,7 @@ func TestL1CombinedMessagesOverGasLimit(t *testing.T) {
630630
{QueueIndex: 2, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{3}}, // different sender
631631
}
632632

633-
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker) bool {
633+
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker, bc *core.BlockChain) bool {
634634
switch blockNum {
635635
case 0:
636636
return false
@@ -674,7 +674,7 @@ func TestLargeL1MessageSkipPayloadCheck(t *testing.T) {
674674
{QueueIndex: 2, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{3}}, // different sender
675675
}
676676

677-
l1MessageTest(t, msgs, true, func(blockNum int, block *types.Block, db ethdb.Database, w *worker) bool {
677+
l1MessageTest(t, msgs, true, func(blockNum int, block *types.Block, db ethdb.Database, w *worker, bc *core.BlockChain) bool {
678678
switch blockNum {
679679
case 0:
680680
return false
@@ -708,15 +708,17 @@ func TestLargeL1MessageSkipPayloadCheck(t *testing.T) {
708708
func TestSkipMessageWithStrangeError(t *testing.T) {
709709
assert := assert.New(t)
710710

711-
// message #0 is skipped because of `Value`
712-
// TODO: trigger skipping in some other way after this behaviour is changed
713711
msgs := []types.L1MessageTx{
714-
{QueueIndex: 0, Gas: 25100, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{2}, Value: big.NewInt(1)},
712+
// message #0 is skipped because of `GasLimit`
713+
// (cannot happen in practice, this is checked in the contracts)
714+
{QueueIndex: 0, Gas: 20000000, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{2}},
715+
716+
// messages #1 and #2 are correct
715717
{QueueIndex: 1, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{2}},
716718
{QueueIndex: 2, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{3}},
717719
}
718720

719-
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker) bool {
721+
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker, bc *core.BlockChain) bool {
720722
switch blockNum {
721723
case 0:
722724
return false
@@ -742,18 +744,58 @@ func TestSkipMessageWithStrangeError(t *testing.T) {
742744
})
743745
}
744746

747+
func TestL1MessageWithInsufficientBalanceNotSkipped(t *testing.T) {
748+
assert := assert.New(t)
749+
750+
msgs := []types.L1MessageTx{
751+
// message #0 sends more funds than available in the sender account
752+
{QueueIndex: 0, Gas: 25100, To: &common.Address{1}, Data: make([]byte, 1025), Sender: common.Address{2}, Value: big.NewInt(1)},
753+
754+
// #message #1 is a correct msg
755+
{QueueIndex: 1, Gas: 25100, To: &common.Address{1}, Data: make([]byte, 1025), Sender: common.Address{2}},
756+
}
757+
758+
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker, bc *core.BlockChain) bool {
759+
switch blockNum {
760+
case 0:
761+
return false
762+
case 1:
763+
// include both #0 and #1
764+
assert.Equal(2, len(block.Transactions()))
765+
assert.True(block.Transactions()[0].IsL1MessageTx())
766+
assert.Equal(uint64(0), block.Transactions()[0].AsL1MessageTx().QueueIndex)
767+
assert.True(block.Transactions()[1].IsL1MessageTx())
768+
assert.Equal(uint64(1), block.Transactions()[1].AsL1MessageTx().QueueIndex)
769+
770+
// #0 fails, #1 succeeds
771+
receipts := bc.GetReceiptsByHash(block.Hash())
772+
assert.Equal(2, len(receipts))
773+
assert.Equal(types.ReceiptStatusFailed, receipts[0].Status)
774+
assert.Equal(types.ReceiptStatusSuccessful, receipts[1].Status)
775+
776+
// db is updated correctly
777+
queueIndex := rawdb.ReadFirstQueueIndexNotInL2Block(db, block.Hash())
778+
assert.NotNil(queueIndex)
779+
assert.Equal(uint64(2), *queueIndex)
780+
781+
return true
782+
default:
783+
return true
784+
}
785+
})
786+
}
787+
745788
func TestSkipAllL1MessagesInBlock(t *testing.T) {
746789
assert := assert.New(t)
747790

748-
// messages are skipped because of `Value`
749-
// TODO: trigger skipping in some other way after this behaviour is changed
791+
// messages are skipped because of `GasLimit`
750792
msgs := []types.L1MessageTx{
751-
{QueueIndex: 0, Gas: 25100, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{2}, Value: big.NewInt(1)},
752-
{QueueIndex: 1, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{2}, Value: big.NewInt(1)},
753-
{QueueIndex: 2, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{3}, Value: big.NewInt(1)},
793+
{QueueIndex: 0, Gas: 20000000, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{2}},
794+
{QueueIndex: 1, Gas: 20000000, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{2}},
795+
{QueueIndex: 2, Gas: 20000000, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{3}},
754796
}
755797

756-
l1MessageTest(t, msgs, true, func(blockNum int, block *types.Block, db ethdb.Database, w *worker) bool {
798+
l1MessageTest(t, msgs, true, func(blockNum int, block *types.Block, db ethdb.Database, w *worker, bc *core.BlockChain) bool {
757799
switch blockNum {
758800
case 0:
759801
return false
@@ -785,7 +827,7 @@ func TestOversizedTxThenNormal(t *testing.T) {
785827
{QueueIndex: 2, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{3}},
786828
}
787829

788-
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker) bool {
830+
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker, bc *core.BlockChain) bool {
789831
switch blockNum {
790832
case 0:
791833
// schedule to skip 2nd call to ccc
@@ -933,7 +975,7 @@ func TestSkippedTransactionDatabaseEntries(t *testing.T) {
933975
{QueueIndex: 1, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{2}},
934976
}
935977

936-
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker) bool {
978+
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker, bc *core.BlockChain) bool {
937979
switch blockNum {
938980
case 0:
939981
return false

params/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
const (
2525
VersionMajor = 5 // Major version component of the current release
2626
VersionMinor = 8 // Minor version component of the current release
27-
VersionPatch = 0 // Patch version component of the current release
27+
VersionPatch = 1 // Patch version component of the current release
2828
VersionMeta = "mainnet" // Version metadata to append to the version string
2929
)
3030

0 commit comments

Comments
 (0)