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
9ddbe51a
Unverified
Commit
9ddbe51a
authored
Sep 28, 2021
by
Kelvin Fichter
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: rework msg sender for l1 to l2 messages
parent
973589da
Changes
30
Hide whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
404 additions
and
321 deletions
+404
-321
SimpleStorage.sol
integration-tests/contracts/SimpleStorage.sol
+3
-0
basic-l1-l2-communication.spec.ts
integration-tests/test/basic-l1-l2-communication.spec.ts
+28
-1
queue-ingestion.spec.ts
integration-tests/test/queue-ingestion.spec.ts
+2
-2
simulated.go
l2geth/accounts/abi/bind/backends/simulated.go
+3
-4
evm.go
l2geth/core/evm.go
+13
-25
state_processor.go
l2geth/core/state_processor.go
+2
-14
state_transition.go
l2geth/core/state_transition.go
+0
-1
transaction.go
l2geth/core/types/transaction.go
+21
-23
evm.go
l2geth/core/vm/evm.go
+1
-2
instructions.go
l2geth/core/vm/instructions.go
+0
-5
jump_table.go
l2geth/core/vm/jump_table.go
+0
-7
opcodes.go
l2geth/core/vm/opcodes.go
+4
-7
interfaces.go
l2geth/interfaces.go
+3
-4
api.go
l2geth/internal/ethapi/api.go
+1
-1
L1CrossDomainMessenger.sol
...ntracts/contracts/L1/messaging/L1CrossDomainMessenger.sol
+4
-1
CanonicalTransactionChain.sol
...ntracts/contracts/L1/rollup/CanonicalTransactionChain.sol
+15
-2
L2CrossDomainMessenger.sol
...ntracts/contracts/L2/messaging/L2CrossDomainMessenger.sol
+12
-52
iOVM_L1MessageSender.sol
...ontracts/contracts/L2/predeploys/iOVM_L1MessageSender.sol
+0
-14
AddressAliasHelper.sol
...ages/contracts/contracts/standards/AddressAliasHelper.sol
+44
-0
TestLib_AddressAliasHelper.sol
...s/test-libraries/standards/TestLib_AddressAliasHelper.sol
+34
-0
connect-contracts.ts
packages/contracts/src/connect-contracts.ts
+0
-5
contract-data.ts
packages/contracts/src/contract-data.ts
+0
-5
make-genesis.ts
packages/contracts/src/make-genesis.ts
+4
-8
predeploys.ts
packages/contracts/src/predeploys.ts
+0
-1
L1CrossDomainMessenger.spec.ts
...est/contracts/L1/messaging/L1CrossDomainMessenger.spec.ts
+35
-39
L2CrossDomainMessenger.spec.ts
...est/contracts/L2/messaging/L2CrossDomainMessenger.spec.ts
+46
-98
AddressAliasHelper.spec.ts
.../contracts/libraries/standards/AddressAliasHelper.spec.ts
+51
-0
alias.ts
packages/core-utils/src/alias.ts
+33
-0
index.ts
packages/core-utils/src/index.ts
+1
-0
alias.spec.ts
packages/core-utils/test/alias.spec.ts
+44
-0
No files found.
integration-tests/contracts/SimpleStorage.sol
View file @
9ddbe51a
...
@@ -6,12 +6,14 @@ contract ICrossDomainMessenger {
...
@@ -6,12 +6,14 @@ contract ICrossDomainMessenger {
contract SimpleStorage {
contract SimpleStorage {
address public msgSender;
address public msgSender;
address public txOrigin;
address public xDomainSender;
address public xDomainSender;
bytes32 public value;
bytes32 public value;
uint256 public totalCount;
uint256 public totalCount;
function setValue(bytes32 newValue) public {
function setValue(bytes32 newValue) public {
msgSender = msg.sender;
msgSender = msg.sender;
txOrigin = tx.origin;
xDomainSender = ICrossDomainMessenger(msg.sender)
xDomainSender = ICrossDomainMessenger(msg.sender)
.xDomainMessageSender();
.xDomainMessageSender();
value = newValue;
value = newValue;
...
@@ -20,6 +22,7 @@ contract SimpleStorage {
...
@@ -20,6 +22,7 @@ contract SimpleStorage {
function setValueNotXDomain(bytes32 newValue) public {
function setValueNotXDomain(bytes32 newValue) public {
msgSender = msg.sender;
msgSender = msg.sender;
txOrigin = tx.origin;
value = newValue;
value = newValue;
totalCount++;
totalCount++;
}
}
...
...
integration-tests/test/basic-l1-l2-communication.spec.ts
View file @
9ddbe51a
...
@@ -2,7 +2,7 @@ import { expect } from 'chai'
...
@@ -2,7 +2,7 @@ import { expect } from 'chai'
/* Imports: External */
/* Imports: External */
import
{
Contract
,
ContractFactory
}
from
'
ethers
'
import
{
Contract
,
ContractFactory
}
from
'
ethers
'
import
{
predeploys
,
getContractInterface
}
from
'
@eth-optimism/contract
s
'
import
{
applyL1ToL2Alias
,
sleep
}
from
'
@eth-optimism/core-util
s
'
/* Imports: Internal */
/* Imports: Internal */
import
simpleStorageJson
from
'
../artifacts/contracts/SimpleStorage.sol/SimpleStorage.json
'
import
simpleStorageJson
from
'
../artifacts/contracts/SimpleStorage.sol/SimpleStorage.json
'
...
@@ -90,6 +90,9 @@ describe('Basic L1<>L2 Communication', async () => {
...
@@ -90,6 +90,9 @@ describe('Basic L1<>L2 Communication', async () => {
expect
(
await
L2SimpleStorage
.
msgSender
()).
to
.
equal
(
expect
(
await
L2SimpleStorage
.
msgSender
()).
to
.
equal
(
env
.
l2Messenger
.
address
env
.
l2Messenger
.
address
)
)
expect
(
await
L2SimpleStorage
.
txOrigin
()).
to
.
equal
(
applyL1ToL2Alias
(
env
.
l1Messenger
.
address
)
)
expect
(
await
L2SimpleStorage
.
xDomainSender
()).
to
.
equal
(
expect
(
await
L2SimpleStorage
.
xDomainSender
()).
to
.
equal
(
env
.
l1Wallet
.
address
env
.
l1Wallet
.
address
)
)
...
@@ -97,6 +100,30 @@ describe('Basic L1<>L2 Communication', async () => {
...
@@ -97,6 +100,30 @@ describe('Basic L1<>L2 Communication', async () => {
expect
((
await
L2SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
1
)
expect
((
await
L2SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
1
)
})
})
it
(
'
should deposit from L1 -> L2 directly via enqueue
'
,
async
()
=>
{
const
value
=
`0x
${
'
42
'
.
repeat
(
32
)}
`
// Send L1 -> L2 message.
await
env
.
ctc
.
connect
(
env
.
l1Wallet
)
.
enqueue
(
L2SimpleStorage
.
address
,
5000000
,
L2SimpleStorage
.
interface
.
encodeFunctionData
(
'
setValueNotXDomain
'
,
[
value
,
])
)
// TODO: We need to have a function that can wait for enqueued txs.
await
sleep
(
10000
)
// No aliasing when an EOA goes directly to L2.
expect
(
await
L2SimpleStorage
.
msgSender
()).
to
.
equal
(
env
.
l1Wallet
.
address
)
expect
(
await
L2SimpleStorage
.
txOrigin
()).
to
.
equal
(
env
.
l1Wallet
.
address
)
expect
(
await
L2SimpleStorage
.
value
()).
to
.
equal
(
value
)
expect
((
await
L2SimpleStorage
.
totalCount
()).
toNumber
()).
to
.
equal
(
1
)
})
it
(
'
should have a receipt with a status of 1 for a successful message
'
,
async
()
=>
{
it
(
'
should have a receipt with a status of 1 for a successful message
'
,
async
()
=>
{
const
value
=
`0x
${
'
42
'
.
repeat
(
32
)}
`
const
value
=
`0x
${
'
42
'
.
repeat
(
32
)}
`
...
...
integration-tests/test/queue-ingestion.spec.ts
View file @
9ddbe51a
...
@@ -2,7 +2,7 @@ import { expect } from 'chai'
...
@@ -2,7 +2,7 @@ import { expect } from 'chai'
/* Imports: Internal */
/* Imports: Internal */
import
{
providers
}
from
'
ethers
'
import
{
providers
}
from
'
ethers
'
import
{
injectL2Context
}
from
'
@eth-optimism/core-utils
'
import
{
injectL2Context
,
applyL1ToL2Alias
}
from
'
@eth-optimism/core-utils
'
/* Imports: External */
/* Imports: External */
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
OptimismEnv
}
from
'
./shared/env
'
...
@@ -57,7 +57,7 @@ describe('Queue Ingestion', () => {
...
@@ -57,7 +57,7 @@ describe('Queue Ingestion', () => {
expect
(
params
.
_target
).
to
.
equal
(
'
0x
'
+
`
${
i
}
`
.
repeat
(
40
))
expect
(
params
.
_target
).
to
.
equal
(
'
0x
'
+
`
${
i
}
`
.
repeat
(
40
))
expect
(
l2Tx
.
queueOrigin
).
to
.
equal
(
'
l1
'
)
expect
(
l2Tx
.
queueOrigin
).
to
.
equal
(
'
l1
'
)
expect
(
l2Tx
.
l1TxOrigin
.
toLowerCase
()).
to
.
equal
(
expect
(
l2Tx
.
l1TxOrigin
.
toLowerCase
()).
to
.
equal
(
env
.
l1Messenger
.
address
.
toLowerCase
()
applyL1ToL2Alias
(
env
.
l1Messenger
.
address
)
.
toLowerCase
()
)
)
expect
(
l2Tx
.
l1BlockNumber
).
to
.
equal
(
l1TxReceipt
.
blockNumber
)
expect
(
l2Tx
.
l1BlockNumber
).
to
.
equal
(
l1TxReceipt
.
blockNumber
)
}
}
...
...
l2geth/accounts/abi/bind/backends/simulated.go
View file @
9ddbe51a
...
@@ -603,10 +603,9 @@ func (m callmsg) Data() []byte { return m.CallMsg.Data }
...
@@ -603,10 +603,9 @@ func (m callmsg) Data() []byte { return m.CallMsg.Data }
// UsingOVM
// UsingOVM
// These getters return OVM specific fields
// These getters return OVM specific fields
func
(
m
callmsg
)
L1Timestamp
()
uint64
{
return
m
.
CallMsg
.
L1Timestamp
}
func
(
m
callmsg
)
L1Timestamp
()
uint64
{
return
m
.
CallMsg
.
L1Timestamp
}
func
(
m
callmsg
)
L1BlockNumber
()
*
big
.
Int
{
return
m
.
CallMsg
.
L1BlockNumber
}
func
(
m
callmsg
)
L1BlockNumber
()
*
big
.
Int
{
return
m
.
CallMsg
.
L1BlockNumber
}
func
(
m
callmsg
)
L1MessageSender
()
*
common
.
Address
{
return
m
.
CallMsg
.
L1MessageSender
}
func
(
m
callmsg
)
QueueOrigin
()
types
.
QueueOrigin
{
return
m
.
CallMsg
.
QueueOrigin
}
func
(
m
callmsg
)
QueueOrigin
()
types
.
QueueOrigin
{
return
m
.
CallMsg
.
QueueOrigin
}
// filterBackend implements filters.Backend to support filtering for logs without
// filterBackend implements filters.Backend to support filtering for logs without
// taking bloom-bits acceleration structures into account.
// taking bloom-bits acceleration structures into account.
...
...
l2geth/core/evm.go
View file @
9ddbe51a
...
@@ -27,10 +27,6 @@ import (
...
@@ -27,10 +27,6 @@ import (
"github.com/ethereum/go-ethereum/rollup/rcfg"
"github.com/ethereum/go-ethereum/rollup/rcfg"
)
)
// DefaultL1MessageSender is the default L1MessageSender value attached to a transaction that is
// not an L1 to L2 message.
var
DefaultL1MessageSender
=
common
.
HexToAddress
(
"0x00000000000000000000000000000000000beef"
)
// ChainContext supports retrieving headers and consensus parameters from the
// ChainContext supports retrieving headers and consensus parameters from the
// current blockchain to be used during transaction processing.
// current blockchain to be used during transaction processing.
type
ChainContext
interface
{
type
ChainContext
interface
{
...
@@ -52,28 +48,20 @@ func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author
...
@@ -52,28 +48,20 @@ func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author
}
}
if
rcfg
.
UsingOVM
{
if
rcfg
.
UsingOVM
{
// When using the OVM, we must:
// When using the OVM, we must:
// (1) Attach the L1MessageSender context value and
// - Set the BlockNumber to be the msg.L1BlockNumber
// (2) Set the BlockNumber to be the msg.L1BlockNumber
// - Set the Time to be the msg.L1Timestamp
// (3) Set the Time to be the msg.L1Timestamp
var
l1MessageSender
common
.
Address
if
msg
.
L1MessageSender
()
==
nil
{
l1MessageSender
=
DefaultL1MessageSender
}
else
{
l1MessageSender
=
*
msg
.
L1MessageSender
()
}
return
vm
.
Context
{
return
vm
.
Context
{
CanTransfer
:
CanTransfer
,
CanTransfer
:
CanTransfer
,
Transfer
:
Transfer
,
Transfer
:
Transfer
,
GetHash
:
GetHashFn
(
header
,
chain
),
GetHash
:
GetHashFn
(
header
,
chain
),
Origin
:
msg
.
From
(),
Origin
:
msg
.
From
(),
Coinbase
:
dump
.
OvmFeeWallet
,
// Coinbase is the fee vault.
Coinbase
:
dump
.
OvmFeeWallet
,
// Coinbase is the fee vault.
BlockNumber
:
new
(
big
.
Int
)
.
Set
(
header
.
Number
),
BlockNumber
:
new
(
big
.
Int
)
.
Set
(
header
.
Number
),
Time
:
new
(
big
.
Int
)
.
SetUint64
(
msg
.
L1Timestamp
()),
Time
:
new
(
big
.
Int
)
.
SetUint64
(
msg
.
L1Timestamp
()),
Difficulty
:
new
(
big
.
Int
),
// Difficulty always returns zero.
Difficulty
:
new
(
big
.
Int
),
// Difficulty always returns zero.
GasLimit
:
header
.
GasLimit
,
GasLimit
:
header
.
GasLimit
,
GasPrice
:
new
(
big
.
Int
)
.
Set
(
msg
.
GasPrice
()),
GasPrice
:
new
(
big
.
Int
)
.
Set
(
msg
.
GasPrice
()),
L1MessageSender
:
l1MessageSender
,
L1BlockNumber
:
msg
.
L1BlockNumber
(),
L1BlockNumber
:
msg
.
L1BlockNumber
(),
}
}
}
else
{
}
else
{
return
vm
.
Context
{
return
vm
.
Context
{
...
...
l2geth/core/state_processor.go
View file @
9ddbe51a
...
@@ -26,7 +26,6 @@ import (
...
@@ -26,7 +26,6 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rollup/fees"
"github.com/ethereum/go-ethereum/rollup/fees"
"github.com/ethereum/go-ethereum/rollup/rcfg"
)
)
// StateProcessor is a basic Processor, which takes care of transitioning
// StateProcessor is a basic Processor, which takes care of transitioning
...
@@ -89,19 +88,8 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
...
@@ -89,19 +88,8 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
// indicating the block was invalid.
// indicating the block was invalid.
func
ApplyTransaction
(
config
*
params
.
ChainConfig
,
bc
ChainContext
,
author
*
common
.
Address
,
gp
*
GasPool
,
statedb
*
state
.
StateDB
,
header
*
types
.
Header
,
tx
*
types
.
Transaction
,
usedGas
*
uint64
,
cfg
vm
.
Config
)
(
*
types
.
Receipt
,
error
)
{
func
ApplyTransaction
(
config
*
params
.
ChainConfig
,
bc
ChainContext
,
author
*
common
.
Address
,
gp
*
GasPool
,
statedb
*
state
.
StateDB
,
header
*
types
.
Header
,
tx
*
types
.
Transaction
,
usedGas
*
uint64
,
cfg
vm
.
Config
)
(
*
types
.
Receipt
,
error
)
{
msg
,
err
:=
tx
.
AsMessage
(
types
.
MakeSigner
(
config
,
header
.
Number
))
msg
,
err
:=
tx
.
AsMessage
(
types
.
MakeSigner
(
config
,
header
.
Number
))
if
rcfg
.
UsingOVM
{
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
// This should only be allowed to pass if the transaction is in the ctc
// already. The presence of `Index` should specify this.
index
:=
tx
.
GetMeta
()
.
Index
if
index
==
nil
&&
msg
.
QueueOrigin
()
!=
types
.
QueueOriginL1ToL2
{
return
nil
,
err
}
}
}
else
{
if
err
!=
nil
{
return
nil
,
err
}
}
}
// Create a new context to be used in the EVM environment
// Create a new context to be used in the EVM environment
context
:=
NewEVMContext
(
msg
,
header
,
bc
,
author
)
context
:=
NewEVMContext
(
msg
,
header
,
bc
,
author
)
...
...
l2geth/core/state_transition.go
View file @
9ddbe51a
...
@@ -82,7 +82,6 @@ type Message interface {
...
@@ -82,7 +82,6 @@ type Message interface {
L1Timestamp
()
uint64
L1Timestamp
()
uint64
L1BlockNumber
()
*
big
.
Int
L1BlockNumber
()
*
big
.
Int
L1MessageSender
()
*
common
.
Address
QueueOrigin
()
types
.
QueueOrigin
QueueOrigin
()
types
.
QueueOrigin
}
}
...
...
l2geth/core/types/transaction.go
View file @
9ddbe51a
...
@@ -27,6 +27,7 @@ import (
...
@@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rollup/rcfg"
)
)
//go:generate gencodec -type txdata -field-override txdataMarshaling -out gen_tx_json.go
//go:generate gencodec -type txdata -field-override txdataMarshaling -out gen_tx_json.go
...
@@ -295,20 +296,20 @@ func (tx *Transaction) AsMessage(s Signer) (Message, error) {
...
@@ -295,20 +296,20 @@ func (tx *Transaction) AsMessage(s Signer) (Message, error) {
data
:
tx
.
data
.
Payload
,
data
:
tx
.
data
.
Payload
,
checkNonce
:
true
,
checkNonce
:
true
,
l1Timestamp
:
tx
.
meta
.
L1Timestamp
,
l1Timestamp
:
tx
.
meta
.
L1Timestamp
,
l1BlockNumber
:
tx
.
meta
.
L1BlockNumber
,
l1BlockNumber
:
tx
.
meta
.
L1BlockNumber
,
l1MessageSender
:
tx
.
meta
.
L1MessageSender
,
queueOrigin
:
tx
.
meta
.
QueueOrigin
,
queueOrigin
:
tx
.
meta
.
QueueOrigin
,
}
}
var
err
error
var
err
error
msg
.
from
,
err
=
Sender
(
s
,
tx
)
if
rcfg
.
UsingOVM
{
if
tx
.
meta
.
QueueOrigin
==
QueueOriginL1ToL2
&&
tx
.
meta
.
L1MessageSender
!=
nil
{
if
tx
.
meta
.
L1MessageSender
!=
nil
{
msg
.
from
=
*
tx
.
meta
.
L1MessageSender
msg
.
l1MessageSender
=
tx
.
meta
.
L1MessageSender
}
else
{
msg
.
from
,
err
=
Sender
(
s
,
tx
)
}
}
else
{
}
else
{
addr
:=
common
.
Address
{}
msg
.
from
,
err
=
Sender
(
s
,
tx
)
msg
.
l1MessageSender
=
&
addr
}
}
return
msg
,
err
return
msg
,
err
...
@@ -479,13 +480,12 @@ type Message struct {
...
@@ -479,13 +480,12 @@ type Message struct {
data
[]
byte
data
[]
byte
checkNonce
bool
checkNonce
bool
l1Timestamp
uint64
l1Timestamp
uint64
l1BlockNumber
*
big
.
Int
l1BlockNumber
*
big
.
Int
l1MessageSender
*
common
.
Address
queueOrigin
QueueOrigin
queueOrigin
QueueOrigin
}
}
func
NewMessage
(
from
common
.
Address
,
to
*
common
.
Address
,
nonce
uint64
,
amount
*
big
.
Int
,
gasLimit
uint64
,
gasPrice
*
big
.
Int
,
data
[]
byte
,
checkNonce
bool
,
l1
MessageSender
*
common
.
Address
,
l1
BlockNumber
*
big
.
Int
,
l1Timestamp
uint64
,
queueOrigin
QueueOrigin
)
Message
{
func
NewMessage
(
from
common
.
Address
,
to
*
common
.
Address
,
nonce
uint64
,
amount
*
big
.
Int
,
gasLimit
uint64
,
gasPrice
*
big
.
Int
,
data
[]
byte
,
checkNonce
bool
,
l1BlockNumber
*
big
.
Int
,
l1Timestamp
uint64
,
queueOrigin
QueueOrigin
)
Message
{
return
Message
{
return
Message
{
from
:
from
,
from
:
from
,
to
:
to
,
to
:
to
,
...
@@ -496,10 +496,9 @@ func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *b
...
@@ -496,10 +496,9 @@ func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *b
data
:
data
,
data
:
data
,
checkNonce
:
checkNonce
,
checkNonce
:
checkNonce
,
l1Timestamp
:
l1Timestamp
,
l1Timestamp
:
l1Timestamp
,
l1BlockNumber
:
l1BlockNumber
,
l1BlockNumber
:
l1BlockNumber
,
l1MessageSender
:
l1MessageSender
,
queueOrigin
:
queueOrigin
,
queueOrigin
:
queueOrigin
,
}
}
}
}
...
@@ -512,7 +511,6 @@ func (m Message) Nonce() uint64 { return m.nonce }
...
@@ -512,7 +511,6 @@ func (m Message) Nonce() uint64 { return m.nonce }
func
(
m
Message
)
Data
()
[]
byte
{
return
m
.
data
}
func
(
m
Message
)
Data
()
[]
byte
{
return
m
.
data
}
func
(
m
Message
)
CheckNonce
()
bool
{
return
m
.
checkNonce
}
func
(
m
Message
)
CheckNonce
()
bool
{
return
m
.
checkNonce
}
func
(
m
Message
)
L1Timestamp
()
uint64
{
return
m
.
l1Timestamp
}
func
(
m
Message
)
L1Timestamp
()
uint64
{
return
m
.
l1Timestamp
}
func
(
m
Message
)
L1BlockNumber
()
*
big
.
Int
{
return
m
.
l1BlockNumber
}
func
(
m
Message
)
L1BlockNumber
()
*
big
.
Int
{
return
m
.
l1BlockNumber
}
func
(
m
Message
)
L1MessageSender
()
*
common
.
Address
{
return
m
.
l1MessageSender
}
func
(
m
Message
)
QueueOrigin
()
QueueOrigin
{
return
m
.
queueOrigin
}
func
(
m
Message
)
QueueOrigin
()
QueueOrigin
{
return
m
.
queueOrigin
}
l2geth/core/vm/evm.go
View file @
9ddbe51a
...
@@ -98,8 +98,7 @@ type Context struct {
...
@@ -98,8 +98,7 @@ type Context struct {
Difficulty
*
big
.
Int
// Provides information for DIFFICULTY
Difficulty
*
big
.
Int
// Provides information for DIFFICULTY
// OVM information
// OVM information
L1MessageSender
common
.
Address
// Provides information for L1MESSAGESENDER
L1BlockNumber
*
big
.
Int
// Provides information for L1BLOCKNUMBER
L1BlockNumber
*
big
.
Int
// Provides information for L1BLOCKNUMBER
}
}
// EVM is the Ethereum Virtual Machine base object and provides
// EVM is the Ethereum Virtual Machine base object and provides
...
...
l2geth/core/vm/instructions.go
View file @
9ddbe51a
...
@@ -969,11 +969,6 @@ func makeSwap(size int64) executionFunc {
...
@@ -969,11 +969,6 @@ func makeSwap(size int64) executionFunc {
}
}
// OVM opcodes
// OVM opcodes
func
opL1MessageSender
(
pc
*
uint64
,
interpreter
*
EVMInterpreter
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
Stack
)
([]
byte
,
error
)
{
stack
.
push
(
interpreter
.
intPool
.
get
()
.
SetBytes
(
interpreter
.
evm
.
L1MessageSender
.
Bytes
()))
return
nil
,
nil
}
func
opL1BlockNumber
(
pc
*
uint64
,
interpreter
*
EVMInterpreter
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
Stack
)
([]
byte
,
error
)
{
func
opL1BlockNumber
(
pc
*
uint64
,
interpreter
*
EVMInterpreter
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
Stack
)
([]
byte
,
error
)
{
stack
.
push
(
math
.
U256
(
interpreter
.
intPool
.
get
()
.
Set
(
interpreter
.
evm
.
L1BlockNumber
)))
stack
.
push
(
math
.
U256
(
interpreter
.
intPool
.
get
()
.
Set
(
interpreter
.
evm
.
L1BlockNumber
)))
return
nil
,
nil
return
nil
,
nil
...
...
l2geth/core/vm/jump_table.go
View file @
9ddbe51a
...
@@ -1155,13 +1155,6 @@ func newFrontierInstructionSet() JumpTable {
...
@@ -1155,13 +1155,6 @@ func newFrontierInstructionSet() JumpTable {
valid
:
true
,
valid
:
true
,
writes
:
true
,
writes
:
true
,
},
},
L1MESSAGESENDER
:
{
execute
:
opL1MessageSender
,
constantGas
:
GasQuickStep
,
minStack
:
minStack
(
0
,
1
),
maxStack
:
maxStack
(
0
,
1
),
valid
:
true
,
},
L1BLOCKNUMBER
:
{
L1BLOCKNUMBER
:
{
execute
:
opL1BlockNumber
,
execute
:
opL1BlockNumber
,
constantGas
:
GasQuickStep
,
constantGas
:
GasQuickStep
,
...
...
l2geth/core/vm/opcodes.go
View file @
9ddbe51a
...
@@ -104,8 +104,7 @@ const (
...
@@ -104,8 +104,7 @@ const (
CHAINID
=
0x46
CHAINID
=
0x46
SELFBALANCE
=
0x47
SELFBALANCE
=
0x47
L1MESSAGESENDER
=
0x4A
L1BLOCKNUMBER
=
0x4B
L1BLOCKNUMBER
=
0x4B
)
)
// 0x50 range - 'storage' and execution.
// 0x50 range - 'storage' and execution.
...
@@ -286,9 +285,8 @@ var opCodeToString = map[OpCode]string{
...
@@ -286,9 +285,8 @@ var opCodeToString = map[OpCode]string{
SELFBALANCE
:
"SELFBALANCE"
,
SELFBALANCE
:
"SELFBALANCE"
,
// OVM opcodes
// OVM opcodes
// 0x4A
// 0x4B
L1MESSAGESENDER
:
"L1MESSAGESENDER"
,
L1BLOCKNUMBER
:
"L1BLOCKNUMBER"
,
L1BLOCKNUMBER
:
"L1BLOCKNUMBER"
,
// 0x50 range - 'storage' and execution.
// 0x50 range - 'storage' and execution.
POP
:
"POP"
,
POP
:
"POP"
,
...
@@ -548,8 +546,7 @@ var stringToOp = map[string]OpCode{
...
@@ -548,8 +546,7 @@ var stringToOp = map[string]OpCode{
"SELFDESTRUCT"
:
SELFDESTRUCT
,
"SELFDESTRUCT"
:
SELFDESTRUCT
,
// OVM opcodes
// OVM opcodes
"L1MESSAGESENDER"
:
L1MESSAGESENDER
,
"L1BLOCKNUMBER"
:
L1BLOCKNUMBER
,
"L1BLOCKNUMBER"
:
L1BLOCKNUMBER
,
}
}
// StringToOp finds the opcode whose name is stored in `str`.
// StringToOp finds the opcode whose name is stored in `str`.
...
...
l2geth/interfaces.go
View file @
9ddbe51a
...
@@ -120,10 +120,9 @@ type CallMsg struct {
...
@@ -120,10 +120,9 @@ type CallMsg struct {
Value
*
big
.
Int
// amount of wei sent along with the call
Value
*
big
.
Int
// amount of wei sent along with the call
Data
[]
byte
// input data, usually an ABI-encoded contract method invocation
Data
[]
byte
// input data, usually an ABI-encoded contract method invocation
L1Timestamp
uint64
L1Timestamp
uint64
L1BlockNumber
*
big
.
Int
L1BlockNumber
*
big
.
Int
L1MessageSender
*
common
.
Address
QueueOrigin
types
.
QueueOrigin
QueueOrigin
types
.
QueueOrigin
}
}
// A ContractCaller provides contract calls, essentially transactions that are executed by
// A ContractCaller provides contract calls, essentially transactions that are executed by
...
...
l2geth/internal/ethapi/api.go
View file @
9ddbe51a
...
@@ -883,7 +883,7 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.Blo
...
@@ -883,7 +883,7 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.Blo
}
}
// Create new call message
// Create new call message
msg
:=
types
.
NewMessage
(
addr
,
args
.
To
,
0
,
value
,
gas
,
gasPrice
,
data
,
false
,
&
addr
,
blockNumber
,
timestamp
,
types
.
QueueOriginSequencer
)
msg
:=
types
.
NewMessage
(
addr
,
args
.
To
,
0
,
value
,
gas
,
gasPrice
,
data
,
false
,
blockNumber
,
timestamp
,
types
.
QueueOriginSequencer
)
// Setup context so it may be cancelled the call has completed
// Setup context so it may be cancelled the call has completed
// or, in case of unmetered gas, setup a context with a timeout.
// or, in case of unmetered gas, setup a context with a timeout.
...
...
packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol
View file @
9ddbe51a
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
pragma solidity ^0.8.8;
pragma solidity ^0.8.8;
/* Library Imports */
/* Library Imports */
import { AddressAliasHelper } from "../../standards/AddressAliasHelper.sol";
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_AddressManager } from "../../libraries/resolver/Lib_AddressManager.sol";
import { Lib_AddressManager } from "../../libraries/resolver/Lib_AddressManager.sol";
...
@@ -62,6 +63,7 @@ contract L1CrossDomainMessenger is
...
@@ -62,6 +63,7 @@ contract L1CrossDomainMessenger is
address internal xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER;
address internal xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER;
/***************
/***************
* Constructor *
* Constructor *
***************/
***************/
...
@@ -75,6 +77,7 @@ contract L1CrossDomainMessenger is
...
@@ -75,6 +77,7 @@ contract L1CrossDomainMessenger is
Lib_AddressResolver(address(0))
Lib_AddressResolver(address(0))
{}
{}
/**********************
/**********************
* Function Modifiers *
* Function Modifiers *
**********************/
**********************/
...
@@ -299,7 +302,7 @@ contract L1CrossDomainMessenger is
...
@@ -299,7 +302,7 @@ contract L1CrossDomainMessenger is
// Compute the transactionHash
// Compute the transactionHash
bytes32 transactionHash = keccak256(
bytes32 transactionHash = keccak256(
abi.encode(
abi.encode(
address(this
),
AddressAliasHelper.applyL1ToL2Alias(address(this)
),
Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER,
Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER,
_gasLimit,
_gasLimit,
_message
_message
...
...
packages/contracts/contracts/L1/rollup/CanonicalTransactionChain.sol
View file @
9ddbe51a
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
pragma solidity ^0.8.8;
pragma solidity ^0.8.8;
/* Library Imports */
/* Library Imports */
import { AddressAliasHelper } from "../../standards/AddressAliasHelper.sol";
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
...
@@ -279,9 +280,21 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes
...
@@ -279,9 +280,21 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes
}
}
}
}
// Apply an aliasing unless msg.sender == tx.origin. This prevents an attack in which a
// contract on L1 has the same address as a contract on L2 but doesn't have the same code.
// We can safely ignore this for EOAs because they're guaranteed to have the same "code"
// (i.e. no code at all). This also makes it possible for users to interact with contracts
// on L2 even when the Sequencer is down.
address sender;
if (msg.sender == tx.origin) {
sender = msg.sender;
} else {
sender = AddressAliasHelper.applyL1ToL2Alias(msg.sender);
}
bytes32 transactionHash = keccak256(
bytes32 transactionHash = keccak256(
abi.encode(
abi.encode(
msg.
sender,
sender,
_target,
_target,
_gasLimit,
_gasLimit,
_data
_data
...
@@ -304,7 +317,7 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes
...
@@ -304,7 +317,7 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes
// to divide by 2 and subtract 1.
// to divide by 2 and subtract 1.
uint256 queueIndex = queueRef.length() / 2 - 1;
uint256 queueIndex = queueRef.length() / 2 - 1;
emit TransactionEnqueued(
emit TransactionEnqueued(
msg.
sender,
sender,
_target,
_target,
_gasLimit,
_gasLimit,
_data,
_data,
...
...
packages/contracts/contracts/L2/messaging/L2CrossDomainMessenger.sol
View file @
9ddbe51a
...
@@ -2,18 +2,15 @@
...
@@ -2,18 +2,15 @@
pragma solidity ^0.8.8;
pragma solidity ^0.8.8;
/* Library Imports */
/* Library Imports */
import { AddressAliasHelper } from "../../standards/AddressAliasHelper.sol";
import { Lib_CrossDomainUtils } from "../../libraries/bridge/Lib_CrossDomainUtils.sol";
import { Lib_CrossDomainUtils } from "../../libraries/bridge/Lib_CrossDomainUtils.sol";
import { Lib_DefaultValues } from "../../libraries/constants/Lib_DefaultValues.sol";
import { Lib_DefaultValues } from "../../libraries/constants/Lib_DefaultValues.sol";
import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol";
import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol";
/* Interface Imports */
/* Interface Imports */
import { IL2CrossDomainMessenger } from "./IL2CrossDomainMessenger.sol";
import { IL2CrossDomainMessenger } from "./IL2CrossDomainMessenger.sol";
import { iOVM_L1MessageSender } from "../predeploys/iOVM_L1MessageSender.sol";
import { iOVM_L2ToL1MessagePasser } from "../predeploys/iOVM_L2ToL1MessagePasser.sol";
import { iOVM_L2ToL1MessagePasser } from "../predeploys/iOVM_L2ToL1MessagePasser.sol";
/* External Imports */
import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
/**
/**
* @title L2CrossDomainMessenger
* @title L2CrossDomainMessenger
* @dev The L2 Cross Domain Messenger contract sends messages from L2 to L1, and is the entry point
* @dev The L2 Cross Domain Messenger contract sends messages from L2 to L1, and is the entry point
...
@@ -21,8 +18,7 @@ import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuar
...
@@ -21,8 +18,7 @@ import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuar
*
*
*/
*/
contract L2CrossDomainMessenger is
contract L2CrossDomainMessenger is
IL2CrossDomainMessenger,
IL2CrossDomainMessenger
ReentrancyGuard
{
{
/*************
/*************
...
@@ -36,18 +32,18 @@ contract L2CrossDomainMessenger is
...
@@ -36,18 +32,18 @@ contract L2CrossDomainMessenger is
address internal xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER;
address internal xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER;
address public l1CrossDomainMessenger;
address public l1CrossDomainMessenger;
/***************
/***************
* Constructor *
* Constructor *
***************/
***************/
constructor(
constructor(
address _l1CrossDomainMessenger
address _l1CrossDomainMessenger
)
) {
ReentrancyGuard()
{
l1CrossDomainMessenger = _l1CrossDomainMessenger;
l1CrossDomainMessenger = _l1CrossDomainMessenger;
}
}
/********************
/********************
* Public Functions *
* Public Functions *
********************/
********************/
...
@@ -85,9 +81,13 @@ contract L2CrossDomainMessenger is
...
@@ -85,9 +81,13 @@ contract L2CrossDomainMessenger is
sentMessages[keccak256(xDomainCalldata)] = true;
sentMessages[keccak256(xDomainCalldata)] = true;
_sendXDomainMessage(xDomainCalldata, _gasLimit);
// Actually send the message.
emit SentMessage(_target, msg.sender, _message, messageNonce, _gasLimit);
iOVM_L2ToL1MessagePasser(
Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER
).passMessageToL1(xDomainCalldata);
// Emit an event before we bump the nonce or the nonce will be off by one.
emit SentMessage(_target, msg.sender, _message, messageNonce, _gasLimit);
messageNonce += 1;
messageNonce += 1;
}
}
...
@@ -101,11 +101,10 @@ contract L2CrossDomainMessenger is
...
@@ -101,11 +101,10 @@ contract L2CrossDomainMessenger is
bytes memory _message,
bytes memory _message,
uint256 _messageNonce
uint256 _messageNonce
)
)
nonReentrant
public
public
{
{
require(
require(
_verifyXDomainMessage() == true
,
AddressAliasHelper.undoL1ToL2Alias(msg.sender) == l1CrossDomainMessenger
,
"Provided message could not be verified."
"Provided message could not be verified."
);
);
...
@@ -157,43 +156,4 @@ contract L2CrossDomainMessenger is
...
@@ -157,43 +156,4 @@ contract L2CrossDomainMessenger is
relayedMessages[relayId] = true;
relayedMessages[relayId] = true;
}
}
/**********************
* Internal Functions *
**********************/
/**
* Verifies that a received cross domain message is valid.
* @return _valid Whether or not the message is valid.
*/
function _verifyXDomainMessage()
internal
view
returns (
bool _valid
)
{
return (
iOVM_L1MessageSender(
Lib_PredeployAddresses.L1_MESSAGE_SENDER
).getL1MessageSender() == l1CrossDomainMessenger
);
}
/**
* Sends a cross domain message.
* @param _message Message to send.
* param _gasLimit Gas limit for the provided message.
*/
function _sendXDomainMessage(
bytes memory _message,
uint256 // _gasLimit
)
internal
{
iOVM_L2ToL1MessagePasser(
Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER
).passMessageToL1(_message);
}
}
}
packages/contracts/contracts/L2/predeploys/iOVM_L1MessageSender.sol
deleted
100644 → 0
View file @
973589da
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
/**
* @title iOVM_L1MessageSender
*/
interface iOVM_L1MessageSender {
/********************
* Public Functions *
********************/
function getL1MessageSender() external view returns (address);
}
packages/contracts/contracts/standards/AddressAliasHelper.sol
0 → 100644
View file @
9ddbe51a
// SPDX-License-Identifier: Apache-2.0
/*
* Copyright 2019-2021, Offchain Labs, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
pragma solidity ^0.8.7;
library AddressAliasHelper {
uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);
/// @notice Utility function that converts the address in the L1 that submitted a tx to
/// the inbox to the msg.sender viewed in the L2
/// @param l1Address the address in the L1 that triggered the tx to L2
/// @return l2Address L2 address as viewed in msg.sender
function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {
unchecked {
l2Address = address(uint160(l1Address) + offset);
}
}
/// @notice Utility function that converts the msg.sender viewed in the L2 to the
/// address in the L1 that submitted a tx to the inbox
/// @param l2Address L2 address as viewed in msg.sender
/// @return l1Address the address in the L1 that triggered the tx to L2
function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {
unchecked {
l1Address = address(uint160(l2Address) - offset);
}
}
}
packages/contracts/contracts/test-libraries/standards/TestLib_AddressAliasHelper.sol
0 → 100644
View file @
9ddbe51a
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
/* Library Imports */
import { AddressAliasHelper } from "../../standards/AddressAliasHelper.sol";
/**
* @title TestLib_AddressAliasHelper
*/
contract TestLib_AddressAliasHelper {
function applyL1ToL2Alias(
address _address
)
public
pure
returns (
address
)
{
return AddressAliasHelper.applyL1ToL2Alias(_address);
}
function undoL1ToL2Alias(
address _address
)
public
pure
returns (
address
)
{
return AddressAliasHelper.undoL1ToL2Alias(_address);
}
}
packages/contracts/src/connect-contracts.ts
View file @
9ddbe51a
...
@@ -17,7 +17,6 @@ interface L2Contracts {
...
@@ -17,7 +17,6 @@ interface L2Contracts {
eth
:
Contract
eth
:
Contract
xDomainMessenger
:
Contract
xDomainMessenger
:
Contract
messagePasser
:
Contract
messagePasser
:
Contract
messageSender
:
Contract
deployerWhiteList
:
Contract
deployerWhiteList
:
Contract
}
}
...
@@ -90,10 +89,6 @@ export const connectL2Contracts = async (
...
@@ -90,10 +89,6 @@ export const connectL2Contracts = async (
eth
:
getEthersContract
(
'
OVM_ETH
'
),
eth
:
getEthersContract
(
'
OVM_ETH
'
),
xDomainMessenger
:
getEthersContract
(
'
L2CrossDomainMessenger
'
),
xDomainMessenger
:
getEthersContract
(
'
L2CrossDomainMessenger
'
),
messagePasser
:
getEthersContract
(
'
OVM_L2ToL1MessagePasser
'
),
messagePasser
:
getEthersContract
(
'
OVM_L2ToL1MessagePasser
'
),
messageSender
:
getEthersContract
(
'
OVM_L1MessageSender
'
,
'
iOVM_L1MessageSender
'
),
deployerWhiteList
:
getEthersContract
(
'
OVM_DeployerWhitelist
'
),
deployerWhiteList
:
getEthersContract
(
'
OVM_DeployerWhitelist
'
),
}
}
}
}
packages/contracts/src/contract-data.ts
View file @
9ddbe51a
...
@@ -67,7 +67,6 @@ export const getL1ContractData = (network: Network) => {
...
@@ -67,7 +67,6 @@ export const getL1ContractData = (network: Network) => {
const
OVM_ETH
=
require
(
'
../artifacts/contracts/L2/predeploys/OVM_ETH.sol/OVM_ETH.json
'
)
const
OVM_ETH
=
require
(
'
../artifacts/contracts/L2/predeploys/OVM_ETH.sol/OVM_ETH.json
'
)
const
L2CrossDomainMessenger
=
require
(
'
../artifacts/contracts/L2/messaging/L2CrossDomainMessenger.sol/L2CrossDomainMessenger.json
'
)
const
L2CrossDomainMessenger
=
require
(
'
../artifacts/contracts/L2/messaging/L2CrossDomainMessenger.sol/L2CrossDomainMessenger.json
'
)
const
OVM_L2ToL1MessagePasser
=
require
(
'
../artifacts/contracts/L2/predeploys/OVM_L2ToL1MessagePasser.sol/OVM_L2ToL1MessagePasser.json
'
)
const
OVM_L2ToL1MessagePasser
=
require
(
'
../artifacts/contracts/L2/predeploys/OVM_L2ToL1MessagePasser.sol/OVM_L2ToL1MessagePasser.json
'
)
const
OVM_L1MessageSender
=
require
(
'
../artifacts/contracts/L2/predeploys/iOVM_L1MessageSender.sol/iOVM_L1MessageSender.json
'
)
const
OVM_DeployerWhitelist
=
require
(
'
../artifacts/contracts/L2/predeploys/OVM_DeployerWhitelist.sol/OVM_DeployerWhitelist.json
'
)
const
OVM_DeployerWhitelist
=
require
(
'
../artifacts/contracts/L2/predeploys/OVM_DeployerWhitelist.sol/OVM_DeployerWhitelist.json
'
)
export
const
getL2ContractData
=
()
=>
{
export
const
getL2ContractData
=
()
=>
{
...
@@ -84,10 +83,6 @@ export const getL2ContractData = () => {
...
@@ -84,10 +83,6 @@ export const getL2ContractData = () => {
abi
:
OVM_L2ToL1MessagePasser
.
abi
,
abi
:
OVM_L2ToL1MessagePasser
.
abi
,
address
:
l2Addresses
.
OVM_L2ToL1MessagePasser
,
address
:
l2Addresses
.
OVM_L2ToL1MessagePasser
,
},
},
OVM_L1MessageSender
:
{
abi
:
OVM_L1MessageSender
.
abi
,
address
:
l2Addresses
.
OVM_L1MessageSender
,
},
OVM_DeployerWhitelist
:
{
OVM_DeployerWhitelist
:
{
abi
:
OVM_DeployerWhitelist
.
abi
,
abi
:
OVM_DeployerWhitelist
.
abi
,
address
:
l2Addresses
.
OVM_DeployerWhitelist
,
address
:
l2Addresses
.
OVM_DeployerWhitelist
,
...
...
packages/contracts/src/make-genesis.ts
View file @
9ddbe51a
...
@@ -79,7 +79,6 @@ export const makeL2GenesisFile = async (
...
@@ -79,7 +79,6 @@ export const makeL2GenesisFile = async (
_symbol
:
'
ETH
'
,
_symbol
:
'
ETH
'
,
},
},
L2CrossDomainMessenger
:
{
L2CrossDomainMessenger
:
{
_status
:
1
,
l1CrossDomainMessenger
:
cfg
.
l1CrossDomainMessengerAddress
,
l1CrossDomainMessenger
:
cfg
.
l1CrossDomainMessengerAddress
,
},
},
}
}
...
@@ -92,14 +91,11 @@ export const makeL2GenesisFile = async (
...
@@ -92,14 +91,11 @@ export const makeL2GenesisFile = async (
storage
:
{},
storage
:
{},
}
}
if
(
predeployName
===
'
OVM_L1
MessageSend
er
'
)
{
if
(
predeployName
===
'
OVM_L1
BlockNumb
er
'
)
{
// OVM_L1
MessageSend
er is a special case where we just inject a specific bytecode string.
// OVM_L1
BlockNumb
er is a special case where we just inject a specific bytecode string.
// We do this because it uses the custom L1
MESSAGESENDER opcode (0x4A
) which cannot be
// We do this because it uses the custom L1
BLOCKNUMBER opcode (0x4B
) which cannot be
// directly used in Solidity (yet). This bytecode string simply executes the 0x4
A
opcode
// directly used in Solidity (yet). This bytecode string simply executes the 0x4
B
opcode
// and returns the address given by that opcode.
// and returns the address given by that opcode.
dump
[
predeployAddress
].
code
=
'
0x4A60005260206000F3
'
}
else
if
(
predeployName
===
'
OVM_L1BlockNumber
'
)
{
// Same as above but for OVM_L1BlockNumber (0x4B).
dump
[
predeployAddress
].
code
=
'
0x4B60005260206000F3
'
dump
[
predeployAddress
].
code
=
'
0x4B60005260206000F3
'
}
else
{
}
else
{
const
artifact
=
getContractArtifact
(
predeployName
)
const
artifact
=
getContractArtifact
(
predeployName
)
...
...
packages/contracts/src/predeploys.ts
View file @
9ddbe51a
...
@@ -9,7 +9,6 @@
...
@@ -9,7 +9,6 @@
*/
*/
export
const
predeploys
=
{
export
const
predeploys
=
{
OVM_L2ToL1MessagePasser
:
'
0x4200000000000000000000000000000000000000
'
,
OVM_L2ToL1MessagePasser
:
'
0x4200000000000000000000000000000000000000
'
,
OVM_L1MessageSender
:
'
0x4200000000000000000000000000000000000001
'
,
OVM_DeployerWhitelist
:
'
0x4200000000000000000000000000000000000002
'
,
OVM_DeployerWhitelist
:
'
0x4200000000000000000000000000000000000002
'
,
L2CrossDomainMessenger
:
'
0x4200000000000000000000000000000000000007
'
,
L2CrossDomainMessenger
:
'
0x4200000000000000000000000000000000000007
'
,
OVM_GasPriceOracle
:
'
0x420000000000000000000000000000000000000F
'
,
OVM_GasPriceOracle
:
'
0x420000000000000000000000000000000000000F
'
,
...
...
packages/contracts/test/contracts/L1/messaging/L1CrossDomainMessenger.spec.ts
View file @
9ddbe51a
...
@@ -4,7 +4,11 @@ import { expect } from '../../../setup'
...
@@ -4,7 +4,11 @@ import { expect } from '../../../setup'
import
{
ethers
}
from
'
hardhat
'
import
{
ethers
}
from
'
hardhat
'
import
{
Signer
,
ContractFactory
,
Contract
,
BigNumber
}
from
'
ethers
'
import
{
Signer
,
ContractFactory
,
Contract
,
BigNumber
}
from
'
ethers
'
import
{
smockit
,
MockContract
}
from
'
@eth-optimism/smock
'
import
{
smockit
,
MockContract
}
from
'
@eth-optimism/smock
'
import
{
remove0x
,
toHexString
}
from
'
@eth-optimism/core-utils
'
import
{
remove0x
,
toHexString
,
applyL1ToL2Alias
,
}
from
'
@eth-optimism/core-utils
'
/* Internal Imports */
/* Internal Imports */
import
{
import
{
...
@@ -20,7 +24,6 @@ import {
...
@@ -20,7 +24,6 @@ import {
getNextBlockNumber
,
getNextBlockNumber
,
encodeXDomainCalldata
,
encodeXDomainCalldata
,
}
from
'
../../../helpers
'
}
from
'
../../../helpers
'
import
{
keccak256
}
from
'
ethers/lib/utils
'
import
{
predeploys
}
from
'
../../../../src
'
import
{
predeploys
}
from
'
../../../../src
'
const
MAX_GAS_LIMIT
=
8
_000_000
const
MAX_GAS_LIMIT
=
8
_000_000
...
@@ -157,26 +160,6 @@ describe('L1CrossDomainMessenger', () => {
...
@@ -157,26 +160,6 @@ describe('L1CrossDomainMessenger', () => {
})
})
})
})
const
getTransactionHash
=
(
sender
:
string
,
target
:
string
,
gasLimit
:
number
,
data
:
string
):
string
=>
{
return
keccak256
(
encodeQueueTransaction
(
sender
,
target
,
gasLimit
,
data
))
}
const
encodeQueueTransaction
=
(
sender
:
string
,
target
:
string
,
gasLimit
:
number
,
data
:
string
):
string
=>
{
return
ethers
.
utils
.
defaultAbiCoder
.
encode
(
[
'
address
'
,
'
address
'
,
'
uint256
'
,
'
bytes
'
],
[
sender
,
target
,
gasLimit
,
data
]
)
}
describe
(
'
sendMessage
'
,
()
=>
{
describe
(
'
sendMessage
'
,
()
=>
{
const
target
=
NON_ZERO_ADDRESS
const
target
=
NON_ZERO_ADDRESS
const
message
=
NON_NULL_BYTES32
const
message
=
NON_NULL_BYTES32
...
@@ -193,13 +176,17 @@ describe('L1CrossDomainMessenger', () => {
...
@@ -193,13 +176,17 @@ describe('L1CrossDomainMessenger', () => {
message
,
message
,
0
0
)
)
const
transactionHash
=
getTransactionHash
(
const
transactionHash
=
ethers
.
utils
.
keccak256
(
L1CrossDomainMessenger
.
address
,
ethers
.
utils
.
defaultAbiCoder
.
encode
(
Mock__L2CrossDomainMessenger
.
address
,
[
'
address
'
,
'
address
'
,
'
uint256
'
,
'
bytes
'
],
gasLimit
,
[
calldata
applyL1ToL2Alias
(
L1CrossDomainMessenger
.
address
),
Mock__L2CrossDomainMessenger
.
address
,
gasLimit
,
calldata
,
]
)
)
)
const
queueLength
=
await
CanonicalTransactionChain
.
getQueueLength
()
const
queueLength
=
await
CanonicalTransactionChain
.
getQueueLength
()
const
queueElement
=
await
CanonicalTransactionChain
.
getQueueElement
(
const
queueElement
=
await
CanonicalTransactionChain
.
getQueueElement
(
queueLength
-
1
queueLength
-
1
...
@@ -274,9 +261,10 @@ describe('L1CrossDomainMessenger', () => {
...
@@ -274,9 +261,10 @@ describe('L1CrossDomainMessenger', () => {
messageNonce
messageNonce
)
)
const
storageKey
=
keccak256
(
const
storageKey
=
ethers
.
utils
.
keccak256
(
keccak256
(
calldata
+
remove0x
(
Mock__L2CrossDomainMessenger
.
address
))
+
ethers
.
utils
.
keccak256
(
'
00
'
.
repeat
(
32
)
calldata
+
remove0x
(
Mock__L2CrossDomainMessenger
.
address
)
)
+
'
00
'
.
repeat
(
32
)
)
)
const
storageGenerator
=
await
TrieTestGenerator
.
fromNodes
({
const
storageGenerator
=
await
TrieTestGenerator
.
fromNodes
({
nodes
:
[
nodes
:
[
...
@@ -294,7 +282,7 @@ describe('L1CrossDomainMessenger', () => {
...
@@ -294,7 +282,7 @@ describe('L1CrossDomainMessenger', () => {
address
:
predeploys
.
OVM_L2ToL1MessagePasser
,
address
:
predeploys
.
OVM_L2ToL1MessagePasser
,
nonce
:
0
,
nonce
:
0
,
balance
:
0
,
balance
:
0
,
codeHash
:
keccak256
(
'
0x1234
'
),
codeHash
:
ethers
.
utils
.
keccak256
(
'
0x1234
'
),
storageRoot
:
toHexString
(
storageGenerator
.
_trie
.
root
),
storageRoot
:
toHexString
(
storageGenerator
.
_trie
.
root
),
},
},
],
],
...
@@ -436,12 +424,14 @@ describe('L1CrossDomainMessenger', () => {
...
@@ -436,12 +424,14 @@ describe('L1CrossDomainMessenger', () => {
)
)
expect
(
expect
(
await
L1CrossDomainMessenger
.
successfulMessages
(
keccak256
(
calldata
))
await
L1CrossDomainMessenger
.
successfulMessages
(
ethers
.
utils
.
keccak256
(
calldata
)
)
).
to
.
equal
(
true
)
).
to
.
equal
(
true
)
expect
(
expect
(
await
L1CrossDomainMessenger
.
relayedMessages
(
await
L1CrossDomainMessenger
.
relayedMessages
(
keccak256
(
ethers
.
utils
.
keccak256
(
calldata
+
calldata
+
remove0x
(
await
signer
.
getAddress
())
+
remove0x
(
await
signer
.
getAddress
())
+
remove0x
(
BigNumber
.
from
(
blockNumber
).
toHexString
()).
padStart
(
remove0x
(
BigNumber
.
from
(
blockNumber
).
toHexString
()).
padStart
(
...
@@ -495,16 +485,18 @@ describe('L1CrossDomainMessenger', () => {
...
@@ -495,16 +485,18 @@ describe('L1CrossDomainMessenger', () => {
it
(
'
should revert if called by an account other than the owner
'
,
async
()
=>
{
it
(
'
should revert if called by an account other than the owner
'
,
async
()
=>
{
const
L1CrossDomainMessenger2
=
L1CrossDomainMessenger
.
connect
(
signer2
)
const
L1CrossDomainMessenger2
=
L1CrossDomainMessenger
.
connect
(
signer2
)
await
expect
(
await
expect
(
L1CrossDomainMessenger2
.
blockMessage
(
keccak256
(
calldata
))
L1CrossDomainMessenger2
.
blockMessage
(
ethers
.
utils
.
keccak256
(
calldata
))
).
to
.
be
.
revertedWith
(
'
Ownable: caller is not the owner
'
)
).
to
.
be
.
revertedWith
(
'
Ownable: caller is not the owner
'
)
await
expect
(
await
expect
(
L1CrossDomainMessenger2
.
allowMessage
(
keccak256
(
calldata
))
L1CrossDomainMessenger2
.
allowMessage
(
ethers
.
utils
.
keccak256
(
calldata
))
).
to
.
be
.
revertedWith
(
'
Ownable: caller is not the owner
'
)
).
to
.
be
.
revertedWith
(
'
Ownable: caller is not the owner
'
)
})
})
it
(
'
should revert if the message is blocked
'
,
async
()
=>
{
it
(
'
should revert if the message is blocked
'
,
async
()
=>
{
await
L1CrossDomainMessenger
.
blockMessage
(
keccak256
(
calldata
))
await
L1CrossDomainMessenger
.
blockMessage
(
ethers
.
utils
.
keccak256
(
calldata
)
)
await
expect
(
await
expect
(
L1CrossDomainMessenger
.
relayMessage
(
target
,
sender
,
message
,
0
,
proof
)
L1CrossDomainMessenger
.
relayMessage
(
target
,
sender
,
message
,
0
,
proof
)
...
@@ -512,13 +504,17 @@ describe('L1CrossDomainMessenger', () => {
...
@@ -512,13 +504,17 @@ describe('L1CrossDomainMessenger', () => {
})
})
it
(
'
should succeed if the message is blocked, then unblocked
'
,
async
()
=>
{
it
(
'
should succeed if the message is blocked, then unblocked
'
,
async
()
=>
{
await
L1CrossDomainMessenger
.
blockMessage
(
keccak256
(
calldata
))
await
L1CrossDomainMessenger
.
blockMessage
(
ethers
.
utils
.
keccak256
(
calldata
)
)
await
expect
(
await
expect
(
L1CrossDomainMessenger
.
relayMessage
(
target
,
sender
,
message
,
0
,
proof
)
L1CrossDomainMessenger
.
relayMessage
(
target
,
sender
,
message
,
0
,
proof
)
).
to
.
be
.
revertedWith
(
'
Provided message has been blocked.
'
)
).
to
.
be
.
revertedWith
(
'
Provided message has been blocked.
'
)
await
L1CrossDomainMessenger
.
allowMessage
(
keccak256
(
calldata
))
await
L1CrossDomainMessenger
.
allowMessage
(
ethers
.
utils
.
keccak256
(
calldata
)
)
await
expect
(
await
expect
(
L1CrossDomainMessenger
.
relayMessage
(
target
,
sender
,
message
,
0
,
proof
)
L1CrossDomainMessenger
.
relayMessage
(
target
,
sender
,
message
,
0
,
proof
)
...
...
packages/contracts/test/contracts/L2/messaging/L2CrossDomainMessenger.spec.ts
View file @
9ddbe51a
import
{
expect
}
from
'
../../../setup
'
import
{
expect
}
from
'
../../../setup
'
/* External Imports */
/* External Imports */
import
{
ethers
}
from
'
hardhat
'
import
hre
,
{
ethers
}
from
'
hardhat
'
import
{
Signer
,
ContractFactory
,
Contract
,
constants
}
from
'
ethers
'
import
{
Signer
,
ContractFactory
,
Contract
}
from
'
ethers
'
import
{
smockit
,
MockContract
}
from
'
@eth-optimism/smock
'
import
{
smockit
,
MockContract
}
from
'
@eth-optimism/smock
'
import
{
solidityKeccak256
}
from
'
ethers/lib/
utils
'
import
{
applyL1ToL2Alias
}
from
'
@eth-optimism/core-
utils
'
/* Internal Imports */
/* Internal Imports */
import
{
import
{
NON_NULL_BYTES32
,
NON_NULL_BYTES32
,
NON_ZERO_ADDRESS
,
NON_ZERO_ADDRESS
,
encodeXDomainCalldata
,
encodeXDomainCalldata
,
getNextBlockNumber
,
}
from
'
../../../helpers
'
}
from
'
../../../helpers
'
import
{
getContractInterface
,
predeploys
}
from
'
../../../../src
'
import
{
predeploys
}
from
'
../../../../src
'
describe
(
'
L2CrossDomainMessenger
'
,
()
=>
{
describe
(
'
L2CrossDomainMessenger
'
,
()
=>
{
let
signer
:
Signer
let
signer
:
Signer
...
@@ -23,7 +22,6 @@ describe('L2CrossDomainMessenger', () => {
...
@@ -23,7 +22,6 @@ describe('L2CrossDomainMessenger', () => {
let
Mock__TargetContract
:
MockContract
let
Mock__TargetContract
:
MockContract
let
Mock__L1CrossDomainMessenger
:
MockContract
let
Mock__L1CrossDomainMessenger
:
MockContract
let
Mock__OVM_L1MessageSender
:
MockContract
let
Mock__OVM_L2ToL1MessagePasser
:
MockContract
let
Mock__OVM_L2ToL1MessagePasser
:
MockContract
before
(
async
()
=>
{
before
(
async
()
=>
{
Mock__TargetContract
=
await
smockit
(
Mock__TargetContract
=
await
smockit
(
...
@@ -32,16 +30,30 @@ describe('L2CrossDomainMessenger', () => {
...
@@ -32,16 +30,30 @@ describe('L2CrossDomainMessenger', () => {
Mock__L1CrossDomainMessenger
=
await
smockit
(
Mock__L1CrossDomainMessenger
=
await
smockit
(
await
ethers
.
getContractFactory
(
'
L1CrossDomainMessenger
'
)
await
ethers
.
getContractFactory
(
'
L1CrossDomainMessenger
'
)
)
)
Mock__OVM_L1MessageSender
=
await
smockit
(
getContractInterface
(
'
iOVM_L1MessageSender
'
),
{
address
:
predeploys
.
OVM_L1MessageSender
}
)
Mock__OVM_L2ToL1MessagePasser
=
await
smockit
(
Mock__OVM_L2ToL1MessagePasser
=
await
smockit
(
await
ethers
.
getContractFactory
(
'
OVM_L2ToL1MessagePasser
'
),
await
ethers
.
getContractFactory
(
'
OVM_L2ToL1MessagePasser
'
),
{
address
:
predeploys
.
OVM_L2ToL1MessagePasser
}
{
address
:
predeploys
.
OVM_L2ToL1MessagePasser
}
)
)
})
})
let
impersonatedL1CrossDomainMessengerSender
:
Signer
before
(
async
()
=>
{
const
impersonatedAddress
=
applyL1ToL2Alias
(
Mock__L1CrossDomainMessenger
.
address
)
await
hre
.
network
.
provider
.
request
({
method
:
'
hardhat_impersonateAccount
'
,
params
:
[
impersonatedAddress
],
})
await
hre
.
network
.
provider
.
request
({
method
:
'
hardhat_setBalance
'
,
params
:
[
impersonatedAddress
,
'
0xFFFFFFFFFFFFFFFFF
'
],
})
impersonatedL1CrossDomainMessengerSender
=
await
ethers
.
getSigner
(
impersonatedAddress
)
})
let
Factory__L2CrossDomainMessenger
:
ContractFactory
let
Factory__L2CrossDomainMessenger
:
ContractFactory
before
(
async
()
=>
{
before
(
async
()
=>
{
Factory__L2CrossDomainMessenger
=
await
ethers
.
getContractFactory
(
Factory__L2CrossDomainMessenger
=
await
ethers
.
getContractFactory
(
...
@@ -94,24 +106,21 @@ describe('L2CrossDomainMessenger', () => {
...
@@ -94,24 +106,21 @@ describe('L2CrossDomainMessenger', () => {
sender
=
await
signer
.
getAddress
()
sender
=
await
signer
.
getAddress
()
})
})
beforeEach
(
async
()
=>
{
Mock__OVM_L1MessageSender
.
smocked
.
getL1MessageSender
.
will
.
return
.
with
(
Mock__L1CrossDomainMessenger
.
address
)
})
it
(
'
should revert if the L1 message sender is not the L1CrossDomainMessenger
'
,
async
()
=>
{
it
(
'
should revert if the L1 message sender is not the L1CrossDomainMessenger
'
,
async
()
=>
{
Mock__OVM_L1MessageSender
.
smocked
.
getL1MessageSender
.
will
.
return
.
with
(
constants
.
AddressZero
)
await
expect
(
await
expect
(
L2CrossDomainMessenger
.
relayMessage
(
target
,
sender
,
message
,
0
)
L2CrossDomainMessenger
.
connect
(
signer
).
relayMessage
(
target
,
sender
,
message
,
0
)
).
to
.
be
.
revertedWith
(
'
Provided message could not be verified.
'
)
).
to
.
be
.
revertedWith
(
'
Provided message could not be verified.
'
)
})
})
it
(
'
should send a call to the target contract
'
,
async
()
=>
{
it
(
'
should send a call to the target contract
'
,
async
()
=>
{
await
L2CrossDomainMessenger
.
relayMessage
(
target
,
sender
,
message
,
0
)
await
L2CrossDomainMessenger
.
connect
(
impersonatedL1CrossDomainMessengerSender
).
relayMessage
(
target
,
sender
,
message
,
0
)
expect
(
Mock__TargetContract
.
smocked
.
setTarget
.
calls
[
0
]).
to
.
deep
.
equal
([
expect
(
Mock__TargetContract
.
smocked
.
setTarget
.
calls
[
0
]).
to
.
deep
.
equal
([
NON_ZERO_ADDRESS
,
NON_ZERO_ADDRESS
,
...
@@ -122,40 +131,38 @@ describe('L2CrossDomainMessenger', () => {
...
@@ -122,40 +131,38 @@ describe('L2CrossDomainMessenger', () => {
await
expect
(
await
expect
(
L2CrossDomainMessenger
.
xDomainMessageSender
()
L2CrossDomainMessenger
.
xDomainMessageSender
()
).
to
.
be
.
revertedWith
(
'
xDomainMessageSender is not set
'
)
).
to
.
be
.
revertedWith
(
'
xDomainMessageSender is not set
'
)
await
L2CrossDomainMessenger
.
relayMessage
(
target
,
sender
,
message
,
0
)
await
L2CrossDomainMessenger
.
connect
(
impersonatedL1CrossDomainMessengerSender
).
relayMessage
(
target
,
sender
,
message
,
0
)
await
expect
(
await
expect
(
L2CrossDomainMessenger
.
xDomainMessageSender
()
L2CrossDomainMessenger
.
xDomainMessageSender
()
).
to
.
be
.
revertedWith
(
'
xDomainMessageSender is not set
'
)
).
to
.
be
.
revertedWith
(
'
xDomainMessageSender is not set
'
)
})
})
it
(
'
should revert if trying to send the same message twice
'
,
async
()
=>
{
it
(
'
should revert if trying to send the same message twice
'
,
async
()
=>
{
Mock__OVM_L1MessageSender
.
smocked
.
getL1MessageSender
.
will
.
return
.
with
(
await
L2CrossDomainMessenger
.
connect
(
Mock__L1CrossDomainMessenger
.
address
impersonatedL1CrossDomainMessengerSender
)
).
relayMessage
(
target
,
sender
,
message
,
0
)
await
L2CrossDomainMessenger
.
relayMessage
(
target
,
sender
,
message
,
0
)
await
expect
(
await
expect
(
L2CrossDomainMessenger
.
relayMessage
(
target
,
sender
,
message
,
0
)
L2CrossDomainMessenger
.
connect
(
impersonatedL1CrossDomainMessengerSender
).
relayMessage
(
target
,
sender
,
message
,
0
)
).
to
.
be
.
revertedWith
(
'
Provided message has already been received.
'
)
).
to
.
be
.
revertedWith
(
'
Provided message has already been received.
'
)
})
})
it
(
'
should not make a call if the target is the L2 MessagePasser
'
,
async
()
=>
{
it
(
'
should not make a call if the target is the L2 MessagePasser
'
,
async
()
=>
{
Mock__OVM_L1MessageSender
.
smocked
.
getL1MessageSender
.
will
.
return
.
with
(
Mock__L1CrossDomainMessenger
.
address
)
target
=
predeploys
.
OVM_L2ToL1MessagePasser
target
=
predeploys
.
OVM_L2ToL1MessagePasser
message
=
Mock__OVM_L2ToL1MessagePasser
.
interface
.
encodeFunctionData
(
message
=
Mock__OVM_L2ToL1MessagePasser
.
interface
.
encodeFunctionData
(
'
passMessageToL1(bytes)
'
,
'
passMessageToL1(bytes)
'
,
[
NON_NULL_BYTES32
]
[
NON_NULL_BYTES32
]
)
)
const
resProm
=
L2CrossDomainMessenger
.
relayMessage
(
const
resProm
=
L2CrossDomainMessenger
.
connect
(
target
,
impersonatedL1CrossDomainMessengerSender
sender
,
).
relayMessage
(
target
,
sender
,
message
,
0
)
message
,
0
)
// The call to relayMessage() should succeed.
// The call to relayMessage() should succeed.
await
expect
(
resProm
).
to
.
not
.
be
.
reverted
await
expect
(
resProm
).
to
.
not
.
be
.
reverted
...
@@ -173,71 +180,12 @@ describe('L2CrossDomainMessenger', () => {
...
@@ -173,71 +180,12 @@ describe('L2CrossDomainMessenger', () => {
// The message should be registered as successful.
// The message should be registered as successful.
expect
(
expect
(
await
L2CrossDomainMessenger
.
successfulMessages
(
await
L2CrossDomainMessenger
.
successfulMessages
(
solidityKeccak256
(
ethers
.
utils
.
solidityKeccak256
(
[
'
bytes
'
],
[
'
bytes
'
],
[
encodeXDomainCalldata
(
target
,
sender
,
message
,
0
)]
[
encodeXDomainCalldata
(
target
,
sender
,
message
,
0
)]
)
)
)
)
).
to
.
be
.
true
).
to
.
be
.
true
})
})
it
(
'
should revert if trying to reenter `relayMessage`
'
,
async
()
=>
{
Mock__OVM_L1MessageSender
.
smocked
.
getL1MessageSender
.
will
.
return
.
with
(
Mock__L1CrossDomainMessenger
.
address
)
const
reentrantMessage
=
L2CrossDomainMessenger
.
interface
.
encodeFunctionData
(
'
relayMessage
'
,
[
target
,
sender
,
message
,
1
,
])
// Calculate xDomainCallData used for indexing
// (within the first call to the L2 Messenger).
const
xDomainCallData
=
encodeXDomainCalldata
(
L2CrossDomainMessenger
.
address
,
sender
,
reentrantMessage
,
0
)
// Make the call.
await
L2CrossDomainMessenger
.
relayMessage
(
L2CrossDomainMessenger
.
address
,
sender
,
reentrantMessage
,
0
)
// We can't test for the nonReentrant revert string because it occurs in the second call frame,
// and target.call() won't "bubble up" the revert. So we need to use other criteria to ensure the
// right things are happening.
// Criteria 1: the reentrant message is NOT listed in successful messages.
expect
(
await
L2CrossDomainMessenger
.
successfulMessages
(
solidityKeccak256
([
'
bytes
'
],
[
xDomainCallData
])
)
).
to
.
be
.
false
// Criteria 2: the relayID of the reentrant message is recorded.
// Get blockNumber at time of the call.
const
blockNumber
=
(
await
getNextBlockNumber
(
ethers
.
provider
))
-
1
const
relayId
=
solidityKeccak256
(
[
'
bytes
'
],
[
ethers
.
utils
.
solidityPack
(
[
'
bytes
'
,
'
address
'
,
'
uint256
'
],
[
xDomainCallData
,
sender
,
blockNumber
]
),
]
)
expect
(
await
L2CrossDomainMessenger
.
relayedMessages
(
relayId
)).
to
.
be
.
true
// Criteria 3: the target contract did not receive a call.
expect
(
Mock__TargetContract
.
smocked
.
setTarget
.
calls
[
0
]).
to
.
be
.
undefined
})
})
})
})
})
packages/contracts/test/contracts/libraries/standards/AddressAliasHelper.spec.ts
0 → 100644
View file @
9ddbe51a
import
{
expect
}
from
'
../../../setup
'
/* External Imports */
import
{
ethers
}
from
'
hardhat
'
import
{
Contract
}
from
'
ethers
'
import
{
applyL1ToL2Alias
,
undoL1ToL2Alias
}
from
'
@eth-optimism/core-utils
'
describe
(
'
AddressAliasHelper
'
,
()
=>
{
let
AddressAliasHelper
:
Contract
before
(
async
()
=>
{
AddressAliasHelper
=
await
(
await
ethers
.
getContractFactory
(
'
TestLib_AddressAliasHelper
'
)
).
deploy
()
})
describe
(
'
applyL1ToL2Alias
'
,
()
=>
{
it
(
'
should be able to apply the alias to a valid address
'
,
async
()
=>
{
expect
(
await
AddressAliasHelper
.
applyL1ToL2Alias
(
'
0x0000000000000000000000000000000000000000
'
)
).
to
.
equal
(
applyL1ToL2Alias
(
'
0x0000000000000000000000000000000000000000
'
))
})
it
(
'
should be able to apply the alias even if the operation overflows
'
,
async
()
=>
{
expect
(
await
AddressAliasHelper
.
applyL1ToL2Alias
(
'
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
'
)
).
to
.
equal
(
applyL1ToL2Alias
(
'
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
'
))
})
})
describe
(
'
undoL1ToL2Alias
'
,
()
=>
{
it
(
'
should be able to undo the alias from a valid address
'
,
async
()
=>
{
expect
(
await
AddressAliasHelper
.
undoL1ToL2Alias
(
'
0x1111000000000000000000000000000000001111
'
)
).
to
.
equal
(
undoL1ToL2Alias
(
'
0x1111000000000000000000000000000000001111
'
))
})
it
(
'
should be able to undo the alias even if the operation underflows
'
,
async
()
=>
{
expect
(
await
AddressAliasHelper
.
undoL1ToL2Alias
(
'
0x1111000000000000000000000000000000001110
'
)
).
to
.
equal
(
undoL1ToL2Alias
(
'
0x1111000000000000000000000000000000001110
'
))
})
})
})
packages/core-utils/src/alias.ts
0 → 100644
View file @
9ddbe51a
import
{
ethers
}
from
'
ethers
'
export
const
L1_TO_L2_ALIAS_OFFSET
=
'
0x1111000000000000000000000000000000001111
'
const
bnToAddress
=
(
bn
:
ethers
.
BigNumber
):
string
=>
{
if
(
bn
.
isNegative
())
{
bn
=
ethers
.
BigNumber
.
from
(
'
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
'
)
.
add
(
bn
)
.
add
(
1
)
}
const
addr
=
bn
.
toHexString
().
slice
(
2
).
padStart
(
40
,
'
0
'
)
return
ethers
.
utils
.
getAddress
(
'
0x
'
+
addr
.
slice
(
addr
.
length
-
40
,
addr
.
length
)
)
}
export
const
applyL1ToL2Alias
=
(
address
:
string
):
string
=>
{
if
(
!
ethers
.
utils
.
isAddress
(
address
))
{
throw
new
Error
(
`not a valid address:
${
address
}
`
)
}
return
bnToAddress
(
ethers
.
BigNumber
.
from
(
address
).
add
(
L1_TO_L2_ALIAS_OFFSET
))
}
export
const
undoL1ToL2Alias
=
(
address
:
string
):
string
=>
{
if
(
!
ethers
.
utils
.
isAddress
(
address
))
{
throw
new
Error
(
`not a valid address:
${
address
}
`
)
}
return
bnToAddress
(
ethers
.
BigNumber
.
from
(
address
).
sub
(
L1_TO_L2_ALIAS_OFFSET
))
}
packages/core-utils/src/index.ts
View file @
9ddbe51a
...
@@ -7,3 +7,4 @@ export * from './batches'
...
@@ -7,3 +7,4 @@ export * from './batches'
export
*
from
'
./bcfg
'
export
*
from
'
./bcfg
'
export
*
from
'
./fees
'
export
*
from
'
./fees
'
export
*
from
'
./provider
'
export
*
from
'
./provider
'
export
*
from
'
./alias
'
packages/core-utils/test/alias.spec.ts
0 → 100644
View file @
9ddbe51a
import
{
expect
}
from
'
./setup
'
import
{
applyL1ToL2Alias
,
undoL1ToL2Alias
}
from
'
../src/alias
'
describe
(
'
address aliasing utils
'
,
()
=>
{
describe
(
'
applyL1ToL2Alias
'
,
()
=>
{
it
(
'
should be able to apply the alias to a valid address
'
,
()
=>
{
expect
(
applyL1ToL2Alias
(
'
0x0000000000000000000000000000000000000000
'
)
).
to
.
equal
(
'
0x1111000000000000000000000000000000001111
'
)
})
it
(
'
should be able to apply the alias even if the operation overflows
'
,
()
=>
{
expect
(
applyL1ToL2Alias
(
'
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
'
)
).
to
.
equal
(
'
0x1111000000000000000000000000000000001110
'
)
})
it
(
'
should throw if the input is not a valid address
'
,
()
=>
{
expect
(()
=>
{
applyL1ToL2Alias
(
'
0x1234
'
)
}).
to
.
throw
})
})
describe
(
'
undoL1ToL2Alias
'
,
()
=>
{
it
(
'
should be able to undo the alias from a valid address
'
,
()
=>
{
expect
(
undoL1ToL2Alias
(
'
0x1111000000000000000000000000000000001111
'
)
).
to
.
equal
(
'
0x0000000000000000000000000000000000000000
'
)
})
it
(
'
should be able to undo the alias even if the operation underflows
'
,
()
=>
{
expect
(
undoL1ToL2Alias
(
'
0x1111000000000000000000000000000000001110
'
)
).
to
.
equal
(
'
0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF
'
)
})
it
(
'
should throw if the input is not a valid address
'
,
()
=>
{
expect
(()
=>
{
undoL1ToL2Alias
(
'
0x1234
'
)
}).
to
.
throw
})
})
})
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