Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
43e3bbe4
Unverified
Commit
43e3bbe4
authored
Dec 16, 2021
by
Indeavr
Committed by
GitHub
Dec 16, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'ethereum-optimism:develop' into develop
parents
410e4094
ff5a87fc
Changes
26
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
1548 additions
and
195 deletions
+1548
-195
gold-ants-breathe.md
.changeset/gold-ants-breathe.md
+0
-5
olive-pots-camp.md
.changeset/olive-pots-camp.md
+0
-5
batch_submitter.go
go/batch-submitter/batch_submitter.go
+2
-4
driver.go
go/batch-submitter/drivers/proposer/driver.go
+15
-0
driver.go
go/batch-submitter/drivers/sequencer/driver.go
+16
-0
metrics.go
go/batch-submitter/metrics/metrics.go
+80
-0
service.go
go/batch-submitter/service.go
+61
-9
CHANGELOG.md
go/proxyd/CHANGELOG.md
+6
-0
package.json
go/proxyd/package.json
+1
-1
CHANGELOG.md
l2geth/CHANGELOG.md
+6
-0
package.json
l2geth/package.json
+1
-1
cross-chain-provider.ts
packages/sdk/src/cross-chain-provider.ts
+182
-0
index.ts
packages/sdk/src/index.ts
+1
-0
cross-chain-provider.ts
packages/sdk/src/interfaces/cross-chain-provider.ts
+4
-9
types.ts
packages/sdk/src/interfaces/types.ts
+53
-32
coercion.ts
packages/sdk/src/utils/coercion.ts
+30
-37
contracts.ts
packages/sdk/src/utils/contracts.ts
+192
-0
index.ts
packages/sdk/src/utils/index.ts
+4
-0
message-encoding.ts
packages/sdk/src/utils/message-encoding.ts
+36
-0
type-utils.ts
packages/sdk/src/utils/type-utils.ts
+6
-0
ICrossDomainMessenger.sol
packages/sdk/test/contracts/ICrossDomainMessenger.sol
+45
-0
MockMessenger.sol
packages/sdk/test/contracts/MockMessenger.sol
+60
-0
cross-chain-provider.spec.ts
packages/sdk/test/cross-chain-provider.spec.ts
+320
-18
coercion.spec.ts
packages/sdk/test/utils/coercion.spec.ts
+4
-74
contracts.spec.ts
packages/sdk/test/utils/contracts.spec.ts
+349
-0
message-encoding.spec.ts
packages/sdk/test/utils/message-encoding.spec.ts
+74
-0
No files found.
.changeset/gold-ants-breathe.md
deleted
100644 → 0
View file @
410e4094
---
'
@eth-optimism/proxyd'
:
patch
---
Force proxyd build
.changeset/olive-pots-camp.md
deleted
100644 → 0
View file @
410e4094
---
'
@eth-optimism/l2geth'
:
patch
---
expose ErrNonceTooHigh from miner
go/batch-submitter/batch_submitter.go
View file @
43e3bbe4
...
...
@@ -119,8 +119,6 @@ func NewBatchSubmitter(cfg Config, gitVersion string) (*BatchSubmitter, error) {
log
.
Root
()
.
SetHandler
(
log
.
LvlFilterHandler
(
logLevel
,
logHandler
))
log
.
Info
(
"Config"
,
"config"
,
fmt
.
Sprintf
(
"%#v"
,
cfg
))
// Parse sequencer private key and CTC contract address.
sequencerPrivKey
,
ctcAddress
,
err
:=
parseWalletPrivKeyAndContractAddr
(
"Sequencer"
,
cfg
.
Mnemonic
,
cfg
.
SequencerHDPath
,
...
...
@@ -171,7 +169,7 @@ func NewBatchSubmitter(cfg Config, gitVersion string) (*BatchSubmitter, error) {
var
batchTxService
*
Service
if
cfg
.
RunTxBatchSubmitter
{
batchTxDriver
,
err
:=
sequencer
.
NewDriver
(
sequencer
.
Config
{
Name
:
"S
EQUENCER
"
,
Name
:
"S
equencer
"
,
L1Client
:
l1Client
,
L2Client
:
l2Client
,
BlockOffset
:
cfg
.
BlockOffset
,
...
...
@@ -196,7 +194,7 @@ func NewBatchSubmitter(cfg Config, gitVersion string) (*BatchSubmitter, error) {
var
batchStateService
*
Service
if
cfg
.
RunStateBatchSubmitter
{
batchStateDriver
,
err
:=
proposer
.
NewDriver
(
proposer
.
Config
{
Name
:
"P
ROPOSER
"
,
Name
:
"P
roposer
"
,
L1Client
:
l1Client
,
L2Client
:
l2Client
,
BlockOffset
:
cfg
.
BlockOffset
,
...
...
go/batch-submitter/drivers/proposer/driver.go
View file @
43e3bbe4
...
...
@@ -5,9 +5,11 @@ import (
"crypto/ecdsa"
"fmt"
"math/big"
"time"
"github.com/ethereum-optimism/optimism/go/batch-submitter/bindings/ctc"
"github.com/ethereum-optimism/optimism/go/batch-submitter/bindings/scc"
"github.com/ethereum-optimism/optimism/go/batch-submitter/metrics"
l2types
"github.com/ethereum-optimism/optimism/l2geth/core/types"
l2ethclient
"github.com/ethereum-optimism/optimism/l2geth/ethclient"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
...
...
@@ -36,6 +38,7 @@ type Driver struct {
sccContract
*
scc
.
StateCommitmentChain
ctcContract
*
ctc
.
CanonicalTransactionChain
walletAddr
common
.
Address
metrics
*
metrics
.
Metrics
}
func
NewDriver
(
cfg
Config
)
(
*
Driver
,
error
)
{
...
...
@@ -60,6 +63,7 @@ func NewDriver(cfg Config) (*Driver, error) {
sccContract
:
sccContract
,
ctcContract
:
ctcContract
,
walletAddr
:
walletAddr
,
metrics
:
metrics
.
NewMetrics
(
cfg
.
Name
),
},
nil
}
...
...
@@ -73,6 +77,11 @@ func (d *Driver) WalletAddr() common.Address {
return
d
.
walletAddr
}
// Metrics returns the subservice telemetry object.
func
(
d
*
Driver
)
Metrics
()
*
metrics
.
Metrics
{
return
d
.
metrics
}
// GetBatchBlockRange returns the start and end L2 block heights that need to be
// processed. Note that the end value is *exclusive*, therefore if the returned
// values are identical nothing needs to be processed.
...
...
@@ -121,6 +130,8 @@ func (d *Driver) SubmitBatchTx(
ctx
context
.
Context
,
start
,
end
,
nonce
,
gasPrice
*
big
.
Int
)
(
*
types
.
Transaction
,
error
)
{
batchTxBuildStart
:=
time
.
Now
()
var
blocks
[]
*
l2types
.
Block
for
i
:=
new
(
big
.
Int
)
.
Set
(
start
);
i
.
Cmp
(
end
)
<
0
;
i
.
Add
(
i
,
bigOne
)
{
block
,
err
:=
d
.
cfg
.
L2Client
.
BlockByNumber
(
ctx
,
i
)
...
...
@@ -139,6 +150,10 @@ func (d *Driver) SubmitBatchTx(
stateRoots
=
append
(
stateRoots
,
block
.
Root
())
}
batchTxBuildTime
:=
float64
(
time
.
Since
(
batchTxBuildStart
)
/
time
.
Millisecond
)
d
.
metrics
.
BatchTxBuildTime
.
Set
(
batchTxBuildTime
)
d
.
metrics
.
NumTxPerBatch
.
Observe
(
float64
(
len
(
blocks
)))
opts
,
err
:=
bind
.
NewKeyedTransactorWithChainID
(
d
.
cfg
.
PrivKey
,
d
.
cfg
.
ChainID
,
)
...
...
go/batch-submitter/drivers/sequencer/driver.go
View file @
43e3bbe4
...
...
@@ -7,8 +7,10 @@ import (
"fmt"
"math/big"
"strings"
"time"
"github.com/ethereum-optimism/optimism/go/batch-submitter/bindings/ctc"
"github.com/ethereum-optimism/optimism/go/batch-submitter/metrics"
l2types
"github.com/ethereum-optimism/optimism/l2geth/core/types"
l2ethclient
"github.com/ethereum-optimism/optimism/l2geth/ethclient"
"github.com/ethereum/go-ethereum/accounts/abi"
...
...
@@ -43,6 +45,7 @@ type Driver struct {
rawCtcContract
*
bind
.
BoundContract
walletAddr
common
.
Address
ctcABI
*
abi
.
ABI
metrics
*
metrics
.
Metrics
}
func
NewDriver
(
cfg
Config
)
(
*
Driver
,
error
)
{
...
...
@@ -78,6 +81,7 @@ func NewDriver(cfg Config) (*Driver, error) {
rawCtcContract
:
rawCtcContract
,
walletAddr
:
walletAddr
,
ctcABI
:
ctcABI
,
metrics
:
metrics
.
NewMetrics
(
cfg
.
Name
),
},
nil
}
...
...
@@ -91,6 +95,11 @@ func (d *Driver) WalletAddr() common.Address {
return
d
.
walletAddr
}
// Metrics returns the subservice telemetry object.
func
(
d
*
Driver
)
Metrics
()
*
metrics
.
Metrics
{
return
d
.
metrics
}
// GetBatchBlockRange returns the start and end L2 block heights that need to be
// processed. Note that the end value is *exclusive*, therefore if the returned
// values are identical nothing needs to be processed.
...
...
@@ -136,6 +145,8 @@ func (d *Driver) SubmitBatchTx(
log
.
Info
(
name
+
" submitting batch tx"
,
"start"
,
start
,
"end"
,
end
,
"gasPrice"
,
gasPrice
)
batchTxBuildStart
:=
time
.
Now
()
var
blocks
[]
*
l2types
.
Block
for
i
:=
new
(
big
.
Int
)
.
Set
(
start
);
i
.
Cmp
(
end
)
<
0
;
i
.
Add
(
i
,
bigOne
)
{
block
,
err
:=
d
.
cfg
.
L2Client
.
BlockByNumber
(
ctx
,
i
)
...
...
@@ -176,6 +187,11 @@ func (d *Driver) SubmitBatchTx(
panic
(
"call data too large"
)
}
// Record the batch_tx_build_time.
batchTxBuildTime
:=
float64
(
time
.
Since
(
batchTxBuildStart
)
/
time
.
Millisecond
)
d
.
metrics
.
BatchTxBuildTime
.
Set
(
batchTxBuildTime
)
d
.
metrics
.
NumTxPerBatch
.
Observe
(
float64
(
len
(
blocks
)))
log
.
Info
(
name
+
" batch call data"
,
"data"
,
hex
.
EncodeToString
(
batchCallData
))
opts
,
err
:=
bind
.
NewKeyedTransactorWithChainID
(
...
...
go/batch-submitter/metrics/metrics.go
0 → 100644
View file @
43e3bbe4
package
metrics
import
(
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
type
Metrics
struct
{
// ETHBalance tracks the amount of ETH in the submitter's account.
ETHBalance
prometheus
.
Gauge
// BatchSizeInBytes tracks the size of batch submission transactions.
BatchSizeInBytes
prometheus
.
Histogram
// NumTxPerBatch tracks the number of L2 transactions in each batch
// submission.
NumTxPerBatch
prometheus
.
Histogram
// SubmissionGasUsed tracks the amount of gas used to submit each batch.
SubmissionGasUsed
prometheus
.
Histogram
// BatchsSubmitted tracks the total number of successful batch submissions.
BatchesSubmitted
prometheus
.
Counter
// FailedSubmissions tracks the total number of failed batch submissions.
FailedSubmissions
prometheus
.
Counter
// BatchTxBuildTime tracks the duration it takes to construct a batch
// transaction.
BatchTxBuildTime
prometheus
.
Gauge
// BatchConfirmationTime tracks the duration it takes to confirm a batch
// transaction.
BatchConfirmationTime
prometheus
.
Gauge
}
func
NewMetrics
(
subsystem
string
)
*
Metrics
{
return
&
Metrics
{
ETHBalance
:
promauto
.
NewGauge
(
prometheus
.
GaugeOpts
{
Name
:
"batch_submitter_eth_balance"
,
Help
:
"ETH balance of the batch submitter"
,
Subsystem
:
subsystem
,
}),
BatchSizeInBytes
:
promauto
.
NewHistogram
(
prometheus
.
HistogramOpts
{
Name
:
"batch_submitter_batch_size_in_bytes"
,
Help
:
"Size of batches in bytes"
,
Subsystem
:
subsystem
,
}),
NumTxPerBatch
:
promauto
.
NewHistogram
(
prometheus
.
HistogramOpts
{
Name
:
"batch_submitter_num_txs_per_batch"
,
Help
:
"Number of transaction in each batch"
,
Subsystem
:
subsystem
,
}),
SubmissionGasUsed
:
promauto
.
NewHistogram
(
prometheus
.
HistogramOpts
{
Name
:
"batch_submitter_submission_gas_used"
,
Help
:
"Gas used to submit each batch"
,
Subsystem
:
subsystem
,
}),
BatchesSubmitted
:
promauto
.
NewCounter
(
prometheus
.
CounterOpts
{
Name
:
"batch_submitter_batches_submitted"
,
Help
:
"Count of batches submitted"
,
Subsystem
:
subsystem
,
}),
FailedSubmissions
:
promauto
.
NewCounter
(
prometheus
.
CounterOpts
{
Name
:
"batch_submitter_failed_submissions"
,
Help
:
"Count of failed batch submissions"
,
Subsystem
:
subsystem
,
}),
BatchTxBuildTime
:
promauto
.
NewGauge
(
prometheus
.
GaugeOpts
{
Name
:
"batch_submitter_batch_tx_build_time"
,
Help
:
"Time to construct batch transactions"
,
Subsystem
:
subsystem
,
}),
BatchConfirmationTime
:
promauto
.
NewGauge
(
prometheus
.
GaugeOpts
{
Name
:
"batch_submitter_batch_confirmation_time"
,
Help
:
"Time to confirm batch transactions"
,
Subsystem
:
subsystem
,
}),
}
}
go/batch-submitter/service.go
View file @
43e3bbe4
...
...
@@ -6,6 +6,7 @@ import (
"sync"
"time"
"github.com/ethereum-optimism/optimism/go/batch-submitter/metrics"
"github.com/ethereum-optimism/optimism/go/batch-submitter/txmgr"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
...
...
@@ -13,6 +14,11 @@ import (
"github.com/ethereum/go-ethereum/log"
)
var
(
// weiToGwei is the conversion rate from wei to gwei.
weiToGwei
=
new
(
big
.
Float
)
.
SetFloat64
(
1e-18
)
)
// Driver is an interface for creating and submitting batch transactions for a
// specific contract.
type
Driver
interface
{
...
...
@@ -23,6 +29,9 @@ type Driver interface {
// fees.
WalletAddr
()
common
.
Address
// Metrics returns the subservice telemetry object.
Metrics
()
*
metrics
.
Metrics
// GetBatchBlockRange returns the start and end L2 block heights that
// need to be processed. Note that the end value is *exclusive*,
// therefore if the returned values are identical nothing needs to be
...
...
@@ -51,7 +60,8 @@ type Service struct {
ctx
context
.
Context
cancel
func
()
txMgr
txmgr
.
TxManager
txMgr
txmgr
.
TxManager
metrics
*
metrics
.
Metrics
wg
sync
.
WaitGroup
}
...
...
@@ -64,10 +74,11 @@ func NewService(cfg ServiceConfig) *Service {
)
return
&
Service
{
cfg
:
cfg
,
ctx
:
ctx
,
cancel
:
cancel
,
txMgr
:
txMgr
,
cfg
:
cfg
,
ctx
:
ctx
,
cancel
:
cancel
,
txMgr
:
txMgr
,
metrics
:
cfg
.
Driver
.
Metrics
(),
}
}
...
...
@@ -91,21 +102,35 @@ func (s *Service) eventLoop() {
for
{
select
{
case
<-
time
.
After
(
s
.
cfg
.
PollInterval
)
:
log
.
Info
(
name
+
" fetching current block range"
)
// Record the submitter's current ETH balance. This is done first in
// case any of the remaining steps fail, we can at least have an
// accurate view of the submitter's balance.
balance
,
err
:=
s
.
cfg
.
L1Client
.
BalanceAt
(
s
.
ctx
,
s
.
cfg
.
Driver
.
WalletAddr
(),
nil
,
)
if
err
!=
nil
{
log
.
Error
(
name
+
" unable to get current balance"
,
"err"
,
err
)
continue
}
s
.
metrics
.
ETHBalance
.
Set
(
weiToGwei64
(
balance
))
// Determine the range of L2 blocks that the batch submitter has not
// processed, and needs to take action on.
log
.
Info
(
name
+
" fetching current block range"
)
start
,
end
,
err
:=
s
.
cfg
.
Driver
.
GetBatchBlockRange
(
s
.
ctx
)
if
err
!=
nil
{
log
.
Error
(
name
+
" unable to get block range"
,
"err"
,
err
)
continue
}
log
.
Info
(
name
+
" block range"
,
"start"
,
start
,
"end"
,
end
)
// No new updates.
if
start
.
Cmp
(
end
)
==
0
{
log
.
Info
(
name
+
" no updates"
,
"start"
,
start
,
"end"
,
end
)
continue
}
log
.
Info
(
name
+
" block range"
,
"start"
,
start
,
"end"
,
end
)
// Query for the submitter's current nonce.
nonce64
,
err
:=
s
.
cfg
.
L1Client
.
NonceAt
(
s
.
ctx
,
s
.
cfg
.
Driver
.
WalletAddr
(),
nil
,
)
...
...
@@ -116,6 +141,8 @@ func (s *Service) eventLoop() {
}
nonce
:=
new
(
big
.
Int
)
.
SetUint64
(
nonce64
)
// Construct the transaction submission clousure that will attempt
// to send the next transaction at the given nonce and gas price.
sendTx
:=
func
(
ctx
context
.
Context
,
gasPrice
*
big
.
Int
,
...
...
@@ -123,20 +150,38 @@ func (s *Service) eventLoop() {
log
.
Info
(
name
+
" attempting batch tx"
,
"start"
,
start
,
"end"
,
end
,
"nonce"
,
nonce
,
"gasPrice"
,
gasPrice
)
return
s
.
cfg
.
Driver
.
SubmitBatchTx
(
tx
,
err
:=
s
.
cfg
.
Driver
.
SubmitBatchTx
(
ctx
,
start
,
end
,
nonce
,
gasPrice
,
)
if
err
!=
nil
{
return
nil
,
err
}
s
.
metrics
.
BatchSizeInBytes
.
Observe
(
float64
(
tx
.
Size
()))
return
tx
,
nil
}
// Wait until one of our submitted transactions confirms. If no
// receipt is received it's likely our gas price was too low.
batchConfirmationStart
:=
time
.
Now
()
receipt
,
err
:=
s
.
txMgr
.
Send
(
s
.
ctx
,
sendTx
)
if
err
!=
nil
{
log
.
Error
(
name
+
" unable to publish batch tx"
,
"err"
,
err
)
s
.
metrics
.
FailedSubmissions
.
Inc
()
continue
}
// The transaction was successfully submitted.
log
.
Info
(
name
+
" batch tx successfully published"
,
"tx_hash"
,
receipt
.
TxHash
)
batchConfirmationTime
:=
time
.
Since
(
batchConfirmationStart
)
/
time
.
Millisecond
s
.
metrics
.
BatchConfirmationTime
.
Set
(
float64
(
batchConfirmationTime
))
s
.
metrics
.
BatchesSubmitted
.
Inc
()
s
.
metrics
.
SubmissionGasUsed
.
Observe
(
float64
(
receipt
.
GasUsed
))
case
err
:=
<-
s
.
ctx
.
Done
()
:
log
.
Error
(
name
+
" service shutting down"
,
"err"
,
err
)
...
...
@@ -144,3 +189,10 @@ func (s *Service) eventLoop() {
}
}
}
func
weiToGwei64
(
wei
*
big
.
Int
)
float64
{
gwei
:=
new
(
big
.
Float
)
.
SetInt
(
wei
)
gwei
.
Mul
(
gwei
,
weiToGwei
)
gwei64
,
_
:=
gwei
.
Float64
()
return
gwei64
}
go/proxyd/CHANGELOG.md
View file @
43e3bbe4
# @eth-optimism/proxyd
## 3.4.1
### Patch Changes
-
415164e1: Force proxyd build
## 3.4.0
### Minor Changes
...
...
go/proxyd/package.json
View file @
43e3bbe4
{
"name"
:
"@eth-optimism/proxyd"
,
"version"
:
"3.4.
0
"
,
"version"
:
"3.4.
1
"
,
"private"
:
true
,
"dependencies"
:
{}
}
l2geth/CHANGELOG.md
View file @
43e3bbe4
# Changelog
## 0.5.5
### Patch Changes
-
2924845d: expose ErrNonceTooHigh from miner
## 0.5.4
### Patch Changes
...
...
l2geth/package.json
View file @
43e3bbe4
{
"name"
:
"@eth-optimism/l2geth"
,
"version"
:
"0.5.
4
"
,
"version"
:
"0.5.
5
"
,
"private"
:
true
,
"devDependencies"
:
{}
}
packages/sdk/src/cross-chain-provider.ts
0 → 100644
View file @
43e3bbe4
/* eslint-disable @typescript-eslint/no-unused-vars */
import
{
Provider
,
BlockTag
,
TransactionReceipt
,
}
from
'
@ethersproject/abstract-provider
'
import
{
BigNumber
}
from
'
ethers
'
import
{
ICrossChainProvider
,
OEContracts
,
OEContractsLike
,
MessageLike
,
TransactionLike
,
AddressLike
,
NumberLike
,
ProviderLike
,
CrossChainMessage
,
MessageDirection
,
MessageStatus
,
TokenBridgeMessage
,
MessageReceipt
,
}
from
'
./interfaces
'
import
{
toProvider
,
toBigNumber
,
toTransactionHash
,
DeepPartial
,
getAllOEContracts
,
}
from
'
./utils
'
export
class
CrossChainProvider
implements
ICrossChainProvider
{
public
l1Provider
:
Provider
public
l2Provider
:
Provider
public
l1ChainId
:
number
public
contracts
:
OEContracts
/**
* Creates a new CrossChainProvider instance.
*
* @param opts Options for the provider.
* @param opts.l1Provider Provider for the L1 chain, or a JSON-RPC url.
* @param opts.l2Provider Provider for the L2 chain, or a JSON-RPC url.
* @param opts.l1ChainId Chain ID for the L1 chain.
* @param opts.contracts Optional contract address overrides.
*/
constructor
(
opts
:
{
l1Provider
:
ProviderLike
l2Provider
:
ProviderLike
l1ChainId
:
NumberLike
contracts
?:
DeepPartial
<
OEContractsLike
>
})
{
this
.
l1Provider
=
toProvider
(
opts
.
l1Provider
)
this
.
l2Provider
=
toProvider
(
opts
.
l2Provider
)
this
.
l1ChainId
=
toBigNumber
(
opts
.
l1ChainId
).
toNumber
()
this
.
contracts
=
getAllOEContracts
(
this
.
l1ChainId
,
{
l1SignerOrProvider
:
this
.
l1Provider
,
l2SignerOrProvider
:
this
.
l2Provider
,
overrides
:
opts
.
contracts
,
})
}
public
async
getMessagesByTransaction
(
transaction
:
TransactionLike
,
opts
:
{
direction
?:
MessageDirection
}
=
{}
):
Promise
<
CrossChainMessage
[]
>
{
const
txHash
=
toTransactionHash
(
transaction
)
let
receipt
:
TransactionReceipt
if
(
opts
.
direction
!==
undefined
)
{
// Get the receipt for the requested direction.
if
(
opts
.
direction
===
MessageDirection
.
L1_TO_L2
)
{
receipt
=
await
this
.
l1Provider
.
getTransactionReceipt
(
txHash
)
}
else
{
receipt
=
await
this
.
l2Provider
.
getTransactionReceipt
(
txHash
)
}
}
else
{
// Try both directions, starting with L1 => L2.
receipt
=
await
this
.
l1Provider
.
getTransactionReceipt
(
txHash
)
if
(
receipt
)
{
opts
.
direction
=
MessageDirection
.
L1_TO_L2
}
else
{
receipt
=
await
this
.
l2Provider
.
getTransactionReceipt
(
txHash
)
opts
.
direction
=
MessageDirection
.
L2_TO_L1
}
}
if
(
!
receipt
)
{
throw
new
Error
(
`unable to find transaction receipt for
${
txHash
}
`
)
}
// By this point opts.direction will always be defined.
const
messenger
=
opts
.
direction
===
MessageDirection
.
L1_TO_L2
?
this
.
contracts
.
l1
.
L1CrossDomainMessenger
:
this
.
contracts
.
l2
.
L2CrossDomainMessenger
return
receipt
.
logs
.
filter
((
log
)
=>
{
// Only look at logs emitted by the messenger address
return
log
.
address
===
messenger
.
address
})
.
filter
((
log
)
=>
{
// Only look at SentMessage logs specifically
const
parsed
=
messenger
.
interface
.
parseLog
(
log
)
return
parsed
.
name
===
'
SentMessage
'
})
.
map
((
log
)
=>
{
// Convert each SentMessage log into a message object
const
parsed
=
messenger
.
interface
.
parseLog
(
log
)
return
{
direction
:
opts
.
direction
,
target
:
parsed
.
args
.
target
,
sender
:
parsed
.
args
.
sender
,
message
:
parsed
.
args
.
message
,
messageNonce
:
parsed
.
args
.
messageNonce
,
}
})
}
public
async
getMessagesByAddress
(
address
:
AddressLike
,
opts
?:
{
direction
?:
MessageDirection
fromBlock
?:
NumberLike
toBlock
?:
NumberLike
}
):
Promise
<
CrossChainMessage
[]
>
{
throw
new
Error
(
'
Not implemented
'
)
}
public
async
getTokenBridgeMessagesByAddress
(
address
:
AddressLike
,
opts
?:
{
direction
?:
MessageDirection
fromBlock
?:
BlockTag
toBlock
?:
BlockTag
}
):
Promise
<
TokenBridgeMessage
[]
>
{
throw
new
Error
(
'
Not implemented
'
)
}
public
async
getMessageStatus
(
message
:
MessageLike
):
Promise
<
MessageStatus
>
{
throw
new
Error
(
'
Not implemented
'
)
}
public
async
getMessageReceipt
(
message
:
MessageLike
):
Promise
<
MessageReceipt
>
{
throw
new
Error
(
'
Not implemented
'
)
}
public
async
waitForMessageReciept
(
message
:
MessageLike
,
opts
?:
{
confirmations
?:
number
pollIntervalMs
?:
number
timeoutMs
?:
number
}
):
Promise
<
MessageReceipt
>
{
throw
new
Error
(
'
Not implemented
'
)
}
public
async
estimateL2MessageGasLimit
(
message
:
MessageLike
):
Promise
<
BigNumber
>
{
throw
new
Error
(
'
Not implemented
'
)
}
public
async
estimateMessageWaitTimeSeconds
(
message
:
MessageLike
):
Promise
<
number
>
{
throw
new
Error
(
'
Not implemented
'
)
}
public
async
estimateMessageWaitTimeBlocks
(
message
:
MessageLike
):
Promise
<
number
>
{
throw
new
Error
(
'
Not implemented
'
)
}
}
packages/sdk/src/index.ts
View file @
43e3bbe4
export
*
from
'
./interfaces
'
export
*
from
'
./utils
'
export
*
from
'
./cross-chain-provider
'
packages/sdk/src/interfaces/cross-chain-provider.ts
View file @
43e3bbe4
...
...
@@ -33,11 +33,6 @@ export interface ICrossChainProvider {
*/
l1ChainId
:
number
/**
* Chain ID for the L2 network.
*/
l2ChainId
:
number
/**
* Contract objects attached to their respective providers and addresses.
*/
...
...
@@ -129,9 +124,9 @@ export interface ICrossChainProvider {
*
* @param message Message to wait for.
* @param opts Options to pass to the waiting function.
*
- `confirmations` (number):
Number of transaction confirmations to wait for before returning.
*
- `pollIntervalMs` (number):
Number of milliseconds to wait between polling for the receipt.
*
- `loopsBeforeTimeout` (number): Number of times to poll
before timing out.
*
@param opts.confirmations
Number of transaction confirmations to wait for before returning.
*
@param opts.pollIntervalMs
Number of milliseconds to wait between polling for the receipt.
*
@param opts.timeoutMs Milliseconds to wait
before timing out.
* @returns CrossChainMessage receipt including receipt of the transaction that relayed the
* given message.
*/
...
...
@@ -140,7 +135,7 @@ export interface ICrossChainProvider {
opts
?:
{
confirmations
?:
number
pollIntervalMs
?:
number
loopsBeforeTimeout
?:
number
timeoutMs
?:
number
}
):
Promise
<
MessageReceipt
>
...
...
packages/sdk/src/interfaces/types.ts
View file @
43e3bbe4
...
...
@@ -6,37 +6,65 @@ import {
import
{
Signer
}
from
'
@ethersproject/abstract-signer
'
import
{
Contract
,
BigNumber
,
Overrides
}
from
'
ethers
'
/**
* L1 contract references.
*/
export
interface
OEL1Contracts
{
AddressManager
:
Contract
L1CrossDomainMessenger
:
Contract
L1StandardBridge
:
Contract
StateCommitmentChain
:
Contract
CanonicalTransactionChain
:
Contract
BondManager
:
Contract
}
/**
* L2 contract references.
*/
export
interface
OEL2Contracts
{
L2CrossDomainMessenger
:
Contract
L2StandardBridge
:
Contract
OVM_L1BlockNumber
:
Contract
OVM_L2ToL1MessagePasser
:
Contract
OVM_DeployerWhitelist
:
Contract
OVM_ETH
:
Contract
OVM_GasPriceOracle
:
Contract
OVM_SequencerFeeVault
:
Contract
WETH
:
Contract
}
/**
* Represents Optimistic Ethereum contracts, assumed to be connected to their appropriate
* providers and addresses.
*/
export
interface
OEContracts
{
/**
* L1 contract references.
*/
l1
:
{
AddressManager
:
Contract
L1CrossDomainMessenger
:
Contract
L1StandardBridge
:
Contract
StateCommitmentChain
:
Contract
CanonicalTransactionChain
:
Contract
BondManager
:
Contract
}
l1
:
OEL1Contracts
l2
:
OEL2Contracts
}
/**
* L2 contract references.
*/
l2
:
{
L2CrossDomainMessenger
:
Contract
L2StandardBridge
:
Contract
OVM_L1BlockNumber
:
Contract
OVM_L2ToL1MessagePasser
:
Contract
OVM_DeployerWhitelist
:
Contract
OVM_ETH
:
Contract
OVM_GasPriceOracle
:
Contract
OVM_SequencerFeeVault
:
Contract
WETH
:
Contract
}
/**
* Convenience type for something that looks like the L1 OE contract interface but could be
* addresses instead of actual contract objects.
*/
export
type
OEL1ContractsLike
=
{
[
K
in
keyof
OEL1Contracts
]:
AddressLike
}
/**
* Convenience type for something that looks like the L2 OE contract interface but could be
* addresses instead of actual contract objects.
*/
export
type
OEL2ContractsLike
=
{
[
K
in
keyof
OEL2Contracts
]:
AddressLike
}
/**
* Convenience type for something that looks like the OE contract interface but could be
* addresses instead of actual contract objects.
*/
export
interface
OEContractsLike
{
l1
:
OEL1ContractsLike
l2
:
OEL2ContractsLike
}
/**
...
...
@@ -164,13 +192,6 @@ export interface StateRootBatch {
stateRoots
:
string
[]
}
/**
* Utility type for deep partials.
*/
export
type
DeepPartial
<
T
>
=
{
[
P
in
keyof
T
]?:
DeepPartial
<
T
[
P
]
>
}
/**
* Extended Ethers overrides object with an l2GasLimit field.
* Only meant to be used for L1 to L2 messages, since L2 to L1 messages don't have a specified gas
...
...
packages/sdk/src/utils.ts
→
packages/sdk/src/utils
/coercion
.ts
View file @
43e3bbe4
...
...
@@ -4,46 +4,13 @@ import {
TransactionReceipt
,
TransactionResponse
,
}
from
'
@ethersproject/abstract-provider
'
import
{
getContractInterface
}
from
'
@eth-optimism/contracts
'
import
{
ethers
}
from
'
ethers
'
import
{
ethers
,
BigNumber
}
from
'
ethers
'
import
{
ProviderLike
,
TransactionLike
,
DirectionlessCrossChainMessage
,
}
from
'
./interfaces
'
/**
* Returns the canonical encoding of a cross chain message. This encoding is used in various
* locations within the Optimistic Ethereum smart contracts.
*
* @param message Cross chain message to encode.
* @returns Canonical encoding of the message.
*/
export
const
encodeCrossChainMessage
=
(
message
:
DirectionlessCrossChainMessage
):
string
=>
{
return
getContractInterface
(
'
L2CrossDomainMessenger
'
).
encodeFunctionData
(
'
relayMessage
'
,
[
message
.
target
,
message
.
sender
,
message
.
message
,
message
.
messageNonce
]
)
}
/**
* Returns the canonical hash of a cross chain message. This hash is used in various locations
* within the Optimistic Ethereum smart contracts and is the keccak256 hash of the result of
* encodeCrossChainMessage.
*
* @param message Cross chain message to hash.
* @returns Canonical hash of the message.
*/
export
const
hashCrossChainMessage
=
(
message
:
DirectionlessCrossChainMessage
):
string
=>
{
return
ethers
.
utils
.
solidityKeccak256
(
[
'
bytes
'
],
[
encodeCrossChainMessage
(
message
)]
)
}
NumberLike
,
AddressLike
,
}
from
'
../interfaces
'
/**
* Converts a ProviderLike into a provider. Assumes that if the ProviderLike is a string then
...
...
@@ -84,3 +51,29 @@ export const toTransactionHash = (transaction: TransactionLike): string => {
throw
new
Error
(
'
Invalid transaction
'
)
}
}
/**
* Converts a number-like into an ethers BigNumber.
*
* @param num Number-like to convert into a BigNumber.
* @returns Number-like as a BigNumber.
*/
export
const
toBigNumber
=
(
num
:
NumberLike
):
BigNumber
=>
{
return
ethers
.
BigNumber
.
from
(
num
)
}
/**
* Converts an address-like into a 0x-prefixed address string.
*
* @param addr Address-like to convert into an address.
* @returns Address-like as an address.
*/
export
const
toAddress
=
(
addr
:
AddressLike
):
string
=>
{
if
(
typeof
addr
===
'
string
'
)
{
assert
(
ethers
.
utils
.
isAddress
(
addr
),
'
Invalid address
'
)
return
ethers
.
utils
.
getAddress
(
addr
)
}
else
{
assert
(
ethers
.
utils
.
isAddress
(
addr
.
address
),
'
Invalid address
'
)
return
ethers
.
utils
.
getAddress
(
addr
.
address
)
}
}
packages/sdk/src/utils/contracts.ts
0 → 100644
View file @
43e3bbe4
import
{
getContractInterface
,
predeploys
}
from
'
@eth-optimism/contracts
'
import
{
ethers
,
Contract
}
from
'
ethers
'
import
{
OEContracts
,
OEL1Contracts
,
OEL2Contracts
,
OEContractsLike
,
OEL2ContractsLike
,
AddressLike
,
}
from
'
../interfaces
'
import
{
toAddress
}
from
'
./coercion
'
import
{
DeepPartial
}
from
'
./type-utils
'
/**
* Full list of default L2 contract addresses.
*/
export
const
DEFAULT_L2_CONTRACT_ADDRESSES
:
OEL2ContractsLike
=
{
L2CrossDomainMessenger
:
predeploys
.
L2CrossDomainMessenger
,
L2StandardBridge
:
predeploys
.
L2StandardBridge
,
OVM_L1BlockNumber
:
predeploys
.
OVM_L1BlockNumber
,
OVM_L2ToL1MessagePasser
:
predeploys
.
OVM_L2ToL1MessagePasser
,
OVM_DeployerWhitelist
:
predeploys
.
OVM_DeployerWhitelist
,
OVM_ETH
:
predeploys
.
OVM_ETH
,
OVM_GasPriceOracle
:
predeploys
.
OVM_GasPriceOracle
,
OVM_SequencerFeeVault
:
predeploys
.
OVM_SequencerFeeVault
,
WETH
:
predeploys
.
WETH9
,
}
/**
* We've changed some contract names in this SDK to be a bit nicer. Here we remap these nicer names
* back to the original contract names so we can look them up.
*/
const
NAME_REMAPPING
=
{
AddressManager
:
'
Lib_AddressManager
'
,
OVM_L1BlockNumber
:
'
iOVM_L1BlockNumber
'
,
WETH
:
'
WETH9
'
,
}
/**
* Mapping of L1 chain IDs to the appropriate contract addresses for the OE deployments to the
* given network. Simplifies the process of getting the correct contract addresses for a given
* contract name.
*/
export
const
CONTRACT_ADDRESSES
:
{
[
l1ChainId
:
number
]:
OEContractsLike
}
=
{
// Mainnet
1
:
{
l1
:
{
AddressManager
:
'
0xdE1FCfB0851916CA5101820A69b13a4E276bd81F
'
,
L1CrossDomainMessenger
:
'
0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1
'
,
L1StandardBridge
:
'
0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1
'
,
StateCommitmentChain
:
'
0xBe5dAb4A2e9cd0F27300dB4aB94BeE3A233AEB19
'
,
CanonicalTransactionChain
:
'
0x5E4e65926BA27467555EB562121fac00D24E9dD2
'
,
BondManager
:
'
0xcd626E1328b41fCF24737F137BcD4CE0c32bc8d1
'
,
},
l2
:
DEFAULT_L2_CONTRACT_ADDRESSES
,
},
// Kovan
42
:
{
l1
:
{
AddressManager
:
'
0x100Dd3b414Df5BbA2B542864fF94aF8024aFdf3a
'
,
L1CrossDomainMessenger
:
'
0x4361d0F75A0186C05f971c566dC6bEa5957483fD
'
,
L1StandardBridge
:
'
0x22F24361D548e5FaAfb36d1437839f080363982B
'
,
StateCommitmentChain
:
'
0xD7754711773489F31A0602635f3F167826ce53C5
'
,
CanonicalTransactionChain
:
'
0xf7B88A133202d41Fe5E2Ab22e6309a1A4D50AF74
'
,
BondManager
:
'
0xc5a603d273E28185c18Ba4d26A0024B2d2F42740
'
,
},
l2
:
DEFAULT_L2_CONTRACT_ADDRESSES
,
},
// Goerli
5
:
{
l1
:
{
AddressManager
:
'
0x2F7E3cAC91b5148d336BbffB224B4dC79F09f01D
'
,
L1CrossDomainMessenger
:
'
0xEcC89b9EDD804850C4F343A278Be902be11AaF42
'
,
L1StandardBridge
:
'
0x73298186A143a54c20ae98EEE5a025bD5979De02
'
,
StateCommitmentChain
:
'
0x1afcA918eff169eE20fF8AB6Be75f3E872eE1C1A
'
,
CanonicalTransactionChain
:
'
0x2ebA8c4EfDB39A8Cd8f9eD65c50ec079f7CEBD81
'
,
BondManager
:
'
0xE5AE60bD6F8DEe4D0c2BC9268e23B92F1cacC58F
'
,
},
l2
:
DEFAULT_L2_CONTRACT_ADDRESSES
,
},
// Hardhat local
// TODO: Get the actual addresses for this, temporary addresses here are fine for now until we
// start using this package in the integration tests.
31337
:
{
l1
:
{
AddressManager
:
'
0x2F7E3cAC91b5148d336BbffB224B4dC79F09f01D
'
,
L1CrossDomainMessenger
:
'
0xEcC89b9EDD804850C4F343A278Be902be11AaF42
'
,
L1StandardBridge
:
'
0x73298186A143a54c20ae98EEE5a025bD5979De02
'
,
StateCommitmentChain
:
'
0x1afcA918eff169eE20fF8AB6Be75f3E872eE1C1A
'
,
CanonicalTransactionChain
:
'
0x2ebA8c4EfDB39A8Cd8f9eD65c50ec079f7CEBD81
'
,
BondManager
:
'
0xE5AE60bD6F8DEe4D0c2BC9268e23B92F1cacC58F
'
,
},
l2
:
DEFAULT_L2_CONTRACT_ADDRESSES
,
},
}
/**
* Returns an ethers.Contract object for the given name, connected to the appropriate address for
* the given L1 chain ID. Users can also provide a custom address to connect the contract to
* instead. If the chain ID is not known then the user MUST provide a custom address or this
* function will throw an error.
*
* @param contractName Name of the contract to connect to.
* @param l1ChainId Chain ID for the L1 network where the OE contracts are deployed.
* @param opts Additional options for connecting to the contract.
* @param opts.address Custom address to connect to the contract.
* @param opts.signerOrProvider Signer or provider to connect to the contract.
* @returns An ethers.Contract object connected to the appropriate address and interface.
*/
export
const
getOEContract
=
(
contractName
:
keyof
OEL1Contracts
|
keyof
OEL2Contracts
,
l1ChainId
:
number
,
opts
:
{
address
?:
AddressLike
signerOrProvider
?:
ethers
.
Signer
|
ethers
.
providers
.
Provider
}
=
{}
):
Contract
=>
{
const
addresses
=
CONTRACT_ADDRESSES
[
l1ChainId
]
if
(
addresses
===
undefined
&&
opts
.
address
===
undefined
)
{
throw
new
Error
(
`cannot get contract
${
contractName
}
for unknown L1 chain ID
${
l1ChainId
}
, you must provide an address`
)
}
return
new
Contract
(
toAddress
(
opts
.
address
||
addresses
.
l1
[
contractName
]
||
addresses
.
l2
[
contractName
]
),
getContractInterface
(
NAME_REMAPPING
[
contractName
]
||
contractName
),
opts
.
signerOrProvider
)
}
/**
* Automatically connects to all contract addresses, both L1 and L2, for the given L1 chain ID. The
* user can provide custom contract address overrides for L1 or L2 contracts. If the given chain ID
* is not known then the user MUST provide custom contract addresses for ALL L1 contracts or this
* function will throw an error.
*
* @param l1ChainId Chain ID for the L1 network where the OE contracts are deployed.
* @param opts Additional options for connecting to the contracts.
* @param opts.l1SignerOrProvider: Signer or provider to connect to the L1 contracts.
* @param opts.l2SignerOrProvider: Signer or provider to connect to the L2 contracts.
* @param opts.overrides Custom contract address overrides for L1 or L2 contracts.
* @returns An object containing ethers.Contract objects connected to the appropriate addresses on
* both L1 and L2.
*/
export
const
getAllOEContracts
=
(
l1ChainId
:
number
,
opts
:
{
l1SignerOrProvider
?:
ethers
.
Signer
|
ethers
.
providers
.
Provider
l2SignerOrProvider
?:
ethers
.
Signer
|
ethers
.
providers
.
Provider
overrides
?:
DeepPartial
<
OEContractsLike
>
}
=
{}
):
OEContracts
=>
{
const
addresses
=
CONTRACT_ADDRESSES
[
l1ChainId
]
||
{
l1
:
{
AddressManager
:
undefined
,
L1CrossDomainMessenger
:
undefined
,
L1StandardBridge
:
undefined
,
StateCommitmentChain
:
undefined
,
CanonicalTransactionChain
:
undefined
,
BondManager
:
undefined
,
},
l2
:
DEFAULT_L2_CONTRACT_ADDRESSES
,
}
// Attach all L1 contracts.
const
l1Contracts
:
OEL1Contracts
=
{}
as
any
for
(
const
[
contractName
,
contractAddress
]
of
Object
.
entries
(
addresses
.
l1
))
{
l1Contracts
[
contractName
]
=
getOEContract
(
contractName
as
any
,
l1ChainId
,
{
address
:
opts
.
overrides
?.
l1
?.[
contractName
]
||
contractAddress
,
signerOrProvider
:
opts
.
l1SignerOrProvider
,
})
}
// Attach all L2 contracts.
const
l2Contracts
:
OEL2Contracts
=
{}
as
any
for
(
const
[
contractName
,
contractAddress
]
of
Object
.
entries
(
addresses
.
l2
))
{
l2Contracts
[
contractName
]
=
getOEContract
(
contractName
as
any
,
l1ChainId
,
{
address
:
opts
.
overrides
?.
l2
?.[
contractName
]
||
contractAddress
,
signerOrProvider
:
opts
.
l2SignerOrProvider
,
})
}
return
{
l1
:
l1Contracts
,
l2
:
l2Contracts
,
}
}
packages/sdk/src/utils/index.ts
0 → 100644
View file @
43e3bbe4
export
*
from
'
./coercion
'
export
*
from
'
./contracts
'
export
*
from
'
./message-encoding
'
export
*
from
'
./type-utils
'
packages/sdk/src/utils/message-encoding.ts
0 → 100644
View file @
43e3bbe4
import
{
getContractInterface
}
from
'
@eth-optimism/contracts
'
import
{
ethers
}
from
'
ethers
'
import
{
DirectionlessCrossChainMessage
}
from
'
../interfaces
'
/**
* Returns the canonical encoding of a cross chain message. This encoding is used in various
* locations within the Optimistic Ethereum smart contracts.
*
* @param message Cross chain message to encode.
* @returns Canonical encoding of the message.
*/
export
const
encodeCrossChainMessage
=
(
message
:
DirectionlessCrossChainMessage
):
string
=>
{
return
getContractInterface
(
'
L2CrossDomainMessenger
'
).
encodeFunctionData
(
'
relayMessage
'
,
[
message
.
target
,
message
.
sender
,
message
.
message
,
message
.
messageNonce
]
)
}
/**
* Returns the canonical hash of a cross chain message. This hash is used in various locations
* within the Optimistic Ethereum smart contracts and is the keccak256 hash of the result of
* encodeCrossChainMessage.
*
* @param message Cross chain message to hash.
* @returns Canonical hash of the message.
*/
export
const
hashCrossChainMessage
=
(
message
:
DirectionlessCrossChainMessage
):
string
=>
{
return
ethers
.
utils
.
solidityKeccak256
(
[
'
bytes
'
],
[
encodeCrossChainMessage
(
message
)]
)
}
packages/sdk/src/utils/type-utils.ts
0 → 100644
View file @
43e3bbe4
/**
* Utility type for deep partials.
*/
export
type
DeepPartial
<
T
>
=
{
[
P
in
keyof
T
]?:
DeepPartial
<
T
[
P
]
>
}
packages/sdk/test/contracts/ICrossDomainMessenger.sol
0 → 100644
View file @
43e3bbe4
pragma solidity ^0.8.9;
// Right now this is copy/pasted from the contracts package. We need to do this because we don't
// currently copy the contracts into the root of the contracts package in the correct way until
// we bundle the contracts package for publication. As a result, we can't properly use the
// package the way we want to from inside the monorepo (yet). Needs to be fixed as part of a
// separate pull request.
interface ICrossDomainMessenger {
/**********
* Events *
**********/
event SentMessage(
address indexed target,
address sender,
bytes message,
uint256 messageNonce,
uint256 gasLimit
);
event RelayedMessage(bytes32 indexed msgHash);
event FailedRelayedMessage(bytes32 indexed msgHash);
/*************
* Variables *
*************/
function xDomainMessageSender() external view returns (address);
/********************
* Public Functions *
********************/
/**
* Sends a cross domain message to the target messenger.
* @param _target Target contract address.
* @param _message Message to send to the target.
* @param _gasLimit Gas limit for the provided message.
*/
function sendMessage(
address _target,
bytes calldata _message,
uint32 _gasLimit
) external;
}
packages/sdk/test/contracts/MockMessenger.sol
0 → 100644
View file @
43e3bbe4
pragma solidity ^0.8.9;
import { ICrossDomainMessenger } from "./ICrossDomainMessenger.sol";
contract MockMessenger is ICrossDomainMessenger {
function xDomainMessageSender() public view returns (address) {
return address(0);
}
// Empty function to satisfy the interface.
function sendMessage(
address _target,
bytes calldata _message,
uint32 _gasLimit
) public {
return;
}
struct SentMessageEventParams {
address target;
address sender;
bytes message;
uint256 messageNonce;
uint256 gasLimit;
}
function doNothing() public {
return;
}
function triggerSentMessageEvents(
SentMessageEventParams[] memory _params
) public {
for (uint256 i = 0; i < _params.length; i++) {
emit SentMessage(
_params[i].target,
_params[i].sender,
_params[i].message,
_params[i].messageNonce,
_params[i].gasLimit
);
}
}
function triggerRelayedMessageEvents(
bytes32[] memory _params
) public {
for (uint256 i = 0; i < _params.length; i++) {
emit RelayedMessage(_params[i]);
}
}
function triggerFailedRelayedMessageEvents(
bytes32[] memory _params
) public {
for (uint256 i = 0; i < _params.length; i++) {
emit FailedRelayedMessage(_params[i]);
}
}
}
packages/sdk/test/cross-chain-provider.spec.ts
View file @
43e3bbe4
This diff is collapsed.
Click to expand it.
packages/sdk/test/utils.spec.ts
→
packages/sdk/test/utils
/coercion
.spec.ts
View file @
43e3bbe4
import
{
expect
}
from
'
./setup
'
import
{
expect
}
from
'
.
.
/setup
'
import
{
Provider
}
from
'
@ethersproject/abstract-provider
'
import
{
Contract
,
Signer
}
from
'
ethers
'
import
{
Contract
}
from
'
ethers
'
import
{
ethers
}
from
'
hardhat
'
import
{
getContractFactory
}
from
'
@eth-optimism/contracts
'
import
{
toProvider
,
toTransactionHash
,
CrossChainMessage
,
MessageDirection
,
encodeCrossChainMessage
,
hashCrossChainMessage
,
}
from
'
../src
'
describe
(
'
utils
'
,
()
=>
{
let
signers
:
Signer
[]
before
(
async
()
=>
{
signers
=
(
await
ethers
.
getSigners
())
as
any
})
describe
(
'
encodeCrossChainMessage
'
,
()
=>
{
let
Lib_CrossDomainUtils
:
Contract
before
(
async
()
=>
{
Lib_CrossDomainUtils
=
(
await
getContractFactory
(
'
TestLib_CrossDomainUtils
'
,
signers
[
0
]
).
deploy
())
as
any
})
it
(
'
should properly encode a message
'
,
async
()
=>
{
const
message
:
CrossChainMessage
=
{
direction
:
MessageDirection
.
L1_TO_L2
,
target
:
'
0x
'
+
'
11
'
.
repeat
(
20
),
sender
:
'
0x
'
+
'
22
'
.
repeat
(
20
),
message
:
'
0x
'
+
'
1234
'
.
repeat
(
32
),
messageNonce
:
1234
,
}
const
actual
=
encodeCrossChainMessage
(
message
)
const
expected
=
await
Lib_CrossDomainUtils
.
encodeXDomainCalldata
(
message
.
target
,
message
.
sender
,
message
.
message
,
message
.
messageNonce
)
expect
(
actual
).
to
.
equal
(
expected
)
})
})
describe
(
'
hashCrossChainMessage
'
,
()
=>
{
let
MessageEncodingHelper
:
Contract
before
(
async
()
=>
{
MessageEncodingHelper
=
(
await
(
await
ethers
.
getContractFactory
(
'
MessageEncodingHelper
'
)
).
deploy
())
as
any
})
it
(
'
should properly hash a message
'
,
async
()
=>
{
const
message
:
CrossChainMessage
=
{
direction
:
MessageDirection
.
L1_TO_L2
,
target
:
'
0x
'
+
'
11
'
.
repeat
(
20
),
sender
:
'
0x
'
+
'
22
'
.
repeat
(
20
),
message
:
'
0x
'
+
'
1234
'
.
repeat
(
32
),
messageNonce
:
1234
,
}
const
actual
=
hashCrossChainMessage
(
message
)
const
expected
=
await
MessageEncodingHelper
.
hashXDomainCalldata
(
message
.
target
,
message
.
sender
,
message
.
message
,
message
.
messageNonce
)
expect
(
actual
).
to
.
equal
(
expected
)
})
})
import
{
toProvider
,
toTransactionHash
}
from
'
../../src
'
describe
(
'
type coercion utils
'
,
()
=>
{
describe
(
'
toProvider
'
,
()
=>
{
it
(
'
should convert a string to a JsonRpcProvider
'
,
()
=>
{
const
provider
=
toProvider
(
'
http://localhost:8545
'
)
...
...
packages/sdk/test/utils/contracts.spec.ts
0 → 100644
View file @
43e3bbe4
This diff is collapsed.
Click to expand it.
packages/sdk/test/utils/message-encoding.spec.ts
0 → 100644
View file @
43e3bbe4
import
{
expect
}
from
'
../setup
'
import
{
Contract
,
Signer
}
from
'
ethers
'
import
{
ethers
}
from
'
hardhat
'
import
{
getContractFactory
}
from
'
@eth-optimism/contracts
'
import
{
CrossChainMessage
,
MessageDirection
,
encodeCrossChainMessage
,
hashCrossChainMessage
,
}
from
'
../../src
'
describe
(
'
message encoding utils
'
,
()
=>
{
let
signers
:
Signer
[]
before
(
async
()
=>
{
signers
=
(
await
ethers
.
getSigners
())
as
any
})
describe
(
'
encodeCrossChainMessage
'
,
()
=>
{
let
Lib_CrossDomainUtils
:
Contract
before
(
async
()
=>
{
Lib_CrossDomainUtils
=
(
await
getContractFactory
(
'
TestLib_CrossDomainUtils
'
,
signers
[
0
]
).
deploy
())
as
any
})
it
(
'
should properly encode a message
'
,
async
()
=>
{
const
message
:
CrossChainMessage
=
{
direction
:
MessageDirection
.
L1_TO_L2
,
target
:
'
0x
'
+
'
11
'
.
repeat
(
20
),
sender
:
'
0x
'
+
'
22
'
.
repeat
(
20
),
message
:
'
0x
'
+
'
1234
'
.
repeat
(
32
),
messageNonce
:
1234
,
}
const
actual
=
encodeCrossChainMessage
(
message
)
const
expected
=
await
Lib_CrossDomainUtils
.
encodeXDomainCalldata
(
message
.
target
,
message
.
sender
,
message
.
message
,
message
.
messageNonce
)
expect
(
actual
).
to
.
equal
(
expected
)
})
})
describe
(
'
hashCrossChainMessage
'
,
()
=>
{
let
MessageEncodingHelper
:
Contract
before
(
async
()
=>
{
MessageEncodingHelper
=
(
await
(
await
ethers
.
getContractFactory
(
'
MessageEncodingHelper
'
)
).
deploy
())
as
any
})
it
(
'
should properly hash a message
'
,
async
()
=>
{
const
message
:
CrossChainMessage
=
{
direction
:
MessageDirection
.
L1_TO_L2
,
target
:
'
0x
'
+
'
11
'
.
repeat
(
20
),
sender
:
'
0x
'
+
'
22
'
.
repeat
(
20
),
message
:
'
0x
'
+
'
1234
'
.
repeat
(
32
),
messageNonce
:
1234
,
}
const
actual
=
hashCrossChainMessage
(
message
)
const
expected
=
await
MessageEncodingHelper
.
hashXDomainCalldata
(
message
.
target
,
message
.
sender
,
message
.
message
,
message
.
messageNonce
)
expect
(
actual
).
to
.
equal
(
expected
)
})
})
})
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment