Commit 8b162c77 authored by Indeavr's avatar Indeavr Committed by GitHub

Merge branch 'ethereum-optimism:develop' into develop

parents 847879c0 dcd82bc1
---
'@eth-optimism/data-transport-layer': patch
---
Smaller filter query for searching for L1 start height. This number should be configured so that the search does not need to happen because using a smaller filter will cause it to take too long.
---
'@eth-optimism/gas-oracle': patch
'@eth-optimism/contracts': patch
'@eth-optimism/data-transport-layer': patch
---
String update to change the system name from OE to Optimism
---
'@eth-optimism/batch-submitter-service': patch
---
Fix metrics server
version: 2.1
orbs:
gcp-gke: circleci/gcp-gke@1.3.0
commands:
build-dockerfile:
parameters:
......@@ -39,6 +41,13 @@ jobs:
image-name: batch-submitter
target: batch-submitter
dockerfile: ./ops/docker/Dockerfile.packages
build-go-batch-submitter:
docker:
- image: cimg/base:2021.04
steps:
- build-dockerfile:
image-name: go-batch-submitter
dockerfile: ./ops/docker/Dockerfile.batch-submitter-service
build-deployer:
docker:
- image: cimg/base:2021.04
......@@ -61,6 +70,45 @@ jobs:
- build-dockerfile:
image-name: gas-oracle
dockerfile: ./ops/docker/Dockerfile.gas-oracle
build-integration-tests:
docker:
- image: cimg/base:2021.04
steps:
- build-dockerfile:
image-name: integration-tests
target: integration-tests
dockerfile: ./ops/docker/Dockerfile.packages
build-proxyd:
docker:
- image: cimg/base:2021.04
steps:
- build-dockerfile:
image-name: proxyd
dockerfile: ./go/proxyd/Dockerfile
deploy-nightly:
docker:
- image: cimg/base:2021.04
steps:
- gcp-gke/install
- gcp-gke/update-kubeconfig-with-credentials:
cluster: $STACKMAN_CLUSTER
gcloud-service-key: STACKMAN_SERVICE_KEY
google-compute-region: STACKMAN_COMPUTE_REGION
google-compute-zone: STACKMAN_COMPUTE_ZONE
google-project-id: STACKMAN_PROJECT_ID
install-kubectl: yes
perform-login: yes
- run:
name: Deploy
command: |
echo "Current nightly pods:"
kubectl get pods --namespace nightly
echo "Redeploying pods:"
kubectl rollout restart statefulset nightly-sequencer --namespace nightly
kubectl rollout restart statefulset nightly-go-batch-submitter --namespace nightly
kubectl rollout restart statefulset nightly-dtl --namespace nightly
kubectl rollout restart deployment nightly-gas-oracle --namespace nightly
kubectl rollout restart deployment edge-proxyd --namespace nightly
workflows:
......@@ -82,4 +130,21 @@ workflows:
- build-l2geth:
context: optimism
- build-gas-oracle:
context: optimism
\ No newline at end of file
context: optimism
- build-integration-tests:
context: optimism
- build-go-batch-submitter:
context: optimism
- build-proxyd:
context: optimism
- deploy-nightly:
context: optimism
requires:
- build-dtl
- build-batch-submitter
- build-go-batch-submitter
- build-deployer
- build-l2geth
- build-gas-oracle
- build-integration-tests
- build-proxyd
\ No newline at end of file
......@@ -28,6 +28,7 @@ jobs:
proxyd: ${{ steps.packages.outputs.proxyd }}
rpc-proxy : ${{ steps.packages.outputs.rpc-proxy }}
op-exporter : ${{ steps.packages.outputs.op-exporter }}
l2geth-exporter : ${{ steps.packages.outputs.l2geth-exporter }}
steps:
- name: Check out source code
......@@ -443,6 +444,43 @@ jobs:
GITCOMMIT=${{ steps.build_args.outputs.GITCOMMIT }}
GITVERSION=${{ steps.build_args.outputs.GITVERSION }}
l2geth-exporter:
name: Publish l2geth-exporter Version ${{ needs.canary-publish.outputs.canary-docker-tag }}
needs: canary-publish
if: needs.canary-publish.outputs.l2geth-exporter != ''
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
- name: Set build args
id: build_args
run: |
echo ::set-output name=GITDATE::"$(date +%d-%m-%Y)"
echo ::set-output name=GITVERSION::$(jq -r .version ./go/l2geth-exporter/package.json)
echo ::set-output name=GITCOMMIT::"$GITHUB_SHA"
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: ./ops/docker/Dockerfile.l2geth-exporter
push: true
tags: ethereumoptimism/l2geth-exporter:${{ needs.canary-publish.outputs.l2geth-exporter }}
build-args: |
GITDATE=${{ steps.build_args.outputs.GITDATE }}
GITCOMMIT=${{ steps.build_args.outputs.GITCOMMIT }}
GITVERSION=${{ steps.build_args.outputs.GITVERSION }}
rpc-proxy:
name: Publish rpc-proxy Version ${{ needs.canary-publish.outputs.canary-docker-tag }}
needs: canary-publish
......
......@@ -24,6 +24,7 @@ jobs:
rpc-proxy: ${{ steps.packages.outputs.rpc-proxy }}
hardhat-node: ${{ steps.packages.outputs.hardhat-node }}
op-exporter : ${{ steps.packages.outputs.op-exporter }}
l2geth-exporter : ${{ steps.packages.outputs.l2geth-exporter }}
steps:
- name: Checkout Repo
......@@ -196,6 +197,43 @@ jobs:
GITCOMMIT=${{ steps.build_args.outputs.GITCOMMIT }}
GITVERSION=${{ steps.build_args.outputs.GITVERSION }}
l2geth-exporter:
name: Publish l2geth-exporter Version ${{ needs.release.outputs.l2geth-exporter}}
needs: release
if: needs.release.outputs.l2geth-exporter != ''
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
- name: Set build args
id: build_args
run: |
echo ::set-output name=GITDATE::"$(date +%d-%m-%Y)"
echo ::set-output name=GITVERSION::$(jq -r .version ./go/l2geth-exporter/package.json)
echo ::set-output name=GITCOMMIT::"$GITHUB_SHA"
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: ./ops/docker/Dockerfile.l2geth-exporter
push: true
tags: ethereumoptimism/l2geth-exporter:${{ needs.release.outputs.l2geth-exporter }},ethereumoptimism/l2geth-exporter:latest
build-args: |
GITDATE=${{ steps.build_args.outputs.GITDATE }}
GITCOMMIT=${{ steps.build_args.outputs.GITCOMMIT }}
GITVERSION=${{ steps.build_args.outputs.GITVERSION }}
op-exporter:
name: Publish op-exporter Version ${{ needs.release.outputs.op-exporter}}
needs: release
......
......@@ -131,6 +131,13 @@ jobs:
fail_ci_if_error: false
verbose: true
flags: message-relayer
- uses: codecov/codecov-action@v1
with:
files: ./packages/sdk/coverage.json
fail_ci_if_error: false
verbose: true
flags: sdk
lint:
name: Linting
runs-on: ubuntu-latest
......
......@@ -98,7 +98,7 @@ Use the above commands to recompile the packages.
### Building the rest of the system
If you want to run an Optimistic Ethereum node OR **if you want to run the integration tests**, you'll need to build the rest of the system.
If you want to run an Optimism node OR **if you want to run the integration tests**, you'll need to build the rest of the system.
```bash
cd ops
......
......@@ -11,7 +11,7 @@
## TL;DR
This is the primary place where [Optimism](https://optimism.io) works on stuff related to [Optimistic Ethereum](https://optimistic.etherscan.io/).
This is where [Optimism](https://optimism.io) gets built.
## Documentation
......@@ -31,16 +31,16 @@ Then check out our list of [good first issues](https://github.com/ethereum-optim
<pre>
root
├── <a href="./packages">packages</a>
│ ├── <a href="./packages/contracts">contracts</a>: L1 and L2 smart contracts for Optimistic Ethereum
│ ├── <a href="./packages/core-utils">core-utils</a>: Low-level utilities that make building Optimistic Ethereum easier
│ ├── <a href="./packages/contracts">contracts</a>: L1 and L2 smart contracts for Optimism
│ ├── <a href="./packages/core-utils">core-utils</a>: Low-level utilities that make building Optimism easier
│ ├── <a href="./packages/common-ts">common-ts</a>: Common tools for building apps in TypeScript
│ ├── <a href="./packages/data-transport-layer">data-transport-layer</a>: Service for indexing Optimistic Ethereum-related L1 data
│ ├── <a href="./packages/data-transport-layer">data-transport-layer</a>: Service for indexing Optimism-related L1 data
│ ├── <a href="./packages/batch-submitter">batch-submitter</a>: Service for submitting batches of transactions and results to L1
│ ├── <a href="./packages/message-relayer">message-relayer</a>: Tool for automatically relaying L1<>L2 messages in development
│ └── <a href="./packages/replica-healthcheck">replica-healthcheck</a>: Service for monitoring the health of a replica node
├── <a href="./l2geth">l2geth</a>: Optimistic Ethereum client software, a fork of <a href="https://github.com/ethereum/go-ethereum/tree/v1.9.10">geth v1.9.10</a>
├── <a href="./integration-tests">integration-tests</a>: Various integration tests for an Optimistic Ethereum network
└── <a href="./ops">ops</a>: Tools for running Optimistic Ethereum nodes and networks
├── <a href="./l2geth">l2geth</a>: Optimism client software, a fork of <a href="https://github.com/ethereum/go-ethereum/tree/v1.9.10">geth v1.9.10</a>
├── <a href="./integration-tests">integration-tests</a>: Various integration tests for the Optimism network
└── <a href="./ops">ops</a>: Tools for running Optimism nodes and networks
</pre>
## Branching Model and Releases
......@@ -64,7 +64,7 @@ Please read the linked post if you're planning to make frequent PRs into this re
The `master` branch contains the code for our latest "stable" releases.
Updates from `master` always come from the `develop` branch.
We only ever update the `master` branch when we intend to deploy code within the `develop` to the Optimistic Ethereum mainnet.
We only ever update the `master` branch when we intend to deploy code within the `develop` to the Optimism mainnet.
Our update process takes the form of a PR merging the `develop` branch into the `master` branch.
### The `develop` branch
......
# @eth-optimism/batch-submitter-service
## 0.0.2
### Patch Changes
- d6e0de5a: Fix metrics server
{
"name": "@eth-optimism/batch-submitter-service",
"version": "0.0.1",
"version": "0.0.2",
"private": true,
"devDependencies": {}
}
......@@ -40,7 +40,7 @@ options.
```
NAME:
gas-oracle - Remotely Control the Optimistic Ethereum Gas Price
gas-oracle - Remotely Control the Optimism Gas Price
USAGE:
gas-oracle [global options] command [command options] [arguments...]
......@@ -49,7 +49,7 @@ VERSION:
0.0.0-1.10.4-stable
DESCRIPTION:
Configure with a private key and an Optimistic Ethereum HTTP endpoint to send transactions that update the L2 gas price.
Configure with a private key and an Optimism HTTP endpoint to send transactions that update the L2 gas price.
COMMANDS:
help, h Shows a list of commands or help for one command
......
......@@ -26,8 +26,8 @@ func main() {
app.Version = GitVersion + "-" + params.VersionWithCommit(GitCommit, GitDate)
app.Name = "gas-oracle"
app.Usage = "Remotely Control the Optimistic Ethereum Gas Price"
app.Description = "Configure with a private key and an Optimistic Ethereum HTTP endpoint " +
app.Usage = "Remotely Control the Optimism Gas Price"
app.Description = "Configure with a private key and an Optimism HTTP endpoint " +
"to send transactions that update the L2 gas price."
// Configure the logging
......
# @eth-optimism/l2geth-exporter
## 0.0.2
### Patch Changes
- 71bfa3fe: Initial build
SHELL := /bin/bash
VERSION := `git describe --abbrev=0`
GITCOMMIT := `git rev-parse HEAD`
BUILDDATE := `date +%Y-%m-%d`
BUILDUSER := `whoami`
LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT)
LDFLAGSSTRING +=-X main.GitDate=$(GITDATE)
LDFLAGSSTRING +=-X main.GitVersion=$(GITVERSION)
LDFLAGS :=-ldflags "$(LDFLAGSSTRING)"
all: build
build:
CGO_ENABLED=0 go build $(LDFLAGS)
clean:
rm l2geth-exporter
test:
go test -v ./...
lint:
golangci-lint run ./...
binding:
$(eval temp := $(shell mktemp))
cat ../../packages/contracts/deployments/mainnet/CanonicalTransactionChain.json \
| jq -r .bytecode > $(temp)
cat ../../packages/contracts/deployments/mainnet/CanonicalTransactionChain.json \
| jq .abi \
| abigen --pkg bindings \
--abi - \
--out bindings/CanonicalTransactionChain.go \
--type CanonicalTransactionChain \
--bin $(temp)
rm $(temp)
This diff is collapsed.
package main
import (
"github.com/prometheus/client_golang/prometheus"
)
//Define the metrics we wish to expose
var (
ctcTotalElements = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "l2geth_ctc_total_elements",
Help: "CTC GetTotalElements value."},
[]string{"state"},
)
ctcTotalElementsCallSuccess = prometheus.NewGauge(
prometheus.GaugeOpts{
Name: "l2geth_ctc_total_elements_call_success",
Help: "CTC GetTotalElements call success."},
)
)
func init() {
//Register metrics with prometheus
prometheus.MustRegister(ctcTotalElements)
prometheus.MustRegister(ctcTotalElementsCallSuccess)
}
module github.com/ethereum-optimism/optimism/go/l2geth-exporter
go 1.16
require (
github.com/ethereum/go-ethereum v1.10.8
github.com/prometheus/client_golang v1.11.0
)
This diff is collapsed.
package l1contracts
import (
"context"
"math/big"
"github.com/ethereum-optimism/optimism/go/l2geth-exporter/bindings"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
)
// CTC interacts with the OVM CTC contract
type CTC struct {
Address common.Address
Client *ethclient.Client
}
func (ctc *CTC) GetTotalElements(ctx context.Context) (*big.Int, error) {
contract, err := bindings.NewCanonicalTransactionChainCaller(ctc.Address, ctc.Client)
if err != nil {
return nil, err
}
totalElements, err := contract.GetTotalElements(&bind.CallOpts{
Context: ctx,
})
if err != nil {
return nil, err
}
return totalElements, nil
}
package main
import (
"context"
"math/big"
"net/http"
"os"
"time"
"github.com/ethereum-optimism/optimism/go/l2geth-exporter/l1contracts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var (
l1TimeoutSeconds = 5
)
func main() {
listenAddress := os.Getenv("LISTEN_ADDRESS")
if listenAddress == "" {
listenAddress = ":9100"
}
log.Root().SetHandler(log.CallerFileHandler(log.StdoutHandler))
l1Url := os.Getenv("L1_URL")
if l1Url == "" {
log.Error("L1_URL environmental variable is required")
os.Exit(1)
}
ctcAddress := os.Getenv("CTC_ADDRESS")
if ctcAddress == "" {
log.Error("CTC_ADDRESS environmental variable is required")
os.Exit(1)
}
client, err := ethclient.Dial(l1Url)
if err != nil {
log.Error("Problem connecting to L1: %s", err)
}
http.Handle("/metrics", promhttp.Handler())
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`<html>
<head><title>L2geth Exporter</title></head>
<body>
<h1>L2geth Exporter</h1>
<p><a href="/metrics">Metrics</a></p>
</body>
</html>`))
})
go getCTCTotalElements(ctcAddress, client)
log.Info("Program starting", "listenAddress", listenAddress, "GETH_URL", l1Url, "CTC_ADDRESS", ctcAddress)
if err := http.ListenAndServe(listenAddress, nil); err != nil {
log.Error("Can't start http server", "error", err)
}
}
func getCTCTotalElements(address string, client *ethclient.Client) {
ctc := l1contracts.CTC{
Address: common.HexToAddress(address),
Client: client,
}
ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop()
for {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(l1TimeoutSeconds))
totalElements, err := ctc.GetTotalElements(ctx)
if err != nil {
ctcTotalElementsCallSuccess.Set(0)
log.Error("Error calling GetTotalElements", "error", err)
cancel()
continue
}
ctcTotalElementsCallSuccess.Set(1)
totalElementsFloat, _ := new(big.Float).SetInt(totalElements).Float64()
ctcTotalElements.WithLabelValues(
"latest").Set(totalElementsFloat)
log.Info("ctc updated", "ctcTotalElements", totalElementsFloat)
cancel()
<-ticker.C
}
}
{
"name": "@eth-optimism/l2geth-exporter",
"version": "0.0.2",
"private": true,
"devDependencies": {}
}
# op_exporter
A prometheus exporter to collect information from an Optimistic Ethereum node and serve metrics for collection
A prometheus exporter to collect information from an Optimism node and serve metrics for collection
## Usage
......
......@@ -14,7 +14,7 @@ program
.option('-r, --runs <n>', 'number of runs. cannot be use with -t/--time')
.option(
'-t, --time <ms>',
'how long to run in milliseconds. cannot be used with -r/--runs',
'how long to run in milliseconds. cannot be used with -r/--runs'
)
.option('-c, --concurrency <n>', 'number of concurrent workers to spawn', '1')
.option('--think-time <n>', 'how long to wait between each run', '0')
......
......@@ -87,7 +87,10 @@ actor('Uniswap swapper', () => {
let tx = await token.transfer(wallet.address, 1000000)
await tx.wait()
const boundToken = token.connect(wallet)
tx = await boundToken.approve(contracts.positionManager.address, 1000000000)
tx = await boundToken.approve(
contracts.positionManager.address,
1000000000
)
await tx.wait()
tx = await boundToken.approve(contracts.router.address, 1000000000)
await tx.wait()
......
......@@ -6,7 +6,7 @@
"scripts": {
"lint": "yarn lint:fix && yarn lint:check",
"lint:fix": "yarn lint:check --fix",
"lint:check": "eslint .",
"lint:check": "eslint . --max-warnings=0",
"build": "hardhat compile",
"test:integration": "hardhat --network optimism test",
"test:actor": "IS_LIVE_NETWORK=true ts-node actor-tests/lib/runner.ts",
......@@ -30,7 +30,7 @@
"devDependencies": {
"@eth-optimism/contracts": "0.5.7",
"@eth-optimism/core-utils": "0.7.3",
"@eth-optimism/message-relayer": "0.2.10",
"@eth-optimism/message-relayer": "0.2.11",
"@ethersproject/abstract-provider": "^5.5.1",
"@ethersproject/providers": "^5.4.5",
"@ethersproject/transactions": "^5.4.0",
......
import { expect } from 'chai'
import { expect } from './shared/setup'
/* Imports: External */
import { Contract, ContractFactory } from 'ethers'
......
import { expect } from './shared/setup'
import { BigNumber, Contract, ContractFactory, utils, Wallet } from 'ethers'
import { ethers } from 'hardhat'
import * as L2Artifact from '@eth-optimism/contracts/artifacts/contracts/standards/L2StandardERC20.sol/L2StandardERC20.json'
import { expect } from 'chai'
import { OptimismEnv } from './shared/env'
import { isLiveNetwork, isMainnet } from './shared/utils'
......
import { expect } from './shared/setup'
import { BigNumber, Contract, ContractFactory, utils, Wallet } from 'ethers'
import { ethers } from 'hardhat'
import { solidity } from 'ethereum-waffle'
import chai, { expect } from 'chai'
import { UniswapV3Deployer } from 'uniswap-v3-deploy-plugin/dist/deployer/UniswapV3Deployer'
import { OptimismEnv } from './shared/env'
......@@ -10,8 +10,6 @@ import { FeeAmount, TICK_SPACINGS } from '@uniswap/v3-sdk'
import { abi as NFTABI } from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json'
import { abi as RouterABI } from '@uniswap/v3-periphery/artifacts/contracts/SwapRouter.sol/SwapRouter.json'
chai.use(solidity)
// Below methods taken from the Uniswap test suite, see
// https://github.com/Uniswap/v3-periphery/blob/main/test/shared/ticks.ts
const getMinTick = (tickSpacing: number) =>
......
import chai, { expect } from 'chai'
import chaiAsPromised from 'chai-as-promised'
chai.use(chaiAsPromised)
import { expect } from './shared/setup'
/* Imports: External */
import { BigNumber, utils } from 'ethers'
......
import { expect } from './shared/setup'
import { BigNumber, Contract, ContractFactory, Wallet } from 'ethers'
import { ethers } from 'hardhat'
import chai, { expect } from 'chai'
import {
fundUser,
encodeSolidityRevertMessage,
gasPriceForL2,
} from './shared/utils'
import { OptimismEnv } from './shared/env'
import { solidity } from 'ethereum-waffle'
chai.use(solidity)
describe('Native ETH value integration tests', () => {
let env: OptimismEnv
......
import { expect } from 'chai'
import { expect } from './shared/setup'
/* Imports: External */
import { Wallet, utils, BigNumber } from 'ethers'
......
import { expect } from 'chai'
import { expect } from './shared/setup'
/* Imports: External */
import { ethers } from 'hardhat'
......
import chai, { expect } from 'chai'
import { solidity } from 'ethereum-waffle'
chai.use(solidity)
import { expect } from './shared/setup'
/* Imports: Internal */
import { ethers } from 'ethers'
......
import { expect } from 'chai'
import { expect } from './shared/setup'
/* Imports: Internal */
import { providers } from 'ethers'
......
import { expect } from './shared/setup'
import { OptimismEnv } from './shared/env'
import {
defaultTransactionFactory,
......@@ -5,7 +6,6 @@ import {
sleep,
isLiveNetwork,
} from './shared/utils'
import { expect } from 'chai'
import { TransactionReceipt } from '@ethersproject/abstract-provider'
describe('Replica Tests', () => {
......
import { expect } from './shared/setup'
import { expectApprox, injectL2Context } from '@eth-optimism/core-utils'
import { Wallet, BigNumber, Contract, ContractFactory } from 'ethers'
import { serialize } from '@ethersproject/transactions'
import { ethers } from 'hardhat'
import chai, { expect } from 'chai'
import {
sleep,
l2Provider,
......@@ -12,18 +13,13 @@ import {
isLiveNetwork,
gasPriceForL2,
} from './shared/utils'
import chaiAsPromised from 'chai-as-promised'
import { OptimismEnv } from './shared/env'
import {
TransactionReceipt,
TransactionRequest,
} from '@ethersproject/providers'
import { solidity } from 'ethereum-waffle'
import simpleStorageJson from '../artifacts/contracts/SimpleStorage.sol/SimpleStorage.json'
chai.use(chaiAsPromised)
chai.use(solidity)
describe('Basic RPC tests', () => {
let env: OptimismEnv
let wallet: Wallet
......@@ -286,7 +282,7 @@ describe('Basic RPC tests', () => {
expect(receipt.status).to.eq(0)
})
// Optimistic Ethereum special fields on the receipt
// Optimism special fields on the receipt
it('includes L1 gas price and L1 gas used', async () => {
const tx = await env.l2Wallet.populateTransaction({
to: env.l2Wallet.address,
......
/* External Imports */
import chai = require('chai')
import chaiAsPromised from 'chai-as-promised'
import { solidity } from 'ethereum-waffle'
chai.use(solidity)
chai.use(chaiAsPromised)
const expect = chai.expect
export { expect }
import { expect } from 'chai'
import { expect } from './shared/setup'
/* Imports: External */
import { Contract, ContractFactory, Wallet, utils } from 'ethers'
......
import { expect } from './shared/setup'
/* Imports: External */
import { ContractFactory } from 'ethers'
import { ethers } from 'hardhat'
import chai, { expect } from 'chai'
import { solidity } from 'ethereum-waffle'
import { predeploys } from '@eth-optimism/contracts'
/* Imports: Internal */
import { OptimismEnv } from './shared/env'
import { l2Provider } from './shared/utils'
chai.use(solidity)
describe('Whitelist', async () => {
const initialAmount = 1000
const tokenName = 'OVM Test'
......
FROM golang:1.16 as builder
ADD ./go/l2geth-exporter /app/
WORKDIR /app/
RUN make build
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/l2geth-exporter /usr/local/bin/
ENTRYPOINT ["l2geth-exporter"]
CMD ["--help"]
......@@ -11,6 +11,7 @@
"specs",
"go/gas-oracle",
"go/batch-submitter",
"go/l2geth-exporter",
"go/proxyd",
"go/op-exporter",
"ops/docker/rpc-proxy",
......
# Changelog
## 0.4.12
### Patch Changes
- 07f1ad01: Fix the numTxPerBatch metric
## 0.4.11
### Patch Changes
......
{
"private": true,
"name": "@eth-optimism/batch-submitter",
"version": "0.4.11",
"version": "0.4.12",
"description": "[Optimism] Service for submitting transactions and transaction results",
"main": "dist/index",
"types": "dist/index",
......@@ -15,7 +15,7 @@
"lint": "yarn lint:fix && yarn lint:check",
"pre-commit": "lint-staged",
"lint:fix": "yarn lint:check --fix",
"lint:check": "eslint .",
"lint:check": "eslint . --max-warnings=0",
"test": "hardhat test --show-stack-traces",
"test:coverage": "nyc hardhat test && nyc merge .nyc_output coverage.json"
},
......
......@@ -154,7 +154,6 @@ export class StateBatchSubmitter extends BatchSubmitter {
startBlock: number,
endBlock: number
): Promise<TransactionReceipt> {
const batchTxBuildStart = performance.now()
const batch = await this._generateStateCommitmentBatch(startBlock, endBlock)
......
......@@ -232,7 +232,7 @@ export class TransactionBatchSubmitter extends BatchSubmitter {
const batchTxBuildEnd = performance.now()
this.metrics.batchTxBuildTime.set(batchTxBuildEnd - batchTxBuildStart)
this.metrics.numTxPerBatch.observe(endBlock - startBlock)
this.metrics.numTxPerBatch.observe(batchParams.totalElementsToAppend)
const l1tipHeight = await this.signer.provider.getBlockNumber()
this.logger.debug('Submitting batch.', {
calldata: batchParams,
......
......@@ -11,7 +11,7 @@
"all": "yarn clean && yarn build && yarn test && yarn lint:fix && yarn lint",
"build": "tsc -p tsconfig.build.json",
"clean": "rimraf dist/ ./tsconfig.build.tsbuildinfo",
"lint:check": "eslint .",
"lint:check": "eslint . --max-warnings=0",
"lint:fix": "yarn lint:check --fix",
"lint": "yarn lint:fix && yarn lint:check",
"pre-commit": "lint-staged",
......
[![codecov](https://codecov.io/gh/ethereum-optimism/optimism/branch/master/graph/badge.svg?token=0VTG7PG7YR&flag=contracts)](https://codecov.io/gh/ethereum-optimism/optimism)
# Optimistic Ethereum Smart Contracts
# Optimism Smart Contracts
`@eth-optimism/contracts` contains the various Solidity smart contracts used within the Optimistic Ethereum system.
Some of these contracts are deployed on Ethereum ("Layer 1"), while others are meant to be deployed to Optimistic Ethereum ("Layer 2").
`@eth-optimism/contracts` contains the various Solidity smart contracts used within the Optimism system.
Some of these contracts are deployed on Ethereum ("Layer 1"), while others are meant to be deployed to Optimism ("Layer 2").
Within each contract file you'll find a comment that lists:
1. The compiler with which a contract is intended to be compiled, `solc` or `optimistic-solc`.
......
# Optimistic Ethereum Deployments
- [Optimistic Ethereum (mainnet)](./mainnet#readme)
- [Optimistic Kovan (public testnet)](./kovan#readme)
- [Optimistic Goerli (internal devnet)](./goerli#readme)
# Optimism Deployments
- [Optimism (mainnet)](./mainnet#readme)
- [Optimism Kovan (public testnet)](./kovan#readme)
- [Optimism Goerli (internal devnet)](./goerli#readme)
# Optimistic Goerli (internal devnet)
# Optimism Goerli (internal devnet)
## Notice
Optimistic Goerli is an internal Optimism development network. You're probably looking for [Optimistic Kovan](../kovan#readme), the public Optimistic Ethereum testnet.
Optimism Goerli is an internal Optimism development network. You're probably looking for [Optimism Kovan](../kovan#readme), the public Optimism testnet.
## Network Info
- **Chain ID**: 420
## Layer 1 Contracts
......
# Optimistic Kovan (public testnet)
# Optimism Kovan (public testnet)
## Network Info
- **Chain ID**: 69
- **Public RPC**: https://kovan.optimism.io
......
# Optimistic Ethereum (mainnet)
# Optimism (mainnet)
## Network Info
- **Chain ID**: 10
- **Public RPC**: https://mainnet.optimism.io
......
{
"name": "@eth-optimism/contracts",
"version": "0.5.7",
"description": "[Optimism] L1 and L2 smart contracts for Optimistic Ethereum",
"description": "[Optimism] L1 and L2 smart contracts for Optimism",
"main": "dist/index",
"types": "dist/index",
"files": [
......@@ -29,7 +29,7 @@
"test:slither": "slither .",
"pretest:slither": "rm -f @openzeppelin && rm -f @ens && rm -f hardhat && ln -s ../../node_modules/@openzeppelin @openzeppelin && ln -s ../../node_modules/@ens @ens && ln -s ../../node_modules/hardhat hardhat",
"posttest:slither": "rm -f @openzeppelin && rm -f @ens && rm -f hardhat",
"lint:ts:check": "eslint .",
"lint:ts:check": "eslint . --max-warnings=0",
"lint:contracts:check": "yarn solhint -f table 'contracts/**/*.sol'",
"lint:check": "yarn lint:contracts:check && yarn lint:ts:check",
"lint:ts:fix": "eslint --fix .",
......
......@@ -16,7 +16,7 @@ interface DeploymentInfo {
const PUBLIC_DEPLOYMENTS: DeploymentInfo[] = [
{
folder: 'mainnet',
name: 'Optimistic Ethereum (mainnet)',
name: 'Optimism (mainnet)',
chainid: 10,
rpc: 'https://mainnet.optimism.io',
l1Explorer: 'https://etherscan.io',
......@@ -24,7 +24,7 @@ const PUBLIC_DEPLOYMENTS: DeploymentInfo[] = [
},
{
folder: 'kovan',
name: 'Optimistic Kovan (public testnet)',
name: 'Optimism Kovan (public testnet)',
chainid: 69,
rpc: 'https://kovan.optimism.io',
l1Explorer: 'https://kovan.etherscan.io',
......@@ -32,9 +32,9 @@ const PUBLIC_DEPLOYMENTS: DeploymentInfo[] = [
},
{
folder: 'goerli',
name: 'Optimistic Goerli (internal devnet)',
name: 'Optimism Goerli (internal devnet)',
chainid: 420,
notice: `Optimistic Goerli is an internal Optimism development network. You're probably looking for [Optimistic Kovan](../kovan#readme), the public Optimistic Ethereum testnet.`,
notice: `Optimism Goerli is an internal Optimism development network. You're probably looking for [Optimism Kovan](../kovan#readme), the public Optimism testnet.`,
l1Explorer: 'https://goerli.etherscan.io',
},
]
......@@ -221,7 +221,7 @@ const main = async () => {
}
let primary = ``
primary = addline(primary, `# Optimistic Ethereum Deployments`)
primary = addline(primary, `# Optimism Deployments`)
for (const deployment of PUBLIC_DEPLOYMENTS) {
primary = addline(
primary,
......
......@@ -12,7 +12,7 @@
"build": "tsc -p tsconfig.build.json",
"clean": "rimraf dist/ ./tsconfig.build.tsbuildinfo",
"lint": "yarn lint:fix && yarn lint:check",
"lint:check": "eslint .",
"lint:check": "eslint . --max-warnings=0",
"lint:fix": "yarn lint:check --fix",
"pre-commit": "lint-staged",
"test": "ts-mocha test/*.spec.ts",
......
......@@ -3,7 +3,7 @@
## What is this?
The Optimistic Ethereum Data Transport Layer is a long-running software service (written in TypeScript) designed to reliably index Optimistic Ethereum transaction data from Layer 1 (Ethereum). Specifically, this service indexes:
The Optimism Data Transport Layer is a long-running software service (written in TypeScript) designed to reliably index Optimism transaction data from Layer 1 (Ethereum). Specifically, this service indexes:
* Transactions that have been enqueued for submission to the CanonicalTransactionChain via [`CanonicalTransactionChain.enqueue`].
* Transactions that have been included in the CanonicalTransactionChain via [`CanonicalTransactionChain.appendQueueBatch`] or [`CanonicalTransactionChain.appendSequencerBatch`].
......
......@@ -13,7 +13,7 @@
"clean:db": "rimraf ./db",
"lint": "yarn run lint:fix && yarn run lint:check",
"lint:fix": "yarn lint:check --fix",
"lint:check": "eslint .",
"lint:check": "eslint . --max-warnings=0",
"start": "ts-node ./src/services/run.ts",
"start:local": "ts-node ./src/services/run.ts | pino-pretty",
"test": "hardhat --config test/config/hardhat.config.ts test",
......
......@@ -167,7 +167,7 @@ export class L1IngestionService extends BaseService<L1IngestionServiceOptions> {
startingL1BlockNumber = this.options.l1StartHeight
} else {
this.logger.info(
'Attempting to find an appropriate L1 block height to begin sync...'
'Attempting to find an appropriate L1 block height to begin sync. This may take a long time.'
)
startingL1BlockNumber = await this._findStartingL1BlockNumber()
}
......@@ -453,12 +453,18 @@ export class L1IngestionService extends BaseService<L1IngestionServiceOptions> {
private async _findStartingL1BlockNumber(): Promise<number> {
const currentL1Block = await this.state.l1RpcProvider.getBlockNumber()
const filter =
this.state.contracts.Lib_AddressManager.filters.OwnershipTransferred()
for (let i = 0; i < currentL1Block; i += 2000) {
const start = i
const end = Math.min(i + 2000, currentL1Block)
this.logger.info(`Searching for ${filter} from ${start} to ${end}`)
for (let i = 0; i < currentL1Block; i += 1000000) {
const events = await this.state.contracts.Lib_AddressManager.queryFilter(
this.state.contracts.Lib_AddressManager.filters.OwnershipTransferred(),
i,
Math.min(i + 1000000, currentL1Block)
filter,
start,
end
)
if (events.length > 0) {
......
......@@ -121,7 +121,7 @@ export class L2IngestionService extends BaseService<L2IngestionServiceOptions> {
}
this.logger.info(
'Synchronizing unconfirmed transactions from Layer 2 (Optimistic Ethereum)',
'Synchronizing unconfirmed transactions from Layer 2 (Optimism)',
{
fromBlock: highestSyncedL2BlockNumber,
toBlock: targetL2Block,
......
# @eth-optimism/message-relayer
## 0.2.11
### Patch Changes
- 3a673322: Removed old node.js service running script
## 0.2.10
### Patch Changes
......
#!/usr/bin/env node
const main = require('../dist/exec/run').default
;(async () => {
await main()
})().catch((err) => {
console.log(err)
process.exit(1)
})
{
"name": "@eth-optimism/message-relayer",
"version": "0.2.10",
"version": "0.2.11",
"description": "[Optimism] Service for automatically relaying L2 to L1 transactions",
"main": "dist/index",
"types": "dist/index",
......@@ -11,13 +11,13 @@
"withdraw": "./src/exec/withdraw.ts"
},
"scripts": {
"start": "node ./exec/run-message-relayer.js",
"start": "ts-node ./src/exec/run.ts",
"build": "tsc -p ./tsconfig.build.json",
"clean": "rimraf dist/ ./tsconfig.build.tsbuildinfo",
"lint": "yarn lint:fix && yarn lint:check",
"pre-commit": "lint-staged",
"lint:fix": "yarn lint:check --fix",
"lint:check": "eslint .",
"lint:check": "eslint . --max-warnings=0",
"test": "hardhat test --show-stack-traces",
"test:coverage": "nyc hardhat test && nyc merge .nyc_output coverage.json"
},
......@@ -72,6 +72,7 @@
"lodash": "^4.17.21",
"mocha": "^8.4.0",
"prettier": "^2.3.1",
"ts-node": "^10.0.0",
"typescript": "^4.3.5"
}
}
......@@ -12,7 +12,7 @@
"clean": "rimraf ./dist ./tsconfig.build.tsbuildinfo",
"lint": "yarn run lint:fix && yarn run lint:check",
"lint:fix": "yarn lint:check --fix",
"lint:check": "eslint .",
"lint:check": "eslint . --max-warnings=0",
"pre-commit": "lint-staged",
"test:surgery": "ts-mocha --timeout 50000000 test/*",
"start": "ts-node ./scripts/surgery.ts"
......
......@@ -68,7 +68,7 @@ describe('EOAs', () => {
// eslint-disable-next-line
before(function() {
if (env.surgeryDataSources.configs.l2NetworkName === 'kovan') {
console.log('1inch deployer does not exist on optimistic kovan')
console.log('1inch deployer does not exist on Optimism Kovan')
this.skip()
}
......
......@@ -12,7 +12,7 @@
"clean": "rimraf ./dist ./tsconfig.build.tsbuildinfo",
"lint": "yarn run lint:fix && yarn run lint:check",
"lint:fix": "yarn lint:check --fix",
"lint:check": "eslint .",
"lint:check": "eslint . --max-warnings=0",
"build": "tsc -p tsconfig.build.json",
"pre-commit": "lint-staged",
"test": "ts-mocha test/*.spec.ts",
......
......@@ -2,7 +2,14 @@
# @eth-optimism/sdk
The `@eth-optimism/sdk` package provides a set of tools for interacting with Optimistic Ethereum.
The `@eth-optimism/sdk` package provides a set of tools for interacting with Optimism.
## NOTICE
WARNING: This package is currently under construction.
You can definitely try to use it, but you probably won't have a good time.
Lots of pieces are missing.
We will announce the 1.0.0 release on Discord and on Twitter once it's ready, keep an eye out!
## Installation
......
{
"name": "@eth-optimism/sdk",
"version": "0.0.3",
"description": "[Optimism] Tools for working with Optimistic Ethereum",
"description": "[Optimism] Tools for working with Optimism",
"main": "dist/index",
"types": "dist/index",
"files": [
......@@ -12,7 +12,7 @@
"build": "tsc -p tsconfig.build.json",
"clean": "rimraf dist/ ./tsconfig.build.tsbuildinfo",
"lint": "yarn lint:fix && yarn lint:check",
"lint:check": "eslint .",
"lint:check": "eslint . --max-warnings=0",
"lint:fix": "yarn lint:check --fix",
"pre-commit": "lint-staged",
"test": "hardhat test",
......
This diff is collapsed.
......@@ -11,6 +11,7 @@ import {
TokenBridgeMessage,
OEContracts,
MessageReceipt,
CustomBridges,
} from './types'
/**
......@@ -38,6 +39,11 @@ export interface ICrossChainProvider {
*/
contracts: OEContracts
/**
* List of custom bridges for the given network.
*/
bridges: CustomBridges
/**
* Retrieves all cross chain messages sent within a given transaction.
*
......@@ -80,7 +86,7 @@ export interface ICrossChainProvider {
/**
* Finds all cross chain messages that correspond to token deposits or withdrawals sent by a
* particular address. Useful for finding deposits/withdrawals because the sender of the message
* will appear to be the StandardBridge contract and not the actual end user. Returns
* will appear to be the StandardBridge contract and not the actual end user.
*
* @param address Address to search for messages from.
* @param opts Options object.
......@@ -101,6 +107,56 @@ export interface ICrossChainProvider {
}
): Promise<TokenBridgeMessage[]>
/**
* Alias for getTokenBridgeMessagesByAddress with a drection of L1_TO_L2.
*
* @param address Address to search for messages from.
* @param opts Options object.
* @param opts.fromBlock Block to start searching for messages from. If not provided, will start
* from the first block (block #0).
* @param opts.toBlock Block to stop searching for messages at. If not provided, will stop at the
* latest known block ("latest").
* @returns All deposit token bridge messages sent by the given address.
*/
getDepositsByAddress(
address: AddressLike,
opts?: {
fromBlock?: BlockTag
toBlock?: BlockTag
}
): Promise<TokenBridgeMessage[]>
/**
* Alias for getTokenBridgeMessagesByAddress with a drection of L2_TO_L1.
*
* @param address Address to search for messages from.
* @param opts Options object.
* @param opts.fromBlock Block to start searching for messages from. If not provided, will start
* from the first block (block #0).
* @param opts.toBlock Block to stop searching for messages at. If not provided, will stop at the
* latest known block ("latest").
* @returns All withdrawal token bridge messages sent by the given address.
*/
getWithdrawalsByAddress(
address: AddressLike,
opts?: {
fromBlock?: BlockTag
toBlock?: BlockTag
}
): Promise<TokenBridgeMessage[]>
/**
* Resolves a MessageLike into a CrossChainMessage object.
* Unlike other coercion functions, this function is stateful and requires making additional
* requests. For now I'm going to keep this function here, but we could consider putting a
* similar function inside of utils/coercion.ts if people want to use this without having to
* create an entire CrossChainProvider object.
*
* @param message MessageLike to resolve into a CrossChainMessage.
* @returns Message coerced into a CrossChainMessage.
*/
toCrossChainMessage(message: MessageLike): Promise<CrossChainMessage>
/**
* Retrieves the status of a particular message as an enum.
*
......
......@@ -34,7 +34,7 @@ export interface OEL2Contracts {
}
/**
* Represents Optimistic Ethereum contracts, assumed to be connected to their appropriate
* Represents Optimism contracts, assumed to be connected to their appropriate
* providers and addresses.
*/
export interface OEContracts {
......@@ -67,6 +67,30 @@ export interface OEContractsLike {
l2: OEL2ContractsLike
}
/**
* Represents list of custom bridges.
*/
export interface CustomBridges {
l1: {
[name: string]: Contract
}
l2: {
[name: string]: Contract
}
}
/**
* Something that looks like the list of custom bridges.
*/
export interface CustomBridgesLike {
l1: {
[K in keyof CustomBridges['l1']]: AddressLike
}
l2: {
[K in keyof CustomBridges['l2']]: AddressLike
}
}
/**
* Enum describing the status of a message.
*/
......@@ -123,11 +147,9 @@ export interface CrossChainMessageRequest {
}
/**
* Describes a message that is sent between L1 and L2. Direction determines where the message was
* sent from and where it's being sent to.
* Core components of a cross chain message.
*/
export interface CrossChainMessage {
direction: MessageDirection
export interface CoreCrossChainMessage {
sender: string
target: string
message: string
......@@ -135,12 +157,15 @@ export interface CrossChainMessage {
}
/**
* Convenience type for when you don't care which direction the message is going in.
* Describes a message that is sent between L1 and L2. Direction determines where the message was
* sent from and where it's being sent to.
*/
export type DirectionlessCrossChainMessage = Omit<
CrossChainMessage,
'direction'
>
export interface CrossChainMessage extends CoreCrossChainMessage {
direction: MessageDirection
logIndex: number
blockNumber: number
transactionHash: string
}
/**
* Describes a token withdrawal or deposit, along with the underlying raw cross chain message
......@@ -153,22 +178,24 @@ export interface TokenBridgeMessage {
l1Token: string
l2Token: string
amount: BigNumber
raw: CrossChainMessage
data: string
logIndex: number
blockNumber: number
transactionHash: string
}
/**
* Enum describing the status of a CrossDomainMessage message receipt.
*/
export enum MessageReceiptStatus {
RELAYED_SUCCEEDED,
RELAYED_FAILED,
RELAYED_SUCCEEDED,
}
/**
* CrossDomainMessage receipt.
*/
export interface MessageReceipt {
messageHash: string
receiptStatus: MessageReceiptStatus
transactionReceipt: TransactionReceipt
}
......
......@@ -7,6 +7,8 @@ import {
OEContractsLike,
OEL2ContractsLike,
AddressLike,
CustomBridges,
CustomBridgesLike,
} from '../interfaces'
import { toAddress } from './coercion'
import { DeepPartial } from './type-utils'
......@@ -36,6 +38,42 @@ const NAME_REMAPPING = {
WETH: 'WETH9',
}
/**
* Mapping of L1 chain IDs to the list of custom bridge addresses for each chain.
*/
export const CUSTOM_BRIDGE_ADDRESSES: {
[l1ChainId: number]: CustomBridgesLike
} = {
// TODO: Maybe we can pull these automatically from the token list?
// Alternatively, check against the token list in CI.
1: {
l1: {
SNX: '0xCd9D4988C0AE61887B075bA77f08cbFAd2b65068',
DAI: '0x10E6593CDda8c58a1d0f14C5164B376352a55f2F',
BitBTC: '0xaBA2c5F108F7E820C049D5Af70B16ac266c8f128',
},
l2: {
SNX: '0x3f87Ff1de58128eF8FCb4c807eFD776E1aC72E51',
DAI: '0x467194771dAe2967Aef3ECbEDD3Bf9a310C76C65',
BitBTC: '0x158F513096923fF2d3aab2BcF4478536de6725e2',
},
},
42: {
l1: {
SNX: '0xD134Db47DDF5A6feB245452af17cCAf92ee53D3c',
DAI: '0xb415e822C4983ecD6B1c1596e8a5f976cf6CD9e3',
BitBTC: '0x0b651A42F32069d62d5ECf4f2a7e5Bd3E9438746',
USX: '0x40E862341b2416345F02c41Ac70df08525150dC7',
},
l2: {
SNX: '0x5C3f51CEd0C2F6157e2be67c029264D6C44bfe42',
DAI: '0x467194771dAe2967Aef3ECbEDD3Bf9a310C76C65',
BitBTC: '0x0CFb46528a7002a7D8877a5F7a69b9AaF1A9058e',
USX: '0xB4d37826b14Cd3CB7257A2A5094507d701fe715f',
},
},
}
/**
* Mapping of L1 chain IDs to the appropriate contract addresses for the OE deployments to the
* given network. Simplifies the process of getting the correct contract addresses for a given
......@@ -190,3 +228,59 @@ export const getAllOEContracts = (
l2: l2Contracts,
}
}
/**
* Gets a series of custom bridges for the given L1 chain ID.
*
* @param l1ChainId L1 chain ID for the L1 network where the custom bridges are deployed.
* @param opts Additional options for connecting to the custom bridges.
* @param opts.l1SignerOrProvider Signer or provider to connect to the L1 contracts.
* @param opts.l2SignerOrProvider Signer or provider to connect to the L2 contracts.
* @param opts.overrides Custom contract address overrides for L1 or L2 contracts.
* @returns An object containing ethers.Contract objects connected to the appropriate addresses on
* both L1 and L2.
*/
export const getCustomBridges = (
l1ChainId: number,
opts: {
l1SignerOrProvider?: ethers.Signer | ethers.providers.Provider
l2SignerOrProvider?: ethers.Signer | ethers.providers.Provider
overrides?: Partial<CustomBridgesLike>
} = {}
): CustomBridges => {
const addresses = CUSTOM_BRIDGE_ADDRESSES[l1ChainId] || {
l1: {},
l2: {},
}
for (const [contractName, contractAddress] of Object.entries(
opts.overrides?.l1 || {}
)) {
addresses.l1[contractName] = contractAddress
}
for (const [contractName, contractAddress] of Object.entries(
opts.overrides?.l2 || {}
)) {
addresses.l2[contractName] = contractAddress
}
const bridges = {
l1: {},
l2: {},
}
for (const [contractName, contractAddress] of Object.entries(addresses.l1)) {
bridges.l1[contractName] = new Contract(
toAddress(contractAddress),
getContractInterface('IL1ERC20Bridge'),
opts.l1SignerOrProvider
)
}
for (const [contractName, contractAddress] of Object.entries(addresses.l2)) {
bridges.l2[contractName] = new Contract(
toAddress(contractAddress),
getContractInterface('IL2ERC20Bridge'),
opts.l2SignerOrProvider
)
}
return bridges
}
......@@ -2,3 +2,4 @@ export * from './coercion'
export * from './contracts'
export * from './message-encoding'
export * from './type-utils'
export * from './misc-utils'
import { getContractInterface } from '@eth-optimism/contracts'
import { ethers } from 'ethers'
import { DirectionlessCrossChainMessage } from '../interfaces'
import { CoreCrossChainMessage } from '../interfaces'
/**
* Returns the canonical encoding of a cross chain message. This encoding is used in various
* locations within the Optimistic Ethereum smart contracts.
* locations within the Optimism smart contracts.
*
* @param message Cross chain message to encode.
* @returns Canonical encoding of the message.
*/
export const encodeCrossChainMessage = (
message: DirectionlessCrossChainMessage
message: CoreCrossChainMessage
): string => {
return getContractInterface('L2CrossDomainMessenger').encodeFunctionData(
'relayMessage',
......@@ -20,14 +20,14 @@ export const encodeCrossChainMessage = (
/**
* Returns the canonical hash of a cross chain message. This hash is used in various locations
* within the Optimistic Ethereum smart contracts and is the keccak256 hash of the result of
* within the Optimism smart contracts and is the keccak256 hash of the result of
* encodeCrossChainMessage.
*
* @param message Cross chain message to hash.
* @returns Canonical hash of the message.
*/
export const hashCrossChainMessage = (
message: DirectionlessCrossChainMessage
message: CoreCrossChainMessage
): string => {
return ethers.utils.solidityKeccak256(
['bytes'],
......
// TODO: A lot of this stuff could probably live in core-utils instead.
// Review this file eventually for stuff that could go into core-utils.
/**
* Returns a copy of the given object ({ ...obj }) with the given keys omitted.
*
* @param obj Object to return with the keys omitted.
* @param keys Keys to omit from the returned object.
* @returns A copy of the given object with the given keys omitted.
*/
export const omit = (obj: any, ...keys: string[]) => {
const copy = { ...obj }
for (const key of keys) {
delete copy[key]
}
return copy
}
pragma solidity ^0.8.9;
import { MockMessenger } from "./MockMessenger.sol";
contract MockBridge {
event ERC20DepositInitiated(
address indexed _l1Token,
address indexed _l2Token,
address indexed _from,
address _to,
uint256 _amount,
bytes _data
);
event ERC20WithdrawalFinalized(
address indexed _l1Token,
address indexed _l2Token,
address indexed _from,
address _to,
uint256 _amount,
bytes _data
);
event WithdrawalInitiated(
address indexed _l1Token,
address indexed _l2Token,
address indexed _from,
address _to,
uint256 _amount,
bytes _data
);
event DepositFinalized(
address indexed _l1Token,
address indexed _l2Token,
address indexed _from,
address _to,
uint256 _amount,
bytes _data
);
event DepositFailed(
address indexed _l1Token,
address indexed _l2Token,
address indexed _from,
address _to,
uint256 _amount,
bytes _data
);
struct TokenEventStruct {
address l1Token;
address l2Token;
address from;
address to;
uint256 amount;
bytes data;
}
MockMessenger public messenger;
constructor(MockMessenger _messenger) {
messenger = _messenger;
}
function emitERC20DepositInitiated(
TokenEventStruct memory _params
) public {
emit ERC20DepositInitiated(_params.l1Token, _params.l2Token, _params.from, _params.to, _params.amount, _params.data);
messenger.triggerSentMessageEvent(
MockMessenger.SentMessageEventParams(
address(0),
address(0),
hex"1234",
1234,
12345678
)
);
}
function emitERC20WithdrawalFinalized(
TokenEventStruct memory _params
) public {
emit ERC20WithdrawalFinalized(_params.l1Token, _params.l2Token, _params.from, _params.to, _params.amount, _params.data);
}
function emitWithdrawalInitiated(
TokenEventStruct memory _params
) public {
emit WithdrawalInitiated(_params.l1Token, _params.l2Token, _params.from, _params.to, _params.amount, _params.data);
messenger.triggerSentMessageEvent(
MockMessenger.SentMessageEventParams(
address(0),
address(0),
hex"1234",
1234,
12345678
)
);
}
function emitDepositFinalized(
TokenEventStruct memory _params
) public {
emit DepositFinalized(_params.l1Token, _params.l2Token, _params.from, _params.to, _params.amount, _params.data);
}
function emitDepositFailed(
TokenEventStruct memory _params
) public {
emit DepositFailed(_params.l1Token, _params.l2Token, _params.from, _params.to, _params.amount, _params.data);
}
}
......@@ -28,17 +28,23 @@ contract MockMessenger is ICrossDomainMessenger {
return;
}
function triggerSentMessageEvent(
SentMessageEventParams memory _params
) public {
emit SentMessage(
_params.target,
_params.sender,
_params.message,
_params.messageNonce,
_params.gasLimit
);
}
function triggerSentMessageEvents(
SentMessageEventParams[] memory _params
) public {
for (uint256 i = 0; i < _params.length; i++) {
emit SentMessage(
_params[i].target,
_params[i].sender,
_params[i].message,
_params[i].messageNonce,
_params[i].gasLimit
);
triggerSentMessageEvent(_params[i]);
}
}
......
......@@ -3,8 +3,7 @@ import { Contract, Signer } from 'ethers'
import { ethers } from 'hardhat'
import { getContractFactory } from '@eth-optimism/contracts'
import {
CrossChainMessage,
MessageDirection,
CoreCrossChainMessage,
encodeCrossChainMessage,
hashCrossChainMessage,
} from '../../src'
......@@ -25,8 +24,7 @@ describe('message encoding utils', () => {
})
it('should properly encode a message', async () => {
const message: CrossChainMessage = {
direction: MessageDirection.L1_TO_L2,
const message: CoreCrossChainMessage = {
target: '0x' + '11'.repeat(20),
sender: '0x' + '22'.repeat(20),
message: '0x' + '1234'.repeat(32),
......@@ -53,8 +51,7 @@ describe('message encoding utils', () => {
})
it('should properly hash a message', async () => {
const message: CrossChainMessage = {
direction: MessageDirection.L1_TO_L2,
const message: CoreCrossChainMessage = {
target: '0x' + '11'.repeat(20),
sender: '0x' + '22'.repeat(20),
message: '0x' + '1234'.repeat(32),
......
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