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
c39e6692
Unverified
Commit
c39e6692
authored
Mar 09, 2023
by
mergify[bot]
Committed by
GitHub
Mar 09, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into fix/remove-ownable-checks-l1xdm
parents
2169ddcf
7eba9adc
Changes
28
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
595 additions
and
276 deletions
+595
-276
flat-adults-hope.md
.changeset/flat-adults-hope.md
+5
-0
three-apes-study.md
.changeset/three-apes-study.md
+5
-0
config.yml
.circleci/config.yml
+8
-3
batch_submitter.go
op-batcher/batcher/batch_submitter.go
+1
-0
l1standardbridge.go
op-bindings/bindings/l1standardbridge.go
+1
-1
l2standardbridge.go
op-bindings/bindings/l2standardbridge.go
+1
-1
l2standardbridge_more.go
op-bindings/bindings/l2standardbridge_more.go
+1
-1
system_tob_test.go
op-e2e/system_tob_test.go
+1
-1
l2_output_submitter.go
op-proposer/proposer/l2_output_submitter.go
+1
-1
cli.go
op-service/log/cli.go
+3
-0
cheat.go
op-wheel/cheat/cheat.go
+33
-6
cli.md
packages/atst/docs/cli.md
+31
-40
sdk.md
packages/atst/docs/sdk.md
+163
-146
createValue.spec.ts
packages/atst/src/lib/createValue.spec.ts
+0
-0
getEvents.spec.ts
packages/atst/src/lib/getEvents.spec.ts
+29
-0
prepareWriteAttestation.spec.ts
packages/atst/src/lib/prepareWriteAttestation.spec.ts
+5
-7
prepareWriteAttestation.ts
packages/atst/src/lib/prepareWriteAttestation.ts
+2
-10
prepareWriteAttestations.spec.ts
packages/atst/src/lib/prepareWriteAttestations.spec.ts
+5
-7
readAttestation.spec.ts
packages/atst/src/lib/readAttestation.spec.ts
+4
-6
readAttestations.ts
packages/atst/src/lib/readAttestations.ts
+2
-7
.gas-snapshot
packages/contracts-bedrock/.gas-snapshot
+10
-6
LegacyMintableERC20.sol
...ontracts-bedrock/contracts/legacy/LegacyMintableERC20.sol
+89
-0
CommonTest.t.sol
packages/contracts-bedrock/contracts/test/CommonTest.t.sol
+10
-0
L2StandardBridge.t.sol
...s/contracts-bedrock/contracts/test/L2StandardBridge.t.sol
+37
-29
StandardBridge.t.sol
...ges/contracts-bedrock/contracts/test/StandardBridge.t.sol
+136
-0
IOptimismMintableERC20.sol
...ts-bedrock/contracts/universal/IOptimismMintableERC20.sol
+2
-2
StandardBridge.sol
.../contracts-bedrock/contracts/universal/StandardBridge.sol
+9
-1
service.ts
packages/fault-detector/src/service.ts
+1
-1
No files found.
.changeset/flat-adults-hope.md
0 → 100644
View file @
c39e6692
---
'
@eth-optimism/atst'
:
minor
---
Update readAttestations and prepareWriteAttestation to handle keys longer than 32 bytes
.changeset/three-apes-study.md
0 → 100644
View file @
c39e6692
---
'
@eth-optimism/fault-detector'
:
patch
---
Fixes a bug that would cause the fault detector to error out if no outputs had been proposed yet.
.circleci/config.yml
View file @
c39e6692
...
@@ -163,6 +163,10 @@ jobs:
...
@@ -163,6 +163,10 @@ jobs:
description
:
Docker build context
description
:
Docker build context
type
:
string
type
:
string
default
:
"
."
default
:
"
."
docker_target
:
description
:
"
target
build
stage"
type
:
string
default
:
"
"
registry
:
registry
:
description
:
Docker registry
description
:
Docker registry
type
:
string
type
:
string
...
@@ -196,7 +200,7 @@ jobs:
...
@@ -196,7 +200,7 @@ jobs:
DOCKER_TAGS=$(echo -ne <<parameters.docker_tags>> | sed "s/,/\n/g" | sed "s/[^a-zA-Z0-9\n]/-/g" | sed -e "s|^|-t ${IMAGE_BASE}:|")
DOCKER_TAGS=$(echo -ne <<parameters.docker_tags>> | sed "s/,/\n/g" | sed "s/[^a-zA-Z0-9\n]/-/g" | sed -e "s|^|-t ${IMAGE_BASE}:|")
docker context create buildx-build
docker context create buildx-build
docker buildx create --use buildx-build
docker buildx create --use buildx-build
docker buildx build --platform=<<parameters.platforms>> --push \
docker buildx build --platform=<<parameters.platforms>> --
target "<<parameters.docker_target>>" --
push \
$(echo -ne $DOCKER_TAGS | tr '\n' ' ') \
$(echo -ne $DOCKER_TAGS | tr '\n' ' ') \
-f <<parameters.docker_file>> \
-f <<parameters.docker_file>> \
<<parameters.docker_context>>
<<parameters.docker_context>>
...
@@ -534,7 +538,7 @@ jobs:
...
@@ -534,7 +538,7 @@ jobs:
command
:
|
command
:
|
# Note: We don't use circle CI test splits because we need to split by test name, not by package. There is an additional
# Note: We don't use circle CI test splits because we need to split by test name, not by package. There is an additional
# constraint that gotestsum does not currently (nor likely will) accept files from different pacakges when building.
# constraint that gotestsum does not currently (nor likely will) accept files from different pacakges when building.
OP_TESTLOG_DISABLE_COLOR=true OP_E2E_DISABLE_PARALLEL=
tru
e OP_E2E_USE_HTTP=<<parameters.use_http>> gotestsum \
OP_TESTLOG_DISABLE_COLOR=true OP_E2E_DISABLE_PARALLEL=
fals
e OP_E2E_USE_HTTP=<<parameters.use_http>> gotestsum \
--format=standard-verbose --junitfile=/tmp/test-results/<<parameters.module>>_http_<<parameters.use_http>>.xml \
--format=standard-verbose --junitfile=/tmp/test-results/<<parameters.module>>_http_<<parameters.use_http>>.xml \
-- -timeout=20m ./...
-- -timeout=20m ./...
working_directory
:
<<parameters.module>>
working_directory
:
<<parameters.module>>
...
@@ -845,7 +849,7 @@ jobs:
...
@@ -845,7 +849,7 @@ jobs:
./hive \
./hive \
-sim=<<parameters.sim>> \
-sim=<<parameters.sim>> \
-sim.loglevel=5 \
-sim.loglevel=5 \
-client=go-ethereum,op-geth_optimism
-history
,op-proposer_<<parameters.version>>,op-batcher_<<parameters.version>>,op-node_<<parameters.version>> |& tee /tmp/hive.log || echo "failed."
-client=go-ethereum,op-geth_optimism,op-proposer_<<parameters.version>>,op-batcher_<<parameters.version>>,op-node_<<parameters.version>> |& tee /tmp/hive.log || echo "failed."
-
run
:
-
run
:
command
:
|
command
:
|
tar -cvf /tmp/workspace.tgz -C /home/circleci/project /home/circleci/project/workspace
tar -cvf /tmp/workspace.tgz -C /home/circleci/project /home/circleci/project/workspace
...
@@ -1137,6 +1141,7 @@ workflows:
...
@@ -1137,6 +1141,7 @@ workflows:
docker_file
:
./ops/docker/Dockerfile.packages
docker_file
:
./ops/docker/Dockerfile.packages
docker_name
:
chain-mon
docker_name
:
chain-mon
docker_tags
:
<<pipeline.git.revision>>,<<pipeline.git.branch>>
docker_tags
:
<<pipeline.git.revision>>,<<pipeline.git.branch>>
docker_target
:
wd-mon
context
:
context
:
-
oplabs-gcr
-
oplabs-gcr
-
hive-test
:
-
hive-test
:
...
...
op-batcher/batcher/batch_submitter.go
View file @
c39e6692
...
@@ -81,6 +81,7 @@ func Main(version string, cliCtx *cli.Context) error {
...
@@ -81,6 +81,7 @@ func Main(version string, cliCtx *cli.Context) error {
rpcCfg
.
ListenAddr
,
rpcCfg
.
ListenAddr
,
rpcCfg
.
ListenPort
,
rpcCfg
.
ListenPort
,
version
,
version
,
oprpc
.
WithLogger
(
l
),
)
)
if
rpcCfg
.
EnableAdmin
{
if
rpcCfg
.
EnableAdmin
{
server
.
AddAPI
(
gethrpc
.
API
{
server
.
AddAPI
(
gethrpc
.
API
{
...
...
op-bindings/bindings/l1standardbridge.go
View file @
c39e6692
This diff is collapsed.
Click to expand it.
op-bindings/bindings/l2standardbridge.go
View file @
c39e6692
This diff is collapsed.
Click to expand it.
op-bindings/bindings/l2standardbridge_more.go
View file @
c39e6692
This diff is collapsed.
Click to expand it.
op-e2e/system_tob_test.go
View file @
c39e6692
...
@@ -415,6 +415,7 @@ func TestMixedDepositValidity(t *testing.T) {
...
@@ -415,6 +415,7 @@ func TestMixedDepositValidity(t *testing.T) {
// TestMixedWithdrawalValidity makes a number of withdrawal transactions and ensures ones with modified parameters are
// TestMixedWithdrawalValidity makes a number of withdrawal transactions and ensures ones with modified parameters are
// rejected while unmodified ones are accepted. This runs test cases in different systems.
// rejected while unmodified ones are accepted. This runs test cases in different systems.
func
TestMixedWithdrawalValidity
(
t
*
testing
.
T
)
{
func
TestMixedWithdrawalValidity
(
t
*
testing
.
T
)
{
parallel
(
t
)
// Setup our logger handler
// Setup our logger handler
if
!
verboseGethNodes
{
if
!
verboseGethNodes
{
log
.
Root
()
.
SetHandler
(
log
.
DiscardHandler
())
log
.
Root
()
.
SetHandler
(
log
.
DiscardHandler
())
...
@@ -424,7 +425,6 @@ func TestMixedWithdrawalValidity(t *testing.T) {
...
@@ -424,7 +425,6 @@ func TestMixedWithdrawalValidity(t *testing.T) {
for
i
:=
0
;
i
<=
8
;
i
++
{
for
i
:=
0
;
i
<=
8
;
i
++
{
i
:=
i
// avoid loop var capture
i
:=
i
// avoid loop var capture
t
.
Run
(
fmt
.
Sprintf
(
"withdrawal test#%d"
,
i
+
1
),
func
(
t
*
testing
.
T
)
{
t
.
Run
(
fmt
.
Sprintf
(
"withdrawal test#%d"
,
i
+
1
),
func
(
t
*
testing
.
T
)
{
parallel
(
t
)
// Create our system configuration, funding all accounts we created for L1/L2, and start it
// Create our system configuration, funding all accounts we created for L1/L2, and start it
cfg
:=
DefaultSystemConfig
(
t
)
cfg
:=
DefaultSystemConfig
(
t
)
cfg
.
DeployConfig
.
FinalizationPeriodSeconds
=
6
cfg
.
DeployConfig
.
FinalizationPeriodSeconds
=
6
...
...
op-proposer/proposer/l2_output_submitter.go
View file @
c39e6692
...
@@ -92,7 +92,7 @@ func Main(version string, cliCtx *cli.Context) error {
...
@@ -92,7 +92,7 @@ func Main(version string, cliCtx *cli.Context) error {
}
}
rpcCfg
:=
cfg
.
RPCConfig
rpcCfg
:=
cfg
.
RPCConfig
server
:=
oprpc
.
NewServer
(
rpcCfg
.
ListenAddr
,
rpcCfg
.
ListenPort
,
version
)
server
:=
oprpc
.
NewServer
(
rpcCfg
.
ListenAddr
,
rpcCfg
.
ListenPort
,
version
,
oprpc
.
WithLogger
(
l
)
)
if
err
:=
server
.
Start
();
err
!=
nil
{
if
err
:=
server
.
Start
();
err
!=
nil
{
cancel
()
cancel
()
return
fmt
.
Errorf
(
"error starting RPC server: %w"
,
err
)
return
fmt
.
Errorf
(
"error starting RPC server: %w"
,
err
)
...
...
op-service/log/cli.go
View file @
c39e6692
...
@@ -65,6 +65,9 @@ func NewLogger(cfg CLIConfig) log.Logger {
...
@@ -65,6 +65,9 @@ func NewLogger(cfg CLIConfig) log.Logger {
handler
:=
log
.
StreamHandler
(
os
.
Stdout
,
Format
(
cfg
.
Format
,
cfg
.
Color
))
handler
:=
log
.
StreamHandler
(
os
.
Stdout
,
Format
(
cfg
.
Format
,
cfg
.
Color
))
handler
=
log
.
SyncHandler
(
handler
)
handler
=
log
.
SyncHandler
(
handler
)
handler
=
log
.
LvlFilterHandler
(
Level
(
cfg
.
Level
),
handler
)
handler
=
log
.
LvlFilterHandler
(
Level
(
cfg
.
Level
),
handler
)
// Set the root handle to what we have configured. Some components like go-ethereum's RPC
// server use log.Root() instead of being able to pass in a log.
log
.
Root
()
.
SetHandler
(
handler
)
logger
:=
log
.
New
()
logger
:=
log
.
New
()
logger
.
SetHandler
(
handler
)
logger
.
SetHandler
(
handler
)
return
logger
return
logger
...
...
op-wheel/cheat/cheat.go
View file @
c39e6692
...
@@ -17,6 +17,7 @@ import (
...
@@ -17,6 +17,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie"
...
@@ -316,6 +317,7 @@ func StoragePatch(patch io.Reader, address common.Address) HeadFn {
...
@@ -316,6 +317,7 @@ func StoragePatch(patch io.Reader, address common.Address) HeadFn {
}
}
type
OvmOwnersConfig
struct
{
type
OvmOwnersConfig
struct
{
Network
string
`json:"network"`
Owner
common
.
Address
`json:"owner"`
Owner
common
.
Address
`json:"owner"`
Sequencer
common
.
Address
`json:"sequencer"`
Sequencer
common
.
Address
`json:"sequencer"`
Proposer
common
.
Address
`json:"proposer"`
Proposer
common
.
Address
`json:"proposer"`
...
@@ -323,17 +325,42 @@ type OvmOwnersConfig struct {
...
@@ -323,17 +325,42 @@ type OvmOwnersConfig struct {
func
OvmOwners
(
conf
*
OvmOwnersConfig
)
HeadFn
{
func
OvmOwners
(
conf
*
OvmOwnersConfig
)
HeadFn
{
return
func
(
headState
*
state
.
StateDB
)
error
{
return
func
(
headState
*
state
.
StateDB
)
error
{
var
addressManager
common
.
Address
// Lib_AddressManager
var
l1SBProxy
common
.
Address
// Proxy__OVM_L1StandardBridge
var
l1XDMProxy
common
.
Address
// Proxy__OVM_L1CrossDomainMessenger
var
l1ERC721BridgeProxy
common
.
Address
switch
conf
.
Network
{
case
"mainnet"
:
addressManager
=
common
.
HexToAddress
(
"0xdE1FCfB0851916CA5101820A69b13a4E276bd81F"
)
l1SBProxy
=
common
.
HexToAddress
(
"0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1"
)
l1XDMProxy
=
common
.
HexToAddress
(
"0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1"
)
l1ERC721BridgeProxy
=
common
.
HexToAddress
(
"0x5a7749f83b81B301cAb5f48EB8516B986DAef23D"
)
case
"goerli"
:
addressManager
=
common
.
HexToAddress
(
"0xa6f73589243a6A7a9023b1Fa0651b1d89c177111"
)
l1SBProxy
=
common
.
HexToAddress
(
"0x636Af16bf2f682dD3109e60102b8E1A089FedAa8"
)
l1XDMProxy
=
common
.
HexToAddress
(
"0x5086d1eEF304eb5284A0f6720f79403b4e9bE294"
)
l1ERC721BridgeProxy
=
common
.
HexToAddress
(
"0x8DD330DdE8D9898d43b4dc840Da27A07dF91b3c9"
)
default
:
return
fmt
.
Errorf
(
"unknown network: %q"
,
conf
.
Network
)
}
// See Proxy.sol OWNER_KEY: https://eips.ethereum.org/EIPS/eip-1967#admin-address
ownerSlot
:=
common
.
HexToHash
(
"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"
)
// Address manager owner
// Address manager owner
headState
.
SetState
(
common
.
HexToAddress
(
"0xa6f73589243a6A7a9023b1Fa0651b1d89c177111"
),
common
.
Hash
{},
conf
.
Owner
.
Hash
())
// Ownable, first storage slot
headState
.
SetState
(
addressManager
,
common
.
Hash
{},
conf
.
Owner
.
Hash
())
// L1SB proxy owner
// L1SB proxy owner
headState
.
SetState
(
common
.
HexToAddress
(
"0x636Af16bf2f682dD3109e60102b8E1A089FedAa8"
),
common
.
HexToHash
(
"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"
)
,
conf
.
Owner
.
Hash
())
headState
.
SetState
(
l1SBProxy
,
ownerSlot
,
conf
.
Owner
.
Hash
())
// L1XDM owner
// L1XDM owner
headState
.
SetState
(
common
.
HexToAddress
(
"0x5086d1eEF304eb5284A0f6720f79403b4e9bE294"
),
common
.
Hash
{
31
:
0x33
},
conf
.
Owner
.
Hash
())
// 0x33 = 51. L1CrossDomainMessenger is L1CrossDomainMessenger (0) Lib_AddressResolver (1) OwnableUpgradeable (1, but covered by gap) + ContextUpgradeable (special gap of 50) and then _owner
headState
.
SetState
(
l1XDMProxy
,
common
.
Hash
{
31
:
0x33
},
conf
.
Owner
.
Hash
())
// L1 ERC721 bridge owner
// L1 ERC721 bridge owner
headState
.
SetState
(
common
.
HexToAddress
(
"0x8DD330DdE8D9898d43b4dc840Da27A07dF91b3c9"
),
common
.
HexToHash
(
"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"
)
,
conf
.
Owner
.
Hash
())
headState
.
SetState
(
l1ERC721BridgeProxy
,
ownerSlot
,
conf
.
Owner
.
Hash
())
// Legacy sequencer/proposer addresses
// Legacy sequencer/proposer addresses
headState
.
SetState
(
common
.
HexToAddress
(
"0xa6f73589243a6A7a9023b1Fa0651b1d89c177111"
),
common
.
HexToHash
(
"0x2e0dfce60e9e27f035ce28f63c1bdd77cff6b13d8909da4d81d623ff9123fbdc"
),
conf
.
Sequencer
.
Hash
())
// See AddressManager.sol "addresses" mapping(bytes32 => address), at slot position 1
headState
.
SetState
(
common
.
HexToAddress
(
"0xa6f73589243a6A7a9023b1Fa0651b1d89c177111"
),
common
.
HexToHash
(
"0x9776dbdebd0d5eedaea450b21da9901ecd5254e5136a3a9b7b0ecd532734d5b5"
),
conf
.
Proposer
.
Hash
())
addressesSlot
:=
common
.
BigToHash
(
big
.
NewInt
(
1
))
headState
.
SetState
(
addressManager
,
crypto
.
Keccak256Hash
(
crypto
.
Keccak256
([]
byte
(
"OVM_Sequencer"
)),
addressesSlot
.
Bytes
()),
conf
.
Sequencer
.
Hash
())
headState
.
SetState
(
addressManager
,
crypto
.
Keccak256Hash
(
crypto
.
Keccak256
([]
byte
(
"OVM_Proposer"
)),
addressesSlot
.
Bytes
()),
conf
.
Proposer
.
Hash
())
// Fund sequencer and proposer with 100 ETH
// Fund sequencer and proposer with 100 ETH
headState
.
SetBalance
(
conf
.
Sequencer
,
HundredETH
)
headState
.
SetBalance
(
conf
.
Sequencer
,
HundredETH
)
headState
.
SetBalance
(
conf
.
Proposer
,
HundredETH
)
headState
.
SetBalance
(
conf
.
Proposer
,
HundredETH
)
...
...
packages/atst/docs/cli.md
View file @
c39e6692
...
@@ -14,10 +14,10 @@ npm install @eth-optimism/atst --global
...
@@ -14,10 +14,10 @@ npm install @eth-optimism/atst --global
npx atst <
command
>
[
options]
npx atst <
command
>
[
options]
```
```
## Commands
##
#
Commands
read
read an attestation
-
`read`
read an attestation
write
write an attestation
-
`write`
write an attestation
For more info, run any command with the
`--help`
flag:
For more info, run any command with the
`--help`
flag:
...
@@ -26,55 +26,46 @@ npx atst read --help
...
@@ -26,55 +26,46 @@ npx atst read --help
npx atst write
--help
npx atst write
--help
```
```
##
Options:
##
# General options
-
h, --help Display this
message
-
`-h`
,
`--help`
Display help
message
-
v, --version
Display version number
-
`-v`
,
`--version`
Display version number
## Usage:
```
bash
npx atst <
command
>
[
options]
```
Commands:
read read an attestation
write write an attestation
For more info, run any command with the
`--help`
flag:
```
bash
npx atst
read
--help
npx atst write
--help
```
### Read
### Read
`--creator <string> Address of the creator of the attestation`
-
`--creator <address>`
Address of the creator of the attestation
`--about <string> Address of the subject of the attestation`
-
`--about <address>`
Address of the subject of the attestation
`--key <string> Key of the attestation either as string or hex number`
-
`--key <string>`
Key of the attestation either as string or hex number
`--data-type [string] Zod validator for the DataType type string | bytes | number | bool | address (default: string)`
-
`[--data-type <string>]`
The DataType type
`string`
|
`bytes`
|
`number`
|
`bool`
|
`address`
(default:
`string`
)
`--rpc-url [url] Rpc url to use (default: https://mainnet.optimism.io)`
-
`[--rpc-url <url>]`
Rpc url to use (default:
`https://mainnet.optimism.io`
)
`--contract [address] Contract address to read from (default: 0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77)`
-
`[--contract <address>]`
Contract address to read from (default:
`0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77`
)
`-h, --help Display this message`
-
`-h`
,
`--help`
Display help message
Example:
Example:
```
bash
```
bash
npx atst
read
--key
"optimist.base-uri"
--about
0x2335022c740d17c2837f9C884Bfe4fFdbf0A95D5
--creator
0x60c5C9c98bcBd0b0F2fD89B24c16e533BaA8CdA3
npx atst
read
--key
"optimist.base-uri"
--about
0x2335022c740d17c2837f9C884Bfe4fFdbf0A95D5
\
--creator
0x60c5C9c98bcBd0b0F2fD89B24c16e533BaA8CdA3
```
```
### write
### Write
-
`--private-key <string>`
Private key of the creator of the attestation
-
`[--data-type <string>]`
The DataType type
`string`
|
`bytes`
|
`number`
|
`bool`
|
`address`
(default:
`string`
)
-
`--about <address>`
Address of the subject of the attestation
-
`--key <address>`
Key of the attestation either as string or hex number
-
`--value <string>`
undefined
-
`[--rpc-url <url>]`
Rpc url to use (default:
`https://mainnet.optimism.io`
)
-
`[--contract <address>]`
Contract address to read from (default: 0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77)
-
`-h`
,
`--help`
Display this message
`--private-key <string> Address of the creator of the attestation`
Example:
`--data-type [string] Zod validator for the DataType type string | bytes | number | bool | address (default: string)`
`--about <string> Address of the subject of the attestation`
`--key <string> Key of the attestation either as string or hex number`
`--value <string> undefined`
`--rpc-url [url] Rpc url to use (default: https://mainnet.optimism.io)`
`--contract [address] Contract address to read from (default: 0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77) -h, --help Display this message`
```
bash
```
bash
atst write
--key
"optimist.base-uri"
--about
0x2335022c740d17c2837f9C884Bfe4fFdbf0A95D5
--value
"my attestation"
--private-key
0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
--rpc-url
http://localhost:8545
atst write
--key
"optimist.base-uri"
\
atst/0.0.0
--about
0x2335022c740d17c2837f9C884Bfe4fFdbf0A95D5
\
--value
"my attestation"
\
--private-key
0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
\
--rpc-url
http://localhost:8545
```
```
packages/atst/docs/sdk.md
View file @
c39e6692
This diff is collapsed.
Click to expand it.
packages/atst/src/lib/createValue.spec.ts
deleted
100644 → 0
View file @
2169ddcf
packages/atst/src/lib/getEvents.spec.ts
View file @
c39e6692
...
@@ -76,6 +76,35 @@ describe(getEvents.name, () => {
...
@@ -76,6 +76,35 @@ describe(getEvents.name, () => {
"transactionHash": "0x61f59bd4dfe54272d9369effe3ae57a0ef2584161fcf2bbd55f5596002e759bd",
"transactionHash": "0x61f59bd4dfe54272d9369effe3ae57a0ef2584161fcf2bbd55f5596002e759bd",
"transactionIndex": 1,
"transactionIndex": 1,
},
},
{
"address": "0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77",
"args": [
"0xBCf86Fd70a0183433763ab0c14E7a760194f3a9F",
"0x00000000000000000000000000000000000060A7",
"0x616e696d616c6661726d2e7363686f6f6c2e617474656e646564000000000000",
"0x01",
],
"blockHash": "0x4870baaac6d7195952dc25e5dc0109ea324f819f8152d2889c7b4ad64040a9bf",
"blockNumber": 6278428,
"data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000",
"decode": [Function],
"event": "AttestationCreated",
"eventSignature": "AttestationCreated(address,address,bytes32,bytes)",
"getBlock": [Function],
"getTransaction": [Function],
"getTransactionReceipt": [Function],
"logIndex": 0,
"removeListener": [Function],
"removed": false,
"topics": [
"0x28710dfecab43d1e29e02aa56b2e1e610c0bae19135c9cf7a83a1adb6df96d85",
"0x000000000000000000000000bcf86fd70a0183433763ab0c14e7a760194f3a9f",
"0x00000000000000000000000000000000000000000000000000000000000060a7",
"0x616e696d616c6661726d2e7363686f6f6c2e617474656e646564000000000000",
],
"transactionHash": "0x4e836b74c51a370375efa374297524d9b0f6eacdd699c30556680ae7dc9a14ea",
"transactionIndex": 1,
},
]
]
`
)
`
)
})
})
...
...
packages/atst/src/lib/prepareWriteAttestation.spec.ts
View file @
c39e6692
...
@@ -43,7 +43,7 @@ describe(prepareWriteAttestation.name, () => {
...
@@ -43,7 +43,7 @@ describe(prepareWriteAttestation.name, () => {
expect
(
result
.
address
).
toMatchInlineSnapshot
(
expect
(
result
.
address
).
toMatchInlineSnapshot
(
'
"0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77"
'
'
"0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77"
'
)
)
expect
(
result
.
chainId
).
toMatchInlineSnapshot
(
'
10
'
)
expect
(
result
.
chainId
).
toMatchInlineSnapshot
(
'
undefined
'
)
expect
(
result
.
functionName
).
toMatchInlineSnapshot
(
'
"attest"
'
)
expect
(
result
.
functionName
).
toMatchInlineSnapshot
(
'
"attest"
'
)
expect
(
result
.
mode
).
toMatchInlineSnapshot
(
'
"prepared"
'
)
expect
(
result
.
mode
).
toMatchInlineSnapshot
(
'
"prepared"
'
)
expect
(
result
.
request
.
gasLimit
).
toMatchInlineSnapshot
(
`
expect
(
result
.
request
.
gasLimit
).
toMatchInlineSnapshot
(
`
...
@@ -54,18 +54,16 @@ describe(prepareWriteAttestation.name, () => {
...
@@ -54,18 +54,16 @@ describe(prepareWriteAttestation.name, () => {
`
)
`
)
})
})
it
(
'
should
throw an error if key is
longer than 32 bytes
'
,
async
()
=>
{
it
(
'
should
work for key
longer than 32 bytes
'
,
async
()
=>
{
const
dataType
=
'
string
'
const
dataType
=
'
string
'
await
expect
(
expect
(
readAttestation
(
await
readAttestation
(
creator
,
creator
,
about
,
about
,
'
this is a key that is way longer than 32 bytes so this key should throw an error matching the inline snapshot
'
,
'
this is a key that is way longer than 32 bytes so this key should throw an error matching the inline snapshot
'
,
dataType
dataType
)
)
).
rejects
.
toThrowErrorMatchingInlineSnapshot
(
).
toMatchInlineSnapshot
(
'
""
'
)
'
"Key is longer than the max length of 32 for attestation keys"
'
)
})
})
})
})
packages/atst/src/lib/prepareWriteAttestation.ts
View file @
c39e6692
import
{
Address
,
prepareWriteContract
}
from
'
@wagmi/core
'
import
{
Address
,
prepareWriteContract
}
from
'
@wagmi/core
'
import
{
formatBytes32String
}
from
'
ethers/lib/utils.js
'
import
{
ATTESTATION_STATION_ADDRESS
}
from
'
../constants/attestationStationAddress
'
import
{
ATTESTATION_STATION_ADDRESS
}
from
'
../constants/attestationStationAddress
'
import
{
WagmiBytes
}
from
'
../types/WagmiBytes
'
import
{
WagmiBytes
}
from
'
../types/WagmiBytes
'
import
{
abi
}
from
'
./abi
'
import
{
abi
}
from
'
./abi
'
import
{
createKey
}
from
'
./createKey
'
import
{
createValue
}
from
'
./createValue
'
import
{
createValue
}
from
'
./createValue
'
export
const
prepareWriteAttestation
=
async
(
export
const
prepareWriteAttestation
=
async
(
...
@@ -13,15 +13,7 @@ export const prepareWriteAttestation = async (
...
@@ -13,15 +13,7 @@ export const prepareWriteAttestation = async (
chainId
:
number
|
undefined
=
undefined
,
chainId
:
number
|
undefined
=
undefined
,
contractAddress
:
Address
=
ATTESTATION_STATION_ADDRESS
contractAddress
:
Address
=
ATTESTATION_STATION_ADDRESS
)
=>
{
)
=>
{
let
formattedKey
:
WagmiBytes
const
formattedKey
=
createKey
(
key
)
as
WagmiBytes
try
{
formattedKey
=
formatBytes32String
(
key
)
as
WagmiBytes
}
catch
(
e
)
{
console
.
error
(
e
)
throw
new
Error
(
`key is longer than 32 bytes:
${
key
}
. Try using a shorter key or using 'encodeRawKey' to encode the key into 32 bytes first`
)
}
return
prepareWriteContract
({
return
prepareWriteContract
({
address
:
contractAddress
,
address
:
contractAddress
,
abi
,
abi
,
...
...
packages/atst/src/lib/prepareWriteAttestations.spec.ts
View file @
c39e6692
...
@@ -49,7 +49,7 @@ describe(prepareWriteAttestations.name, () => {
...
@@ -49,7 +49,7 @@ describe(prepareWriteAttestations.name, () => {
expect
(
result
.
address
).
toMatchInlineSnapshot
(
expect
(
result
.
address
).
toMatchInlineSnapshot
(
'
"0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77"
'
'
"0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77"
'
)
)
expect
(
result
.
chainId
).
toMatchInlineSnapshot
(
'
10
'
)
expect
(
result
.
chainId
).
toMatchInlineSnapshot
(
'
undefined
'
)
expect
(
result
.
functionName
).
toMatchInlineSnapshot
(
'
"attest"
'
)
expect
(
result
.
functionName
).
toMatchInlineSnapshot
(
'
"attest"
'
)
expect
(
result
.
mode
).
toMatchInlineSnapshot
(
'
"prepared"
'
)
expect
(
result
.
mode
).
toMatchInlineSnapshot
(
'
"prepared"
'
)
expect
(
result
.
request
.
gasLimit
).
toMatchInlineSnapshot
(
`
expect
(
result
.
request
.
gasLimit
).
toMatchInlineSnapshot
(
`
...
@@ -60,18 +60,16 @@ describe(prepareWriteAttestations.name, () => {
...
@@ -60,18 +60,16 @@ describe(prepareWriteAttestations.name, () => {
`
)
`
)
})
})
it
(
'
should
throw an error
if key is longer than 32 bytes
'
,
async
()
=>
{
it
(
'
should
work
if key is longer than 32 bytes
'
,
async
()
=>
{
const
dataType
=
'
string
'
const
dataType
=
'
string
'
await
expect
(
expect
(
readAttestation
(
await
readAttestation
(
creator
,
creator
,
about
,
about
,
'
this is a key that is way longer than 32 bytes so this key should throw an error matching the inline snapshot
'
,
'
this is a key that is way longer than 32 bytes so this key should throw an error matching the inline snapshot
'
,
dataType
dataType
)
)
).
rejects
.
toThrowErrorMatchingInlineSnapshot
(
).
toMatchInlineSnapshot
(
'
""
'
)
'
"Key is longer than the max length of 32 for attestation keys"
'
)
})
})
})
})
packages/atst/src/lib/readAttestation.spec.ts
View file @
c39e6692
...
@@ -26,16 +26,14 @@ describe(readAttestation.name, () => {
...
@@ -26,16 +26,14 @@ describe(readAttestation.name, () => {
)
)
})
})
it
(
'
should
throw an error
if key is longer than 32 bytes
'
,
async
()
=>
{
it
(
'
should
work
if key is longer than 32 bytes
'
,
async
()
=>
{
await
expect
(
expect
(
readAttestation
(
await
readAttestation
(
creator
,
creator
,
about
,
about
,
'
this is a key that is way longer than 32 bytes so this key should throw an error matching the inline snapshot
'
,
'
this is a key that is way longer than 32 bytes so this key should throw an error matching the inline snapshot
'
,
dataType
dataType
)
)
).
rejects
.
toThrowErrorMatchingInlineSnapshot
(
).
toMatchInlineSnapshot
(
'
""
'
)
'
"Key is longer than the max length of 32 for attestation keys"
'
)
})
})
})
})
packages/atst/src/lib/readAttestations.ts
View file @
c39e6692
import
{
readContracts
}
from
'
@wagmi/core
'
import
{
readContracts
}
from
'
@wagmi/core
'
import
{
formatBytes32String
}
from
'
ethers/lib/utils.js
'
import
{
ATTESTATION_STATION_ADDRESS
}
from
'
../constants/attestationStationAddress
'
import
{
ATTESTATION_STATION_ADDRESS
}
from
'
../constants/attestationStationAddress
'
import
type
{
AttestationReadParams
}
from
'
../types/AttestationReadParams
'
import
type
{
AttestationReadParams
}
from
'
../types/AttestationReadParams
'
import
{
DEFAULT_DATA_TYPE
}
from
'
../types/DataTypeOption
'
import
{
DEFAULT_DATA_TYPE
}
from
'
../types/DataTypeOption
'
import
type
{
WagmiBytes
}
from
'
../types/WagmiBytes
'
import
type
{
WagmiBytes
}
from
'
../types/WagmiBytes
'
import
{
abi
}
from
'
./abi
'
import
{
abi
}
from
'
./abi
'
import
{
createKey
}
from
'
./createKey
'
import
{
parseAttestationBytes
}
from
'
./parseAttestationBytes
'
import
{
parseAttestationBytes
}
from
'
./parseAttestationBytes
'
/**
/**
...
@@ -39,16 +39,11 @@ export const readAttestations = async (
...
@@ -39,16 +39,11 @@ export const readAttestations = async (
key
,
key
,
contractAddress
=
ATTESTATION_STATION_ADDRESS
,
contractAddress
=
ATTESTATION_STATION_ADDRESS
,
}
=
attestation
}
=
attestation
if
(
key
.
length
>
32
)
{
throw
new
Error
(
'
Key is longer than the max length of 32 for attestation keys
'
)
}
return
{
return
{
address
:
contractAddress
,
address
:
contractAddress
,
abi
,
abi
,
functionName
:
'
attestations
'
,
functionName
:
'
attestations
'
,
args
:
[
creator
,
about
,
formatBytes32String
(
key
)
as
WagmiBytes
],
args
:
[
creator
,
about
,
createKey
(
key
)
as
WagmiBytes
],
}
as
const
}
as
const
})
})
...
...
packages/contracts-bedrock/.gas-snapshot
View file @
c39e6692
...
@@ -174,16 +174,18 @@ L2OutputOracleUpgradeable_Test:test_initValuesOnProxy_succeeds() (gas: 26208)
...
@@ -174,16 +174,18 @@ L2OutputOracleUpgradeable_Test:test_initValuesOnProxy_succeeds() (gas: 26208)
L2OutputOracleUpgradeable_Test:test_initializeImpl_alreadyInitialized_reverts() (gas: 15149)
L2OutputOracleUpgradeable_Test:test_initializeImpl_alreadyInitialized_reverts() (gas: 15149)
L2OutputOracleUpgradeable_Test:test_initializeProxy_alreadyInitialized_reverts() (gas: 20175)
L2OutputOracleUpgradeable_Test:test_initializeProxy_alreadyInitialized_reverts() (gas: 20175)
L2OutputOracleUpgradeable_Test:test_upgrading_succeeds() (gas: 180481)
L2OutputOracleUpgradeable_Test:test_upgrading_succeeds() (gas: 180481)
L2StandardBridge_BridgeERC20To_Test:test_bridgeERC20To_succeeds() (gas: 387833)
L2StandardBridge_BridgeERC20To_Test:test_bridgeERC20To_succeeds() (gas: 389773)
L2StandardBridge_BridgeERC20To_Test:test_withdrawTo_withdrawingERC20_succeeds() (gas: 388064)
L2StandardBridge_BridgeERC20To_Test:test_withdrawTo_withdrawingERC20_succeeds() (gas: 390006)
L2StandardBridge_BridgeERC20_Test:test_bridgeERC20_succeeds() (gas: 383536)
L2StandardBridge_BridgeERC20_Test:test_bridgeERC20_succeeds() (gas: 385280)
L2StandardBridge_BridgeERC20_Test:test_bridgeLegacyERC20_succeeds() (gas: 393552)
L2StandardBridge_BridgeERC20_Test:test_withdrawLegacyERC20_succeeds() (gas: 393878)
L2StandardBridge_BridgeERC20_Test:test_withdraw_notEOA_reverts() (gas: 251758)
L2StandardBridge_BridgeERC20_Test:test_withdraw_notEOA_reverts() (gas: 251758)
L2StandardBridge_BridgeERC20_Test:test_withdraw_withdrawingERC20_succeeds() (gas: 38
3722
)
L2StandardBridge_BridgeERC20_Test:test_withdraw_withdrawingERC20_succeeds() (gas: 38
5508
)
L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 23843)
L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 23843)
L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 23982)
L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 23982)
L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToSelf_reverts() (gas: 23870)
L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToSelf_reverts() (gas: 23870)
L2StandardBridge_Bridge_Test:test_finalizeDeposit_depositingERC20_succeeds() (gas: 9
1013
)
L2StandardBridge_Bridge_Test:test_finalizeDeposit_depositingERC20_succeeds() (gas: 9
3824
)
L2StandardBridge_Bridge_Test:test_finalizeDeposit_depositingETH_succeeds() (gas:
89889
)
L2StandardBridge_Bridge_Test:test_finalizeDeposit_depositingETH_succeeds() (gas:
92700
)
L2StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 43155)
L2StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 43155)
L2StandardBridge_Test:test_initialize_succeeds() (gas: 24292)
L2StandardBridge_Test:test_initialize_succeeds() (gas: 24292)
L2StandardBridge_Test:test_receive_succeeds() (gas: 174011)
L2StandardBridge_Test:test_receive_succeeds() (gas: 174011)
...
@@ -412,6 +414,8 @@ SequencerFeeVault_Test:test_minWithdrawalAmount_succeeds() (gas: 5442)
...
@@ -412,6 +414,8 @@ SequencerFeeVault_Test:test_minWithdrawalAmount_succeeds() (gas: 5442)
SequencerFeeVault_Test:test_receive_succeeds() (gas: 17373)
SequencerFeeVault_Test:test_receive_succeeds() (gas: 17373)
SequencerFeeVault_Test:test_withdraw_notEnough_reverts() (gas: 9331)
SequencerFeeVault_Test:test_withdraw_notEnough_reverts() (gas: 9331)
SequencerFeeVault_Test:test_withdraw_succeeds() (gas: 163228)
SequencerFeeVault_Test:test_withdraw_succeeds() (gas: 163228)
StandardBridge_Stateless_Test:test_isCorrectTokenPair_succeeds() (gas: 49936)
StandardBridge_Stateless_Test:test_isOptimismMintableERC20_succeeds() (gas: 33072)
SystemConfig_Initialize_TestFail:test_initialize_lowGasLimit_reverts() (gas: 62012)
SystemConfig_Initialize_TestFail:test_initialize_lowGasLimit_reverts() (gas: 62012)
SystemConfig_Setters_TestFail:test_setBatcherHash_notOwner_reverts() (gas: 10612)
SystemConfig_Setters_TestFail:test_setBatcherHash_notOwner_reverts() (gas: 10612)
SystemConfig_Setters_TestFail:test_setGasConfig_notOwner_reverts() (gas: 10555)
SystemConfig_Setters_TestFail:test_setGasConfig_notOwner_reverts() (gas: 10555)
...
...
packages/contracts-bedrock/contracts/legacy/LegacyMintableERC20.sol
0 → 100644
View file @
c39e6692
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { ILegacyMintableERC20 } from "../universal/OptimismMintableERC20.sol";
/**
* @title LegacyMintableERC20
* @notice The legacy implementation of the OptimismMintableERC20. This
* contract is deprecated and should no longer be used.
*/
contract LegacyMintableERC20 is ILegacyMintableERC20, ERC20 {
/**
* @notice Emitted when the token is minted by the bridge.
*/
event Mint(address indexed _account, uint256 _amount);
/**
* @notice Emitted when a token is burned by the bridge.
*/
event Burn(address indexed _account, uint256 _amount);
/**
* @notice The token on the remote domain.
*/
address public l1Token;
/**
* @notice The local bridge.
*/
address public l2Bridge;
/**
* @param _l2Bridge Address of the L2 standard bridge.
* @param _l1Token Address of the corresponding L1 token.
* @param _name ERC20 name.
* @param _symbol ERC20 symbol.
*/
constructor(
address _l2Bridge,
address _l1Token,
string memory _name,
string memory _symbol
) ERC20(_name, _symbol) {
l1Token = _l1Token;
l2Bridge = _l2Bridge;
}
/**
* @notice Modifier that requires the contract was called by the bridge.
*/
modifier onlyL2Bridge() {
require(msg.sender == l2Bridge, "Only L2 Bridge can mint and burn");
_;
}
/**
* @notice EIP165 implementation.
*/
function supportsInterface(bytes4 _interfaceId) public pure returns (bool) {
bytes4 firstSupportedInterface = bytes4(keccak256("supportsInterface(bytes4)")); // ERC165
bytes4 secondSupportedInterface = ILegacyMintableERC20.l1Token.selector ^
ILegacyMintableERC20.mint.selector ^
ILegacyMintableERC20.burn.selector;
return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface;
}
/**
* @notice Only the bridge can mint tokens.
* @param _to The account receiving tokens.
* @param _amount The amount of tokens to receive.
*/
function mint(address _to, uint256 _amount) public virtual onlyL2Bridge {
_mint(_to, _amount);
emit Mint(_to, _amount);
}
/**
* @notice Only the bridge can burn tokens.
* @param _from The account having tokens burnt.
* @param _amount The amount of tokens being burnt.
*/
function burn(address _from, uint256 _amount) public virtual onlyL2Bridge {
_burn(_from, _amount);
emit Burn(_from, _amount);
}
}
packages/contracts-bedrock/contracts/test/CommonTest.t.sol
View file @
c39e6692
...
@@ -27,6 +27,7 @@ import { AddressManager } from "../legacy/AddressManager.sol";
...
@@ -27,6 +27,7 @@ import { AddressManager } from "../legacy/AddressManager.sol";
import { L1ChugSplashProxy } from "../legacy/L1ChugSplashProxy.sol";
import { L1ChugSplashProxy } from "../legacy/L1ChugSplashProxy.sol";
import { IL1ChugSplashDeployer } from "../legacy/L1ChugSplashProxy.sol";
import { IL1ChugSplashDeployer } from "../legacy/L1ChugSplashProxy.sol";
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
import { LegacyMintableERC20 } from "../legacy/LegacyMintableERC20.sol";
contract CommonTest is Test {
contract CommonTest is Test {
address alice = address(128);
address alice = address(128);
...
@@ -276,6 +277,7 @@ contract Bridge_Initializer is Messenger_Initializer {
...
@@ -276,6 +277,7 @@ contract Bridge_Initializer is Messenger_Initializer {
ERC20 L1Token;
ERC20 L1Token;
ERC20 BadL1Token;
ERC20 BadL1Token;
OptimismMintableERC20 L2Token;
OptimismMintableERC20 L2Token;
LegacyMintableERC20 LegacyL2Token;
ERC20 NativeL2Token;
ERC20 NativeL2Token;
ERC20 BadL2Token;
ERC20 BadL2Token;
OptimismMintableERC20 RemoteL1Token;
OptimismMintableERC20 RemoteL1Token;
...
@@ -398,6 +400,14 @@ contract Bridge_Initializer is Messenger_Initializer {
...
@@ -398,6 +400,14 @@ contract Bridge_Initializer is Messenger_Initializer {
L1Token = new ERC20("Native L1 Token", "L1T");
L1Token = new ERC20("Native L1 Token", "L1T");
LegacyL2Token = new LegacyMintableERC20({
_l2Bridge: address(L2Bridge),
_l1Token: address(L1Token),
_name: string.concat("LegacyL2-", L1Token.name()),
_symbol: string.concat("LegacyL2-", L1Token.symbol())
});
vm.label(address(LegacyL2Token), "LegacyMintableERC20");
// Deploy the L2 ERC20 now
// Deploy the L2 ERC20 now
L2Token = OptimismMintableERC20(
L2Token = OptimismMintableERC20(
L2TokenFactory.createStandardL2Token(
L2TokenFactory.createStandardL2Token(
...
...
packages/contracts-bedrock/contracts/test/L2StandardBridge.t.sol
View file @
c39e6692
...
@@ -155,15 +155,15 @@ contract L2StandardBridge_Test is Bridge_Initializer {
...
@@ -155,15 +155,15 @@ contract L2StandardBridge_Test is Bridge_Initializer {
contract PreBridgeERC20 is Bridge_Initializer {
contract PreBridgeERC20 is Bridge_Initializer {
// withdraw and BridgeERC20 should behave the same when transferring ERC20 tokens
// withdraw and BridgeERC20 should behave the same when transferring ERC20 tokens
// so they should share the same setup and expectEmit calls
// so they should share the same setup and expectEmit calls
function _preBridgeERC20(bool
isLegacy
) internal {
function _preBridgeERC20(bool
_isLegacy, address _l2Token
) internal {
// Alice has 100 L2Token
// Alice has 100 L2Token
deal(
address(L2Token)
, alice, 100, true);
deal(
_l2Token
, alice, 100, true);
assertEq(
L2Token
.balanceOf(alice), 100);
assertEq(
ERC20(_l2Token)
.balanceOf(alice), 100);
uint256 nonce = L2Messenger.messageNonce();
uint256 nonce = L2Messenger.messageNonce();
bytes memory message = abi.encodeWithSelector(
bytes memory message = abi.encodeWithSelector(
StandardBridge.finalizeBridgeERC20.selector,
StandardBridge.finalizeBridgeERC20.selector,
address(L1Token),
address(L1Token),
address(L2Token)
,
_l2Token
,
alice,
alice,
alice,
alice,
100,
100,
...
@@ -190,23 +190,17 @@ contract PreBridgeERC20 is Bridge_Initializer {
...
@@ -190,23 +190,17 @@ contract PreBridgeERC20 is Bridge_Initializer {
})
})
);
);
if (isLegacy) {
if (
_
isLegacy) {
vm.expectCall(
vm.expectCall(
address(L2Bridge),
address(L2Bridge),
abi.encodeWithSelector(
abi.encodeWithSelector(L2Bridge.withdraw.selector, _l2Token, 100, 1000, hex"")
L2Bridge.withdraw.selector,
address(L2Token),
100,
1000,
hex""
)
);
);
} else {
} else {
vm.expectCall(
vm.expectCall(
address(L2Bridge),
address(L2Bridge),
abi.encodeWithSelector(
abi.encodeWithSelector(
L2Bridge.bridgeERC20.selector,
L2Bridge.bridgeERC20.selector,
address(L2Token)
,
_l2Token
,
address(L1Token),
address(L1Token),
100,
100,
1000,
1000,
...
@@ -237,15 +231,15 @@ contract PreBridgeERC20 is Bridge_Initializer {
...
@@ -237,15 +231,15 @@ contract PreBridgeERC20 is Bridge_Initializer {
// The L2Bridge should burn the tokens
// The L2Bridge should burn the tokens
vm.expectCall(
vm.expectCall(
address(L2Token)
,
_l2Token
,
abi.encodeWithSelector(OptimismMintableERC20.burn.selector, alice, 100)
abi.encodeWithSelector(OptimismMintableERC20.burn.selector, alice, 100)
);
);
vm.expectEmit(true, true, true, true);
vm.expectEmit(true, true, true, true);
emit WithdrawalInitiated(address(L1Token),
address(L2Token)
, alice, alice, 100, hex"");
emit WithdrawalInitiated(address(L1Token),
_l2Token
, alice, alice, 100, hex"");
vm.expectEmit(true, true, true, true);
vm.expectEmit(true, true, true, true);
emit ERC20BridgeInitiated(
address(L2Token)
, address(L1Token), alice, alice, 100, hex"");
emit ERC20BridgeInitiated(
_l2Token
, address(L1Token), alice, alice, 100, hex"");
vm.expectEmit(true, true, true, true);
vm.expectEmit(true, true, true, true);
emit MessagePassed(
emit MessagePassed(
...
@@ -276,7 +270,7 @@ contract L2StandardBridge_BridgeERC20_Test is PreBridgeERC20 {
...
@@ -276,7 +270,7 @@ contract L2StandardBridge_BridgeERC20_Test is PreBridgeERC20 {
// - emits WithdrawalInitiated
// - emits WithdrawalInitiated
// - calls Withdrawer.initiateWithdrawal
// - calls Withdrawer.initiateWithdrawal
function test_withdraw_withdrawingERC20_succeeds() external {
function test_withdraw_withdrawingERC20_succeeds() external {
_preBridgeERC20({
isLegacy: true
});
_preBridgeERC20({
_isLegacy: true, _l2Token: address(L2Token)
});
L2Bridge.withdraw(address(L2Token), 100, 1000, hex"");
L2Bridge.withdraw(address(L2Token), 100, 1000, hex"");
assertEq(L2Token.balanceOf(alice), 0);
assertEq(L2Token.balanceOf(alice), 0);
...
@@ -287,12 +281,26 @@ contract L2StandardBridge_BridgeERC20_Test is PreBridgeERC20 {
...
@@ -287,12 +281,26 @@ contract L2StandardBridge_BridgeERC20_Test is PreBridgeERC20 {
// - emits WithdrawalInitiated
// - emits WithdrawalInitiated
// - calls Withdrawer.initiateWithdrawal
// - calls Withdrawer.initiateWithdrawal
function test_bridgeERC20_succeeds() external {
function test_bridgeERC20_succeeds() external {
_preBridgeERC20({
isLegacy: false
});
_preBridgeERC20({
_isLegacy: false, _l2Token: address(L2Token)
});
L2Bridge.bridgeERC20(address(L2Token), address(L1Token), 100, 1000, hex"");
L2Bridge.bridgeERC20(address(L2Token), address(L1Token), 100, 1000, hex"");
assertEq(L2Token.balanceOf(alice), 0);
assertEq(L2Token.balanceOf(alice), 0);
}
}
function test_withdrawLegacyERC20_succeeds() external {
_preBridgeERC20({ _isLegacy: true, _l2Token: address(LegacyL2Token) });
L2Bridge.withdraw(address(LegacyL2Token), 100, 1000, hex"");
assertEq(L2Token.balanceOf(alice), 0);
}
function test_bridgeLegacyERC20_succeeds() external {
_preBridgeERC20({ _isLegacy: false, _l2Token: address(LegacyL2Token) });
L2Bridge.bridgeERC20(address(LegacyL2Token), address(L1Token), 100, 1000, hex"");
assertEq(L2Token.balanceOf(alice), 0);
}
function test_withdraw_notEOA_reverts() external {
function test_withdraw_notEOA_reverts() external {
// This contract has 100 L2Token
// This contract has 100 L2Token
deal(address(L2Token), address(this), 100, true);
deal(address(L2Token), address(this), 100, true);
...
@@ -305,14 +313,14 @@ contract L2StandardBridge_BridgeERC20_Test is PreBridgeERC20 {
...
@@ -305,14 +313,14 @@ contract L2StandardBridge_BridgeERC20_Test is PreBridgeERC20 {
contract PreBridgeERC20To is Bridge_Initializer {
contract PreBridgeERC20To is Bridge_Initializer {
// withdrawTo and BridgeERC20To should behave the same when transferring ERC20 tokens
// withdrawTo and BridgeERC20To should behave the same when transferring ERC20 tokens
// so they should share the same setup and expectEmit calls
// so they should share the same setup and expectEmit calls
function _preBridgeERC20To(bool
isLegacy
) internal {
function _preBridgeERC20To(bool
_isLegacy, address _l2Token
) internal {
deal(
address(L2Token)
, alice, 100, true);
deal(
_l2Token
, alice, 100, true);
assertEq(
L2Token
.balanceOf(alice), 100);
assertEq(
ERC20(L2Token)
.balanceOf(alice), 100);
uint256 nonce = L2Messenger.messageNonce();
uint256 nonce = L2Messenger.messageNonce();
bytes memory message = abi.encodeWithSelector(
bytes memory message = abi.encodeWithSelector(
StandardBridge.finalizeBridgeERC20.selector,
StandardBridge.finalizeBridgeERC20.selector,
address(L1Token),
address(L1Token),
address(L2Token)
,
_l2Token
,
alice,
alice,
bob,
bob,
100,
100,
...
@@ -340,10 +348,10 @@ contract PreBridgeERC20To is Bridge_Initializer {
...
@@ -340,10 +348,10 @@ contract PreBridgeERC20To is Bridge_Initializer {
);
);
vm.expectEmit(true, true, true, true, address(L2Bridge));
vm.expectEmit(true, true, true, true, address(L2Bridge));
emit WithdrawalInitiated(address(L1Token),
address(L2Token)
, alice, bob, 100, hex"");
emit WithdrawalInitiated(address(L1Token),
_l2Token
, alice, bob, 100, hex"");
vm.expectEmit(true, true, true, true, address(L2Bridge));
vm.expectEmit(true, true, true, true, address(L2Bridge));
emit ERC20BridgeInitiated(
address(L2Token)
, address(L1Token), alice, bob, 100, hex"");
emit ERC20BridgeInitiated(
_l2Token
, address(L1Token), alice, bob, 100, hex"");
vm.expectEmit(true, true, true, true, address(messagePasser));
vm.expectEmit(true, true, true, true, address(messagePasser));
emit MessagePassed(
emit MessagePassed(
...
@@ -364,12 +372,12 @@ contract PreBridgeERC20To is Bridge_Initializer {
...
@@ -364,12 +372,12 @@ contract PreBridgeERC20To is Bridge_Initializer {
vm.expectEmit(true, true, true, true, address(L2Messenger));
vm.expectEmit(true, true, true, true, address(L2Messenger));
emit SentMessageExtension1(address(L2Bridge), 0);
emit SentMessageExtension1(address(L2Bridge), 0);
if (isLegacy) {
if (
_
isLegacy) {
vm.expectCall(
vm.expectCall(
address(L2Bridge),
address(L2Bridge),
abi.encodeWithSelector(
abi.encodeWithSelector(
L2Bridge.withdrawTo.selector,
L2Bridge.withdrawTo.selector,
address(L2Token)
,
_l2Token
,
bob,
bob,
100,
100,
1000,
1000,
...
@@ -381,7 +389,7 @@ contract PreBridgeERC20To is Bridge_Initializer {
...
@@ -381,7 +389,7 @@ contract PreBridgeERC20To is Bridge_Initializer {
address(L2Bridge),
address(L2Bridge),
abi.encodeWithSelector(
abi.encodeWithSelector(
L2Bridge.bridgeERC20To.selector,
L2Bridge.bridgeERC20To.selector,
address(L2Token)
,
_l2Token
,
address(L1Token),
address(L1Token),
bob,
bob,
100,
100,
...
@@ -427,7 +435,7 @@ contract L2StandardBridge_BridgeERC20To_Test is PreBridgeERC20To {
...
@@ -427,7 +435,7 @@ contract L2StandardBridge_BridgeERC20To_Test is PreBridgeERC20To {
// - emits WithdrawalInitiated w/ correct recipient
// - emits WithdrawalInitiated w/ correct recipient
// - calls Withdrawer.initiateWithdrawal
// - calls Withdrawer.initiateWithdrawal
function test_withdrawTo_withdrawingERC20_succeeds() external {
function test_withdrawTo_withdrawingERC20_succeeds() external {
_preBridgeERC20To({
isLegacy: true
});
_preBridgeERC20To({
_isLegacy: true, _l2Token: address(L2Token)
});
L2Bridge.withdrawTo(address(L2Token), bob, 100, 1000, hex"");
L2Bridge.withdrawTo(address(L2Token), bob, 100, 1000, hex"");
assertEq(L2Token.balanceOf(alice), 0);
assertEq(L2Token.balanceOf(alice), 0);
...
@@ -438,7 +446,7 @@ contract L2StandardBridge_BridgeERC20To_Test is PreBridgeERC20To {
...
@@ -438,7 +446,7 @@ contract L2StandardBridge_BridgeERC20To_Test is PreBridgeERC20To {
// - emits WithdrawalInitiated w/ correct recipient
// - emits WithdrawalInitiated w/ correct recipient
// - calls Withdrawer.initiateWithdrawal
// - calls Withdrawer.initiateWithdrawal
function test_bridgeERC20To_succeeds() external {
function test_bridgeERC20To_succeeds() external {
_preBridgeERC20To({
isLegacy: false
});
_preBridgeERC20To({
_isLegacy: false, _l2Token: address(L2Token)
});
L2Bridge.bridgeERC20To(address(L2Token), address(L1Token), bob, 100, 1000, hex"");
L2Bridge.bridgeERC20To(address(L2Token), address(L1Token), bob, 100, 1000, hex"");
assertEq(L2Token.balanceOf(alice), 0);
assertEq(L2Token.balanceOf(alice), 0);
}
}
...
...
packages/contracts-bedrock/contracts/test/StandardBridge.t.sol
0 → 100644
View file @
c39e6692
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { StandardBridge } from "../universal/StandardBridge.sol";
import { CommonTest } from "./CommonTest.t.sol";
import {
OptimismMintableERC20,
ILegacyMintableERC20
} from "../universal/OptimismMintableERC20.sol";
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
/**
* @title StandardBridgeTester
* @notice Simple wrapper around the StandardBridge contract that exposes
* internal functions so they can be more easily tested directly.
*/
contract StandardBridgeTester is StandardBridge {
constructor(address payable _messenger, address payable _otherBridge)
StandardBridge(_messenger, _otherBridge)
{}
function isOptimismMintableERC20(address _token) external view returns (bool) {
return _isOptimismMintableERC20(_token);
}
function isCorrectTokenPair(address _mintableToken, address _otherToken)
external
view
returns (bool)
{
return _isCorrectTokenPair(_mintableToken, _otherToken);
}
receive() external payable override {}
}
/**
* @title LegacyMintable
* @notice Simple implementation of the legacy OptimismMintableERC20.
*/
contract LegacyMintable is ERC20, ILegacyMintableERC20 {
constructor(string memory _name, string memory _ticker) ERC20(_name, _ticker) {}
function l1Token() external view returns (address) {
return address(0);
}
function mint(address _to, uint256 _amount) external pure {}
function burn(address _from, uint256 _amount) external pure {}
/**
* @notice Implements ERC165. This implementation should not be changed as
* it is how the actual legacy optimism mintable token does the
* check. Allows for testing against code that is has been deployed,
* assuming different compiler version is no problem.
*/
function supportsInterface(bytes4 _interfaceId) external view returns (bool) {
bytes4 firstSupportedInterface = bytes4(keccak256("supportsInterface(bytes4)")); // ERC165
bytes4 secondSupportedInterface = ILegacyMintableERC20.l1Token.selector ^
ILegacyMintableERC20.mint.selector ^
ILegacyMintableERC20.burn.selector;
return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface;
}
}
/**
* @title StandardBridge_Stateless_Test
* @notice Tests internal functions that require no existing state or contract
* interactions with the messenger.
*/
contract StandardBridge_Stateless_Test is CommonTest {
StandardBridgeTester internal bridge;
OptimismMintableERC20 internal mintable;
ERC20 internal erc20;
LegacyMintable internal legacy;
function setUp() public override {
super.setUp();
bridge = new StandardBridgeTester({
_messenger: payable(address(0)),
_otherBridge: payable(address(0))
});
mintable = new OptimismMintableERC20({
_bridge: address(0),
_remoteToken: address(0),
_name: "Stonks",
_symbol: "STONK"
});
erc20 = new ERC20("Altcoin", "ALT");
legacy = new LegacyMintable("Legacy", "LEG");
}
/**
* @notice Test coverage for identifying OptimismMintableERC20 tokens.
* This function should return true for both modern and legacy
* OptimismMintableERC20 tokens and false for any accounts that
* do not implement the interface.
*/
function test_isOptimismMintableERC20_succeeds() external {
// Both the modern and legacy mintable tokens should return true
assertTrue(bridge.isOptimismMintableERC20(address(mintable)));
assertTrue(bridge.isOptimismMintableERC20(address(legacy)));
// A regular ERC20 should return false
assertFalse(bridge.isOptimismMintableERC20(address(erc20)));
// Non existent contracts should return false and not revert
assertEq(address(0x20).code.length, 0);
assertFalse(bridge.isOptimismMintableERC20(address(0x20)));
}
/**
* @notice Test coverage of isCorrectTokenPair under different types of
* tokens.
*/
function test_isCorrectTokenPair_succeeds() external {
// Modern + known to be correct remote token
assertTrue(bridge.isCorrectTokenPair(address(mintable), mintable.remoteToken()));
// Modern + known to be correct l1Token (legacy interface)
assertTrue(bridge.isCorrectTokenPair(address(mintable), mintable.l1Token()));
// Modern + known to be incorrect remote token
assertTrue(mintable.remoteToken() != address(0x20));
assertFalse(bridge.isCorrectTokenPair(address(mintable), address(0x20)));
// Legacy + known to be correct l1Token
assertTrue(bridge.isCorrectTokenPair(address(legacy), legacy.l1Token()));
// Legacy + known to be incorrect l1Token
assertTrue(legacy.l1Token() != address(0x20));
assertFalse(bridge.isCorrectTokenPair(address(legacy), address(0x20)));
// A token that doesn't support either modern or legacy interface
// will revert
vm.expectRevert();
bridge.isCorrectTokenPair(address(erc20), address(1));
}
}
packages/contracts-bedrock/contracts/universal/IOptimismMintableERC20.sol
View file @
c39e6692
...
@@ -10,7 +10,7 @@ import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol
...
@@ -10,7 +10,7 @@ import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol
* OptimismMintableERC20.
* OptimismMintableERC20.
*/
*/
interface IOptimismMintableERC20 is IERC165 {
interface IOptimismMintableERC20 is IERC165 {
function remoteToken() external returns (address);
function remoteToken() external
view
returns (address);
function bridge() external returns (address);
function bridge() external returns (address);
...
@@ -26,7 +26,7 @@ interface IOptimismMintableERC20 is IERC165 {
...
@@ -26,7 +26,7 @@ interface IOptimismMintableERC20 is IERC165 {
* on the OptimismMintableERC20 contract for backwards compatibility.
* on the OptimismMintableERC20 contract for backwards compatibility.
*/
*/
interface ILegacyMintableERC20 is IERC165 {
interface ILegacyMintableERC20 is IERC165 {
function l1Token() external returns (address);
function l1Token() external
view
returns (address);
function mint(address _to, uint256 _amount) external;
function mint(address _to, uint256 _amount) external;
...
...
packages/contracts-bedrock/contracts/universal/StandardBridge.sol
View file @
c39e6692
...
@@ -458,6 +458,8 @@ abstract contract StandardBridge {
...
@@ -458,6 +458,8 @@ abstract contract StandardBridge {
/**
/**
* @notice Checks if the "other token" is the correct pair token for the OptimismMintableERC20.
* @notice Checks if the "other token" is the correct pair token for the OptimismMintableERC20.
* Calls can be saved in the future by combining this logic with
* `_isOptimismMintableERC20`.
*
*
* @param _mintableToken OptimismMintableERC20 to check against.
* @param _mintableToken OptimismMintableERC20 to check against.
* @param _otherToken Pair token to check.
* @param _otherToken Pair token to check.
...
@@ -469,7 +471,13 @@ abstract contract StandardBridge {
...
@@ -469,7 +471,13 @@ abstract contract StandardBridge {
view
view
returns (bool)
returns (bool)
{
{
return _otherToken == OptimismMintableERC20(_mintableToken).l1Token();
if (
ERC165Checker.supportsInterface(_mintableToken, type(ILegacyMintableERC20).interfaceId)
) {
return _otherToken == ILegacyMintableERC20(_mintableToken).l1Token();
} else {
return _otherToken == IOptimismMintableERC20(_mintableToken).remoteToken();
}
}
}
/** @notice Emits the ETHBridgeInitiated event and if necessary the appropriate legacy event
/** @notice Emits the ETHBridgeInitiated event and if necessary the appropriate legacy event
...
...
packages/fault-detector/src/service.ts
View file @
c39e6692
...
@@ -124,7 +124,7 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
...
@@ -124,7 +124,7 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
this
.
state
.
oo
=
{
this
.
state
.
oo
=
{
contract
:
oo
,
contract
:
oo
,
filter
:
oo
.
filters
.
OutputProposed
(),
filter
:
oo
.
filters
.
OutputProposed
(),
getTotalElements
:
async
()
=>
oo
.
lates
tOutputIndex
(),
getTotalElements
:
async
()
=>
oo
.
nex
tOutputIndex
(),
getEventIndex
:
(
args
)
=>
args
.
l2OutputIndex
,
getEventIndex
:
(
args
)
=>
args
.
l2OutputIndex
,
}
}
}
else
{
}
else
{
...
...
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