Commit 1341ddb9 authored by Mark Tyneway's avatar Mark Tyneway Committed by GitHub

Merge branch 'develop' into debug/devnet-ci

parents ab7f5402 9d435aec
---
'@eth-optimism/foundry': minor
---
Initial release, pin to b7b1ec471bdd38221773e1a569dc4f20297bd7db
---
'@eth-optimism/contracts-bedrock': patch
---
Port RLPWriter tests
---
'@eth-optimism/ci-builder': patch
---
Use ethereumoptimism/foundry:latest
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
'@eth-optimism/contracts-bedrock': patch '@eth-optimism/contracts-bedrock': patch
--- ---
Move encoding and hashing into Encoding and Hashing libraries Cleans up natspec in MerkleTrie and SecureMerkleTrie contracts
---
'@eth-optimism/contracts-bedrock': patch
---
Fix solc warnings in ProxyAdmin
---
'@eth-optimism/contracts-bedrock': patch
---
Remove unnecessary DefaultValues library
---
'@eth-optimism/contracts-bedrock': patch
---
Fixes a bug that caused L2 timestamps to be computed incorrectly
---
'@eth-optimism/contracts-bedrock': patch
---
Standardizes comments, errors, and events for contracts in the /universal package
---
'@eth-optimism/contracts-bedrock': patch
---
Bump typechain to 8.1.0
---
'@eth-optimism/contracts-bedrock': patch
---
Clean up comments and errors for legacy contracts
---
'@eth-optimism/contracts-bedrock': patch
---
Cleaned up enums, should be CapitalCase enums and UPPER_CASE values
---
'@eth-optimism/contracts-bedrock': patch
---
Update to new L2 tx hash style for deposits
---
'@eth-optimism/contracts-bedrock': patch
---
Standardizes initialization logic for L1 contracts
---
'@eth-optimism/contracts-bedrock': patch
---
Move contracts written by external parties into a vendor folder
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
'@eth-optimism/contracts-bedrock': patch '@eth-optimism/contracts-bedrock': patch
--- ---
Use external version of ExcessivelySafeCall Minor cleanups to initialization and semver for L1 contracts
---
'@eth-optimism/contracts-bedrock': patch
---
Reduce the number of compiler warnings
---
'@eth-optimism/contracts-bedrock': patch
---
Remove storage slot buffer in xdomain messengers
---
'@eth-optimism/contracts-bedrock': patch
---
Cleans up initialization logic everywhere
---
'@eth-optimism/contracts-bedrock': patch
---
Rename OptimismMintableTokenFactory to OptimismMintableERC20Factory
---
'@eth-optimism/foundry': patch
---
Use alpine:3.14
---
'@eth-optimism/contracts-bedrock': patch
---
Fix initialization logic
---
'@eth-optimism/contracts-bedrock': patch
---
Clean up the PredeployAddresses library
---
'@eth-optimism/hardhat-deploy-config': patch
---
Use lazyObject
---
'@eth-optimism/contracts-bedrock': patch
---
Tests for RLPReader
---
'@eth-optimism/indexer': patch
---
Fix contract bindings
---
'@eth-optimism/contracts-bedrock': patch
'@eth-optimism/contracts-periphery': patch
---
Bump forge-std to 62caef29b0f87a2c6aaaf634b2ca4c09b6867c92
---
'@eth-optimism/contracts-bedrock': patch
---
Add semver to L2 contracts
---
'@eth-optimism/contracts-bedrock': patch
---
Resolve compiler warnings in Proxy.sol
---
'@eth-optimism/contracts-periphery': minor
---
Fixes a bug in the OptimismMintableERC721. Requires an interface change, so this is a minor and not patch.
---
'@eth-optimism/l2geth': patch
---
fix NPE in debug_standardTraceBlockToFile
---
'@eth-optimism/contracts-bedrock': patch
'@eth-optimism/core-utils': patch
---
Move the `DepositTx` type to `core-utils`. This way it can be more easily used across projects
---
'@eth-optimism/ci-builder': minor
---
Update foundry in ci builder
---
'@eth-optimism/contracts-bedrock': minor
---
Remove Lib* and OVM* prefixes from all contracts
---
'@eth-optimism/contracts-bedrock': patch
---
Remove "not implemented" errors in virtual functions
---
'@eth-optimism/contracts-bedrock': patch
---
Update typechain pipeline
---
'@eth-optimism/contracts-bedrock': patch
'@eth-optimism/contracts-periphery': patch
'@eth-optimism/fault-detector': patch
'@eth-optimism/hardhat-deploy-config': patch
---
Update dev deps
...@@ -127,7 +127,9 @@ jobs: ...@@ -127,7 +127,9 @@ jobs:
working_directory: packages/contracts-bedrock working_directory: packages/contracts-bedrock
- run: - run:
name: slither name: slither
command: yarn slither || exit 0 command: |
slither --version
yarn slither || exit 0
working_directory: packages/contracts-bedrock working_directory: packages/contracts-bedrock
- run: - run:
name: test name: test
...@@ -137,12 +139,30 @@ jobs: ...@@ -137,12 +139,30 @@ jobs:
name: gas snapshot name: gas snapshot
command: | command: |
forge --version forge --version
forge snapshot --check forge snapshot --check || exit 0
working_directory: packages/contracts-bedrock working_directory: packages/contracts-bedrock
- run: - run:
name: storage snapshot name: storage snapshot
command: yarn storage-snapshot && git diff --exit-code .storage-layout command: yarn storage-snapshot && git diff --exit-code .storage-layout
working_directory: packages/contracts-bedrock working_directory: packages/contracts-bedrock
op-bindings-build:
docker:
- image: ethereumoptimism/ci-builder:latest
resource_class: medium
steps:
- restore_cache:
keys:
- v2-cache-yarn-build-{{ .Revision }}
- checkout
- run:
name: Check if we should run
command: |
shopt -s inherit_errexit
CHANGED=$(check-changed "(contracts-bedrock|op-bindings)")
if [[ "$CHANGED" = "FALSE" ]]; then
circleci step halt
fi
- run: - run:
name: check go bindings name: check go bindings
command: make && git diff --exit-code command: make && git diff --exit-code
...@@ -399,6 +419,9 @@ jobs: ...@@ -399,6 +419,9 @@ jobs:
environment: environment:
DOCKER_BUILDKIT: 1 DOCKER_BUILDKIT: 1
steps: steps:
- run:
name: temporary pause
command: circleci step halt
- checkout - checkout
- run: - run:
name: Check if we should run name: Check if we should run
...@@ -545,6 +568,9 @@ workflows: ...@@ -545,6 +568,9 @@ workflows:
- contracts-bedrock-tests: - contracts-bedrock-tests:
requires: requires:
- yarn-monorepo - yarn-monorepo
- op-bindings-build:
requires:
- yarn-monorepo
- js-lint-test: - js-lint-test:
name: contracts-governance-tests name: contracts-governance-tests
package_name: contracts-governance package_name: contracts-governance
......
...@@ -232,7 +232,7 @@ jobs: ...@@ -232,7 +232,7 @@ jobs:
- name: Publish ci-builder - name: Publish ci-builder
uses: docker/build-push-action@v2 uses: docker/build-push-action@v2
with: with:
context: . context: ./ops/docker/ci-builder
file: ./ops/docker/ci-builder/Dockerfile file: ./ops/docker/ci-builder/Dockerfile
push: true push: true
tags: ethereumoptimism/ci-builder:${{ needs.release.outputs.ci-builder }},ethereumoptimism/ci-builder:latest tags: ethereumoptimism/ci-builder:${{ needs.release.outputs.ci-builder }},ethereumoptimism/ci-builder:latest
......
# @eth-optimism/indexer # @eth-optimism/indexer
## 0.1.3
### Patch Changes
- f30a5d39: Fix contract bindings
## 0.1.2 ## 0.1.2
### Patch Changes ### Patch Changes
......
{ {
"name": "@eth-optimism/indexer", "name": "@eth-optimism/indexer",
"version": "0.1.2", "version": "0.1.3",
"private": true, "private": true,
"license": "MIT" "license": "MIT"
} }
...@@ -29,10 +29,10 @@ ...@@ -29,10 +29,10 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/eslint-parser": "^7.5.4", "@babel/eslint-parser": "^7.5.4",
"@eth-optimism/contracts": "^0.5.29", "@eth-optimism/contracts": "^0.5.30",
"@eth-optimism/contracts-periphery": "^0.1.3", "@eth-optimism/contracts-periphery": "^0.2.0",
"@eth-optimism/core-utils": "0.9.0", "@eth-optimism/core-utils": "0.9.1",
"@eth-optimism/sdk": "1.2.0", "@eth-optimism/sdk": "1.3.0",
"@ethersproject/abstract-provider": "^5.6.1", "@ethersproject/abstract-provider": "^5.6.1",
"@ethersproject/providers": "^5.6.8", "@ethersproject/providers": "^5.6.8",
"@ethersproject/transactions": "^5.6.2", "@ethersproject/transactions": "^5.6.2",
......
...@@ -4,8 +4,8 @@ import { ethers } from 'hardhat' ...@@ -4,8 +4,8 @@ import { ethers } from 'hardhat'
import { getChainId } from '@eth-optimism/core-utils' import { getChainId } from '@eth-optimism/core-utils'
import { predeploys } from '@eth-optimism/contracts' import { predeploys } from '@eth-optimism/contracts'
import Artifact__TestERC721 from '@eth-optimism/contracts-periphery/artifacts/contracts/testing/helpers/TestERC721.sol/TestERC721.json' import Artifact__TestERC721 from '@eth-optimism/contracts-periphery/artifacts/contracts/testing/helpers/TestERC721.sol/TestERC721.json'
import Artifact__L1ERC721Bridge from '@eth-optimism/contracts-periphery/artifacts/contracts/L1/messaging/L1ERC721Bridge.sol/L1ERC721Bridge.json' import Artifact__L1ERC721Bridge from '@eth-optimism/contracts-periphery/artifacts/contracts/L1/L1ERC721Bridge.sol/L1ERC721Bridge.json'
import Artifact__L2ERC721Bridge from '@eth-optimism/contracts-periphery/artifacts/contracts/L2/messaging/L2ERC721Bridge.sol/L2ERC721Bridge.json' import Artifact__L2ERC721Bridge from '@eth-optimism/contracts-periphery/artifacts/contracts/L2/L2ERC721Bridge.sol/L2ERC721Bridge.json'
import Artifact__OptimismMintableERC721Factory from '@eth-optimism/contracts-periphery/artifacts/contracts/universal/op-erc721/OptimismMintableERC721Factory.sol/OptimismMintableERC721Factory.json' import Artifact__OptimismMintableERC721Factory from '@eth-optimism/contracts-periphery/artifacts/contracts/universal/op-erc721/OptimismMintableERC721Factory.sol/OptimismMintableERC721Factory.json'
import Artifact__OptimismMintableERC721 from '@eth-optimism/contracts-periphery/artifacts/contracts/universal/op-erc721/OptimismMintableERC721.sol/OptimismMintableERC721.json' import Artifact__OptimismMintableERC721 from '@eth-optimism/contracts-periphery/artifacts/contracts/universal/op-erc721/OptimismMintableERC721.sol/OptimismMintableERC721.json'
......
# Changelog # Changelog
## 0.5.23
### Patch Changes
- c3363225: fix NPE in debug_standardTraceBlockToFile
## 0.5.22 ## 0.5.22
### Patch Changes ### Patch Changes
......
{ {
"name": "@eth-optimism/l2geth", "name": "@eth-optimism/l2geth",
"version": "0.5.22", "version": "0.5.23",
"private": true, "private": true,
"devDependencies": {} "devDependencies": {}
} }
...@@ -2,6 +2,8 @@ FROM golang:1.18.0-alpine3.15 as builder ...@@ -2,6 +2,8 @@ FROM golang:1.18.0-alpine3.15 as builder
RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash
# build op-batcher with local monorepo go modules
COPY ./op-batcher/docker.go.work /app/go.work
COPY ./op-bindings /app/op-bindings COPY ./op-bindings /app/op-bindings
COPY ./op-node /app/op-node COPY ./op-node /app/op-node
COPY ./op-proposer /app/op-proposer COPY ./op-proposer /app/op-proposer
......
go 1.18
use (
./op-batcher
./op-bindings
./op-node
./op-proposer
)
...@@ -3,8 +3,8 @@ module github.com/ethereum-optimism/optimism/op-batcher ...@@ -3,8 +3,8 @@ module github.com/ethereum-optimism/optimism/op-batcher
go 1.18 go 1.18
require ( require (
github.com/ethereum-optimism/optimism/op-node v0.0.0 github.com/ethereum-optimism/optimism/op-node v0.3.0
github.com/ethereum-optimism/optimism/op-proposer v0.0.0 github.com/ethereum-optimism/optimism/op-proposer v0.3.0
github.com/ethereum/go-ethereum v1.10.17 github.com/ethereum/go-ethereum v1.10.17
github.com/miguelmota/go-ethereum-hdwallet v0.1.1 github.com/miguelmota/go-ethereum-hdwallet v0.1.1
github.com/urfave/cli v1.22.5 github.com/urfave/cli v1.22.5
...@@ -21,7 +21,7 @@ require ( ...@@ -21,7 +21,7 @@ require (
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/deckarep/golang-set v1.8.0 // indirect github.com/deckarep/golang-set v1.8.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/ethereum-optimism/optimism/op-bindings v0.0.0 // indirect github.com/ethereum-optimism/optimism/op-bindings v0.3.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-stack/stack v1.8.1 // indirect github.com/go-stack/stack v1.8.1 // indirect
github.com/golang-jwt/jwt/v4 v4.3.0 // indirect github.com/golang-jwt/jwt/v4 v4.3.0 // indirect
...@@ -54,10 +54,4 @@ require ( ...@@ -54,10 +54,4 @@ require (
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
) )
replace (
github.com/ethereum-optimism/optimism/op-bindings v0.0.0 => ../op-bindings
github.com/ethereum-optimism/optimism/op-node v0.0.0 => ../op-node
github.com/ethereum-optimism/optimism/op-proposer v0.0.0 => ../op-proposer
)
replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d
...@@ -161,6 +161,12 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m ...@@ -161,6 +161,12 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum-optimism/optimism/op-bindings v0.0.0-20220614233543-0d8fa52afca2/go.mod h1:e9mMYiVsdJf9BI//FdaA77BwNNgNMR043JtB7CPXNxY= github.com/ethereum-optimism/optimism/op-bindings v0.0.0-20220614233543-0d8fa52afca2/go.mod h1:e9mMYiVsdJf9BI//FdaA77BwNNgNMR043JtB7CPXNxY=
github.com/ethereum-optimism/optimism/op-bindings v0.3.0 h1:d2Mwb8FzR2zuhW0sS5xFKWz/6VFPTEIE+XINqZj0Rv4=
github.com/ethereum-optimism/optimism/op-bindings v0.3.0/go.mod h1:CrvUVIISKcyJ7o27ub/HY4Kq9wEJQxrGmWthTqxPSGo=
github.com/ethereum-optimism/optimism/op-node v0.3.0 h1:jep/cbIbP7fjBSAR48yk5NJVEoGYvoNlYI00KpBI6Mw=
github.com/ethereum-optimism/optimism/op-node v0.3.0/go.mod h1:iF9AhYjr8jNeoCDNP/Vs/ywQ2USZU5L66AxZbSAUi0E=
github.com/ethereum-optimism/optimism/op-proposer v0.3.0 h1:K1ipZt3TLD0BJi7tKOmx8tCLXj9i4f4baBIhbPmUxk4=
github.com/ethereum-optimism/optimism/op-proposer v0.3.0/go.mod h1:GcQ9VCWz2zEVexecq5IYo/2eadK/y7IBOEfx4YV1QJk=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d h1:AYFFbxrz7kLyFbvNHGhUPZQT8KnN1PPjCj4oAcgaVCk= github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d h1:AYFFbxrz7kLyFbvNHGhUPZQT8KnN1PPjCj4oAcgaVCk=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d/go.mod h1:8AfU1epKggKxDt9wr7rH5KmCeiT3yT0sEvroru1mO6Q= github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d/go.mod h1:8AfU1epKggKxDt9wr7rH5KmCeiT3yT0sEvroru1mO6Q=
github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg=
......
This diff is collapsed.
...@@ -3,10 +3,10 @@ module github.com/ethereum-optimism/optimism/op-e2e ...@@ -3,10 +3,10 @@ module github.com/ethereum-optimism/optimism/op-e2e
go 1.18 go 1.18
require ( require (
github.com/ethereum-optimism/optimism/op-batcher v0.0.0 github.com/ethereum-optimism/optimism/op-batcher v0.3.0
github.com/ethereum-optimism/optimism/op-bindings v0.0.0 github.com/ethereum-optimism/optimism/op-bindings v0.3.0
github.com/ethereum-optimism/optimism/op-node v0.0.0 github.com/ethereum-optimism/optimism/op-node v0.3.0
github.com/ethereum-optimism/optimism/op-proposer v0.0.0 github.com/ethereum-optimism/optimism/op-proposer v0.3.0
github.com/ethereum/go-ethereum v1.10.17 github.com/ethereum/go-ethereum v1.10.17
github.com/libp2p/go-libp2p v0.18.1 github.com/libp2p/go-libp2p v0.18.1
github.com/libp2p/go-libp2p-core v0.15.0 github.com/libp2p/go-libp2p-core v0.15.0
...@@ -160,11 +160,4 @@ require ( ...@@ -160,11 +160,4 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )
replace (
github.com/ethereum-optimism/optimism/op-batcher v0.0.0 => ../op-batcher
github.com/ethereum-optimism/optimism/op-bindings v0.0.0 => ../op-bindings
github.com/ethereum-optimism/optimism/op-node v0.0.0 => ../op-node
github.com/ethereum-optimism/optimism/op-proposer v0.0.0 => ../op-proposer
)
replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d
...@@ -249,7 +249,15 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m ...@@ -249,7 +249,15 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum-optimism/optimism/op-batcher v0.3.0 h1:rNEUyu7ZTUZc1W1lM9lO71w/HZ9pjQtnNwR/e1I0XyQ=
github.com/ethereum-optimism/optimism/op-batcher v0.3.0/go.mod h1:1imFCpIIA70WVZX7gp4dH/ZSnfqcG/WNvVp8Xm2s2VU=
github.com/ethereum-optimism/optimism/op-bindings v0.0.0-20220614233543-0d8fa52afca2/go.mod h1:e9mMYiVsdJf9BI//FdaA77BwNNgNMR043JtB7CPXNxY= github.com/ethereum-optimism/optimism/op-bindings v0.0.0-20220614233543-0d8fa52afca2/go.mod h1:e9mMYiVsdJf9BI//FdaA77BwNNgNMR043JtB7CPXNxY=
github.com/ethereum-optimism/optimism/op-bindings v0.3.0 h1:d2Mwb8FzR2zuhW0sS5xFKWz/6VFPTEIE+XINqZj0Rv4=
github.com/ethereum-optimism/optimism/op-bindings v0.3.0/go.mod h1:CrvUVIISKcyJ7o27ub/HY4Kq9wEJQxrGmWthTqxPSGo=
github.com/ethereum-optimism/optimism/op-node v0.3.0 h1:jep/cbIbP7fjBSAR48yk5NJVEoGYvoNlYI00KpBI6Mw=
github.com/ethereum-optimism/optimism/op-node v0.3.0/go.mod h1:iF9AhYjr8jNeoCDNP/Vs/ywQ2USZU5L66AxZbSAUi0E=
github.com/ethereum-optimism/optimism/op-proposer v0.3.0 h1:K1ipZt3TLD0BJi7tKOmx8tCLXj9i4f4baBIhbPmUxk4=
github.com/ethereum-optimism/optimism/op-proposer v0.3.0/go.mod h1:GcQ9VCWz2zEVexecq5IYo/2eadK/y7IBOEfx4YV1QJk=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d h1:AYFFbxrz7kLyFbvNHGhUPZQT8KnN1PPjCj4oAcgaVCk= github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d h1:AYFFbxrz7kLyFbvNHGhUPZQT8KnN1PPjCj4oAcgaVCk=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d/go.mod h1:8AfU1epKggKxDt9wr7rH5KmCeiT3yT0sEvroru1mO6Q= github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d/go.mod h1:8AfU1epKggKxDt9wr7rH5KmCeiT3yT0sEvroru1mO6Q=
github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg=
......
...@@ -2,15 +2,12 @@ FROM golang:1.18.0-alpine3.15 as builder ...@@ -2,15 +2,12 @@ FROM golang:1.18.0-alpine3.15 as builder
RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash
COPY ./op-node/go.mod /app/op-node/go.mod # build op-node with local monorepo go modules
COPY ./op-node/go.sum /app/op-node/go.sum COPY ./op-node/docker.go.work /app/go.work
COPY ./op-bindings /app/op-bindings COPY ./op-bindings /app/op-bindings
COPY ./op-node /app/op-node
WORKDIR /app/op-node WORKDIR /app/op-node
RUN go mod download -x
COPY ./op-node /app/op-node
RUN make op-node RUN make op-node
......
go 1.18
use (
./op-bindings
./op-node
)
...@@ -3,7 +3,7 @@ module github.com/ethereum-optimism/optimism/op-node ...@@ -3,7 +3,7 @@ module github.com/ethereum-optimism/optimism/op-node
go 1.18 go 1.18
require ( require (
github.com/ethereum-optimism/optimism/op-bindings v0.0.0 github.com/ethereum-optimism/optimism/op-bindings v0.3.0
github.com/ethereum/go-ethereum v1.10.17 github.com/ethereum/go-ethereum v1.10.17
github.com/golang/snappy v0.0.4 github.com/golang/snappy v0.0.4
github.com/google/go-cmp v0.5.8 github.com/google/go-cmp v0.5.8
...@@ -173,8 +173,6 @@ require ( ...@@ -173,8 +173,6 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )
replace github.com/ethereum-optimism/optimism/op-bindings v0.0.0 => ../op-bindings
replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d
// For local debugging: // For local debugging:
......
...@@ -232,6 +232,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m ...@@ -232,6 +232,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum-optimism/optimism/op-bindings v0.0.0-20220614233543-0d8fa52afca2/go.mod h1:e9mMYiVsdJf9BI//FdaA77BwNNgNMR043JtB7CPXNxY= github.com/ethereum-optimism/optimism/op-bindings v0.0.0-20220614233543-0d8fa52afca2/go.mod h1:e9mMYiVsdJf9BI//FdaA77BwNNgNMR043JtB7CPXNxY=
github.com/ethereum-optimism/optimism/op-bindings v0.3.0 h1:d2Mwb8FzR2zuhW0sS5xFKWz/6VFPTEIE+XINqZj0Rv4=
github.com/ethereum-optimism/optimism/op-bindings v0.3.0/go.mod h1:CrvUVIISKcyJ7o27ub/HY4Kq9wEJQxrGmWthTqxPSGo=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d h1:AYFFbxrz7kLyFbvNHGhUPZQT8KnN1PPjCj4oAcgaVCk= github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d h1:AYFFbxrz7kLyFbvNHGhUPZQT8KnN1PPjCj4oAcgaVCk=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d/go.mod h1:8AfU1epKggKxDt9wr7rH5KmCeiT3yT0sEvroru1mO6Q= github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d/go.mod h1:8AfU1epKggKxDt9wr7rH5KmCeiT3yT0sEvroru1mO6Q=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
......
package derive
import (
"context"
"fmt"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
)
// L1ReceiptsFetcher fetches L1 header info and receipts for the payload attributes derivation (the info tx and deposits)
type L1ReceiptsFetcher interface {
InfoByHash(ctx context.Context, hash common.Hash) (eth.L1Info, error)
Fetch(ctx context.Context, blockHash common.Hash) (eth.L1Info, types.Transactions, types.Receipts, error)
}
// PreparePayloadAttributes prepares a PayloadAttributes template that is ready to build a L2 block with deposits only, on top of the given l2Parent, with the given epoch as L1 origin.
// The template defaults to NoTxPool=true, and no sequencer transactions: the caller has to modify the template to add transactions,
// by setting NoTxPool=false as sequencer, or by appending batch transactions as verifier.
// The severity of the error is returned; a crit=false error means there was a temporary issue, like a failed RPC or time-out.
// A crit=true error means the input arguments are inconsistent or invalid.
func PreparePayloadAttributes(ctx context.Context, cfg *rollup.Config, dl L1ReceiptsFetcher, l2Parent eth.L2BlockRef, epoch eth.BlockID) (attrs *eth.PayloadAttributes, crit bool, err error) {
var l1Info eth.L1Info
var depositTxs []hexutil.Bytes
var seqNumber uint64
// If the L1 origin changed this block, then we are in the first block of the epoch. In this
// case we need to fetch all transaction receipts from the L1 origin block so we can scan for
// user deposits.
if l2Parent.L1Origin.Number != epoch.Number {
info, _, receipts, err := dl.Fetch(ctx, epoch.Hash)
if err != nil {
return nil, false, fmt.Errorf("failed to fetch L1 block info and receipts: %w", err)
}
if l2Parent.L1Origin.Hash != info.ParentHash() {
return nil, true, fmt.Errorf("cannot create new block with L1 origin %s (parent %s) on top of L1 origin %s", epoch, info.ParentHash(), l2Parent.L1Origin)
}
deposits, err := DeriveDeposits(receipts, cfg.DepositContractAddress)
if err != nil {
return nil, true, fmt.Errorf("failed to derive some deposits: %w", err)
}
l1Info = info
depositTxs = deposits
seqNumber = 0
} else {
if l2Parent.L1Origin.Hash != epoch.Hash {
return nil, true, fmt.Errorf("cannot create new block with L1 origin %s in conflict with L1 origin %s", epoch, l2Parent.L1Origin)
}
info, err := dl.InfoByHash(ctx, epoch.Hash)
if err != nil {
return nil, false, fmt.Errorf("failed to fetch L1 block info: %w", err)
}
l1Info = info
depositTxs = nil
seqNumber = l2Parent.SequenceNumber + 1
}
l1InfoTx, err := L1InfoDepositBytes(seqNumber, l1Info)
if err != nil {
return nil, true, fmt.Errorf("failed to create l1InfoTx: %w", err)
}
txs := make([]hexutil.Bytes, 0, 1+len(depositTxs))
txs = append(txs, l1InfoTx)
txs = append(txs, depositTxs...)
return &eth.PayloadAttributes{
Timestamp: hexutil.Uint64(l2Parent.Time + cfg.BlockTime),
PrevRandao: eth.Bytes32(l1Info.MixDigest()),
SuggestedFeeRecipient: cfg.FeeRecipientAddress,
Transactions: txs,
NoTxPool: true,
}, false, nil
}
...@@ -8,16 +8,9 @@ import ( ...@@ -8,16 +8,9 @@ import (
"github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
type L1ReceiptsFetcher interface {
Fetch(ctx context.Context, blockHash common.Hash) (eth.L1Info, types.Transactions, types.Receipts, error)
}
type AttributesQueueOutput interface { type AttributesQueueOutput interface {
AddSafeAttributes(attributes *eth.PayloadAttributes) AddSafeAttributes(attributes *eth.PayloadAttributes)
SafeL2Head() eth.L2BlockRef SafeL2Head() eth.L2BlockRef
...@@ -55,82 +48,43 @@ func (aq *AttributesQueue) Step(ctx context.Context, outer Progress) error { ...@@ -55,82 +48,43 @@ func (aq *AttributesQueue) Step(ctx context.Context, outer Progress) error {
if changed, err := aq.progress.Update(outer); err != nil || changed { if changed, err := aq.progress.Update(outer); err != nil || changed {
return err return err
} }
attr, err := aq.DeriveL2Inputs(ctx, aq.next.SafeL2Head())
if err != nil {
return err
}
aq.next.AddSafeAttributes(attr)
return nil
}
func (aq *AttributesQueue) ResetStep(ctx context.Context, l1Fetcher L1Fetcher) error {
aq.batches = aq.batches[:0]
aq.progress = aq.next.Progress()
return io.EOF
}
func (aq *AttributesQueue) SafeL2Head() eth.L2BlockRef {
return aq.next.SafeL2Head()
}
// DeriveL2Inputs turns the next L2 batch into an Payload Attributes that builds off of the safe head
func (aq *AttributesQueue) DeriveL2Inputs(ctx context.Context, l2SafeHead eth.L2BlockRef) (*eth.PayloadAttributes, error) {
if len(aq.batches) == 0 { if len(aq.batches) == 0 {
return nil, io.EOF return io.EOF
} }
batch := aq.batches[0] batch := aq.batches[0]
seqNumber := l2SafeHead.SequenceNumber + 1
// Check if we need to advance an epoch & update local state
if l2SafeHead.L1Origin != batch.Epoch() {
aq.log.Info("advancing epoch in the attributes queue", "l2SafeHead", l2SafeHead, "l2SafeHead_origin", l2SafeHead.L1Origin, "batch_timestamp", batch.Timestamp, "batch_epoch", batch.Epoch())
seqNumber = 0
}
fetchCtx, cancel := context.WithTimeout(ctx, 20*time.Second) fetchCtx, cancel := context.WithTimeout(ctx, 20*time.Second)
defer cancel() defer cancel()
l1Info, _, receipts, err := aq.dl.Fetch(fetchCtx, batch.EpochHash) attrs, crit, err := PreparePayloadAttributes(fetchCtx, aq.config, aq.dl, aq.next.SafeL2Head(), batch.Epoch())
if err != nil { if err != nil {
aq.log.Error("failed to fetch L1 block info", "l1Origin", batch.Epoch(), "err", err) if crit {
return nil, err return fmt.Errorf("failed to prepare payload attributes for batch: %v", err)
} } else {
aq.log.Error("temporarily failing to prepare payload attributes for batch", "err", err)
// Fill in deposits if we are the first block of the epoch return nil
var deposits []hexutil.Bytes
if seqNumber == 0 {
var errs []error
deposits, errs = DeriveDeposits(receipts, aq.config.DepositContractAddress)
for _, err := range errs {
aq.log.Error("Failed to derive a deposit", "l1Origin", batch.Epoch(), "err", err)
}
if len(errs) != 0 {
// TODO: Multierror here
return nil, fmt.Errorf("failed to derive some deposits: %v", errs)
} }
} }
var txns []eth.Data
l1InfoTx, err := L1InfoDepositBytes(seqNumber, l1Info)
if err != nil {
return nil, fmt.Errorf("failed to create l1InfoTx: %w", err)
}
txns = append(txns, l1InfoTx)
if seqNumber == 0 {
txns = append(txns, deposits...)
}
txns = append(txns, batch.Transactions...)
attrs := &eth.PayloadAttributes{
Timestamp: hexutil.Uint64(batch.Timestamp),
PrevRandao: eth.Bytes32(l1Info.MixDigest()),
SuggestedFeeRecipient: aq.config.FeeRecipientAddress,
Transactions: txns,
// we are verifying, not sequencing, we've got all transactions and do not pull from the tx-pool // we are verifying, not sequencing, we've got all transactions and do not pull from the tx-pool
// (that would make the block derivation non-deterministic) // (that would make the block derivation non-deterministic)
NoTxPool: true, attrs.NoTxPool = true
} attrs.Transactions = append(attrs.Transactions, batch.Transactions...)
aq.log.Info("generated attributes in payload queue", "tx_count", len(txns), "timestamp", batch.Timestamp)
aq.log.Info("generated attributes in payload queue", "txs", len(attrs.Transactions), "timestamp", batch.Timestamp)
// Slice off the batch once we are guaranteed to succeed // Slice off the batch once we are guaranteed to succeed
aq.batches = aq.batches[1:] aq.batches = aq.batches[1:]
return attrs, nil
aq.next.AddSafeAttributes(attrs)
return nil
}
func (aq *AttributesQueue) ResetStep(ctx context.Context, l1Fetcher L1Fetcher) error {
aq.batches = aq.batches[:0]
aq.progress = aq.next.Progress()
return io.EOF
}
func (aq *AttributesQueue) SafeL2Head() eth.L2BlockRef {
return aq.next.SafeL2Head()
} }
package derive package derive
import (
"context"
"io"
"math/big"
"math/rand"
"testing"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-node/testutils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
)
type MockAttributesQueueOutput struct {
MockOriginStage
}
func (m *MockAttributesQueueOutput) AddSafeAttributes(attributes *eth.PayloadAttributes) {
m.Mock.MethodCalled("AddSafeAttributes", attributes)
}
func (m *MockAttributesQueueOutput) ExpectAddSafeAttributes(attributes *eth.PayloadAttributes) {
m.Mock.On("AddSafeAttributes", attributes).Once().Return()
}
func (m *MockAttributesQueueOutput) SafeL2Head() eth.L2BlockRef {
return m.Mock.MethodCalled("SafeL2Head").Get(0).(eth.L2BlockRef)
}
func (m *MockAttributesQueueOutput) ExpectSafeL2Head(head eth.L2BlockRef) {
m.Mock.On("SafeL2Head").Once().Return(head)
}
var _ AttributesQueueOutput = (*MockAttributesQueueOutput)(nil)
func TestAttributesQueue_Step(t *testing.T) {
// test config, only init the necessary fields
cfg := &rollup.Config{
BlockTime: 2,
L1ChainID: big.NewInt(101),
L2ChainID: big.NewInt(102),
FeeRecipientAddress: common.Address{0xaa},
DepositContractAddress: common.Address{0xbb},
}
rng := rand.New(rand.NewSource(1234))
l1Info := testutils.RandomL1Info(rng)
l1Fetcher := &testutils.MockL1Source{}
defer l1Fetcher.AssertExpectations(t)
l1Fetcher.ExpectInfoByHash(l1Info.InfoHash, l1Info, nil)
out := &MockAttributesQueueOutput{}
out.progress = Progress{
Origin: l1Info.BlockRef(),
Closed: false,
}
defer out.AssertExpectations(t)
safeHead := testutils.RandomL2BlockRef(rng)
safeHead.L1Origin = l1Info.ID()
out.ExpectSafeL2Head(safeHead)
batch := &BatchData{BatchV1{
EpochNum: rollup.Epoch(l1Info.InfoNum),
EpochHash: l1Info.InfoHash,
Timestamp: 12345,
Transactions: []eth.Data{eth.Data("foobar"), eth.Data("example")},
}}
l1InfoTx, err := L1InfoDepositBytes(safeHead.SequenceNumber+1, l1Info)
require.NoError(t, err)
attrs := eth.PayloadAttributes{
Timestamp: eth.Uint64Quantity(safeHead.Time + cfg.BlockTime),
PrevRandao: eth.Bytes32(l1Info.InfoMixDigest),
SuggestedFeeRecipient: cfg.FeeRecipientAddress,
Transactions: []eth.Data{l1InfoTx, eth.Data("foobar"), eth.Data("example")},
NoTxPool: true,
}
out.ExpectAddSafeAttributes(&attrs)
aq := NewAttributesQueue(testlog.Logger(t, log.LvlError), cfg, l1Fetcher, out)
require.NoError(t, RepeatResetStep(t, aq.ResetStep, l1Fetcher, 1))
aq.AddBatch(batch)
require.NoError(t, aq.Step(context.Background(), out.progress), "adding batch to next stage, no EOF yet")
require.Equal(t, io.EOF, aq.Step(context.Background(), out.progress), "done with batches")
}
package derive
import (
"context"
"errors"
"fmt"
"math/big"
"math/rand"
"testing"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/testutils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/stretchr/testify/require"
)
func TestPreparePayloadAttributes(t *testing.T) {
// test config, only init the necessary fields
cfg := &rollup.Config{
BlockTime: 2,
L1ChainID: big.NewInt(101),
L2ChainID: big.NewInt(102),
FeeRecipientAddress: common.Address{0xaa},
DepositContractAddress: common.Address{0xbb},
}
t.Run("inconsistent next height origin", func(t *testing.T) {
rng := rand.New(rand.NewSource(1234))
l1Fetcher := &testutils.MockL1Source{}
defer l1Fetcher.AssertExpectations(t)
l2Parent := testutils.RandomL2BlockRef(rng)
l1Info := testutils.RandomL1Info(rng)
l1Info.InfoNum = l2Parent.L1Origin.Number + 1
epoch := l1Info.ID()
l1Fetcher.ExpectFetch(epoch.Hash, l1Info, nil, nil, nil)
_, crit, err := PreparePayloadAttributes(context.Background(), cfg, l1Fetcher, l2Parent, epoch)
require.NotNil(t, err, "inconsistent L1 origin error expected")
require.True(t, crit, "inconsistent L1 origin transition must be handled like a critical error with reorg")
})
t.Run("inconsistent equal height origin", func(t *testing.T) {
rng := rand.New(rand.NewSource(1234))
l1Fetcher := &testutils.MockL1Source{}
defer l1Fetcher.AssertExpectations(t)
l2Parent := testutils.RandomL2BlockRef(rng)
l1Info := testutils.RandomL1Info(rng)
l1Info.InfoNum = l2Parent.L1Origin.Number
epoch := l1Info.ID()
_, crit, err := PreparePayloadAttributes(context.Background(), cfg, l1Fetcher, l2Parent, epoch)
require.NotNil(t, err, "inconsistent L1 origin error expected")
require.True(t, crit, "inconsistent L1 origin transition must be handled like a critical error with reorg")
})
t.Run("rpc fail Fetch", func(t *testing.T) {
rng := rand.New(rand.NewSource(1234))
l1Fetcher := &testutils.MockL1Source{}
defer l1Fetcher.AssertExpectations(t)
l2Parent := testutils.RandomL2BlockRef(rng)
epoch := l2Parent.L1Origin
epoch.Number += 1
mockRPCErr := errors.New("mock rpc error")
l1Fetcher.ExpectFetch(epoch.Hash, nil, nil, nil, mockRPCErr)
_, crit, err := PreparePayloadAttributes(context.Background(), cfg, l1Fetcher, l2Parent, epoch)
require.ErrorIs(t, err, mockRPCErr, "mock rpc error expected")
require.False(t, crit, "rpc errors should not be critical, it is not necessary to reorg")
})
t.Run("rpc fail InfoByHash", func(t *testing.T) {
rng := rand.New(rand.NewSource(1234))
l1Fetcher := &testutils.MockL1Source{}
defer l1Fetcher.AssertExpectations(t)
l2Parent := testutils.RandomL2BlockRef(rng)
epoch := l2Parent.L1Origin
mockRPCErr := errors.New("mock rpc error")
l1Fetcher.ExpectInfoByHash(epoch.Hash, nil, mockRPCErr)
_, crit, err := PreparePayloadAttributes(context.Background(), cfg, l1Fetcher, l2Parent, epoch)
require.ErrorIs(t, err, mockRPCErr, "mock rpc error expected")
require.False(t, crit, "rpc errors should not be critical, it is not necessary to reorg")
})
t.Run("next origin without deposits", func(t *testing.T) {
rng := rand.New(rand.NewSource(1234))
l1Fetcher := &testutils.MockL1Source{}
defer l1Fetcher.AssertExpectations(t)
l2Parent := testutils.RandomL2BlockRef(rng)
l1Info := testutils.RandomL1Info(rng)
l1Info.InfoParentHash = l2Parent.L1Origin.Hash
l1Info.InfoNum = l2Parent.L1Origin.Number + 1
epoch := l1Info.ID()
l1InfoTx, err := L1InfoDepositBytes(0, l1Info)
require.NoError(t, err)
l1Fetcher.ExpectFetch(epoch.Hash, l1Info, nil, nil, nil)
attrs, crit, err := PreparePayloadAttributes(context.Background(), cfg, l1Fetcher, l2Parent, epoch)
require.NoError(t, err)
require.False(t, crit)
require.NotNil(t, attrs)
require.Equal(t, l2Parent.Time+cfg.BlockTime, uint64(attrs.Timestamp))
require.Equal(t, eth.Bytes32(l1Info.InfoMixDigest), attrs.PrevRandao)
require.Equal(t, cfg.FeeRecipientAddress, attrs.SuggestedFeeRecipient)
require.Equal(t, 1, len(attrs.Transactions))
require.Equal(t, l1InfoTx, []byte(attrs.Transactions[0]))
require.True(t, attrs.NoTxPool)
})
t.Run("next origin with deposits", func(t *testing.T) {
rng := rand.New(rand.NewSource(1234))
l1Fetcher := &testutils.MockL1Source{}
defer l1Fetcher.AssertExpectations(t)
l2Parent := testutils.RandomL2BlockRef(rng)
l1Info := testutils.RandomL1Info(rng)
l1Info.InfoParentHash = l2Parent.L1Origin.Hash
l1Info.InfoNum = l2Parent.L1Origin.Number + 1
receipts, depositTxs := makeReceipts(rng, l1Info.InfoHash, cfg.DepositContractAddress, []receiptData{
{goodReceipt: true, DepositLogs: []bool{true, false}},
{goodReceipt: true, DepositLogs: []bool{true}},
{goodReceipt: false, DepositLogs: []bool{true}},
{goodReceipt: false, DepositLogs: []bool{false}},
})
usedDepositTxs, err := encodeDeposits(depositTxs)
require.NoError(t, err)
epoch := l1Info.ID()
l1InfoTx, err := L1InfoDepositBytes(0, l1Info)
require.NoError(t, err)
l2Txs := append(append(make([]eth.Data, 0), l1InfoTx), usedDepositTxs...)
// txs are ignored, API is a bit bloated to previous approach. Only l1Info and receipts matter.
l1Txs := make(types.Transactions, len(receipts))
l1Fetcher.ExpectFetch(epoch.Hash, l1Info, l1Txs, receipts, nil)
attrs, crit, err := PreparePayloadAttributes(context.Background(), cfg, l1Fetcher, l2Parent, epoch)
require.NoError(t, err)
require.False(t, crit)
require.NotNil(t, attrs)
require.Equal(t, l2Parent.Time+cfg.BlockTime, uint64(attrs.Timestamp))
require.Equal(t, eth.Bytes32(l1Info.InfoMixDigest), attrs.PrevRandao)
require.Equal(t, cfg.FeeRecipientAddress, attrs.SuggestedFeeRecipient)
require.Equal(t, len(l2Txs), len(attrs.Transactions), "Expected txs to equal l1 info tx + user deposit txs")
require.Equal(t, l2Txs, attrs.Transactions)
require.True(t, attrs.NoTxPool)
})
t.Run("same origin again", func(t *testing.T) {
rng := rand.New(rand.NewSource(1234))
l1Fetcher := &testutils.MockL1Source{}
defer l1Fetcher.AssertExpectations(t)
l2Parent := testutils.RandomL2BlockRef(rng)
l1Info := testutils.RandomL1Info(rng)
l1Info.InfoHash = l2Parent.L1Origin.Hash
l1Info.InfoNum = l2Parent.L1Origin.Number
epoch := l1Info.ID()
l1InfoTx, err := L1InfoDepositBytes(l2Parent.SequenceNumber+1, l1Info)
require.NoError(t, err)
l1Fetcher.ExpectInfoByHash(epoch.Hash, l1Info, nil)
attrs, crit, err := PreparePayloadAttributes(context.Background(), cfg, l1Fetcher, l2Parent, epoch)
require.NoError(t, err)
require.False(t, crit)
require.NotNil(t, attrs)
require.Equal(t, l2Parent.Time+cfg.BlockTime, uint64(attrs.Timestamp))
require.Equal(t, eth.Bytes32(l1Info.InfoMixDigest), attrs.PrevRandao)
require.Equal(t, cfg.FeeRecipientAddress, attrs.SuggestedFeeRecipient)
require.Equal(t, 1, len(attrs.Transactions))
require.Equal(t, l1InfoTx, []byte(attrs.Transactions[0]))
require.True(t, attrs.NoTxPool)
})
}
func encodeDeposits(deposits []*types.DepositTx) (out []eth.Data, err error) {
for i, tx := range deposits {
opaqueTx, err := types.NewTx(tx).MarshalBinary()
if err != nil {
return nil, fmt.Errorf("bad deposit %d: %v", i, err)
}
out = append(out, opaqueTx)
}
return
}
...@@ -6,8 +6,10 @@ import ( ...@@ -6,8 +6,10 @@ import (
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-node/testutils" "github.com/ethereum-optimism/optimism/op-node/testutils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestUnmarshalLogEvent(t *testing.T) { func TestUnmarshalLogEvent(t *testing.T) {
...@@ -43,32 +45,9 @@ type receiptData struct { ...@@ -43,32 +45,9 @@ type receiptData struct {
DepositLogs []bool DepositLogs []bool
} }
type DeriveUserDepositsTestCase struct { func makeReceipts(rng *rand.Rand, blockHash common.Hash, depositContractAddr common.Address, testReceipts []receiptData) (receipts []*types.Receipt, expectedDeposits []*types.DepositTx) {
name string
// generate len(receipts) receipts
receipts []receiptData
}
func TestDeriveUserDeposits(t *testing.T) {
testCases := []DeriveUserDepositsTestCase{
{"no deposits", []receiptData{}},
{"other log", []receiptData{{true, []bool{false}}}},
{"success deposit", []receiptData{{true, []bool{true}}}},
{"failed deposit", []receiptData{{false, []bool{true}}}},
{"mixed deposits", []receiptData{{true, []bool{true}}, {false, []bool{true}}}},
{"success multiple logs", []receiptData{{true, []bool{true, true}}}},
{"failed multiple logs", []receiptData{{false, []bool{true, true}}}},
{"not all deposit logs", []receiptData{{true, []bool{true, false, true}}}},
{"random", []receiptData{{true, []bool{false, false, true}}, {false, []bool{}}, {true, []bool{true}}}},
}
for i, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
rng := rand.New(rand.NewSource(1234 + int64(i)))
var receipts []*types.Receipt
var expectedDeposits []*types.DepositTx
logIndex := uint(0) logIndex := uint(0)
blockHash := testutils.RandomHash(rng) for txIndex, rData := range testReceipts {
for txIndex, rData := range testCase.receipts {
var logs []*types.Log var logs []*types.Log
status := types.ReceiptStatusSuccessful status := types.ReceiptStatusSuccessful
if !rData.goodReceipt { if !rData.goodReceipt {
...@@ -82,7 +61,7 @@ func TestDeriveUserDeposits(t *testing.T) { ...@@ -82,7 +61,7 @@ func TestDeriveUserDeposits(t *testing.T) {
if status == types.ReceiptStatusSuccessful { if status == types.ReceiptStatusSuccessful {
expectedDeposits = append(expectedDeposits, dep) expectedDeposits = append(expectedDeposits, dep)
} }
ev = MarshalDepositLogEvent(MockDepositContractAddr, dep) ev = MarshalDepositLogEvent(depositContractAddr, dep)
} else { } else {
ev = testutils.GenerateLog(testutils.RandomAddress(rng), nil, nil) ev = testutils.GenerateLog(testutils.RandomAddress(rng), nil, nil)
} }
...@@ -101,12 +80,38 @@ func TestDeriveUserDeposits(t *testing.T) { ...@@ -101,12 +80,38 @@ func TestDeriveUserDeposits(t *testing.T) {
TransactionIndex: uint(txIndex), TransactionIndex: uint(txIndex),
}) })
} }
got, errs := UserDeposits(receipts, MockDepositContractAddr) return
assert.Equal(t, len(errs), 0) }
assert.Equal(t, len(got), len(expectedDeposits))
type DeriveUserDepositsTestCase struct {
name string
// generate len(receipts) receipts
receipts []receiptData
}
func TestDeriveUserDeposits(t *testing.T) {
testCases := []DeriveUserDepositsTestCase{
{"no deposits", []receiptData{}},
{"other log", []receiptData{{true, []bool{false}}}},
{"success deposit", []receiptData{{true, []bool{true}}}},
{"failed deposit", []receiptData{{false, []bool{true}}}},
{"mixed deposits", []receiptData{{true, []bool{true}}, {false, []bool{true}}}},
{"success multiple logs", []receiptData{{true, []bool{true, true}}}},
{"failed multiple logs", []receiptData{{false, []bool{true, true}}}},
{"not all deposit logs", []receiptData{{true, []bool{true, false, true}}}},
{"random", []receiptData{{true, []bool{false, false, true}}, {false, []bool{}}, {true, []bool{true}}}},
}
for i, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
rng := rand.New(rand.NewSource(1234 + int64(i)))
blockHash := testutils.RandomHash(rng)
receipts, expectedDeposits := makeReceipts(rng, blockHash, MockDepositContractAddr, testCase.receipts)
got, err := UserDeposits(receipts, MockDepositContractAddr)
require.NoError(t, err)
require.Equal(t, len(got), len(expectedDeposits))
for d, depTx := range got { for d, depTx := range got {
expected := expectedDeposits[d] expected := expectedDeposits[d]
assert.Equal(t, expected, depTx) require.Equal(t, expected, depTx)
} }
}) })
} }
......
...@@ -3,16 +3,17 @@ package derive ...@@ -3,16 +3,17 @@ package derive
import ( import (
"fmt" "fmt"
"github.com/hashicorp/go-multierror"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
) )
// UserDeposits transforms the L2 block-height and L1 receipts into the transaction inputs for a full L2 block // UserDeposits transforms the L2 block-height and L1 receipts into the transaction inputs for a full L2 block
func UserDeposits(receipts []*types.Receipt, depositContractAddr common.Address) ([]*types.DepositTx, []error) { func UserDeposits(receipts []*types.Receipt, depositContractAddr common.Address) ([]*types.DepositTx, error) {
var out []*types.DepositTx var out []*types.DepositTx
var errs []error var result error
for i, rec := range receipts { for i, rec := range receipts {
if rec.Status != types.ReceiptStatusSuccessful { if rec.Status != types.ReceiptStatusSuccessful {
continue continue
...@@ -21,26 +22,30 @@ func UserDeposits(receipts []*types.Receipt, depositContractAddr common.Address) ...@@ -21,26 +22,30 @@ func UserDeposits(receipts []*types.Receipt, depositContractAddr common.Address)
if log.Address == depositContractAddr && len(log.Topics) > 0 && log.Topics[0] == DepositEventABIHash { if log.Address == depositContractAddr && len(log.Topics) > 0 && log.Topics[0] == DepositEventABIHash {
dep, err := UnmarshalDepositLogEvent(log) dep, err := UnmarshalDepositLogEvent(log)
if err != nil { if err != nil {
errs = append(errs, fmt.Errorf("malformatted L1 deposit log in receipt %d, log %d: %w", i, j, err)) result = multierror.Append(result, fmt.Errorf("malformatted L1 deposit log in receipt %d, log %d: %w", i, j, err))
} else { } else {
out = append(out, dep) out = append(out, dep)
} }
} }
} }
} }
return out, errs return out, result
} }
func DeriveDeposits(receipts []*types.Receipt, depositContractAddr common.Address) ([]hexutil.Bytes, []error) { func DeriveDeposits(receipts []*types.Receipt, depositContractAddr common.Address) ([]hexutil.Bytes, error) {
userDeposits, errs := UserDeposits(receipts, depositContractAddr) var result error
userDeposits, err := UserDeposits(receipts, depositContractAddr)
if err != nil {
result = multierror.Append(result, err)
}
encodedTxs := make([]hexutil.Bytes, 0, len(userDeposits)) encodedTxs := make([]hexutil.Bytes, 0, len(userDeposits))
for i, tx := range userDeposits { for i, tx := range userDeposits {
opaqueTx, err := types.NewTx(tx).MarshalBinary() opaqueTx, err := types.NewTx(tx).MarshalBinary()
if err != nil { if err != nil {
errs = append(errs, fmt.Errorf("failed to encode user tx %d", i)) result = multierror.Append(result, fmt.Errorf("failed to encode user tx %d", i))
} else { } else {
encodedTxs = append(encodedTxs, opaqueTx) encodedTxs = append(encodedTxs, opaqueTx)
} }
} }
return encodedTxs, errs return encodedTxs, result
} }
...@@ -9,8 +9,6 @@ import ( ...@@ -9,8 +9,6 @@ import (
"github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
...@@ -27,70 +25,16 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, ...@@ -27,70 +25,16 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef,
fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20)
defer cancel() defer cancel()
var l1Info eth.L1Info attrs, _, err := derive.PreparePayloadAttributes(fetchCtx, d.Config, d.dl, l2Head, l1Origin.ID())
var receipts types.Receipts
var err error
seqNumber := l2Head.SequenceNumber + 1
// If the L1 origin changed this block, then we are in the first block of the epoch. In this
// case we need to fetch all transaction receipts from the L1 origin block so we can scan for
// user deposits.
if l2Head.L1Origin.Number != l1Origin.Number {
if l2Head.L1Origin.Hash != l1Origin.ParentHash {
d.log.Error("SEQUENCING BUG: cannot create new block on top of l2Head with new origin", "head", l2Head,
"head_origin", l2Head.L1Origin, "head_seq_nr", l2Head.SequenceNumber, "new_origin", l1Origin, "new_origin_parent", l1Origin.ParentID())
return l2Head, nil, fmt.Errorf("cannot create new block with L1 origin %s (parent %s) on top of L1 origin %s", l1Origin, l1Origin.ParentID(), l2Head.L1Origin)
}
l1Info, _, receipts, err = d.dl.Fetch(fetchCtx, l1Origin.Hash)
seqNumber = 0 // reset sequence number at the start of the epoch
} else {
if l2Head.L1Origin.Hash != l1Origin.Hash {
d.log.Error("SEQUENCING BUG: cannot create new block on top of l2Head with different origin at same height",
"head", l2Head, "head_origin", l2Head.L1Origin, "head_seq_nr", l2Head.SequenceNumber, "new_origin", l1Origin, "new_origin_parent", l1Origin.ParentID())
return l2Head, nil, fmt.Errorf("cannot create new block with L1 origin %s (parent %s) on top of L1 origin %s", l1Origin, l1Origin.ParentID(), l2Head.L1Origin)
}
l1Info, err = d.dl.InfoByHash(fetchCtx, l1Origin.Hash)
}
if err != nil {
return l2Head, nil, fmt.Errorf("failed to fetch L1 block info of %s: %v", l1Origin, err)
}
// Start building the list of transactions to include in the new block.
var txns []eth.Data
// First transaction in every block is always the L1 info transaction.
l1InfoTx, err := derive.L1InfoDepositBytes(seqNumber, l1Info)
if err != nil { if err != nil {
return l2Head, nil, err return l2Head, nil, err
} }
txns = append(txns, l1InfoTx)
// Next we append user deposits. If we're not the first block in an epoch, then receipts will
// be empty and no deposits will be derived.
deposits, errs := derive.DeriveDeposits(receipts, d.Config.DepositContractAddress)
d.log.Info("Derived deposits", "deposits", deposits, "l2Parent", l2Head, "l1Origin", l1Origin)
for _, err := range errs {
d.log.Error("Failed to derive a deposit", "l1OriginHash", l1Origin.Hash, "err", err)
}
// TODO: Should we halt if len(errs) > 0? Opens up a denial of service attack, but prevents lockup of funds.
txns = append(txns, deposits...)
// If our next L2 block timestamp is beyond the Sequencer drift threshold, then we must produce // If our next L2 block timestamp is beyond the Sequencer drift threshold, then we must produce
// empty blocks (other than the L1 info deposit and any user deposits). We handle this by // empty blocks (other than the L1 info deposit and any user deposits). We handle this by
// setting NoTxPool to true, which will cause the Sequencer to not include any transactions // setting NoTxPool to true, which will cause the Sequencer to not include any transactions
// from the transaction pool. // from the transaction pool.
nextL2Time := l2Head.Time + d.Config.BlockTime attrs.NoTxPool = uint64(attrs.Timestamp) >= l1Origin.Time+d.Config.MaxSequencerDrift
shouldProduceEmptyBlock := nextL2Time >= l1Origin.Time+d.Config.MaxSequencerDrift
// Put together our payload attributes.
attrs := &eth.PayloadAttributes{
Timestamp: hexutil.Uint64(nextL2Time),
PrevRandao: eth.Bytes32(l1Info.MixDigest()),
SuggestedFeeRecipient: d.Config.FeeRecipientAddress,
Transactions: txns,
NoTxPool: shouldProduceEmptyBlock,
}
// And construct our fork choice state. This is our current fork choice state and will be // And construct our fork choice state. This is our current fork choice state and will be
// updated as a result of executing the block based on the attributes described above. // updated as a result of executing the block based on the attributes described above.
......
...@@ -13,6 +13,15 @@ type MockL1Source struct { ...@@ -13,6 +13,15 @@ type MockL1Source struct {
mock.Mock mock.Mock
} }
func (m *MockL1Source) InfoByHash(ctx context.Context, hash common.Hash) (eth.L1Info, error) {
out := m.Mock.MethodCalled("InfoByHash", hash)
return *out[0].(*eth.L1Info), *out[1].(*error)
}
func (m *MockL1Source) ExpectInfoByHash(hash common.Hash, info eth.L1Info, err error) {
m.Mock.On("InfoByHash", hash).Once().Return(&info, &err)
}
func (m *MockL1Source) L1BlockRefByNumber(ctx context.Context, u uint64) (eth.L1BlockRef, error) { func (m *MockL1Source) L1BlockRefByNumber(ctx context.Context, u uint64) (eth.L1BlockRef, error) {
out := m.Mock.MethodCalled("L1BlockRefByNumber", u) out := m.Mock.MethodCalled("L1BlockRefByNumber", u)
return out[0].(eth.L1BlockRef), *out[1].(*error) return out[0].(eth.L1BlockRef), *out[1].(*error)
...@@ -33,11 +42,11 @@ func (m *MockL1Source) ExpectL1BlockRefByHash(hash common.Hash, ref eth.L1BlockR ...@@ -33,11 +42,11 @@ func (m *MockL1Source) ExpectL1BlockRefByHash(hash common.Hash, ref eth.L1BlockR
func (m *MockL1Source) Fetch(ctx context.Context, blockHash common.Hash) (eth.L1Info, types.Transactions, types.Receipts, error) { func (m *MockL1Source) Fetch(ctx context.Context, blockHash common.Hash) (eth.L1Info, types.Transactions, types.Receipts, error) {
out := m.Mock.MethodCalled("Fetch", blockHash) out := m.Mock.MethodCalled("Fetch", blockHash)
return out[0].(eth.L1Info), out[1].(types.Transactions), out[2].(types.Receipts), *out[3].(*error) return *out[0].(*eth.L1Info), out[1].(types.Transactions), out[2].(types.Receipts), *out[3].(*error)
} }
func (m *MockL1Source) ExpectFetch(hash common.Hash, info eth.L1Info, transactions types.Transactions, receipts types.Receipts, err error) { func (m *MockL1Source) ExpectFetch(hash common.Hash, info eth.L1Info, transactions types.Transactions, receipts types.Receipts, err error) {
m.Mock.On("Fetch", hash).Once().Return(info, transactions, receipts, &err) m.Mock.On("Fetch", hash).Once().Return(&info, transactions, receipts, &err)
} }
func (m *MockL1Source) InfoAndTxsByHash(ctx context.Context, hash common.Hash) (eth.L1Info, types.Transactions, error) { func (m *MockL1Source) InfoAndTxsByHash(ctx context.Context, hash common.Hash) (eth.L1Info, types.Transactions, error) {
......
...@@ -2,6 +2,8 @@ FROM golang:1.18.0-alpine3.15 as builder ...@@ -2,6 +2,8 @@ FROM golang:1.18.0-alpine3.15 as builder
RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash
# build op-proposer with local monorepo go modules
COPY ./op-proposer/docker.go.work /app/go.work
COPY ./op-bindings /app/op-bindings COPY ./op-bindings /app/op-bindings
COPY ./op-node /app/op-node COPY ./op-node /app/op-node
COPY ./op-proposer /app/op-proposer COPY ./op-proposer /app/op-proposer
......
go 1.18
use (
./op-bindings
./op-node
./op-proposer
)
...@@ -3,8 +3,8 @@ module github.com/ethereum-optimism/optimism/op-proposer ...@@ -3,8 +3,8 @@ module github.com/ethereum-optimism/optimism/op-proposer
go 1.18 go 1.18
require ( require (
github.com/ethereum-optimism/optimism/op-bindings v0.0.0 github.com/ethereum-optimism/optimism/op-bindings v0.3.0
github.com/ethereum-optimism/optimism/op-node v0.0.0 github.com/ethereum-optimism/optimism/op-node v0.3.0
github.com/ethereum/go-ethereum v1.10.17 github.com/ethereum/go-ethereum v1.10.17
github.com/miguelmota/go-ethereum-hdwallet v0.1.1 github.com/miguelmota/go-ethereum-hdwallet v0.1.1
github.com/stretchr/testify v1.8.0 github.com/stretchr/testify v1.8.0
...@@ -60,8 +60,4 @@ require ( ...@@ -60,8 +60,4 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )
replace github.com/ethereum-optimism/optimism/op-node v0.0.0 => ../op-node
replace github.com/ethereum-optimism/optimism/op-bindings v0.0.0 => ../op-bindings
replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d
...@@ -191,6 +191,10 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m ...@@ -191,6 +191,10 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum-optimism/optimism/op-bindings v0.0.0-20220614233543-0d8fa52afca2/go.mod h1:e9mMYiVsdJf9BI//FdaA77BwNNgNMR043JtB7CPXNxY= github.com/ethereum-optimism/optimism/op-bindings v0.0.0-20220614233543-0d8fa52afca2/go.mod h1:e9mMYiVsdJf9BI//FdaA77BwNNgNMR043JtB7CPXNxY=
github.com/ethereum-optimism/optimism/op-bindings v0.3.0 h1:d2Mwb8FzR2zuhW0sS5xFKWz/6VFPTEIE+XINqZj0Rv4=
github.com/ethereum-optimism/optimism/op-bindings v0.3.0/go.mod h1:CrvUVIISKcyJ7o27ub/HY4Kq9wEJQxrGmWthTqxPSGo=
github.com/ethereum-optimism/optimism/op-node v0.3.0 h1:jep/cbIbP7fjBSAR48yk5NJVEoGYvoNlYI00KpBI6Mw=
github.com/ethereum-optimism/optimism/op-node v0.3.0/go.mod h1:iF9AhYjr8jNeoCDNP/Vs/ywQ2USZU5L66AxZbSAUi0E=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d h1:AYFFbxrz7kLyFbvNHGhUPZQT8KnN1PPjCj4oAcgaVCk= github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d h1:AYFFbxrz7kLyFbvNHGhUPZQT8KnN1PPjCj4oAcgaVCk=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d/go.mod h1:8AfU1epKggKxDt9wr7rH5KmCeiT3yT0sEvroru1mO6Q= github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220711171946-f579014dc46d/go.mod h1:8AfU1epKggKxDt9wr7rH5KmCeiT3yT0sEvroru1mO6Q=
github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg=
......
...@@ -79,7 +79,7 @@ fi ...@@ -79,7 +79,7 @@ fi
( (
cd ops-bedrock cd ops-bedrock
echo "Bringing up L1..." echo "Bringing up L1..."
DOCKER_BUILDKIT=1 docker-compose build DOCKER_BUILDKIT=1 docker-compose build --progress plain
docker-compose up -d l1 docker-compose up -d l1
wait_up $L1_URL wait_up $L1_URL
) )
......
...@@ -42,7 +42,7 @@ services: ...@@ -42,7 +42,7 @@ services:
- l2 - l2
build: build:
context: ../ context: ../
dockerfile: ./ops-bedrock/Dockerfile.node dockerfile: ./op-node/Dockerfile
command: > command: >
op-node op-node
--l1=ws://l1:8546 --l1=ws://l1:8546
...@@ -81,7 +81,7 @@ services: ...@@ -81,7 +81,7 @@ services:
- op-node - op-node
build: build:
context: ../ context: ../
dockerfile: ./ops-bedrock/Dockerfile.proposer dockerfile: ./op-proposer/Dockerfile
environment: environment:
L1_ETH_RPC: http://l1:8545 L1_ETH_RPC: http://l1:8545
L2_ETH_RPC: http://l2:8545 L2_ETH_RPC: http://l2:8545
...@@ -102,7 +102,7 @@ services: ...@@ -102,7 +102,7 @@ services:
- op-node - op-node
build: build:
context: ../ context: ../
dockerfile: ./ops-bedrock/Dockerfile.batcher dockerfile: ./op-batcher/Dockerfile
environment: environment:
L1_ETH_RPC: http://l1:8545 L1_ETH_RPC: http://l1:8545
L2_ETH_RPC: http://l2:8545 L2_ETH_RPC: http://l2:8545
......
# @eth-optimism/ci-builder
## 0.1.2
### Patch Changes
- 184f13b6: Retrigger release of ci-builder
## 0.1.1
### Patch Changes
- 7bf30513: Fix publishing
- a60502f9: Install new version of bash
## 0.1.0
### Minor Changes
- 8c121ece: Update foundry in ci builder
### Patch Changes
- 445efe9d: Use ethereumoptimism/foundry:latest
...@@ -13,7 +13,7 @@ COPY --from=geth /usr/local/bin/abigen /usr/local/bin/abigen ...@@ -13,7 +13,7 @@ COPY --from=geth /usr/local/bin/abigen /usr/local/bin/abigen
COPY check-changed.sh /usr/local/bin/check-changed COPY check-changed.sh /usr/local/bin/check-changed
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y curl openssh-client git build-essential ca-certificates jq musl && \ apt-get install -y bash curl openssh-client git build-essential ca-certificates jq musl && \
curl -sL https://deb.nodesource.com/setup_16.x -o nodesource_setup.sh && \ curl -sL https://deb.nodesource.com/setup_16.x -o nodesource_setup.sh && \
curl -sL https://go.dev/dl/go1.18.2.linux-amd64.tar.gz -o go1.18.2.linux-amd64.tar.gz && \ curl -sL https://go.dev/dl/go1.18.2.linux-amd64.tar.gz -o go1.18.2.linux-amd64.tar.gz && \
tar -C /usr/local/ -xzvf go1.18.2.linux-amd64.tar.gz && \ tar -C /usr/local/ -xzvf go1.18.2.linux-amd64.tar.gz && \
...@@ -51,4 +51,8 @@ RUN echo "downloading solidity compilers" && \ ...@@ -51,4 +51,8 @@ RUN echo "downloading solidity compilers" && \
mkdir -p ~/.svm/0.8.10 && \ mkdir -p ~/.svm/0.8.10 && \
cp solc-linux-amd64-v0.8.10+commit.fc410830 ~/.svm/0.8.10/solc-0.8.10 && \ cp solc-linux-amd64-v0.8.10+commit.fc410830 ~/.svm/0.8.10/solc-0.8.10 && \
mkdir -p ~/.svm/0.8.12 && \ mkdir -p ~/.svm/0.8.12 && \
cp solc-linux-amd64-v0.8.12+commit.f00d7308 ~/.svm/0.8.12/solc-0.8.12 cp solc-linux-amd64-v0.8.12+commit.f00d7308 ~/.svm/0.8.12/solc-0.8.12 && \
rm solc-linux-amd64-v0.5.17+commit.d19bba13 && \
rm solc-linux-amd64-v0.8.9+commit.e5eed63a && \
rm solc-linux-amd64-v0.8.10+commit.fc410830 && \
rm solc-linux-amd64-v0.8.12+commit.f00d7308
{ {
"name": "@eth-optimism/ci-builder", "name": "@eth-optimism/ci-builder",
"version": "0.0.0", "version": "0.1.2",
"scripts": {}, "scripts": {},
"license": "MIT", "license": "MIT",
"dependencies": {} "dependencies": {}
......
# @eth-optimism/foundry
## 0.1.0
### Minor Changes
- 5ae9c133: Initial release, pin to b7b1ec471bdd38221773e1a569dc4f20297bd7db
### Patch Changes
- d4de18ea: Use alpine:3.14
{ {
"name": "@eth-optimism/foundry", "name": "@eth-optimism/foundry",
"version": "0.0.0", "version": "0.1.0",
"scripts": {}, "scripts": {},
"license": "MIT", "license": "MIT",
"dependencies": {} "dependencies": {}
} }
# @eth-optimism/common-ts # @eth-optimism/common-ts
## 0.6.1
### Patch Changes
- Updated dependencies [f9fee446]
- @eth-optimism/core-utils@0.9.1
## 0.6.0 ## 0.6.0
### Minor Changes ### Minor Changes
......
{ {
"name": "@eth-optimism/common-ts", "name": "@eth-optimism/common-ts",
"version": "0.6.0", "version": "0.6.1",
"description": "[Optimism] Advanced typescript tooling used by various services", "description": "[Optimism] Advanced typescript tooling used by various services",
"main": "dist/index", "main": "dist/index",
"types": "dist/index", "types": "dist/index",
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
"url": "https://github.com/ethereum-optimism/optimism.git" "url": "https://github.com/ethereum-optimism/optimism.git"
}, },
"dependencies": { "dependencies": {
"@eth-optimism/core-utils": "0.9.0", "@eth-optimism/core-utils": "0.9.1",
"@sentry/node": "^6.3.1", "@sentry/node": "^6.3.1",
"bcfg": "^0.1.7", "bcfg": "^0.1.7",
"body-parser": "^1.20.0", "body-parser": "^1.20.0",
......
GasBenchMark_L1CrossDomainMessenger:test_L1MessengerSendMessage_benchmark_0() (gas: 158608) GasBenchMark_L1CrossDomainMessenger:test_L1MessengerSendMessage_benchmark_0() (gas: 158650)
GasBenchMark_L1CrossDomainMessenger:test_L1MessengerSendMessage_benchmark_1() (gas: 75017) GasBenchMark_L1CrossDomainMessenger:test_L1MessengerSendMessage_benchmark_1() (gas: 75059)
GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 249829) GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 249871)
GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 116083) GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 116125)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 249851) GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 249893)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 116058) GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 116100)
GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 45413) GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 45413)
GasBenchMark_L2OutputOracle:test_appendL2Output_benchmark() (gas: 68673) GasBenchMark_L2OutputOracle:test_appendL2Output_benchmark() (gas: 68673)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 75069) GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 75069)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 35373) GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 35373)
DeployerWhitelist_Test:test_owner() (gas: 7658) DeployerWhitelist_Test:test_owner() (gas: 7658)
DeployerWhitelist_Test:test_storageSlots() (gas: 33494) DeployerWhitelist_Test:test_storageSlots() (gas: 33494)
Encoding_Test:test_encodeDepositTransaction() (gas: 64610)
GasPriceOracle_Test:test_baseFee() (gas: 8370) GasPriceOracle_Test:test_baseFee() (gas: 8370)
GasPriceOracle_Test:test_gasPrice() (gas: 8381) GasPriceOracle_Test:test_gasPrice() (gas: 8381)
GasPriceOracle_Test:test_l1BaseFee() (gas: 10582) GasPriceOracle_Test:test_l1BaseFee() (gas: 10582)
...@@ -23,7 +24,8 @@ GasPriceOracle_Test:test_setL1BaseFeeReverts() (gas: 11717) ...@@ -23,7 +24,8 @@ GasPriceOracle_Test:test_setL1BaseFeeReverts() (gas: 11717)
GasPriceOracle_Test:test_setOverhead() (gas: 36767) GasPriceOracle_Test:test_setOverhead() (gas: 36767)
GasPriceOracle_Test:test_setScalar() (gas: 36818) GasPriceOracle_Test:test_setScalar() (gas: 36818)
GasPriceOracle_Test:test_storageLayout() (gas: 86683) GasPriceOracle_Test:test_storageLayout() (gas: 86683)
Hashing_Test:test_l2TransactionHash() (gas: 104047) Hashing_Test:test_hashDepositSource() (gas: 673)
Hashing_Test:test_hashDepositTransaction() (gas: 39129)
L1BlockTest:test_basefee() (gas: 7531) L1BlockTest:test_basefee() (gas: 7531)
L1BlockTest:test_hash() (gas: 7575) L1BlockTest:test_hash() (gas: 7575)
L1BlockTest:test_number() (gas: 7630) L1BlockTest:test_number() (gas: 7630)
...@@ -35,20 +37,20 @@ L1BlockNumberTest:test_getL1BlockNumber() (gas: 10657) ...@@ -35,20 +37,20 @@ L1BlockNumberTest:test_getL1BlockNumber() (gas: 10657)
L1BlockNumberTest:test_receive() (gas: 25437) L1BlockNumberTest:test_receive() (gas: 25437)
L1CrossDomainMessenger_Test:testCannot_L1MessengerPause() (gas: 24517) L1CrossDomainMessenger_Test:testCannot_L1MessengerPause() (gas: 24517)
L1CrossDomainMessenger_Test:testCannot_L1MessengerUnpause() (gas: 24509) L1CrossDomainMessenger_Test:testCannot_L1MessengerUnpause() (gas: 24509)
L1CrossDomainMessenger_Test:test_L1MessengerMessageVersion() (gas: 24671) L1CrossDomainMessenger_Test:test_L1MessengerMessageVersion() (gas: 24716)
L1CrossDomainMessenger_Test:test_L1MessengerPause() (gas: 47995) L1CrossDomainMessenger_Test:test_L1MessengerPause() (gas: 47995)
L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageSucceeds() (gas: 77935) L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageSucceeds() (gas: 77773)
L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageToSystemContract() (gas: 67946) L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageToSystemContract() (gas: 67784)
L1CrossDomainMessenger_Test:test_L1MessengerRelayShouldRevertIfPaused() (gas: 60472) L1CrossDomainMessenger_Test:test_L1MessengerRelayShouldRevertIfPaused() (gas: 60472)
L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 196861) L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 196878)
L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 1273524) L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 1273626)
L1CrossDomainMessenger_Test:test_L1MessengerUnpause() (gas: 40890) L1CrossDomainMessenger_Test:test_L1MessengerUnpause() (gas: 40890)
L1CrossDomainMessenger_Test:test_L1MessengerXDomainSenderReverts() (gas: 24272) L1CrossDomainMessenger_Test:test_L1MessengerXDomainSenderReverts() (gas: 24272)
L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 86782) L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 86701)
L1StandardBridge_Test:test_depositERC20() (gas: 474966) L1StandardBridge_Test:test_depositERC20() (gas: 475008)
L1StandardBridge_Test:test_depositERC20To() (gas: 477147) L1StandardBridge_Test:test_depositERC20To() (gas: 477189)
L1StandardBridge_Test:test_depositETH() (gas: 268899) L1StandardBridge_Test:test_depositETH() (gas: 268941)
L1StandardBridge_Test:test_depositETHTo() (gas: 226721) L1StandardBridge_Test:test_depositETHTo() (gas: 226763)
L1StandardBridge_Test:test_finalizeERC20Withdrawal() (gas: 490759) L1StandardBridge_Test:test_finalizeERC20Withdrawal() (gas: 490759)
L1StandardBridge_Test:test_finalizeETHWithdrawal() (gas: 64409) L1StandardBridge_Test:test_finalizeETHWithdrawal() (gas: 64409)
L1StandardBridge_Test:test_initialize() (gas: 26336) L1StandardBridge_Test:test_initialize() (gas: 26336)
...@@ -56,17 +58,17 @@ L1StandardBridge_Test:test_onlyEOADepositERC20() (gas: 22363) ...@@ -56,17 +58,17 @@ L1StandardBridge_Test:test_onlyEOADepositERC20() (gas: 22363)
L1StandardBridge_Test:test_onlyEOADepositETH() (gas: 40882) L1StandardBridge_Test:test_onlyEOADepositETH() (gas: 40882)
L1StandardBridge_Test:test_onlyL2BridgeFinalizeERC20Withdrawal() (gas: 36271) L1StandardBridge_Test:test_onlyL2BridgeFinalizeERC20Withdrawal() (gas: 36271)
L1StandardBridge_Test:test_onlyPortalFinalizeERC20Withdrawal() (gas: 35600) L1StandardBridge_Test:test_onlyPortalFinalizeERC20Withdrawal() (gas: 35600)
L1StandardBridge_Test:test_receive() (gas: 413479) L1StandardBridge_Test:test_receive() (gas: 413521)
L2CrossDomainMessenger_Test:testCannot_L2MessengerPause() (gas: 10821) L2CrossDomainMessenger_Test:testCannot_L2MessengerPause() (gas: 10821)
L2CrossDomainMessenger_Test:test_L2MessengerMessageVersion() (gas: 8400) L2CrossDomainMessenger_Test:test_L2MessengerMessageVersion() (gas: 8445)
L2CrossDomainMessenger_Test:test_L2MessengerPause() (gas: 31815) L2CrossDomainMessenger_Test:test_L2MessengerPause() (gas: 31815)
L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageSucceeds() (gas: 57494) L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageSucceeds() (gas: 57332)
L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageToSystemContract() (gas: 36221) L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageToSystemContract() (gas: 36140)
L2CrossDomainMessenger_Test:test_L2MessengerRelayShouldRevertIfPaused() (gas: 41664) L2CrossDomainMessenger_Test:test_L2MessengerRelayShouldRevertIfPaused() (gas: 41664)
L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 119619) L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 119627)
L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 133146) L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 133248)
L2CrossDomainMessenger_Test:test_L2MessengerXDomainSenderReverts() (gas: 10599) L2CrossDomainMessenger_Test:test_L2MessengerXDomainSenderReverts() (gas: 10599)
L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 54925) L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 54844)
L2OutputOracleTest:testCannot_AppendWithUnmatchedBlockhash() (gas: 26811) L2OutputOracleTest:testCannot_AppendWithUnmatchedBlockhash() (gas: 26811)
L2OutputOracleTest:testCannot_appendEmptyOutput() (gas: 24086) L2OutputOracleTest:testCannot_appendEmptyOutput() (gas: 24086)
L2OutputOracleTest:testCannot_appendFutureTimetamp() (gas: 26075) L2OutputOracleTest:testCannot_appendFutureTimetamp() (gas: 26075)
...@@ -90,14 +92,14 @@ L2OutputOracleUpgradeable_Test:test_cannotInitImpl() (gas: 8476) ...@@ -90,14 +92,14 @@ L2OutputOracleUpgradeable_Test:test_cannotInitImpl() (gas: 8476)
L2OutputOracleUpgradeable_Test:test_cannotInitProxy() (gas: 13497) L2OutputOracleUpgradeable_Test:test_cannotInitProxy() (gas: 13497)
L2OutputOracleUpgradeable_Test:test_initValuesOnProxy() (gas: 38865) L2OutputOracleUpgradeable_Test:test_initValuesOnProxy() (gas: 38865)
L2OutputOracleUpgradeable_Test:test_upgrading() (gas: 230843) L2OutputOracleUpgradeable_Test:test_upgrading() (gas: 230843)
L2StandardBridge_Test:test_ERC20BridgeFailed_whenLocalTokenIsBridge() (gas: 133158) L2StandardBridge_Test:test_ERC20BridgeFailed_whenLocalTokenIsBridge() (gas: 133200)
L2StandardBridge_Test:test_cannotWithdrawEthWithoutSendingIt() (gas: 21656) L2StandardBridge_Test:test_cannotWithdrawEthWithoutSendingIt() (gas: 21656)
L2StandardBridge_Test:test_finalizeDeposit() (gas: 93203) L2StandardBridge_Test:test_finalizeDeposit() (gas: 93203)
L2StandardBridge_Test:test_finalizeDeposit_failsToCompleteOutboundTransfer() (gas: 140168) L2StandardBridge_Test:test_finalizeDeposit_failsToCompleteOutboundTransfer() (gas: 140210)
L2StandardBridge_Test:test_initialize() (gas: 14802) L2StandardBridge_Test:test_initialize() (gas: 14802)
L2StandardBridge_Test:test_receive() (gas: 136483) L2StandardBridge_Test:test_receive() (gas: 136525)
L2StandardBridge_Test:test_withdraw() (gas: 352780) L2StandardBridge_Test:test_withdraw() (gas: 352813)
L2StandardBridge_Test:test_withdrawTo() (gas: 353464) L2StandardBridge_Test:test_withdrawTo() (gas: 353498)
L2StandardBridge_Test:test_withdraw_onlyEOA() (gas: 252006) L2StandardBridge_Test:test_withdraw_onlyEOA() (gas: 252006)
L2ToL1MessagePasserTest:test_burn() (gas: 112037) L2ToL1MessagePasserTest:test_burn() (gas: 112037)
L2ToL1MessagePasserTest:test_initiateWithdrawal_fromContract() (gas: 67892) L2ToL1MessagePasserTest:test_initiateWithdrawal_fromContract() (gas: 67892)
...@@ -252,13 +254,13 @@ RLPWriter_Test:test_writeUint_smallint3() (gas: 7372) ...@@ -252,13 +254,13 @@ RLPWriter_Test:test_writeUint_smallint3() (gas: 7372)
RLPWriter_Test:test_writeUint_smallint4() (gas: 7351) RLPWriter_Test:test_writeUint_smallint4() (gas: 7351)
RLPWriter_Test:test_writeUint_zero() (gas: 7798) RLPWriter_Test:test_writeUint_zero() (gas: 7798)
ResourceMetering_Test:test_initialResourceParams() (gas: 8964) ResourceMetering_Test:test_initialResourceParams() (gas: 8964)
ResourceMetering_Test:test_updateNoGasDelta() (gas: 2008269) ResourceMetering_Test:test_updateNoGasDelta() (gas: 2008317)
ResourceMetering_Test:test_updateOneEmptyBlock() (gas: 18123) ResourceMetering_Test:test_updateOneEmptyBlock() (gas: 18171)
ResourceMetering_Test:test_updateParamsNoChange() (gas: 13860) ResourceMetering_Test:test_updateParamsNoChange() (gas: 13956)
ResourceMetering_Test:test_updateTenEmptyBlocks() (gas: 20523) ResourceMetering_Test:test_updateTenEmptyBlocks() (gas: 20571)
ResourceMetering_Test:test_updateTwoEmptyBlocks() (gas: 20546) ResourceMetering_Test:test_updateTwoEmptyBlocks() (gas: 20594)
ResourceMetering_Test:test_useMaxSucceeds() (gas: 8017023) ResourceMetering_Test:test_useMaxSucceeds() (gas: 8017119)
ResourceMetering_Test:test_useMoreThanMaxReverts() (gas: 16002) ResourceMetering_Test:test_useMoreThanMaxReverts() (gas: 16047)
Semver_Test:test_behindProxy() (gas: 504908) Semver_Test:test_behindProxy() (gas: 504908)
Semver_Test:test_major() (gas: 5406) Semver_Test:test_major() (gas: 5406)
Semver_Test:test_minor() (gas: 5430) Semver_Test:test_minor() (gas: 5430)
...@@ -267,4 +269,4 @@ SequencerFeeVault_Test:test_constructor() (gas: 7656) ...@@ -267,4 +269,4 @@ SequencerFeeVault_Test:test_constructor() (gas: 7656)
SequencerFeeVault_Test:test_minWithdrawalAmount() (gas: 5407) SequencerFeeVault_Test:test_minWithdrawalAmount() (gas: 5407)
SequencerFeeVault_Test:test_receive() (gas: 17258) SequencerFeeVault_Test:test_receive() (gas: 17258)
SequencerFeeVault_Test:test_revertWithdraw() (gas: 9332) SequencerFeeVault_Test:test_revertWithdraw() (gas: 9332)
SequencerFeeVault_Test:test_withdraw() (gas: 147281) SequencerFeeVault_Test:test_withdraw() (gas: 147323)
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
|------------------------+--------------------------+------+--------+-------+----------------------------------------------------------------| |------------------------+--------------------------+------+--------+-------+----------------------------------------------------------------|
| xDomainMsgSender | address | 202 | 0 | 20 | contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger | | xDomainMsgSender | address | 202 | 0 | 20 | contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger |
|------------------------+--------------------------+------+--------+-------+----------------------------------------------------------------| |------------------------+--------------------------+------+--------+-------+----------------------------------------------------------------|
| msgNonce | uint256 | 203 | 0 | 32 | contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger | | msgNonce | uint240 | 203 | 0 | 30 | contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger |
|------------------------+--------------------------+------+--------+-------+----------------------------------------------------------------| |------------------------+--------------------------+------+--------+-------+----------------------------------------------------------------|
| otherMessenger | address | 204 | 0 | 20 | contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger | | otherMessenger | address | 204 | 0 | 20 | contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger |
|------------------------+--------------------------+------+--------+-------+----------------------------------------------------------------| |------------------------+--------------------------+------+--------+-------+----------------------------------------------------------------|
...@@ -192,7 +192,7 @@ ...@@ -192,7 +192,7 @@
|------------------------+--------------------------+------+--------+-------+----------------------------------------------------------------| |------------------------+--------------------------+------+--------+-------+----------------------------------------------------------------|
| xDomainMsgSender | address | 202 | 0 | 20 | contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger | | xDomainMsgSender | address | 202 | 0 | 20 | contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger |
|------------------------+--------------------------+------+--------+-------+----------------------------------------------------------------| |------------------------+--------------------------+------+--------+-------+----------------------------------------------------------------|
| msgNonce | uint256 | 203 | 0 | 32 | contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger | | msgNonce | uint240 | 203 | 0 | 30 | contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger |
|------------------------+--------------------------+------+--------+-------+----------------------------------------------------------------| |------------------------+--------------------------+------+--------+-------+----------------------------------------------------------------|
| otherMessenger | address | 204 | 0 | 20 | contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger | | otherMessenger | address | 204 | 0 | 20 | contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger |
|------------------------+--------------------------+------+--------+-------+----------------------------------------------------------------| |------------------------+--------------------------+------+--------+-------+----------------------------------------------------------------|
......
# @eth-optimism/contracts-bedrock # @eth-optimism/contracts-bedrock
## 0.5.0
### Minor Changes
- 42a4cc30: Remove Lib* and OVM* prefixes from all contracts
### Patch Changes
- 0cb3929e: Move encoding and hashing into Encoding and Hashing libraries
- 28bd76ae: Cleans up hashing and encoding library natspec and function names
- 4279647f: Port RLPWriter tests
- ce6cb121: Use external version of ExcessivelySafeCall
- 8986f165: Fix solc warnings in ProxyAdmin
- 69ee689f: Remove unnecessary DefaultValues library
- 2e89f634: Fixes a bug that caused L2 timestamps to be computed incorrectly
- 49d33b08: Standardizes comments, errors, and events for contracts in the /universal package
- 821907e2: Bump typechain to 8.1.0
- 91b31168: Clean up comments and errors for legacy contracts
- 3c5726d4: Cleaned up enums, should be CapitalCase enums and UPPER_CASE values
- eb11a5bb: Add comments to RLP libraries
- 092b0901: Update to new L2 tx hash style for deposits
- 4ea33e13: Standardizes initialization logic for L1 contracts
- 297af083: Move contracts written by external parties into a vendor folder
- 71800503: Reduce the number of compiler warnings
- 611d93a1: Remove storage slot buffer in xdomain messengers
- 75089d0a: Cleans up initialization logic everywhere
- b9a90f32: Rename OptimismMintableTokenFactory to OptimismMintableERC20Factory
- 50e20ea1: Fix initialization logic
- 6f74ca9f: Clean up the PredeployAddresses library
- c031ec95: Tests for RLPReader
- 9c8b1f00: Bump forge-std to 62caef29b0f87a2c6aaaf634b2ca4c09b6867c92
- 89d01f2e: Add semver to L2 contracts
- 7d9820b6: Resolve compiler warnings in Proxy.sol
- f9fee446: Move the `DepositTx` type to `core-utils`. This way it can be more easily used across projects
- 5050e0fb: Remove "not implemented" errors in virtual functions
- 78d7c2ec: Update typechain pipeline
- 89d01f2e: Update dev deps
- Updated dependencies [f9fee446]
- @eth-optimism/core-utils@0.9.1
## 0.4.1 ## 0.4.1
### Patch Changes ### Patch Changes
......
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
## Install ## Install
The repo currently uses a mix of typescript tests (run with HardHat) and solidity tests (run with Forge). The project The repo currently uses solidity tests (run with Forge). The project uses the default hardhat directory structure, and all build/test steps should be run using the yarn scripts to ensure
uses the default hardhat directory structure, and all build/test steps should be run using the yarn scripts to ensure
the correct options are set. the correct options are set.
Install node modules with yarn (v1), and Node.js (14+). Install node modules with yarn (v1), and Node.js (14+).
...@@ -22,28 +21,12 @@ yarn build ...@@ -22,28 +21,12 @@ yarn build
## Running Tests ## Running Tests
First get the dependencies:
`git submodule init` and `git submodule update`
Then the full test suite can be executed via `yarn`: Then the full test suite can be executed via `yarn`:
```shell ```shell
yarn test yarn test
``` ```
To run only typescript tests:
```shell
yarn test:hh
```
To run only solidity tests:
```shell
yarn test:forge
```
## Deployment ## Deployment
Create a file that corresponds to the network name in the `deploy-config` Create a file that corresponds to the network name in the `deploy-config`
...@@ -52,7 +35,7 @@ directory and then run the command: ...@@ -52,7 +35,7 @@ directory and then run the command:
```shell ```shell
L1_RPC=<ETHEREUM L1 RPC endpoint> \ L1_RPC=<ETHEREUM L1 RPC endpoint> \
PRIVATE_KEY_DEPLOYER=<PRIVATE KEY TO PAY FOR THE DEPLOYMENT> \ PRIVATE_KEY_DEPLOYER=<PRIVATE KEY TO PAY FOR THE DEPLOYMENT> \
npx hardhat deploy --network <network-name> npx hardhat deploy --network <network-name>
``` ```
In the `hardhat.config.ts`, there is a `deployConfigSpec` field that validates that the types In the `hardhat.config.ts`, there is a `deployConfigSpec` field that validates that the types
......
...@@ -86,6 +86,8 @@ contract L1StandardBridge is StandardBridge, Semver { ...@@ -86,6 +86,8 @@ contract L1StandardBridge is StandardBridge, Semver {
); );
/** /**
* @custom:semver 0.0.1
*
* @param _messenger Address of the L1CrossDomainMessenger. * @param _messenger Address of the L1CrossDomainMessenger.
*/ */
constructor(address payable _messenger) Semver(0, 0, 1) { constructor(address payable _messenger) Semver(0, 0, 1) {
......
...@@ -99,12 +99,11 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { ...@@ -99,12 +99,11 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
constructor(L2OutputOracle _l2Oracle, uint256 _finalizationPeriodSeconds) Semver(0, 0, 1) { constructor(L2OutputOracle _l2Oracle, uint256 _finalizationPeriodSeconds) Semver(0, 0, 1) {
L2_ORACLE = _l2Oracle; L2_ORACLE = _l2Oracle;
FINALIZATION_PERIOD_SECONDS = _finalizationPeriodSeconds; FINALIZATION_PERIOD_SECONDS = _finalizationPeriodSeconds;
initialize(); initialize();
} }
/** /**
* @notice Intializes mutable variables. * @notice Initializer;
*/ */
function initialize() public initializer { function initialize() public initializer {
l2Sender = DEFAULT_L2_SENDER; l2Sender = DEFAULT_L2_SENDER;
...@@ -242,13 +241,13 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { ...@@ -242,13 +241,13 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
// Verify that the output root can be generated with the elements in the proof. // Verify that the output root can be generated with the elements in the proof.
require( require(
proposal.outputRoot == Hashing._deriveOutputRoot(_outputRootProof), proposal.outputRoot == Hashing.hashOutputRootProof(_outputRootProof),
"OptimismPortal: invalid output root proof" "OptimismPortal: invalid output root proof"
); );
// All withdrawals have a unique hash, we'll use this as the identifier for the withdrawal // All withdrawals have a unique hash, we'll use this as the identifier for the withdrawal
// and to prevent replay attacks. // and to prevent replay attacks.
bytes32 withdrawalHash = Hashing.withdrawalHash( bytes32 withdrawalHash = Hashing.hashWithdrawal(
_nonce, _nonce,
_sender, _sender,
_target, _target,
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.10; pragma solidity 0.8.10;
import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
import { SignedMath } from "@openzeppelin/contracts/utils/math/SignedMath.sol"; import { SignedMath } from "@openzeppelin/contracts/utils/math/SignedMath.sol";
import { FixedPointMathLib } from "@rari-capital/solmate/src/utils/FixedPointMathLib.sol"; import { FixedPointMathLib } from "@rari-capital/solmate/src/utils/FixedPointMathLib.sol";
...@@ -11,7 +12,7 @@ import { Burn } from "../libraries/Burn.sol"; ...@@ -11,7 +12,7 @@ import { Burn } from "../libraries/Burn.sol";
* @notice ResourceMetering implements an EIP-1559 style resource metering system where pricing * @notice ResourceMetering implements an EIP-1559 style resource metering system where pricing
* updates automatically based on current demand. * updates automatically based on current demand.
*/ */
contract ResourceMetering { abstract contract ResourceMetering is Initializable {
/** /**
* @notice Represents the various parameters that control the way in which resources are * @notice Represents the various parameters that control the way in which resources are
* metered. Corresponds to the EIP-1559 resource metering system. * metered. Corresponds to the EIP-1559 resource metering system.
...@@ -62,19 +63,11 @@ contract ResourceMetering { ...@@ -62,19 +63,11 @@ contract ResourceMetering {
*/ */
uint256[49] private __gap; uint256[49] private __gap;
/**
* @notice Set the initial values. In order to enable this contract to be used in an upgradable
* context, the constructor calls a separate init function.
*/
constructor() {
__ResourceMetering_init();
}
/** /**
* @notice Sets initial resource parameter values. This function must either be called by the * @notice Sets initial resource parameter values. This function must either be called by the
* initializer function of an upgradeable child contract. * initializer function of an upgradeable child contract.
*/ */
function __ResourceMetering_init() internal { function __ResourceMetering_init() internal onlyInitializing {
params = ResourceParams({ params = ResourceParams({
prevBaseFee: INITIAL_BASE_FEE, prevBaseFee: INITIAL_BASE_FEE,
prevBoughtGas: 0, prevBoughtGas: 0,
......
...@@ -79,7 +79,7 @@ contract L2ToL1MessagePasser is Semver { ...@@ -79,7 +79,7 @@ contract L2ToL1MessagePasser is Semver {
uint256 _gasLimit, uint256 _gasLimit,
bytes memory _data bytes memory _data
) public payable { ) public payable {
bytes32 withdrawalHash = Hashing.withdrawalHash( bytes32 withdrawalHash = Hashing.hashWithdrawal(
nonce, nonce,
msg.sender, msg.sender,
_target, _target,
......
...@@ -10,73 +10,58 @@ import { RLPWriter } from "./rlp/RLPWriter.sol"; ...@@ -10,73 +10,58 @@ import { RLPWriter } from "./rlp/RLPWriter.sol";
*/ */
library Encoding { library Encoding {
/** /**
* Generates the correct cross domain calldata for a message. * @notice RLP encodes the L2 transaction that would be generated when a given deposit is sent
* @param _target Target contract address. * to the L2 system. Useful for searching for a deposit in the L2 system.
* @param _sender Message sender address. *
* @param _message Message to send to the target. * @param _from Address of the sender of the deposit.
* @param _messageNonce Nonce for the provided message. * @param _to Address of the receiver of the deposit.
* @return ABI encoded cross domain calldata. * @param _value ETH value to send to the receiver.
* @param _mint ETH value to mint on L2.
* @param _gasLimit Gas limit to use for the transaction.
* @param _isCreation Whether or not the transaction is a contract creation.
* @param _data Data to send with the transaction.
* @param _l1BlockHash Hash of the L1 block where the deposit was included.
* @param _logIndex Index of the deposit event in the L1 block.
*
* @return RLP encoded L2 deposit transaction.
*/ */
function encodeXDomainCalldata( function encodeDepositTransaction(
address _target,
address _sender,
bytes memory _message,
uint256 _messageNonce
) internal pure returns (bytes memory) {
return
abi.encodeWithSignature(
"relayMessage(address,address,bytes,uint256)",
_target,
_sender,
_message,
_messageNonce
);
}
/**
* @notice RLP encode a deposit transaction
* This only works for user deposits, not system deposits
* TODO: better name + rearrange the input param ordering?
*/
function L2Transaction(
bytes32 _l1BlockHash,
uint256 _logIndex,
address _from, address _from,
address _to, address _to,
bool _isCreate,
uint256 _mint,
uint256 _value, uint256 _value,
uint256 _gas, uint256 _mint,
bytes memory _data uint64 _gasLimit,
bool _isCreation,
bytes memory _data,
bytes32 _l1BlockHash,
uint256 _logIndex
) internal pure returns (bytes memory) { ) internal pure returns (bytes memory) {
bytes32 source = Hashing.sourceHash(_l1BlockHash, _logIndex); bytes32 source = Hashing.hashDepositSource(_l1BlockHash, _logIndex);
bytes[] memory raw = new bytes[](7); bytes[] memory raw = new bytes[](7);
raw[0] = RLPWriter.writeBytes(abi.encodePacked(source)); raw[0] = RLPWriter.writeBytes(abi.encodePacked(source));
raw[1] = RLPWriter.writeAddress(_from); raw[1] = RLPWriter.writeAddress(_from);
raw[2] = _isCreation ? RLPWriter.writeBytes("") : RLPWriter.writeAddress(_to);
if (_isCreate == true) {
require(_to == address(0));
raw[2] = RLPWriter.writeBytes("");
} else {
raw[2] = RLPWriter.writeAddress(_to);
}
raw[3] = RLPWriter.writeUint(_mint); raw[3] = RLPWriter.writeUint(_mint);
raw[4] = RLPWriter.writeUint(_value); raw[4] = RLPWriter.writeUint(_value);
raw[5] = RLPWriter.writeUint(_gas); raw[5] = RLPWriter.writeUint(uint256(_gasLimit));
raw[6] = RLPWriter.writeBytes(_data); raw[6] = RLPWriter.writeBytes(_data);
return abi.encodePacked(uint8(0x7e), uint8(0x0), RLPWriter.writeList(raw));
bytes memory encoded = RLPWriter.writeList(raw);
return abi.encodePacked(uint8(0x7e), uint8(0x0), encoded);
} }
/** /**
* @notice Encodes the cross domain message based on the version that * @notice Encodes the cross domain message based on the version that is encoded into the
* is encoded in the nonce * message nonce.
*
* @param _nonce Message nonce with version encoded into the first two bytes.
* @param _sender Address of the sender of the message.
* @param _target Address of the target of the message.
* @param _value ETH value to send to the target.
* @param _gasLimit Gas limit to use for the message.
* @param _data Data to send with the message.
*
* @return Encoded cross domain message.
*/ */
function getVersionedEncoding( function encodeCrossDomainMessage(
uint256 _nonce, uint256 _nonce,
address _sender, address _sender,
address _target, address _target,
...@@ -84,32 +69,55 @@ library Encoding { ...@@ -84,32 +69,55 @@ library Encoding {
uint256 _gasLimit, uint256 _gasLimit,
bytes memory _data bytes memory _data
) internal pure returns (bytes memory) { ) internal pure returns (bytes memory) {
uint16 version = getVersionFromNonce(_nonce); (, uint16 version) = decodeVersionedNonce(_nonce);
if (version == 0) { if (version == 0) {
return getEncodingV0(_target, _sender, _data, _nonce); return encodeCrossDomainMessageV0(_target, _sender, _data, _nonce);
} else if (version == 1) { } else if (version == 1) {
return getEncodingV1(_nonce, _sender, _target, _value, _gasLimit, _data); return encodeCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);
} else {
revert("Encoding: unknown cross domain message version");
} }
revert("Unknown version.");
} }
/** /**
* @notice Compute the legacy cross domain serialization * @notice Encodes a cross domain message based on the V0 (legacy) encoding.
*
* @param _target Address of the target of the message.
* @param _sender Address of the sender of the message.
* @param _data Data to send with the message.
* @param _nonce Message nonce.
*
* @return Encoded cross domain message.
*/ */
function getEncodingV0( function encodeCrossDomainMessageV0(
address _target, address _target,
address _sender, address _sender,
bytes memory _data, bytes memory _data,
uint256 _nonce uint256 _nonce
) internal pure returns (bytes memory) { ) internal pure returns (bytes memory) {
return encodeXDomainCalldata(_target, _sender, _data, _nonce); return
abi.encodeWithSignature(
"relayMessage(address,address,bytes,uint256)",
_target,
_sender,
_data,
_nonce
);
} }
/** /**
* @notice Compute the V1 cross domain serialization * @notice Encodes a cross domain message based on the V1 (current) encoding.
*
* @param _nonce Message nonce.
* @param _sender Address of the sender of the message.
* @param _target Address of the target of the message.
* @param _value ETH value to send to the target.
* @param _gasLimit Gas limit to use for the message.
* @param _data Data to send with the message.
*
* @return Encoded cross domain message.
*/ */
function getEncodingV1( function encodeCrossDomainMessageV1(
uint256 _nonce, uint256 _nonce,
address _sender, address _sender,
address _target, address _target,
...@@ -130,24 +138,36 @@ library Encoding { ...@@ -130,24 +138,36 @@ library Encoding {
} }
/** /**
* @notice Adds the version to the nonce * @notice Adds a version number into the first two bytes of a message nonce.
*
* @param _nonce Message nonce to encode into.
* @param _version Version number to encode into the message nonce.
*
* @return Message nonce with version encoded into the first two bytes.
*/ */
function addVersionToNonce(uint256 _nonce, uint16 _version) function encodeVersionedNonce(uint240 _nonce, uint16 _version) internal pure returns (uint256) {
internal uint256 nonce;
pure
returns (uint256 nonce)
{
assembly { assembly {
nonce := or(shl(240, _version), _nonce) nonce := or(shl(240, _version), _nonce)
} }
return nonce;
} }
/** /**
* @notice Gets the version out of the nonce * @notice Pulls the version out of a version-encoded nonce.
*
* @param _nonce Message nonce with version encoded into the first two bytes.
*
* @return Nonce without encoded version.
* @return Version of the message.
*/ */
function getVersionFromNonce(uint256 _nonce) internal pure returns (uint16 version) { function decodeVersionedNonce(uint256 _nonce) internal pure returns (uint240, uint16) {
uint240 nonce;
uint16 version;
assembly { assembly {
nonce := and(_nonce, 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
version := shr(240, _nonce) version := shr(240, _nonce)
} }
return (nonce, version);
} }
} }
...@@ -8,7 +8,10 @@ import { Encoding } from "./Encoding.sol"; ...@@ -8,7 +8,10 @@ import { Encoding } from "./Encoding.sol";
* @notice Hashing handles Optimism's various different hashing schemes. * @notice Hashing handles Optimism's various different hashing schemes.
*/ */
library Hashing { library Hashing {
/// @notice A struct containing the elements hashed together to generate the output root. /**
* @notice Struct representing the elements that are hashed together to generate an output root
* which itself represents a snapshot of the L2 state.
*/
struct OutputRootProof { struct OutputRootProof {
bytes32 version; bytes32 version;
bytes32 stateRoot; bytes32 stateRoot;
...@@ -17,66 +20,81 @@ library Hashing { ...@@ -17,66 +20,81 @@ library Hashing {
} }
/** /**
* @notice Compute the L2 transaction hash given * @notice Computes the hash of the RLP encoded L2 transaction that would be generated when a
* data about an L1 deposit transaction. This is useful for * given deposit is sent to the L2 system. Useful for searching for a deposit in the L2
* environments that do not have access to arbitrary * system.
* RLP encoding functionality but have access to the *
* standard web3 API * @param _from Address of the sender of the deposit.
* TODO: rearrange args in a sane way * @param _to Address of the receiver of the deposit.
* @param _l1BlockHash The L1 block hash corresponding to the block * @param _value ETH value to send to the receiver.
* the deposit was included in * @param _mint ETH value to mint on L2.
* @param _logIndex The log index of the event that the deposit was * @param _gasLimit Gas limit to use for the transaction.
* created from. This can be found on the transaction receipt * @param _isCreation Whether or not the transaction is a contract creation.
* @param _from The sender of the deposit * @param _data Data to send with the transaction.
* @param _to The L2 contract to be called by the deposit transaction * @param _l1BlockHash Hash of the L1 block where the deposit was included.
* @param _isCreate Indicates if the deposit creates a contract * @param _logIndex Index of the deposit event in the L1 block.
* @param _mint The amount of ETH being minted by the transaction *
* @param _value The amount of ETH send in the L2 call * @return Hash of the RLP encoded L2 deposit transaction.
* @param _gas The gas limit for the L2 call
*/ */
function L2TransactionHash( function hashDepositTransaction(
bytes32 _l1BlockHash,
uint256 _logIndex,
address _from, address _from,
address _to, address _to,
bool _isCreate,
uint256 _mint,
uint256 _value, uint256 _value,
uint256 _gas, uint256 _mint,
bytes memory _data uint64 _gasLimit,
bool _isCreation,
bytes memory _data,
bytes32 _l1BlockHash,
uint256 _logIndex
) internal pure returns (bytes32) { ) internal pure returns (bytes32) {
bytes memory raw = Encoding.L2Transaction( bytes memory raw = Encoding.encodeDepositTransaction(
_l1BlockHash,
_logIndex,
_from, _from,
_to, _to,
_isCreate,
_mint,
_value, _value,
_gas, _mint,
_data _gasLimit,
_isCreation,
_data,
_l1BlockHash,
_logIndex
); );
return keccak256(raw); return keccak256(raw);
} }
/** /**
* @notice Compute the deposit transaction source hash. * @notice Computes the deposit transaction's "source hash", a value that guarantees the hash
* This value ensures that the L2 transaction hash is unique * of the L2 transaction that corresponds to a deposit is unique and is
* and deterministic based on L1 execution * deterministically generated from L1 transaction data.
* @param l1BlockHash The L1 blockhash corresponding to the block including *
* the deposit * @param _l1BlockHash Hash of the L1 block where the deposit was included.
* @param logIndex The index of the log that created the deposit transaction * @param _logIndex The index of the log that created the deposit transaction.
*
* @return Hash of the deposit transaction's "source hash".
*/ */
function sourceHash(bytes32 l1BlockHash, uint256 logIndex) internal pure returns (bytes32) { function hashDepositSource(bytes32 _l1BlockHash, uint256 _logIndex)
bytes32 depositId = keccak256(abi.encode(l1BlockHash, logIndex)); internal
pure
returns (bytes32)
{
bytes32 depositId = keccak256(abi.encode(_l1BlockHash, _logIndex));
return keccak256(abi.encode(bytes32(0), depositId)); return keccak256(abi.encode(bytes32(0), depositId));
} }
/** /**
* @notice Compute the cross domain hash based on the versioned nonce * @notice Hashes the cross domain message based on the version that is encoded into the
* message nonce.
*
* @param _nonce Message nonce with version encoded into the first two bytes.
* @param _sender Address of the sender of the message.
* @param _target Address of the target of the message.
* @param _value ETH value to send to the target.
* @param _gasLimit Gas limit to use for the message.
* @param _data Data to send with the message.
*
* @return Hashed cross domain message.
*/ */
function getVersionedHash( function hashCrossDomainMessage(
uint256 _nonce, uint256 _nonce,
address _sender, address _sender,
address _target, address _target,
...@@ -84,32 +102,48 @@ library Hashing { ...@@ -84,32 +102,48 @@ library Hashing {
uint256 _gasLimit, uint256 _gasLimit,
bytes memory _data bytes memory _data
) internal pure returns (bytes32) { ) internal pure returns (bytes32) {
uint16 version = Encoding.getVersionFromNonce(_nonce); (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);
if (version == 0) { if (version == 0) {
return getHashV0(_target, _sender, _data, _nonce); return hashCrossDomainMessageV0(_target, _sender, _data, _nonce);
} else if (version == 1) { } else if (version == 1) {
return getHashV1(_nonce, _sender, _target, _value, _gasLimit, _data); return hashCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);
} else {
revert("Hashing: unknown cross domain message version");
} }
revert("Unknown version.");
} }
/** /**
* @notice Compute the legacy hash of a cross domain message * @notice Hashes a cross domain message based on the V0 (legacy) encoding.
*
* @param _target Address of the target of the message.
* @param _sender Address of the sender of the message.
* @param _data Data to send with the message.
* @param _nonce Message nonce.
*
* @return Hashed cross domain message.
*/ */
function getHashV0( function hashCrossDomainMessageV0(
address _target, address _target,
address _sender, address _sender,
bytes memory _data, bytes memory _data,
uint256 _nonce uint256 _nonce
) internal pure returns (bytes32) { ) internal pure returns (bytes32) {
return keccak256(Encoding.getEncodingV0(_target, _sender, _data, _nonce)); return keccak256(Encoding.encodeCrossDomainMessageV0(_target, _sender, _data, _nonce));
} }
/** /**
* @notice Compute the V1 hash of a cross domain message * @notice Hashes a cross domain message based on the V1 (current) encoding.
*
* @param _nonce Message nonce.
* @param _sender Address of the sender of the message.
* @param _target Address of the target of the message.
* @param _value ETH value to send to the target.
* @param _gasLimit Gas limit to use for the message.
* @param _data Data to send with the message.
*
* @return Hashed cross domain message.
*/ */
function getHashV1( function hashCrossDomainMessageV1(
uint256 _nonce, uint256 _nonce,
address _sender, address _sender,
address _target, address _target,
...@@ -118,7 +152,16 @@ library Hashing { ...@@ -118,7 +152,16 @@ library Hashing {
bytes memory _data bytes memory _data
) internal pure returns (bytes32) { ) internal pure returns (bytes32) {
return return
keccak256(Encoding.getEncodingV1(_nonce, _sender, _target, _value, _gasLimit, _data)); keccak256(
Encoding.encodeCrossDomainMessageV1(
_nonce,
_sender,
_target,
_value,
_gasLimit,
_data
)
);
} }
/** /**
...@@ -130,7 +173,7 @@ library Hashing { ...@@ -130,7 +173,7 @@ library Hashing {
* @param _gasLimit Gas to be forwarded to the target. * @param _gasLimit Gas to be forwarded to the target.
* @param _data Data to send to the target. * @param _data Data to send to the target.
*/ */
function withdrawalHash( function hashWithdrawal(
uint256 _nonce, uint256 _nonce,
address _sender, address _sender,
address _target, address _target,
...@@ -142,11 +185,14 @@ library Hashing { ...@@ -142,11 +185,14 @@ library Hashing {
} }
/** /**
* @notice Derives the output root corresponding to the elements provided in the proof. * @notice Hashes the various elements of an output root proof into an output root hash which
* @param _outputRootProof The elements which were hashed together to generate the output root. * can be used to check if the proof is valid.
* @return Whether or not the output root matches the hashed output of the proof. *
* @param _outputRootProof Output root proof which should hash to an output root.
*
* @return Hashed output root proof.
*/ */
function _deriveOutputRoot(OutputRootProof memory _outputRootProof) function hashOutputRootProof(OutputRootProof memory _outputRootProof)
internal internal
pure pure
returns (bytes32) returns (bytes32)
......
...@@ -2,41 +2,42 @@ ...@@ -2,41 +2,42 @@
pragma solidity ^0.8.9; pragma solidity ^0.8.9;
/** /**
* @custom:attribution https://github.com/hamdiallam/Solidity-RLP
* @title RLPReader * @title RLPReader
* @dev Adapted from "RLPReader" by Hamdi Allam (hamdi.allam97@gmail.com). * @notice RLPReader is a library for parsing RLP-encoded byte arrays into Solidity types. Adapted
* from Solidity-RLP (https://github.com/hamdiallam/Solidity-RLP) by Hamdi Allam with
* various tweaks to improve readability.
*/ */
library RLPReader { library RLPReader {
/************* /**
* Constants * * @notice Max list length that this library will accept.
*************/ */
uint256 internal constant MAX_LIST_LENGTH = 32; uint256 internal constant MAX_LIST_LENGTH = 32;
/********* /**
* Enums * * @notice RLP item types.
*********/ *
* @custom:value DATA_ITEM Represents an RLP data item (NOT a list).
* @custom:value LIST_ITEM Represents an RLP list item.
*/
enum RLPItemType { enum RLPItemType {
DATA_ITEM, DATA_ITEM,
LIST_ITEM LIST_ITEM
} }
/*********** /**
* Structs * * @notice Struct representing an RLP item.
***********/ */
struct RLPItem { struct RLPItem {
uint256 length; uint256 length;
uint256 ptr; uint256 ptr;
} }
/**********************
* Internal Functions *
**********************/
/** /**
* Converts bytes to a reference to memory position and length. * @notice Converts bytes to a reference to memory position and length.
*
* @param _in Input bytes to convert. * @param _in Input bytes to convert.
*
* @return Output memory reference. * @return Output memory reference.
*/ */
function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory) { function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory) {
...@@ -49,8 +50,10 @@ library RLPReader { ...@@ -49,8 +50,10 @@ library RLPReader {
} }
/** /**
* Reads an RLP list value into a list of RLP items. * @notice Reads an RLP list value into a list of RLP items.
*
* @param _in RLP list value. * @param _in RLP list value.
*
* @return Decoded RLP list items. * @return Decoded RLP list items.
*/ */
function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory) { function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory) {
...@@ -88,8 +91,10 @@ library RLPReader { ...@@ -88,8 +91,10 @@ library RLPReader {
} }
/** /**
* Reads an RLP list value into a list of RLP items. * @notice Reads an RLP list value into a list of RLP items.
*
* @param _in RLP list value. * @param _in RLP list value.
*
* @return Decoded RLP list items. * @return Decoded RLP list items.
*/ */
function readList(bytes memory _in) internal pure returns (RLPItem[] memory) { function readList(bytes memory _in) internal pure returns (RLPItem[] memory) {
...@@ -97,8 +102,10 @@ library RLPReader { ...@@ -97,8 +102,10 @@ library RLPReader {
} }
/** /**
* Reads an RLP bytes value into bytes. * @notice Reads an RLP bytes value into bytes.
*
* @param _in RLP bytes value. * @param _in RLP bytes value.
*
* @return Decoded bytes. * @return Decoded bytes.
*/ */
function readBytes(RLPItem memory _in) internal pure returns (bytes memory) { function readBytes(RLPItem memory _in) internal pure returns (bytes memory) {
...@@ -110,8 +117,10 @@ library RLPReader { ...@@ -110,8 +117,10 @@ library RLPReader {
} }
/** /**
* Reads an RLP bytes value into bytes. * @notice Reads an RLP bytes value into bytes.
*
* @param _in RLP bytes value. * @param _in RLP bytes value.
*
* @return Decoded bytes. * @return Decoded bytes.
*/ */
function readBytes(bytes memory _in) internal pure returns (bytes memory) { function readBytes(bytes memory _in) internal pure returns (bytes memory) {
...@@ -119,8 +128,10 @@ library RLPReader { ...@@ -119,8 +128,10 @@ library RLPReader {
} }
/** /**
* Reads an RLP string value into a string. * @notice Reads an RLP string value into a string.
*
* @param _in RLP string value. * @param _in RLP string value.
*
* @return Decoded string. * @return Decoded string.
*/ */
function readString(RLPItem memory _in) internal pure returns (string memory) { function readString(RLPItem memory _in) internal pure returns (string memory) {
...@@ -128,8 +139,10 @@ library RLPReader { ...@@ -128,8 +139,10 @@ library RLPReader {
} }
/** /**
* Reads an RLP string value into a string. * @notice Reads an RLP string value into a string.
*
* @param _in RLP string value. * @param _in RLP string value.
*
* @return Decoded string. * @return Decoded string.
*/ */
function readString(bytes memory _in) internal pure returns (string memory) { function readString(bytes memory _in) internal pure returns (string memory) {
...@@ -137,8 +150,10 @@ library RLPReader { ...@@ -137,8 +150,10 @@ library RLPReader {
} }
/** /**
* Reads an RLP bytes32 value into a bytes32. * @notice Reads an RLP bytes32 value into a bytes32.
*
* @param _in RLP bytes32 value. * @param _in RLP bytes32 value.
*
* @return Decoded bytes32. * @return Decoded bytes32.
*/ */
function readBytes32(RLPItem memory _in) internal pure returns (bytes32) { function readBytes32(RLPItem memory _in) internal pure returns (bytes32) {
...@@ -163,8 +178,10 @@ library RLPReader { ...@@ -163,8 +178,10 @@ library RLPReader {
} }
/** /**
* Reads an RLP bytes32 value into a bytes32. * @notice Reads an RLP bytes32 value into a bytes32.
*
* @param _in RLP bytes32 value. * @param _in RLP bytes32 value.
*
* @return Decoded bytes32. * @return Decoded bytes32.
*/ */
function readBytes32(bytes memory _in) internal pure returns (bytes32) { function readBytes32(bytes memory _in) internal pure returns (bytes32) {
...@@ -172,8 +189,10 @@ library RLPReader { ...@@ -172,8 +189,10 @@ library RLPReader {
} }
/** /**
* Reads an RLP uint256 value into a uint256. * @notice Reads an RLP uint256 value into a uint256.
*
* @param _in RLP uint256 value. * @param _in RLP uint256 value.
*
* @return Decoded uint256. * @return Decoded uint256.
*/ */
function readUint256(RLPItem memory _in) internal pure returns (uint256) { function readUint256(RLPItem memory _in) internal pure returns (uint256) {
...@@ -181,8 +200,10 @@ library RLPReader { ...@@ -181,8 +200,10 @@ library RLPReader {
} }
/** /**
* Reads an RLP uint256 value into a uint256. * @notice Reads an RLP uint256 value into a uint256.
*
* @param _in RLP uint256 value. * @param _in RLP uint256 value.
*
* @return Decoded uint256. * @return Decoded uint256.
*/ */
function readUint256(bytes memory _in) internal pure returns (uint256) { function readUint256(bytes memory _in) internal pure returns (uint256) {
...@@ -190,8 +211,10 @@ library RLPReader { ...@@ -190,8 +211,10 @@ library RLPReader {
} }
/** /**
* Reads an RLP bool value into a bool. * @notice Reads an RLP bool value into a bool.
*
* @param _in RLP bool value. * @param _in RLP bool value.
*
* @return Decoded bool. * @return Decoded bool.
*/ */
function readBool(RLPItem memory _in) internal pure returns (bool) { function readBool(RLPItem memory _in) internal pure returns (bool) {
...@@ -209,8 +232,10 @@ library RLPReader { ...@@ -209,8 +232,10 @@ library RLPReader {
} }
/** /**
* Reads an RLP bool value into a bool. * @notice Reads an RLP bool value into a bool.
*
* @param _in RLP bool value. * @param _in RLP bool value.
*
* @return Decoded bool. * @return Decoded bool.
*/ */
function readBool(bytes memory _in) internal pure returns (bool) { function readBool(bytes memory _in) internal pure returns (bool) {
...@@ -218,8 +243,10 @@ library RLPReader { ...@@ -218,8 +243,10 @@ library RLPReader {
} }
/** /**
* Reads an RLP address value into a address. * @notice Reads an RLP address value into a address.
*
* @param _in RLP address value. * @param _in RLP address value.
*
* @return Decoded address. * @return Decoded address.
*/ */
function readAddress(RLPItem memory _in) internal pure returns (address) { function readAddress(RLPItem memory _in) internal pure returns (address) {
...@@ -233,8 +260,10 @@ library RLPReader { ...@@ -233,8 +260,10 @@ library RLPReader {
} }
/** /**
* Reads an RLP address value into a address. * @notice Reads an RLP address value into a address.
*
* @param _in RLP address value. * @param _in RLP address value.
*
* @return Decoded address. * @return Decoded address.
*/ */
function readAddress(bytes memory _in) internal pure returns (address) { function readAddress(bytes memory _in) internal pure returns (address) {
...@@ -242,8 +271,10 @@ library RLPReader { ...@@ -242,8 +271,10 @@ library RLPReader {
} }
/** /**
* Reads the raw bytes of an RLP item. * @notice Reads the raw bytes of an RLP item.
*
* @param _in RLP item to read. * @param _in RLP item to read.
*
* @return Raw RLP bytes. * @return Raw RLP bytes.
*/ */
function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory) { function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory) {
...@@ -255,8 +286,10 @@ library RLPReader { ...@@ -255,8 +286,10 @@ library RLPReader {
*********************/ *********************/
/** /**
* Decodes the length of an RLP item. * @notice Decodes the length of an RLP item.
*
* @param _in RLP item to decode. * @param _in RLP item to decode.
*
* @return Offset of the encoded data. * @return Offset of the encoded data.
* @return Length of the encoded data. * @return Length of the encoded data.
* @return RLP item type (LIST_ITEM or DATA_ITEM). * @return RLP item type (LIST_ITEM or DATA_ITEM).
...@@ -333,10 +366,12 @@ library RLPReader { ...@@ -333,10 +366,12 @@ library RLPReader {
} }
/** /**
* Copies the bytes from a memory location. * @notice Copies the bytes from a memory location.
*
* @param _src Pointer to the location to read from. * @param _src Pointer to the location to read from.
* @param _offset Offset to start reading from. * @param _offset Offset to start reading from.
* @param _length Number of bytes to read. * @param _length Number of bytes to read.
*
* @return Copied bytes. * @return Copied bytes.
*/ */
function _copy( function _copy(
...@@ -378,8 +413,10 @@ library RLPReader { ...@@ -378,8 +413,10 @@ library RLPReader {
} }
/** /**
* Copies an RLP item into bytes. * @notice Copies an RLP item into bytes.
*
* @param _in RLP item to copy. * @param _in RLP item to copy.
*
* @return Copied bytes. * @return Copied bytes.
*/ */
function _copy(RLPItem memory _in) private pure returns (bytes memory) { function _copy(RLPItem memory _in) private pure returns (bytes memory) {
......
...@@ -2,17 +2,18 @@ ...@@ -2,17 +2,18 @@
pragma solidity ^0.8.9; pragma solidity ^0.8.9;
/** /**
* @custom:attribution https://github.com/bakaoh/solidity-rlp-encode
* @title RLPWriter * @title RLPWriter
* @author Bakaoh (with modifications) * @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's
* RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor
* modifications to improve legibility.
*/ */
library RLPWriter { library RLPWriter {
/**********************
* Internal Functions *
**********************/
/** /**
* RLP encodes a byte string. * @notice RLP encodes a byte string.
*
* @param _in The byte string to encode. * @param _in The byte string to encode.
*
* @return The RLP encoded string in bytes. * @return The RLP encoded string in bytes.
*/ */
function writeBytes(bytes memory _in) internal pure returns (bytes memory) { function writeBytes(bytes memory _in) internal pure returns (bytes memory) {
...@@ -28,8 +29,10 @@ library RLPWriter { ...@@ -28,8 +29,10 @@ library RLPWriter {
} }
/** /**
* RLP encodes a list of RLP encoded byte byte strings. * @notice RLP encodes a list of RLP encoded byte byte strings.
*
* @param _in The list of RLP encoded byte strings. * @param _in The list of RLP encoded byte strings.
*
* @return The RLP encoded list of items in bytes. * @return The RLP encoded list of items in bytes.
*/ */
function writeList(bytes[] memory _in) internal pure returns (bytes memory) { function writeList(bytes[] memory _in) internal pure returns (bytes memory) {
...@@ -38,8 +41,10 @@ library RLPWriter { ...@@ -38,8 +41,10 @@ library RLPWriter {
} }
/** /**
* RLP encodes a string. * @notice RLP encodes a string.
*
* @param _in The string to encode. * @param _in The string to encode.
*
* @return The RLP encoded string in bytes. * @return The RLP encoded string in bytes.
*/ */
function writeString(string memory _in) internal pure returns (bytes memory) { function writeString(string memory _in) internal pure returns (bytes memory) {
...@@ -47,8 +52,10 @@ library RLPWriter { ...@@ -47,8 +52,10 @@ library RLPWriter {
} }
/** /**
* RLP encodes an address. * @notice RLP encodes an address.
*
* @param _in The address to encode. * @param _in The address to encode.
*
* @return The RLP encoded address in bytes. * @return The RLP encoded address in bytes.
*/ */
function writeAddress(address _in) internal pure returns (bytes memory) { function writeAddress(address _in) internal pure returns (bytes memory) {
...@@ -56,8 +63,10 @@ library RLPWriter { ...@@ -56,8 +63,10 @@ library RLPWriter {
} }
/** /**
* RLP encodes a uint. * @notice RLP encodes a uint.
*
* @param _in The uint256 to encode. * @param _in The uint256 to encode.
*
* @return The RLP encoded uint256 in bytes. * @return The RLP encoded uint256 in bytes.
*/ */
function writeUint(uint256 _in) internal pure returns (bytes memory) { function writeUint(uint256 _in) internal pure returns (bytes memory) {
...@@ -65,8 +74,10 @@ library RLPWriter { ...@@ -65,8 +74,10 @@ library RLPWriter {
} }
/** /**
* RLP encodes a bool. * @notice RLP encodes a bool.
*
* @param _in The bool to encode. * @param _in The bool to encode.
*
* @return The RLP encoded bool in bytes. * @return The RLP encoded bool in bytes.
*/ */
function writeBool(bool _in) internal pure returns (bytes memory) { function writeBool(bool _in) internal pure returns (bytes memory) {
...@@ -75,14 +86,12 @@ library RLPWriter { ...@@ -75,14 +86,12 @@ library RLPWriter {
return encoded; return encoded;
} }
/*********************
* Private Functions *
*********************/
/** /**
* Encode the first byte, followed by the `len` in binary form if `length` is more than 55. * @notice Encode the first byte and then the `len` in binary form if `length` is more than 55.
*
* @param _len The length of the string or the payload. * @param _len The length of the string or the payload.
* @param _offset 128 if item is string, 192 if item is list. * @param _offset 128 if item is string, 192 if item is list.
*
* @return RLP encoded bytes. * @return RLP encoded bytes.
*/ */
function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory) { function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory) {
...@@ -110,9 +119,10 @@ library RLPWriter { ...@@ -110,9 +119,10 @@ library RLPWriter {
} }
/** /**
* Encode integer in big endian binary form with no leading zeroes. * @notice Encode integer in big endian binary form with no leading zeroes.
* @notice TODO: This should be optimized with assembly to save gas costs. *
* @param _x The integer to encode. * @param _x The integer to encode.
*
* @return RLP encoded bytes. * @return RLP encoded bytes.
*/ */
function _toBinary(uint256 _x) private pure returns (bytes memory) { function _toBinary(uint256 _x) private pure returns (bytes memory) {
...@@ -134,8 +144,9 @@ library RLPWriter { ...@@ -134,8 +144,9 @@ library RLPWriter {
} }
/** /**
* Copies a piece of memory to another location. * @custom:attribution https://github.com/Arachnid/solidity-stringutils
* @notice From: https://github.com/Arachnid/solidity-stringutils/blob/master/src/strings.sol. * @notice Copies a piece of memory to another location.
*
* @param _dest Destination location. * @param _dest Destination location.
* @param _src Source location. * @param _src Source location.
* @param _len Length of memory to copy. * @param _len Length of memory to copy.
...@@ -169,9 +180,11 @@ library RLPWriter { ...@@ -169,9 +180,11 @@ library RLPWriter {
} }
/** /**
* Flattens a list of byte strings into one byte string. * @custom:attribution https://github.com/sammayo/solidity-rlp-encoder
* @notice From: https://github.com/sammayo/solidity-rlp-encoder/blob/master/RLPEncode.sol. * @notice Flattens a list of byte strings into one byte string.
*
* @param _list List of byte strings to flatten. * @param _list List of byte strings to flatten.
*
* @return The flattened byte string. * @return The flattened byte string.
*/ */
function _flatten(bytes[] memory _list) private pure returns (bytes memory) { function _flatten(bytes[] memory _list) private pure returns (bytes memory) {
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity ^0.8.9; pragma solidity ^0.8.9;
/* Library Imports */
import { BytesUtils } from "../BytesUtils.sol"; import { BytesUtils } from "../BytesUtils.sol";
import { RLPReader } from "../rlp/RLPReader.sol"; import { RLPReader } from "../rlp/RLPReader.sol";
import { RLPWriter } from "../rlp/RLPWriter.sol"; import { RLPWriter } from "../rlp/RLPWriter.sol";
/** /**
* @title MerkleTrie * @title MerkleTrie
* @notice MerkleTrie is a small library for verifying standard Ethereum Merkle-Patricia trie
* inclusion proofs. By default, this library assumes a hexary trie. One can change the
* trie radix constant to support other trie radixes.
*/ */
library MerkleTrie { library MerkleTrie {
/******************* /**
* Data Structures * * @notice Struct representing a node in the trie.
*******************/ */
struct TrieNode { struct TrieNode {
bytes encoded; bytes encoded;
RLPReader.RLPItem[] decoded; RLPReader.RLPItem[] decoded;
} }
/********************** /**
* Contract Constants * * @notice Determines the number of elements per branch node.
**********************/ */
// TREE_RADIX determines the number of elements per branch node.
uint256 constant TREE_RADIX = 16; uint256 constant TREE_RADIX = 16;
// Branch nodes have TREE_RADIX elements plus an additional `value` slot.
/**
* @notice Branch nodes have TREE_RADIX elements and one value element.
*/
uint256 constant BRANCH_NODE_LENGTH = TREE_RADIX + 1; uint256 constant BRANCH_NODE_LENGTH = TREE_RADIX + 1;
// Leaf nodes and extension nodes always have two elements, a `path` and a `value`.
/**
* @notice Leaf nodes and extension nodes have two elements, a `path` and a `value`.
*/
uint256 constant LEAF_OR_EXTENSION_NODE_LENGTH = 2; uint256 constant LEAF_OR_EXTENSION_NODE_LENGTH = 2;
// Prefixes are prepended to the `path` within a leaf or extension node and /**
// allow us to differentiate between the two node types. `ODD` or `EVEN` is * @notice Prefix for even-nibbled extension node paths.
// determined by the number of nibbles within the unprefixed `path`. If the */
// number of nibbles if even, we need to insert an extra padding nibble so
// the resulting prefixed `path` has an even number of nibbles.
uint8 constant PREFIX_EXTENSION_EVEN = 0; uint8 constant PREFIX_EXTENSION_EVEN = 0;
/**
* @notice Prefix for odd-nibbled extension node paths.
*/
uint8 constant PREFIX_EXTENSION_ODD = 1; uint8 constant PREFIX_EXTENSION_ODD = 1;
/**
* @notice Prefix for even-nibbled leaf node paths.
*/
uint8 constant PREFIX_LEAF_EVEN = 2; uint8 constant PREFIX_LEAF_EVEN = 2;
/**
* @notice Prefix for odd-nibbled leaf node paths.
*/
uint8 constant PREFIX_LEAF_ODD = 3; uint8 constant PREFIX_LEAF_ODD = 3;
// Just a utility constant. RLP represents `NULL` as 0x80. /**
* @notice RLP representation of `NULL`.
*/
bytes1 constant RLP_NULL = bytes1(0x80); bytes1 constant RLP_NULL = bytes1(0x80);
/**********************
* Internal Functions *
**********************/
/** /**
* @notice Verifies a proof that a given key/value pair is present in the * @notice Verifies a proof that a given key/value pair is present in the trie.
* Merkle trie. *
* @param _key Key of the node to search for, as a hex string. * @param _key Key of the node to search for, as a hex string.
* @param _value Value of the node to search for, as a hex string. * @param _value Value of the node to search for, as a hex string.
* @param _proof Merkle trie inclusion proof for the desired node. Unlike * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle
* traditional Merkle trees, this proof is executed top-down and consists * trees, this proof is executed top-down and consists of a list of RLP-encoded
* of a list of RLP-encoded nodes that make a path down to the target node. * nodes that make a path down to the target node.
* @param _root Known root of the Merkle trie. Used to verify that the * @param _root Known root of the Merkle trie. Used to verify that the included proof is
* included proof is correctly constructed. * correctly constructed.
* @return _verified `true` if the k/v pair exists in the trie, `false` otherwise. *
* @return Whether or not the proof is valid.
*/ */
function verifyInclusionProof( function verifyInclusionProof(
bytes memory _key, bytes memory _key,
bytes memory _value, bytes memory _value,
bytes memory _proof, bytes memory _proof,
bytes32 _root bytes32 _root
) internal pure returns (bool _verified) { ) internal pure returns (bool) {
(bool exists, bytes memory value) = get(_key, _proof, _root); (bool exists, bytes memory value) = get(_key, _proof, _root);
return (exists && BytesUtils.equal(_value, value)); return (exists && BytesUtils.equal(_value, value));
} }
/** /**
* @notice Retrieves the value associated with a given key. * @notice Retrieves the value associated with a given key.
*
* @param _key Key to search for, as hex bytes. * @param _key Key to search for, as hex bytes.
* @param _proof Merkle trie inclusion proof for the key. * @param _proof Merkle trie inclusion proof for the key.
* @param _root Known root of the Merkle trie. * @param _root Known root of the Merkle trie.
* @return _exists Whether or not the key exists. *
* @return _value Value of the key if it exists. * @return Whether or not the key exists.
* @return Value of the key if it exists.
*/ */
function get( function get(
bytes memory _key, bytes memory _key,
bytes memory _proof, bytes memory _proof,
bytes32 _root bytes32 _root
) internal pure returns (bool _exists, bytes memory _value) { ) internal pure returns (bool, bytes memory) {
TrieNode[] memory proof = _parseProof(_proof); TrieNode[] memory proof = _parseProof(_proof);
(uint256 pathLength, bytes memory keyRemainder, bool isFinalNode) = _walkNodePath( (uint256 pathLength, bytes memory keyRemainder, bool isFinalNode) = _walkNodePath(
proof, proof,
...@@ -99,18 +114,16 @@ library MerkleTrie { ...@@ -99,18 +114,16 @@ library MerkleTrie {
return (exists, value); return (exists, value);
} }
/*********************
* Private Functions *
*********************/
/** /**
* @notice Walks through a proof using a provided key. * @notice Walks through a proof using a provided key.
*
* @param _proof Inclusion proof to walk through. * @param _proof Inclusion proof to walk through.
* @param _key Key to use for the walk. * @param _key Key to use for the walk.
* @param _root Known root of the trie. * @param _root Known root of the trie.
* @return _pathLength Length of the final path *
* @return _keyRemainder Portion of the key remaining after the walk. * @return Length of the final path
* @return _isFinalNode Whether or not we've hit a dead end. * @return Portion of the key remaining after the walk.
* @return Whether or not we've hit a dead end.
*/ */
function _walkNodePath( function _walkNodePath(
TrieNode[] memory _proof, TrieNode[] memory _proof,
...@@ -120,9 +133,9 @@ library MerkleTrie { ...@@ -120,9 +133,9 @@ library MerkleTrie {
private private
pure pure
returns ( returns (
uint256 _pathLength, uint256,
bytes memory _keyRemainder, bytes memory,
bool _isFinalNode bool
) )
{ {
uint256 pathLength = 0; uint256 pathLength = 0;
...@@ -223,10 +236,12 @@ library MerkleTrie { ...@@ -223,10 +236,12 @@ library MerkleTrie {
/** /**
* @notice Parses an RLP-encoded proof into something more useful. * @notice Parses an RLP-encoded proof into something more useful.
*
* @param _proof RLP-encoded proof to parse. * @param _proof RLP-encoded proof to parse.
* @return _parsed Proof parsed into easily accessible structs. *
* @return Proof parsed into easily accessible structs.
*/ */
function _parseProof(bytes memory _proof) private pure returns (TrieNode[] memory _parsed) { function _parseProof(bytes memory _proof) private pure returns (TrieNode[] memory) {
RLPReader.RLPItem[] memory nodes = RLPReader.readList(_proof); RLPReader.RLPItem[] memory nodes = RLPReader.readList(_proof);
TrieNode[] memory proof = new TrieNode[](nodes.length); TrieNode[] memory proof = new TrieNode[](nodes.length);
...@@ -239,13 +254,14 @@ library MerkleTrie { ...@@ -239,13 +254,14 @@ library MerkleTrie {
} }
/** /**
* @notice Picks out the ID for a node. Node ID is referred to as the * @notice Picks out the ID for a node. Node ID is referred to as the "hash" within the
* "hash" within the specification, but nodes < 32 bytes are not actually * specification, but nodes < 32 bytes are not actually hashed.
* hashed. *
* @param _node Node to pull an ID for. * @param _node Node to pull an ID for.
* @return _nodeID ID for the node, depending on the size of its contents. *
* @return ID for the node, depending on the size of its contents.
*/ */
function _getNodeID(RLPReader.RLPItem memory _node) private pure returns (bytes32 _nodeID) { function _getNodeID(RLPReader.RLPItem memory _node) private pure returns (bytes32) {
bytes memory nodeID; bytes memory nodeID;
if (_node.length < 32) { if (_node.length < 32) {
...@@ -261,33 +277,38 @@ library MerkleTrie { ...@@ -261,33 +277,38 @@ library MerkleTrie {
/** /**
* @notice Gets the path for a leaf or extension node. * @notice Gets the path for a leaf or extension node.
*
* @param _node Node to get a path for. * @param _node Node to get a path for.
* @return _path Node path, converted to an array of nibbles. *
* @return Node path, converted to an array of nibbles.
*/ */
function _getNodePath(TrieNode memory _node) private pure returns (bytes memory _path) { function _getNodePath(TrieNode memory _node) private pure returns (bytes memory) {
return BytesUtils.toNibbles(RLPReader.readBytes(_node.decoded[0])); return BytesUtils.toNibbles(RLPReader.readBytes(_node.decoded[0]));
} }
/** /**
* @notice Gets the path for a node. * @notice Gets the path for a node.
*
* @param _node Node to get a value for. * @param _node Node to get a value for.
* @return _value Node value, as hex bytes. *
* @return Node value, as hex bytes.
*/ */
function _getNodeValue(TrieNode memory _node) private pure returns (bytes memory _value) { function _getNodeValue(TrieNode memory _node) private pure returns (bytes memory) {
return RLPReader.readBytes(_node.decoded[_node.decoded.length - 1]); return RLPReader.readBytes(_node.decoded[_node.decoded.length - 1]);
} }
/** /**
* @notice Utility; determines the number of nibbles shared between two * @notice Utility; determines the number of nibbles shared between two nibble arrays.
* nibble arrays. *
* @param _a First nibble array. * @param _a First nibble array.
* @param _b Second nibble array. * @param _b Second nibble array.
* @return _shared Number of shared nibbles. *
* @return Number of shared nibbles.
*/ */
function _getSharedNibbleLength(bytes memory _a, bytes memory _b) function _getSharedNibbleLength(bytes memory _a, bytes memory _b)
private private
pure pure
returns (uint256 _shared) returns (uint256)
{ {
uint256 i = 0; uint256 i = 0;
while (_a.length > i && _b.length > i && _a[i] == _b[i]) { while (_a.length > i && _b.length > i && _a[i] == _b[i]) {
......
...@@ -6,61 +6,60 @@ import { MerkleTrie } from "./MerkleTrie.sol"; ...@@ -6,61 +6,60 @@ import { MerkleTrie } from "./MerkleTrie.sol";
/** /**
* @title SecureMerkleTrie * @title SecureMerkleTrie
* @notice SecureMerkleTrie is a thin wrapper around the MerkleTrie library that hashes the input
* keys. Ethereum's state trie hashes input keys before storing them.
*/ */
library SecureMerkleTrie { library SecureMerkleTrie {
/**********************
* Internal Functions *
**********************/
/** /**
* @notice Verifies a proof that a given key/value pair is present in the * @notice Verifies a proof that a given key/value pair is present in the Merkle trie.
* Merkle trie. *
* @param _key Key of the node to search for, as a hex string. * @param _key Key of the node to search for, as a hex string.
* @param _value Value of the node to search for, as a hex string. * @param _value Value of the node to search for, as a hex string.
* @param _proof Merkle trie inclusion proof for the desired node. Unlike * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle
* traditional Merkle trees, this proof is executed top-down and consists * trees, this proof is executed top-down and consists of a list of RLP-encoded
* of a list of RLP-encoded nodes that make a path down to the target node. * nodes that make a path down to the target node.
* @param _root Known root of the Merkle trie. Used to verify that the * @param _root Known root of the Merkle trie. Used to verify that the included proof is
* included proof is correctly constructed. * correctly constructed.
* @return _verified `true` if the k/v pair exists in the trie, `false` otherwise. *
* @return Whether or not the proof is valid.
*/ */
function verifyInclusionProof( function verifyInclusionProof(
bytes memory _key, bytes memory _key,
bytes memory _value, bytes memory _value,
bytes memory _proof, bytes memory _proof,
bytes32 _root bytes32 _root
) internal pure returns (bool _verified) { ) internal pure returns (bool) {
bytes memory key = _getSecureKey(_key); bytes memory key = _getSecureKey(_key);
return MerkleTrie.verifyInclusionProof(key, _value, _proof, _root); return MerkleTrie.verifyInclusionProof(key, _value, _proof, _root);
} }
/** /**
* @notice Retrieves the value associated with a given key. * @notice Retrieves the value associated with a given key.
*
* @param _key Key to search for, as hex bytes. * @param _key Key to search for, as hex bytes.
* @param _proof Merkle trie inclusion proof for the key. * @param _proof Merkle trie inclusion proof for the key.
* @param _root Known root of the Merkle trie. * @param _root Known root of the Merkle trie.
* @return _exists Whether or not the key exists. *
* @return _value Value of the key if it exists. * @return Whether or not the key exists.
* @return Value of the key if it exists.
*/ */
function get( function get(
bytes memory _key, bytes memory _key,
bytes memory _proof, bytes memory _proof,
bytes32 _root bytes32 _root
) internal pure returns (bool _exists, bytes memory _value) { ) internal pure returns (bool, bytes memory) {
bytes memory key = _getSecureKey(_key); bytes memory key = _getSecureKey(_key);
return MerkleTrie.get(key, _proof, _root); return MerkleTrie.get(key, _proof, _root);
} }
/*********************
* Private Functions *
*********************/
/** /**
* Computes the secure counterpart to a key. * @notice Computes the hashed version of the input key.
* @param _key Key to get a secure key from. *
* @return _secureKey Secure version of the key. * @param _key Key to hash.
*
* @return Hashed version of the key.
*/ */
function _getSecureKey(bytes memory _key) private pure returns (bytes memory _secureKey) { function _getSecureKey(bytes memory _key) private pure returns (bytes memory) {
return abi.encodePacked(keccak256(_key)); return abi.encodePacked(keccak256(_key));
} }
} }
...@@ -6,8 +6,29 @@ import { Encoding } from "../libraries/Encoding.sol"; ...@@ -6,8 +6,29 @@ import { Encoding } from "../libraries/Encoding.sol";
contract Encoding_Test is CommonTest { contract Encoding_Test is CommonTest {
function test_nonceVersioning(uint240 _nonce, uint16 _version) external { function test_nonceVersioning(uint240 _nonce, uint16 _version) external {
uint256 nonce = Encoding.addVersionToNonce(uint256(_nonce), _version); (uint240 nonce, uint16 version) = Encoding.decodeVersionedNonce(
uint16 version = Encoding.getVersionFromNonce(nonce); Encoding.encodeVersionedNonce(_nonce, _version)
);
assertEq(version, _version); assertEq(version, _version);
assertEq(nonce, _nonce);
}
function test_encodeDepositTransaction() external {
bytes memory raw = Encoding.encodeDepositTransaction(
0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266,
0xB79f76EF2c5F0286176833E7B2eEe103b1CC3244,
0xde0b6b3a7640000,
0xe043da617250000,
0x2dc6c0,
false,
hex"",
0xd25df7858efc1778118fb133ac561b138845361626dfb976699c5287ed0f4959,
0x1
);
assertEq(
raw,
hex"7e00f862a0f923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc94f39fd6e51aad88f6f4ce6ab8827279cfffb9226694b79f76ef2c5f0286176833e7b2eee103b1cc3244880e043da617250000880de0b6b3a7640000832dc6c080"
);
} }
} }
...@@ -8,54 +8,29 @@ import { Encoding } from "../libraries/Encoding.sol"; ...@@ -8,54 +8,29 @@ import { Encoding } from "../libraries/Encoding.sol";
contract Hashing_Test is CommonTest { contract Hashing_Test is CommonTest {
// TODO(tynes): turn this into differential fuzzing // TODO(tynes): turn this into differential fuzzing
// it is very easy to do so with the typescript // it is very easy to do so with the typescript
function test_l2TransactionHash() external { function test_hashDepositSource() external {
bytes32 l1BlockHash = 0xd25df7858efc1778118fb133ac561b138845361626dfb976699c5287ed0f4959; bytes32 sourceHash = Hashing.hashDepositSource(
uint256 logIndex = 0x1; 0xd25df7858efc1778118fb133ac561b138845361626dfb976699c5287ed0f4959,
address from = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; 0x1
address to = 0xB79f76EF2c5F0286176833E7B2eEe103b1CC3244;
bool isCreate = false;
uint256 mint = 0xe043da617250000;
uint256 value = 0xde0b6b3a7640000;
uint256 gas = 0x2dc6c0;
bytes memory data = hex"";
bytes32 sourceHash = Hashing.sourceHash(
l1BlockHash,
logIndex
); );
assertEq( assertEq(
sourceHash, sourceHash,
0xf923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc 0xf923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc
); );
}
bytes memory raw = Encoding.L2Transaction( function test_hashDepositTransaction() external {
l1BlockHash, bytes32 digest = Hashing.hashDepositTransaction(
logIndex, 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266,
from, 0xB79f76EF2c5F0286176833E7B2eEe103b1CC3244,
to, 0xde0b6b3a7640000,
isCreate, 0xe043da617250000,
mint, 0x2dc6c0,
value, false,
gas, hex"",
data 0xd25df7858efc1778118fb133ac561b138845361626dfb976699c5287ed0f4959,
); 0x1
assertEq(
raw,
hex"7e00f862a0f923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc94f39fd6e51aad88f6f4ce6ab8827279cfffb9226694b79f76ef2c5f0286176833e7b2eee103b1cc3244880e043da617250000880de0b6b3a7640000832dc6c080"
);
bytes32 digest = Hashing.L2TransactionHash(
l1BlockHash,
logIndex,
from,
to,
isCreate,
mint,
value,
gas,
data
); );
assertEq( assertEq(
......
...@@ -56,8 +56,9 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -56,8 +56,9 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
// the version is encoded in the nonce // the version is encoded in the nonce
function test_L1MessengerMessageVersion() external { function test_L1MessengerMessageVersion() external {
(,uint16 version) = Encoding.decodeVersionedNonce(L1Messenger.messageNonce());
assertEq( assertEq(
Encoding.getVersionFromNonce(L1Messenger.messageNonce()), version,
L1Messenger.MESSAGE_VERSION() L1Messenger.MESSAGE_VERSION()
); );
} }
...@@ -75,7 +76,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -75,7 +76,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
0, 0,
100 + L1Messenger.baseGas(hex"ff"), 100 + L1Messenger.baseGas(hex"ff"),
false, false,
Encoding.getVersionedEncoding( Encoding.encodeCrossDomainMessage(
L1Messenger.messageNonce(), L1Messenger.messageNonce(),
alice, alice,
recipient, recipient,
...@@ -95,7 +96,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -95,7 +96,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
0, 0,
100 + L1Messenger.baseGas(hex"ff"), 100 + L1Messenger.baseGas(hex"ff"),
false, false,
Encoding.getVersionedEncoding( Encoding.encodeCrossDomainMessage(
L1Messenger.messageNonce(), L1Messenger.messageNonce(),
alice, alice,
recipient, recipient,
...@@ -145,7 +146,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -145,7 +146,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
vm.expectEmit(true, true, true, true); vm.expectEmit(true, true, true, true);
bytes32 hash = Hashing.getVersionedHash(0, sender, target, 0, 0, hex"1111"); bytes32 hash = Hashing.hashCrossDomainMessage(0, sender, target, 0, 0, hex"1111");
emit RelayedMessage(hash); emit RelayedMessage(hash);
......
...@@ -31,8 +31,9 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -31,8 +31,9 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
} }
function test_L2MessengerMessageVersion() external { function test_L2MessengerMessageVersion() external {
(, uint16 version) = Encoding.decodeVersionedNonce(L2Messenger.messageNonce());
assertEq( assertEq(
Encoding.getVersionFromNonce(L2Messenger.messageNonce()), version,
L2Messenger.MESSAGE_VERSION() L2Messenger.MESSAGE_VERSION()
); );
} }
...@@ -44,7 +45,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -44,7 +45,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
L2ToL1MessagePasser.initiateWithdrawal.selector, L2ToL1MessagePasser.initiateWithdrawal.selector,
address(L1Messenger), address(L1Messenger),
100 + L2Messenger.baseGas(hex"ff"), 100 + L2Messenger.baseGas(hex"ff"),
Encoding.getVersionedEncoding( Encoding.encodeCrossDomainMessage(
L2Messenger.messageNonce(), L2Messenger.messageNonce(),
alice, alice,
recipient, recipient,
...@@ -63,7 +64,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -63,7 +64,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
address(L1Messenger), address(L1Messenger),
0, 0,
100 + L2Messenger.baseGas(hex"ff"), 100 + L2Messenger.baseGas(hex"ff"),
Encoding.getVersionedEncoding( Encoding.encodeCrossDomainMessage(
L2Messenger.messageNonce(), L2Messenger.messageNonce(),
alice, alice,
recipient, recipient,
...@@ -104,7 +105,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -104,7 +105,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
vm.expectEmit(true, true, true, true); vm.expectEmit(true, true, true, true);
bytes32 hash = Hashing.getVersionedHash( bytes32 hash = Hashing.hashCrossDomainMessage(
0, 0,
sender, sender,
target, target,
......
...@@ -64,7 +64,7 @@ contract L2ToL1MessagePasserTest is CommonTest { ...@@ -64,7 +64,7 @@ contract L2ToL1MessagePasserTest is CommonTest {
data data
); );
bytes32 withdrawalHash = Hashing.withdrawalHash( bytes32 withdrawalHash = Hashing.hashWithdrawal(
nonce, nonce,
alice, alice,
target, target,
......
...@@ -7,6 +7,10 @@ import { Proxy } from "../universal/Proxy.sol"; ...@@ -7,6 +7,10 @@ import { Proxy } from "../universal/Proxy.sol";
contract MeterUser is ResourceMetering { contract MeterUser is ResourceMetering {
constructor() { constructor() {
initialize();
}
function initialize() public initializer {
__ResourceMetering_init(); __ResourceMetering_init();
} }
......
...@@ -111,7 +111,7 @@ abstract contract CrossDomainMessenger is ...@@ -111,7 +111,7 @@ abstract contract CrossDomainMessenger is
* messageNonce getter which will insert the message version into the nonce to give you * messageNonce getter which will insert the message version into the nonce to give you
* the actual nonce to be used for the message. * the actual nonce to be used for the message.
*/ */
uint256 internal msgNonce; uint240 internal msgNonce;
/** /**
* @notice Address of the paired CrossDomainMessenger contract on the other chain. * @notice Address of the paired CrossDomainMessenger contract on the other chain.
...@@ -172,7 +172,7 @@ abstract contract CrossDomainMessenger is ...@@ -172,7 +172,7 @@ abstract contract CrossDomainMessenger is
* @return Nonce of the next message to be sent, with added message version. * @return Nonce of the next message to be sent, with added message version.
*/ */
function messageNonce() public view returns (uint256) { function messageNonce() public view returns (uint256) {
return Encoding.addVersionToNonce(msgNonce, MESSAGE_VERSION); return Encoding.encodeVersionedNonce(msgNonce, MESSAGE_VERSION);
} }
/** /**
...@@ -250,7 +250,7 @@ abstract contract CrossDomainMessenger is ...@@ -250,7 +250,7 @@ abstract contract CrossDomainMessenger is
uint256 _minGasLimit, uint256 _minGasLimit,
bytes calldata _message bytes calldata _message
) external payable nonReentrant whenNotPaused { ) external payable nonReentrant whenNotPaused {
bytes32 versionedHash = Hashing.getVersionedHash( bytes32 versionedHash = Hashing.hashCrossDomainMessage(
_nonce, _nonce,
_sender, _sender,
_target, _target,
......
{ {
"name": "@eth-optimism/contracts-bedrock", "name": "@eth-optimism/contracts-bedrock",
"version": "0.4.1", "version": "0.5.0",
"description": "Contracts for Optimism Specs", "description": "Contracts for Optimism Specs",
"main": "dist/index", "main": "dist/index",
"types": "dist/index", "types": "dist/index",
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
"typechain": "typechain --target ethers-v5 --out-dir dist/types --glob 'artifacts/!(build-info)/**/+([a-zA-Z0-9_]).json'" "typechain": "typechain --target ethers-v5 --out-dir dist/types --glob 'artifacts/!(build-info)/**/+([a-zA-Z0-9_]).json'"
}, },
"dependencies": { "dependencies": {
"@eth-optimism/core-utils": "^0.9.0", "@eth-optimism/core-utils": "^0.9.1",
"@openzeppelin/contracts": "^4.5.0", "@openzeppelin/contracts": "^4.5.0",
"@openzeppelin/contracts-upgradeable": "^4.5.2", "@openzeppelin/contracts-upgradeable": "^4.5.2",
"@rari-capital/solmate": "https://github.com/rari-capital/solmate.git#8f9b23f8838670afda0fd8983f2c41e8037ae6bc", "@rari-capital/solmate": "https://github.com/rari-capital/solmate.git#8f9b23f8838670afda0fd8983f2c41e8037ae6bc",
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
"rlp": "^2.2.7" "rlp": "^2.2.7"
}, },
"devDependencies": { "devDependencies": {
"@eth-optimism/hardhat-deploy-config": "^0.2.0", "@eth-optimism/hardhat-deploy-config": "^0.2.1",
"@defi-wonderland/smock": "^2.0.2", "@defi-wonderland/smock": "^2.0.2",
"@foundry-rs/hardhat-forge": "^0.1.12", "@foundry-rs/hardhat-forge": "^0.1.12",
"@nomiclabs/hardhat-ethers": "^2.0.0", "@nomiclabs/hardhat-ethers": "^2.0.0",
......
# @eth-optimism/contracts-governance # @eth-optimism/contracts-governance
## 0.1.4
### Patch Changes
- dc9cf2b6: Clean up the hardhat config
- Updated dependencies [f9fee446]
- @eth-optimism/core-utils@0.9.1
- @eth-optimism/sdk@1.2.1
## 0.1.3 ## 0.1.3
### Patch Changes ### Patch Changes
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment