From a0a00525d4e6bfdd6fd577be5bba59dc521016d7 Mon Sep 17 00:00:00 2001
From: Mark Tyneway <mark.tyneway@gmail.com>
Date: Wed, 5 May 2021 15:43:45 -0700
Subject: [PATCH] fix: backport value fixes (#766)

* dtl: index the value field (#686)

* chore: add changeset

* chore: add changeset

* dtl: pass through value field

* core-utils: update and test toRpcString

* lint: fix

* l2geth: parse value fields

* chore: add changeset

* dtl: prevent null reference in L1 handler (#757)

* dtl: prevent reference of null value

* chore: add changeset

* dtl: propagate value

* lint: fix
---
 .changeset/beige-keys-hammer.md               |  5 ++++
 .changeset/brown-bananas-deny.md              |  5 ++++
 .changeset/tough-lamps-hammer.md              |  5 ++++
 .changeset/violet-comics-reflect.md           |  5 ++++
 l2geth/rollup/client.go                       |  8 +++++--
 packages/core-utils/src/common/hex-strings.ts | 15 ++++++++----
 .../core-utils/test/common/hex-utils.spec.ts  | 24 ++++++++++++++++++-
 .../handlers/sequencer-batch-appended.ts      |  5 ++++
 .../l2-ingestion/handlers/transaction.ts      |  2 ++
 .../src/types/database-types.ts               |  2 ++
 10 files changed, 69 insertions(+), 7 deletions(-)
 create mode 100644 .changeset/beige-keys-hammer.md
 create mode 100644 .changeset/brown-bananas-deny.md
 create mode 100644 .changeset/tough-lamps-hammer.md
 create mode 100644 .changeset/violet-comics-reflect.md

diff --git a/.changeset/beige-keys-hammer.md b/.changeset/beige-keys-hammer.md
new file mode 100644
index 000000000..c7f737b87
--- /dev/null
+++ b/.changeset/beige-keys-hammer.md
@@ -0,0 +1,5 @@
+---
+"@eth-optimism/data-transport-layer": patch
+---
+
+Parse and index the value field in the data transport layer
diff --git a/.changeset/brown-bananas-deny.md b/.changeset/brown-bananas-deny.md
new file mode 100644
index 000000000..0f8c2ca18
--- /dev/null
+++ b/.changeset/brown-bananas-deny.md
@@ -0,0 +1,5 @@
+---
+"@eth-optimism/l2geth": patch
+---
+
+Add value parsing to the rollup client
diff --git a/.changeset/tough-lamps-hammer.md b/.changeset/tough-lamps-hammer.md
new file mode 100644
index 000000000..204262b71
--- /dev/null
+++ b/.changeset/tough-lamps-hammer.md
@@ -0,0 +1,5 @@
+---
+"@eth-optimism/core-utils": patch
+---
+
+Update toRpcHexString to accept ethers.BigNumber and add tests
diff --git a/.changeset/violet-comics-reflect.md b/.changeset/violet-comics-reflect.md
new file mode 100644
index 000000000..8f52dda5c
--- /dev/null
+++ b/.changeset/violet-comics-reflect.md
@@ -0,0 +1,5 @@
+---
+'@eth-optimism/data-transport-layer': patch
+---
+
+Prevent access of null value in L1 transaction deserialization
diff --git a/l2geth/rollup/client.go b/l2geth/rollup/client.go
index 0e55550e4..795c8d394 100644
--- a/l2geth/rollup/client.go
+++ b/l2geth/rollup/client.go
@@ -70,6 +70,7 @@ type transaction struct {
 	BatchIndex  uint64          `json:"batchIndex"`
 	BlockNumber uint64          `json:"blockNumber"`
 	Timestamp   uint64          `json:"timestamp"`
+	Value       hexutil.Uint64  `json:"value"`
 	GasLimit    uint64          `json:"gasLimit"`
 	Target      common.Address  `json:"target"`
 	Origin      *common.Address `json:"origin"`
@@ -104,6 +105,7 @@ type signature struct {
 // it means that the decoding failed.
 type decoded struct {
 	Signature signature      `json:"sig"`
+	Value     hexutil.Uint64 `json:"value"`
 	GasLimit  uint64         `json:"gasLimit"`
 	GasPrice  uint64         `json:"gasPrice"`
 	Nonce     uint64         `json:"nonce"`
@@ -228,6 +230,7 @@ func enqueueToTransaction(enqueue *Enqueue) (*types.Transaction, error) {
 	}
 	data := *enqueue.Data
 
+	// enqueue transactions have no value
 	value := big.NewInt(0)
 	tx := types.NewTransaction(nonce, target, value, gasLimit, big.NewInt(0), data)
 
@@ -303,7 +306,7 @@ func batchedTransactionToTransaction(res *transaction, signer *types.OVMSigner)
 	if res.Decoded != nil {
 		nonce := res.Decoded.Nonce
 		to := res.Decoded.Target
-		value := new(big.Int)
+		value := new(big.Int).SetUint64(uint64(res.Decoded.Value))
 		// Note: there are two gas limits, one top level and
 		// another on the raw transaction itself. Maybe maxGasLimit
 		// for the top level?
@@ -357,7 +360,8 @@ func batchedTransactionToTransaction(res *transaction, signer *types.OVMSigner)
 	gasLimit := res.GasLimit
 	data := res.Data
 	origin := res.Origin
-	tx := types.NewTransaction(nonce, target, big.NewInt(0), gasLimit, big.NewInt(0), data)
+	value := new(big.Int).SetUint64(uint64(res.Value))
+	tx := types.NewTransaction(nonce, target, value, gasLimit, big.NewInt(0), data)
 	txMeta := types.NewTransactionMeta(
 		new(big.Int).SetUint64(res.BlockNumber),
 		res.Timestamp,
diff --git a/packages/core-utils/src/common/hex-strings.ts b/packages/core-utils/src/common/hex-strings.ts
index d87c3673f..71b412c76 100644
--- a/packages/core-utils/src/common/hex-strings.ts
+++ b/packages/core-utils/src/common/hex-strings.ts
@@ -60,11 +60,18 @@ export const toHexString = (inp: Buffer | string | number | null): string => {
   }
 }
 
-export const toRpcHexString = (n: number): string => {
-  if (n === 0) {
-    return '0x0'
+export const toRpcHexString = (n: number | BigNumber): string => {
+  let num
+  if (typeof n === 'number') {
+    num = '0x' + n.toString(16)
   } else {
-    return '0x' + toHexString(n).slice(2).replace(/^0+/, '')
+    num = n.toHexString()
+  }
+
+  if (num === '0x0') {
+    return num
+  } else {
+    return num.replace(/^0x0/, '0x')
   }
 }
 
diff --git a/packages/core-utils/test/common/hex-utils.spec.ts b/packages/core-utils/test/common/hex-utils.spec.ts
index 7bb26b70d..c91ceca9f 100644
--- a/packages/core-utils/test/common/hex-utils.spec.ts
+++ b/packages/core-utils/test/common/hex-utils.spec.ts
@@ -1,7 +1,8 @@
 import { expect } from '../setup'
+import { BigNumber } from 'ethers'
 
 /* Imports: Internal */
-import { getRandomHexString } from '../../src'
+import { getRandomHexString, toRpcHexString } from '../../src'
 
 describe('getRandomHexString', () => {
   const random = global.Math.random
@@ -18,3 +19,24 @@ describe('getRandomHexString', () => {
     expect(getRandomHexString(8)).to.equal('0x' + '88'.repeat(8))
   })
 })
+
+describe('toRpcHexString', () => {
+  it('should parse 0', () => {
+    expect(toRpcHexString(0)).to.deep.equal('0x0')
+    expect(toRpcHexString(BigNumber.from(0))).to.deep.equal('0x0')
+  })
+
+  it('should parse non 0', () => {
+    const cases = [
+      { input: 2, output: '0x2' },
+      { input: BigNumber.from(2), output: '0x2' },
+      { input: 100, output: '0x64' },
+      { input: BigNumber.from(100), output: '0x64' },
+      { input: 300, output: '0x12c' },
+      { input: BigNumber.from(300), output: '0x12c' },
+    ]
+    for (const test of cases) {
+      expect(toRpcHexString(test.input)).to.deep.equal(test.output)
+    }
+  })
+})
diff --git a/packages/data-transport-layer/src/services/l1-ingestion/handlers/sequencer-batch-appended.ts b/packages/data-transport-layer/src/services/l1-ingestion/handlers/sequencer-batch-appended.ts
index 5ecf06fdc..c162994a7 100644
--- a/packages/data-transport-layer/src/services/l1-ingestion/handlers/sequencer-batch-appended.ts
+++ b/packages/data-transport-layer/src/services/l1-ingestion/handlers/sequencer-batch-appended.ts
@@ -5,6 +5,7 @@ import {
   ctcCoder,
   fromHexString,
   toHexString,
+  toRpcHexString,
   TxType,
   EventArgsSequencerBatchAppended,
 } from '@eth-optimism/core-utils'
@@ -120,6 +121,7 @@ export const handleEventsSequencerBatchAppended: EventHandlerSet<
           data: toHexString(sequencerTransaction),
           queueOrigin: 'sequencer',
           type,
+          value: decoded ? decoded.value : '0x0',
           queueIndex: null,
           decoded,
           confirmed: true,
@@ -152,6 +154,7 @@ export const handleEventsSequencerBatchAppended: EventHandlerSet<
           data: '0x',
           queueOrigin: 'l1',
           type: 'EIP155',
+          value: '0x0',
           queueIndex: queueIndex.toNumber(),
           decoded: null,
           confirmed: true,
@@ -254,6 +257,8 @@ const maybeDecodeSequencerBatchTransaction = (
     } else {
       throw new Error(`Unknown sequencer transaction type.`)
     }
+    // Temporary fix to propagate the value
+    decoded.value = '0x0'
     // Validate the transaction
     if (!validateBatchTransaction(type, decoded)) {
       decoded = null
diff --git a/packages/data-transport-layer/src/services/l2-ingestion/handlers/transaction.ts b/packages/data-transport-layer/src/services/l2-ingestion/handlers/transaction.ts
index b4199ba53..176900422 100644
--- a/packages/data-transport-layer/src/services/l2-ingestion/handlers/transaction.ts
+++ b/packages/data-transport-layer/src/services/l2-ingestion/handlers/transaction.ts
@@ -32,6 +32,7 @@ export const handleSequencerBlock = {
     let transactionEntry: Partial<TransactionEntry> = {
       // Legacy support.
       index: transactionIndex,
+      value: transaction.value,
       batchIndex: null,
       blockNumber: BigNumber.from(transaction.l1BlockNumber).toNumber(),
       timestamp: BigNumber.from(transaction.l1Timestamp).toNumber(),
@@ -47,6 +48,7 @@ export const handleSequencerBlock = {
           r: padHexString(transaction.r, 32),
           s: padHexString(transaction.s, 32),
         },
+        value: transaction.value,
         gasLimit: BigNumber.from(transaction.gas).toNumber(),
         gasPrice: BigNumber.from(transaction.gasPrice).toNumber(), // ?
         nonce: BigNumber.from(transaction.nonce).toNumber(),
diff --git a/packages/data-transport-layer/src/types/database-types.ts b/packages/data-transport-layer/src/types/database-types.ts
index 42074ee45..f477f5a37 100644
--- a/packages/data-transport-layer/src/types/database-types.ts
+++ b/packages/data-transport-layer/src/types/database-types.ts
@@ -4,6 +4,7 @@ export interface DecodedSequencerBatchTransaction {
     s: string
     v: number
   }
+  value: string
   gasLimit: number
   gasPrice: number
   nonce: number
@@ -31,6 +32,7 @@ export interface TransactionEntry {
   gasLimit: number
   target: string
   origin: string
+  value: string
   queueOrigin: 'sequencer' | 'l1'
   queueIndex: number | null
   type: 'EIP155' | 'ETH_SIGN' | null
-- 
2.23.0