Commit 33ed5e38 authored by Hamdi Allam's avatar Hamdi Allam

track withdrawal success status

parent f2008fb3
...@@ -39,12 +39,12 @@ type L1TransactionDeposit struct { ...@@ -39,12 +39,12 @@ type L1TransactionDeposit struct {
type L2TransactionWithdrawal struct { type L2TransactionWithdrawal struct {
WithdrawalHash common.Hash `gorm:"serializer:json;primaryKey"` WithdrawalHash common.Hash `gorm:"serializer:json;primaryKey"`
Nonce U256
InitiatedL2EventGUID uuid.UUID InitiatedL2EventGUID uuid.UUID
ProvenL1EventGUID *uuid.UUID ProvenL1EventGUID *uuid.UUID
FinalizedL1EventGUID *uuid.UUID FinalizedL1EventGUID *uuid.UUID
Succeeded *bool
Nonce U256
Tx Transaction `gorm:"embedded"` Tx Transaction `gorm:"embedded"`
GasLimit U256 GasLimit U256
...@@ -62,7 +62,7 @@ type BridgeTransactionsDB interface { ...@@ -62,7 +62,7 @@ type BridgeTransactionsDB interface {
StoreL2TransactionWithdrawals([]*L2TransactionWithdrawal) error StoreL2TransactionWithdrawals([]*L2TransactionWithdrawal) error
MarkL2TransactionWithdrawalProvenEvent(common.Hash, uuid.UUID) error MarkL2TransactionWithdrawalProvenEvent(common.Hash, uuid.UUID) error
MarkL2TransactionWithdrawalFinalizedEvent(common.Hash, uuid.UUID) error MarkL2TransactionWithdrawalFinalizedEvent(common.Hash, uuid.UUID, bool) error
} }
/** /**
...@@ -136,7 +136,7 @@ func (db *bridgeTransactionsDB) MarkL2TransactionWithdrawalProvenEvent(withdrawa ...@@ -136,7 +136,7 @@ func (db *bridgeTransactionsDB) MarkL2TransactionWithdrawalProvenEvent(withdrawa
} }
// MarkL2TransactionWithdrawalProvenEvent links a withdrawn transaction in its finalized state // MarkL2TransactionWithdrawalProvenEvent links a withdrawn transaction in its finalized state
func (db *bridgeTransactionsDB) MarkL2TransactionWithdrawalFinalizedEvent(withdrawalHash common.Hash, finalizedL1EventGuid uuid.UUID) error { func (db *bridgeTransactionsDB) MarkL2TransactionWithdrawalFinalizedEvent(withdrawalHash common.Hash, finalizedL1EventGuid uuid.UUID, succeeded bool) error {
withdrawal, err := db.L2TransactionWithdrawal(withdrawalHash) withdrawal, err := db.L2TransactionWithdrawal(withdrawalHash)
if err != nil { if err != nil {
return err return err
...@@ -147,6 +147,7 @@ func (db *bridgeTransactionsDB) MarkL2TransactionWithdrawalFinalizedEvent(withdr ...@@ -147,6 +147,7 @@ func (db *bridgeTransactionsDB) MarkL2TransactionWithdrawalFinalizedEvent(withdr
} }
withdrawal.FinalizedL1EventGUID = &finalizedL1EventGuid withdrawal.FinalizedL1EventGUID = &finalizedL1EventGuid
withdrawal.Succeeded = &succeeded
result := db.gorm.Save(&withdrawal) result := db.gorm.Save(&withdrawal)
return result.Error return result.Error
} }
...@@ -158,9 +158,50 @@ func TestE2EBridgeTransactionsL2ToL1MessagePasserWithdrawal(t *testing.T) { ...@@ -158,9 +158,50 @@ func TestE2EBridgeTransactionsL2ToL1MessagePasserWithdrawal(t *testing.T) {
withdraw, err = testSuite.DB.BridgeTransactions.L2TransactionWithdrawal(withdrawalHash) withdraw, err = testSuite.DB.BridgeTransactions.L2TransactionWithdrawal(withdrawalHash)
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, withdraw.FinalizedL1EventGUID) require.NotNil(t, withdraw.FinalizedL1EventGUID)
require.NotNil(t, withdraw.Succeeded)
require.True(t, *withdraw.Succeeded)
finalizedEvent, err := testSuite.DB.ContractEvents.L1ContractEvent(*withdraw.FinalizedL1EventGUID) finalizedEvent, err := testSuite.DB.ContractEvents.L1ContractEvent(*withdraw.FinalizedL1EventGUID)
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, event) require.NotNil(t, event)
require.Equal(t, finalizedEvent.TransactionHash, finalizeReceipt.TxHash) require.Equal(t, finalizedEvent.TransactionHash, finalizeReceipt.TxHash)
} }
func TestE2EBridgeTransactionsL2ToL1MessagePasserFailedWithdrawal(t *testing.T) {
testSuite := createE2ETestSuite(t)
testCtx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
l2ToL1MessagePasser, err := bindings.NewL2ToL1MessagePasser(predeploys.L2ToL1MessagePasserAddr, testSuite.L2Client)
require.NoError(t, err)
aliceAddr := testSuite.OpCfg.Secrets.Addresses().Alice
// Try to withdrawl 1 ETH from L2 without any corresponding deposits on L1
l2Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L2ChainIDBig())
require.NoError(t, err)
l2Opts.Value = big.NewInt(params.Ether)
withdrawTx, err := l2ToL1MessagePasser.InitiateWithdrawal(l2Opts, aliceAddr, big.NewInt(100_000), nil)
require.NoError(t, err)
withdrawReceipt, err := utils.WaitReceiptOK(testCtx, testSuite.L2Client, withdrawTx.Hash())
require.NoError(t, err)
msgPassed, err := withdrawals.ParseMessagePassed(withdrawReceipt)
require.NoError(t, err)
withdrawalHash, err := withdrawals.WithdrawalHash(msgPassed)
require.NoError(t, err)
// Prove&Finalize withdrawal
_, finalizeReceipt := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, testSuite.OpSys.Nodes["sequencer"], testSuite.OpCfg.Secrets.Alice, withdrawReceipt)
require.NoError(t, utils.WaitFor(testCtx, 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader()
return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil
}))
// Withdrawal registered but marked as unsuccessful
withdraw, err := testSuite.DB.BridgeTransactions.L2TransactionWithdrawal(withdrawalHash)
require.NoError(t, err)
require.NotNil(t, withdraw.Succeeded)
require.False(t, *withdraw.Succeeded)
}
...@@ -94,6 +94,7 @@ CREATE TABLE IF NOT EXISTS l2_transaction_withdrawals ( ...@@ -94,6 +94,7 @@ CREATE TABLE IF NOT EXISTS l2_transaction_withdrawals (
-- Multistep (bedrock) process of a withdrawal -- Multistep (bedrock) process of a withdrawal
proven_l1_event_guid VARCHAR REFERENCES l1_contract_events(guid), proven_l1_event_guid VARCHAR REFERENCES l1_contract_events(guid),
finalized_l1_event_guid VARCHAR REFERENCES l1_contract_events(guid), finalized_l1_event_guid VARCHAR REFERENCES l1_contract_events(guid),
succeeded BOOLEAN,
-- L2ToL1MessagePasser specific -- L2ToL1MessagePasser specific
nonce UINT256 UNIQUE, nonce UINT256 UNIQUE,
......
...@@ -328,14 +328,16 @@ func l1ProcessContractEventsBridgeTransactions(processLog log.Logger, db *databa ...@@ -328,14 +328,16 @@ func l1ProcessContractEventsBridgeTransactions(processLog log.Logger, db *databa
withdrawal, err := db.BridgeTransactions.L2TransactionWithdrawal(withdrawalHash) withdrawal, err := db.BridgeTransactions.L2TransactionWithdrawal(withdrawalHash)
if err != nil { if err != nil {
return err return err
} else if withdrawal == nil { }
if withdrawal == nil {
// We need to ensure we are in a caught up state before claiming a missing event. Since L2 timestamps // We need to ensure we are in a caught up state before claiming a missing event. Since L2 timestamps
// are derived from L1, we can simply compare the timestamp of this event with the latest L2 header. // are derived from L1, we can simply compare the timestamp of this event with the latest L2 header.
if provenWithdrawal.RawEvent.Timestamp > latestL2Header.Timestamp { if provenWithdrawal.RawEvent.Timestamp > latestL2Header.Timestamp {
processLog.Warn("behind on indexed L2 withdrawals") processLog.Warn("behind on indexed L2 withdrawals")
return errors.New("waiting for L2Processor to catch up") return errors.New("waiting for L2Processor to catch up")
} else { } else {
processLog.Crit("withdrawal missing!", "hash", withdrawalHash) processLog.Crit("L2 withdrawal missing!", "withdrawal_hash", withdrawalHash)
return errors.New("withdrawal missing!") return errors.New("withdrawal missing!")
} }
} }
...@@ -367,7 +369,7 @@ func l1ProcessContractEventsBridgeTransactions(processLog log.Logger, db *databa ...@@ -367,7 +369,7 @@ func l1ProcessContractEventsBridgeTransactions(processLog log.Logger, db *databa
return errors.New("withdrawal missing!") return errors.New("withdrawal missing!")
} }
err = db.BridgeTransactions.MarkL2TransactionWithdrawalFinalizedEvent(withdrawalHash, finalizedWithdrawal.RawEvent.GUID) err = db.BridgeTransactions.MarkL2TransactionWithdrawalFinalizedEvent(withdrawalHash, finalizedWithdrawal.RawEvent.GUID, finalizedWithdrawal.Success)
if err != nil { if err != nil {
return err return err
} }
......
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