Commit 2c966cdf authored by Adrian Sutton's avatar Adrian Sutton

Merge branch 'develop' into aj/geth-1.13.5

parents 2f3a4863 2e35a8f6
...@@ -3,7 +3,7 @@ version: 2.1 ...@@ -3,7 +3,7 @@ version: 2.1
parameters: parameters:
ci_builder_image: ci_builder_image:
type: string type: string
default: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:v0.27.0 default: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:v0.30.0
orbs: orbs:
go: circleci/go@1.8.0 go: circleci/go@1.8.0
...@@ -127,8 +127,11 @@ jobs: ...@@ -127,8 +127,11 @@ jobs:
resource_class: xlarge resource_class: xlarge
steps: steps:
- checkout - checkout
- run:
name: git submodules
command: make submodules
- check-changed: - check-changed:
patterns: op-chain-ops,packages/ patterns: op-chain-ops,packages/,op-node
- restore_cache: - restore_cache:
name: Restore PNPM Package Cache name: Restore PNPM Package Cache
keys: keys:
...@@ -317,12 +320,16 @@ jobs: ...@@ -317,12 +320,16 @@ jobs:
resource_class: xlarge resource_class: xlarge
steps: steps:
- checkout - checkout
- run:
name: git submodules
command: make submodules
- check-changed: - check-changed:
patterns: contracts-bedrock,op-node patterns: contracts-bedrock,op-node
- run: - run:
name: print forge version name: print forge version
command: forge --version command: forge --version
working_directory: packages/contracts-bedrock working_directory: packages/contracts-bedrock
# We do not use the pre-built contracts becuase forge coverage uses different optimizer settings
- run: - run:
name: test and generate coverage name: test and generate coverage
command: pnpm coverage:lcov command: pnpm coverage:lcov
...@@ -339,11 +346,23 @@ jobs: ...@@ -339,11 +346,23 @@ jobs:
contracts-bedrock-tests: contracts-bedrock-tests:
docker: docker:
- image: <<pipeline.parameters.ci_builder_image>> - image: <<pipeline.parameters.ci_builder_image>>
resource_class: xlarge resource_class: medium
steps: steps:
- checkout - checkout
- run:
name: git submodules
command: make submodules
- restore_cache:
name: Restore PNPM Package Cache
keys:
- pnpm-packages-v2-{{ checksum "pnpm-lock.yaml" }}
- attach_workspace: { at: "." }
- check-changed: - check-changed:
patterns: contracts-bedrock,op-node patterns: contracts-bedrock,op-node
# populate node modules from the cache
- run:
name: Install dependencies
command: pnpm install --frozen-lockfile --prefer-offline
- run: - run:
name: print forge version name: print forge version
command: forge --version command: forge --version
...@@ -359,22 +378,33 @@ jobs: ...@@ -359,22 +378,33 @@ jobs:
contracts-bedrock-checks: contracts-bedrock-checks:
docker: docker:
- image: <<pipeline.parameters.ci_builder_image>> - image: <<pipeline.parameters.ci_builder_image>>
resource_class: xlarge resource_class: medium
steps: steps:
- checkout - checkout
- run:
name: git submodules
command: make submodules
- restore_cache: - restore_cache:
name: Restore PNPM Package Cache name: Restore PNPM Package Cache
keys: keys:
- pnpm-packages-v2-{{ checksum "pnpm-lock.yaml" }} - pnpm-packages-v2-{{ checksum "pnpm-lock.yaml" }}
- attach_workspace: { at: "." }
- check-changed: - check-changed:
patterns: contracts-bedrock,op-node patterns: contracts-bedrock,op-node
# populate node modules from the cache # populate node modules from the cache
- run: - run:
name: Install dependencies name: Install dependencies
command: pnpm install --frozen-lockfile --prefer-offline command: pnpm install --frozen-lockfile --prefer-offline
# Note: this step needs to come first because one of the later steps modifies the cache & forces a contracts rebuild
- run: - run:
name: build contracts name: semver lock
command: pnpm build command: |
pnpm semver-lock
git diff --exit-code semver-lock.json || echo "export SEMVER_LOCK_STATUS=1" >> "$BASH_ENV"
working_directory: packages/contracts-bedrock
- run:
name: check deploy configs
command: pnpm validate-deploy-configs || echo "export DEPLOY_CONFIGS_STATUS=1" >> "$BASH_ENV"
working_directory: packages/contracts-bedrock working_directory: packages/contracts-bedrock
- run: - run:
name: lint name: lint
...@@ -396,22 +426,12 @@ jobs: ...@@ -396,22 +426,12 @@ jobs:
pnpm storage-snapshot pnpm storage-snapshot
git diff --exit-code .storage-layout || echo "export STORAGE_SNAPSHOT_STATUS=1" >> "$BASH_ENV" git diff --exit-code .storage-layout || echo "export STORAGE_SNAPSHOT_STATUS=1" >> "$BASH_ENV"
working_directory: packages/contracts-bedrock working_directory: packages/contracts-bedrock
- run:
name: semver lock
command: |
pnpm semver-lock
git diff --exit-code semver-lock.json || echo "export SEMVER_LOCK_STATUS=1" >> "$BASH_ENV"
working_directory: packages/contracts-bedrock
- run: - run:
name: invariant docs name: invariant docs
command: | command: |
pnpm autogen:invariant-docs pnpm autogen:invariant-docs
git diff --exit-code ./invariant-docs/*.md || echo "export INVARIANT_DOCS_STATUS=1" >> "$BASH_ENV" git diff --exit-code ./invariant-docs/*.md || echo "export INVARIANT_DOCS_STATUS=1" >> "$BASH_ENV"
working_directory: packages/contracts-bedrock working_directory: packages/contracts-bedrock
- run:
name: check deploy configs
command: pnpm validate-deploy-configs || echo "export DEPLOY_CONFIGS_STATUS=1" >> "$BASH_ENV"
working_directory: packages/contracts-bedrock
- run: - run:
name: check statuses name: check statuses
command: | command: |
...@@ -446,7 +466,7 @@ jobs: ...@@ -446,7 +466,7 @@ jobs:
contracts-bedrock-slither: contracts-bedrock-slither:
docker: docker:
- image: <<pipeline.parameters.ci_builder_image>> - image: <<pipeline.parameters.ci_builder_image>>
resource_class: xlarge resource_class: medium
steps: steps:
- checkout - checkout
- check-changed: - check-changed:
...@@ -1293,7 +1313,9 @@ workflows: ...@@ -1293,7 +1313,9 @@ workflows:
package_name: core-utils package_name: core-utils
requires: requires:
- pnpm-monorepo - pnpm-monorepo
- contracts-bedrock-tests - contracts-bedrock-tests:
requires:
- pnpm-monorepo
- contracts-bedrock-coverage - contracts-bedrock-coverage
- contracts-bedrock-checks: - contracts-bedrock-checks:
requires: requires:
...@@ -1520,11 +1542,6 @@ workflows: ...@@ -1520,11 +1542,6 @@ workflows:
- check-generated-mocks-op-service - check-generated-mocks-op-service
- cannon-go-lint-and-test - cannon-go-lint-and-test
- cannon-build-test-vectors - cannon-build-test-vectors
- check-values-match:
pattern_file1: "uint8 internal constant INITIALIZER ="
pattern_file2: "const InitializedValue ="
file1_path: "packages/contracts-bedrock/src/libraries/Constants.sol"
file2_path: "op-chain-ops/genesis/config.go"
release: release:
when: when:
not: not:
...@@ -1832,6 +1849,16 @@ workflows: ...@@ -1832,6 +1849,16 @@ workflows:
context: context:
- oplabs-gcr - oplabs-gcr
- slack - slack
- docker-build:
name: contracts-bedrock-docker-publish
docker_name: contracts-bedrock
docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
resource_class: xlarge
requires: [ 'chain-mon-docker-publish' ] # use the cached base image
publish: true
context:
- oplabs-gcr
- slack
- docker-build: - docker-build:
name: ufm-metamask-docker-publish name: ufm-metamask-docker-publish
docker_name: ufm-metamask docker_name: ufm-metamask
......
1a2e2e071ef0a1b6f41fdcba773b04c30498752f 3e962e2efe17396886fcb1fd141ccf4204cd3a21
...@@ -30,6 +30,8 @@ We recommend using the [Conventional Commits](https://www.conventionalcommits.or ...@@ -30,6 +30,8 @@ We recommend using the [Conventional Commits](https://www.conventionalcommits.or
Unless your PR is ready for immediate review and merging, please mark it as 'draft' (or simply do not open a PR yet). Unless your PR is ready for immediate review and merging, please mark it as 'draft' (or simply do not open a PR yet).
Once ready for review, make sure to include a thorough PR description to help reviewers. You can read more about the guidelines for opening PRs in the [PR Guidelines](./handbook/pr-guidelines.md) file.
**Bonus:** Add comments to the diff under the "Files Changed" tab on the PR page to clarify any sections where you think we might have questions about the approach taken. **Bonus:** Add comments to the diff under the "Files Changed" tab on the PR page to clarify any sections where you think we might have questions about the approach taken.
### Response time: ### Response time:
......
...@@ -39,6 +39,15 @@ golang-docker: ...@@ -39,6 +39,15 @@ golang-docker:
op-node op-batcher op-proposer op-challenger op-node op-batcher op-proposer op-challenger
.PHONY: golang-docker .PHONY: golang-docker
contracts-bedrock-docker:
IMAGE_TAGS=$$(git rev-parse HEAD),latest \
docker buildx bake \
--progress plain \
--load \
-f docker-bake.hcl \
contracts-bedrock
.PHONY: contracts-bedrock-docker
submodules: submodules:
git submodule update --init --recursive git submodule update --init --recursive
.PHONY: submodules .PHONY: submodules
......
...@@ -6,7 +6,6 @@ import ( ...@@ -6,7 +6,6 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"path"
"github.com/ethereum-optimism/optimism/op-service/ioutil" "github.com/ethereum-optimism/optimism/op-service/ioutil"
) )
...@@ -35,18 +34,16 @@ func writeJSON[X any](outputPath string, value X) error { ...@@ -35,18 +34,16 @@ func writeJSON[X any](outputPath string, value X) error {
var out io.Writer var out io.Writer
finish := func() error { return nil } finish := func() error { return nil }
if outputPath != "-" { if outputPath != "-" {
// Write to a tmp file but reserve the file extension if present f, err := ioutil.NewAtomicWriterCompressed(outputPath, 0755)
tmpPath := outputPath + "-tmp" + path.Ext(outputPath)
f, err := ioutil.OpenCompressed(tmpPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
if err != nil { if err != nil {
return fmt.Errorf("failed to open output file: %w", err) return fmt.Errorf("failed to open output file: %w", err)
} }
// Ensure we close the stream even if failures occur.
defer f.Close() defer f.Close()
out = f out = f
finish = func() error { // Closing the file causes it to be renamed to the final destination
// Rename the file into place as atomically as the OS will allow // so make sure we handle any errors it returns
return os.Rename(tmpPath, outputPath) finish = f.Close
}
} else { } else {
out = os.Stdout out = os.Stdout
} }
......
...@@ -2,10 +2,8 @@ package mipsevm ...@@ -2,10 +2,8 @@ package mipsevm
import ( import (
"encoding/binary" "encoding/binary"
"encoding/json"
"fmt" "fmt"
"math/big" "math/big"
"os"
"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"
...@@ -22,27 +20,6 @@ import ( ...@@ -22,27 +20,6 @@ import (
"github.com/ethereum-optimism/optimism/op-chain-ops/srcmap" "github.com/ethereum-optimism/optimism/op-chain-ops/srcmap"
) )
var (
StepBytes4 []byte
LoadKeccak256PreimagePartBytes4 []byte
LoadLocalDataBytes4 []byte
)
func init() {
mipsAbi, err := bindings.MIPSMetaData.GetAbi()
if err != nil {
panic(fmt.Errorf("failed to load MIPS ABI: %w", err))
}
StepBytes4 = mipsAbi.Methods["step"].ID[:4]
preimageAbi, err := bindings.PreimageOracleMetaData.GetAbi()
if err != nil {
panic(fmt.Errorf("failed to load pre-image oracle ABI: %w", err))
}
LoadKeccak256PreimagePartBytes4 = preimageAbi.Methods["loadKeccak256PreimagePart"].ID[:4]
LoadLocalDataBytes4 = preimageAbi.Methods["loadLocalData"].ID[:4]
}
// LoadContracts loads the Cannon contracts, from op-bindings package // LoadContracts loads the Cannon contracts, from op-bindings package
func LoadContracts() (*Contracts, error) { func LoadContracts() (*Contracts, error) {
var mips, oracle Contract var mips, oracle Contract
...@@ -56,34 +33,6 @@ func LoadContracts() (*Contracts, error) { ...@@ -56,34 +33,6 @@ func LoadContracts() (*Contracts, error) {
}, nil }, nil
} }
// LoadContractsFromFiles loads the Cannon contracts, from local filesystem
func LoadContractsFromFiles() (*Contracts, error) {
mips, err := LoadContract("MIPS")
if err != nil {
return nil, err
}
oracle, err := LoadContract("PreimageOracle")
if err != nil {
return nil, err
}
return &Contracts{
MIPS: mips,
Oracle: oracle,
}, nil
}
func LoadContract(name string) (*Contract, error) {
dat, err := os.ReadFile(fmt.Sprintf("../../packages/contracts-bedrock/forge-artifacts/%s.sol/%s.json", name, name))
if err != nil {
return nil, fmt.Errorf("failed to read contract JSON definition of %q: %w", name, err)
}
var out Contract
if err := json.Unmarshal(dat, &out); err != nil {
return nil, fmt.Errorf("failed to parse contract JSON definition of %q: %w", name, err)
}
return &out, nil
}
type Contract struct { type Contract struct {
DeployedBytecode struct { DeployedBytecode struct {
Object hexutil.Bytes `json:"object"` Object hexutil.Bytes `json:"object"`
......
...@@ -3,6 +3,8 @@ package mipsevm ...@@ -3,6 +3,8 @@ package mipsevm
import ( import (
"bytes" "bytes"
"debug/elf" "debug/elf"
"errors"
"fmt"
"io" "io"
"math/big" "math/big"
"os" "os"
...@@ -11,6 +13,8 @@ import ( ...@@ -11,6 +13,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
"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/state" "github.com/ethereum/go-ethereum/core/state"
...@@ -76,13 +80,13 @@ func (m *MIPSEVM) Step(t *testing.T, stepWitness *StepWitness) []byte { ...@@ -76,13 +80,13 @@ func (m *MIPSEVM) Step(t *testing.T, stepWitness *StepWitness) []byte {
if stepWitness.HasPreimage() { if stepWitness.HasPreimage() {
t.Logf("reading preimage key %x at offset %d", stepWitness.PreimageKey, stepWitness.PreimageOffset) t.Logf("reading preimage key %x at offset %d", stepWitness.PreimageKey, stepWitness.PreimageOffset)
poInput, err := stepWitness.EncodePreimageOracleInput(0) poInput, err := encodePreimageOracleInput(t, stepWitness, 0)
require.NoError(t, err, "encode preimage oracle input") require.NoError(t, err, "encode preimage oracle input")
_, leftOverGas, err := m.env.Call(vm.AccountRef(sender), m.addrs.Oracle, poInput, startingGas, big.NewInt(0)) _, leftOverGas, err := m.env.Call(vm.AccountRef(sender), m.addrs.Oracle, poInput, startingGas, big.NewInt(0))
require.NoErrorf(t, err, "evm should not fail, took %d gas", startingGas-leftOverGas) require.NoErrorf(t, err, "evm should not fail, took %d gas", startingGas-leftOverGas)
} }
input := stepWitness.EncodeStepInput(0) input := encodeStepInput(t, stepWitness, 0)
ret, leftOverGas, err := m.env.Call(vm.AccountRef(sender), m.addrs.MIPS, input, startingGas, big.NewInt(0)) ret, leftOverGas, err := m.env.Call(vm.AccountRef(sender), m.addrs.MIPS, input, startingGas, big.NewInt(0))
require.NoError(t, err, "evm should not fail") require.NoError(t, err, "evm should not fail")
require.Len(t, ret, 32, "expecting 32-byte state hash") require.Len(t, ret, 32, "expecting 32-byte state hash")
...@@ -101,6 +105,53 @@ func (m *MIPSEVM) Step(t *testing.T, stepWitness *StepWitness) []byte { ...@@ -101,6 +105,53 @@ func (m *MIPSEVM) Step(t *testing.T, stepWitness *StepWitness) []byte {
return evmPost return evmPost
} }
func encodeStepInput(t *testing.T, wit *StepWitness, localContext LocalContext) []byte {
mipsAbi, err := bindings.MIPSMetaData.GetAbi()
require.NoError(t, err)
input, err := mipsAbi.Pack("step", wit.State, wit.MemProof, new(big.Int).SetUint64(uint64(localContext)))
require.NoError(t, err)
return input
}
func encodePreimageOracleInput(t *testing.T, wit *StepWitness, localContext LocalContext) ([]byte, error) {
if wit.PreimageKey == ([32]byte{}) {
return nil, errors.New("cannot encode pre-image oracle input, witness has no pre-image to proof")
}
preimageAbi, err := bindings.PreimageOracleMetaData.GetAbi()
require.NoError(t, err, "failed to load pre-image oracle ABI")
switch preimage.KeyType(wit.PreimageKey[0]) {
case preimage.LocalKeyType:
if len(wit.PreimageValue) > 32+8 {
return nil, fmt.Errorf("local pre-image exceeds maximum size of 32 bytes with key 0x%x", wit.PreimageKey)
}
preimagePart := wit.PreimageValue[8:]
var tmp [32]byte
copy(tmp[:], preimagePart)
input, err := preimageAbi.Pack("loadLocalData",
new(big.Int).SetBytes(wit.PreimageKey[1:]),
new(big.Int).SetUint64(uint64(localContext)),
tmp,
new(big.Int).SetUint64(uint64(len(preimagePart))),
new(big.Int).SetUint64(uint64(wit.PreimageOffset)),
)
require.NoError(t, err)
return input, nil
case preimage.Keccak256KeyType:
input, err := preimageAbi.Pack(
"loadKeccak256PreimagePart",
new(big.Int).SetUint64(uint64(wit.PreimageOffset)),
wit.PreimageValue[8:])
require.NoError(t, err)
return input, nil
default:
return nil, fmt.Errorf("unsupported pre-image type %d, cannot prepare preimage with key %x offset %d for oracle",
wit.PreimageKey[0], wit.PreimageKey, wit.PreimageOffset)
}
}
func TestEVM(t *testing.T) { func TestEVM(t *testing.T) {
testFiles, err := os.ReadDir("open_mips_tests/test/bin") testFiles, err := os.ReadDir("open_mips_tests/test/bin")
require.NoError(t, err) require.NoError(t, err)
...@@ -241,7 +292,7 @@ func TestEVMFault(t *testing.T) { ...@@ -241,7 +292,7 @@ func TestEVMFault(t *testing.T) {
State: initialState.EncodeWitness(), State: initialState.EncodeWitness(),
MemProof: insnProof[:], MemProof: insnProof[:],
} }
input := stepWitness.EncodeStepInput(0) input := encodeStepInput(t, stepWitness, 0)
startingGas := uint64(30_000_000) startingGas := uint64(30_000_000)
_, _, err := env.Call(vm.AccountRef(sender), addrs.MIPS, input, startingGas, big.NewInt(0)) _, _, err := env.Call(vm.AccountRef(sender), addrs.MIPS, input, startingGas, big.NewInt(0))
......
package mipsevm package mipsevm
import (
"encoding/binary"
"errors"
"fmt"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
)
type LocalContext uint64 type LocalContext uint64
type StepWitness struct { type StepWitness struct {
...@@ -21,78 +13,6 @@ type StepWitness struct { ...@@ -21,78 +13,6 @@ type StepWitness struct {
PreimageOffset uint32 PreimageOffset uint32
} }
func uint32ToBytes32(v uint32) []byte {
var out [32]byte
binary.BigEndian.PutUint32(out[32-4:], v)
return out[:]
}
func uint64ToBytes32(v uint64) []byte {
var out [32]byte
binary.BigEndian.PutUint64(out[32-8:], v)
return out[:]
}
func (wit *StepWitness) EncodeStepInput(localContext LocalContext) []byte {
abiStateLen := len(wit.State)
if abiStateLen%32 != 0 {
abiStateLen += 32 - (abiStateLen % 32)
}
// pad state to 32 byte multiple per ABI
abiState := make([]byte, abiStateLen)
copy(abiState, wit.State)
var input []byte
input = append(input, StepBytes4...)
input = append(input, uint32ToBytes32(32*3)...) // state data offset in bytes
input = append(input, uint32ToBytes32(32*3+32+uint32(len(abiState)))...) // proof data offset in bytes
input = append(input, uint64ToBytes32(uint64(localContext))...) // local context in bytes
input = append(input, uint32ToBytes32(uint32(len(wit.State)))...) // state data length in bytes
input = append(input, abiState[:]...)
input = append(input, uint32ToBytes32(uint32(len(wit.MemProof)))...) // proof data length in bytes
input = append(input, wit.MemProof[:]...)
return input
}
func (wit *StepWitness) HasPreimage() bool { func (wit *StepWitness) HasPreimage() bool {
return wit.PreimageKey != ([32]byte{}) return wit.PreimageKey != ([32]byte{})
} }
func (wit *StepWitness) EncodePreimageOracleInput(localContext LocalContext) ([]byte, error) {
if wit.PreimageKey == ([32]byte{}) {
return nil, errors.New("cannot encode pre-image oracle input, witness has no pre-image to proof")
}
switch preimage.KeyType(wit.PreimageKey[0]) {
case preimage.LocalKeyType:
if len(wit.PreimageValue) > 32+8 {
return nil, fmt.Errorf("local pre-image exceeds maximum size of 32 bytes with key 0x%x", wit.PreimageKey)
}
var input []byte
input = append(input, LoadLocalDataBytes4...)
input = append(input, wit.PreimageKey[:]...)
input = append(input, uint64ToBytes32(uint64(localContext))...) // local context in bytes
preimagePart := wit.PreimageValue[8:]
var tmp [32]byte
copy(tmp[:], preimagePart)
input = append(input, tmp[:]...)
input = append(input, uint32ToBytes32(uint32(len(wit.PreimageValue)-8))...)
input = append(input, uint32ToBytes32(wit.PreimageOffset)...)
// Note: we can pad calldata to 32 byte multiple, but don't strictly have to
return input, nil
case preimage.Keccak256KeyType:
var input []byte
input = append(input, LoadKeccak256PreimagePartBytes4...)
input = append(input, uint32ToBytes32(wit.PreimageOffset)...)
input = append(input, uint32ToBytes32(32+32)...) // partOffset, calldata offset
input = append(input, uint32ToBytes32(uint32(len(wit.PreimageValue))-8)...)
input = append(input, wit.PreimageValue[8:]...)
// Note: we can pad calldata to 32 byte multiple, but don't strictly have to
return input, nil
default:
return nil, fmt.Errorf("unsupported pre-image type %d, cannot prepare preimage with key %x offset %d for oracle",
wit.PreimageKey[0], wit.PreimageKey, wit.PreimageOffset)
}
}
...@@ -180,4 +180,10 @@ target "ci-builder" { ...@@ -180,4 +180,10 @@ target "ci-builder" {
tags = [for tag in split(",", IMAGE_TAGS) : "${REGISTRY}/${REPOSITORY}/ci-builder:${tag}"] tags = [for tag in split(",", IMAGE_TAGS) : "${REGISTRY}/${REPOSITORY}/ci-builder:${tag}"]
} }
target "contracts-bedrock" {
dockerfile = "./ops/docker/Dockerfile.packages"
context = "."
target = "contracts-bedrock"
platforms = split(",", PLATFORMS)
tags = [for tag in split(",", IMAGE_TAGS) : "${REGISTRY}/${REPOSITORY}/contracts-bedrock:${tag}"]
}
# Pull Request Guidelines and Best Practices
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- [Overview](#overview)
- [PR Lifecycle Best Practices](#pr-lifecycle-best-practices)
- [Before Starting PRs](#before-starting-prs)
- [Opening PRs](#opening-prs)
- [Reviewing PRs](#reviewing-prs)
- [Merging PRs](#merging-prs)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Overview
This document contains guidelines best practices for PRs that should be enforced as much as possible. The motivations and goals behind these best practices are:
- **Ensure thorough reviews**: By the time the PR is merged, at least one other person—because there is always at least one reviewer—should understand the PR’s changes just as well as the PR author. This helps improve security by reducing bugs and single points of failure (i.e. there should never be only one person who understands certain code).
- **Reduce PR churn**: PRs should be quickly reviewable and mergeable without much churn (both in terms of code rewrites and comment cycles). This saves time by reducing the number of rebases due to conflicts. Similarly, too many review cycles is a burden for both PR authors and reviewers, and results in “review fatigue” where reviews become less careful and thorough, increasing the likelihood of bugs.
- **Traceability**: We should be able to look back at issues and PRs to understand why a certain decision was made or why a given approach was taken.
## PR Lifecycle Best Practices
This is organized by current state of PR, so it can be easily be referenced frequently to help internalize the guidelines.
### Before Starting PRs
- **Keep PRs Focused**: Each PR should be a single, narrow, well-defined scope.
### Opening PRs
- **Review Your Own Code**: Reviewing the diff yourself *in a different context*, can be very useful for discovering issues, typos, and bugs before opening the PR. For example, write code in your IDE, then review it in the GitHub diff view. The perspective change forces you to slow down and helps reveal issues you may have missed.
- **Explain Decisions/Tradeoffs**: Explain rationale for any design/architecture decisions and implementation details in the PR description. If it closes an issue, remember to mention the issue it closes, e.g. `Closes <issueUrl>`. Otherwise, just link to the issue. If there is no issue, whatever details would have been in the issue should be in the PR description.
- **Guide PR reviewers:** Let them know about areas of concern, under-tested areas, or vague requirements that should be ironed out.
### Reviewing PRs
- **Verify Requirements are Met**: If the PR claims to fix or close an issue, check that all the requirements in the issue are actually met. Otherwise the issue may be in a good place to merge, but just shouldn’t close the issue.
- **Focus on Tests**: The tests are the spec and therefore should be the focus of reviews. If tests are thorough and passing, the rest is an implementation detail (to an extent—don’t skip source code reviews) that can be fixed in a future optimization/cleanup PR. Make sure edge case behaviors are defined and handled.
- **Think like an Auditor:** What edge cases were ignored? How can the code break? When might it behave incorrectly and unexpectedly? What code should have been changed that isn’t in the diff? What implicit assumptions are made that might be invalid?
- **Ensure Comment Significance is Clear**: Indicate which comments are nits/optionals that the PR author can resolve, compared to which you want to follow up on.
- Prefix non-blocking comments with `[nit]` or `[non-blocking]`.
- **Consider Reviewing in Your IDE**: For example, GitHub has [this VSCode extension](https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-pull-request-github) to review PRs. This provides more code context and enables review to benefit from your standard lints and IDE features, whereas GitHub’s diff shows none of that.
### Merging PRs
- **Resolve all Comments**: Comments can be resolved by (1) the PR author for nits/optionals, (2) the author or reviewer after discussions, or (3) extracting the comment into an issue to address in a future PR. For (3), ensure the new issue links to the specific comment thread. This is currently enforced by GitHub's merge requirements.
- **Other Standard Merge Requirements**: The PR must be approved by the appropriate reviewers, CI must passing, and other standard merge requirements apply.
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.
...@@ -70,6 +70,8 @@ func NewBackendWithGenesisTimestamp(ts uint64, shanghai bool) *backends.Simulate ...@@ -70,6 +70,8 @@ func NewBackendWithGenesisTimestamp(ts uint64, shanghai bool) *backends.Simulate
LondonBlock: big.NewInt(0), LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0), ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0), GrayGlacierBlock: big.NewInt(0),
ShanghaiTime: nil,
CancunTime: nil,
// Activated proof of stake. We manually build/commit blocks in the simulator anyway, // Activated proof of stake. We manually build/commit blocks in the simulator anyway,
// and the timestamp verification of PoS is not against the wallclock, // and the timestamp verification of PoS is not against the wallclock,
// preventing blocks from getting stuck temporarily in the future-blocks queue, decreasing setup time a lot. // preventing blocks from getting stuck temporarily in the future-blocks queue, decreasing setup time a lot.
......
This diff is collapsed.
...@@ -64,6 +64,7 @@ func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, erro ...@@ -64,6 +64,7 @@ func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, erro
RegolithTime: config.RegolithTime(block.Time()), RegolithTime: config.RegolithTime(block.Time()),
CanyonTime: config.CanyonTime(block.Time()), CanyonTime: config.CanyonTime(block.Time()),
ShanghaiTime: config.CanyonTime(block.Time()), ShanghaiTime: config.CanyonTime(block.Time()),
CancunTime: nil, // no Dencun on L2 yet.
Optimism: &params.OptimismConfig{ Optimism: &params.OptimismConfig{
EIP1559Denominator: eip1559Denom, EIP1559Denominator: eip1559Denom,
EIP1559Elasticity: eip1559Elasticity, EIP1559Elasticity: eip1559Elasticity,
...@@ -134,6 +135,8 @@ func NewL1Genesis(config *DeployConfig) (*core.Genesis, error) { ...@@ -134,6 +135,8 @@ func NewL1Genesis(config *DeployConfig) (*core.Genesis, error) {
LondonBlock: big.NewInt(0), LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0), ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0), GrayGlacierBlock: big.NewInt(0),
ShanghaiTime: nil,
CancunTime: nil,
} }
extraData := make([]byte, 0) extraData := make([]byte, 0)
...@@ -168,6 +171,10 @@ func NewL1Genesis(config *DeployConfig) (*core.Genesis, error) { ...@@ -168,6 +171,10 @@ func NewL1Genesis(config *DeployConfig) (*core.Genesis, error) {
if timestamp == 0 { if timestamp == 0 {
timestamp = hexutil.Uint64(time.Now().Unix()) timestamp = hexutil.Uint64(time.Now().Unix())
} }
if !config.L1UseClique && config.L1CancunTimeOffset != nil {
cancunTime := uint64(timestamp) + *config.L1CancunTimeOffset
chainConfig.CancunTime = &cancunTime
}
return &core.Genesis{ return &core.Genesis{
Config: &chainConfig, Config: &chainConfig,
......
This diff is collapsed.
This diff is collapsed.
...@@ -34,6 +34,7 @@ var ( ...@@ -34,6 +34,7 @@ var (
ErrCannonNetworkAndL2Genesis = errors.New("only specify one of network or l2 genesis path") ErrCannonNetworkAndL2Genesis = errors.New("only specify one of network or l2 genesis path")
ErrCannonNetworkUnknown = errors.New("unknown cannon network") ErrCannonNetworkUnknown = errors.New("unknown cannon network")
ErrMissingRollupRpc = errors.New("missing rollup rpc url") ErrMissingRollupRpc = errors.New("missing rollup rpc url")
ErrCannonAndOutputCannonConflict = errors.New("trace types cannon and outputCannon cannot be enabled at the same time")
) )
type TraceType string type TraceType string
...@@ -187,6 +188,9 @@ func (c Config) Check() error { ...@@ -187,6 +188,9 @@ func (c Config) Check() error {
return ErrMissingRollupRpc return ErrMissingRollupRpc
} }
} }
if c.TraceTypeEnabled(TraceTypeCannon) && c.TraceTypeEnabled(TraceTypeOutputCannon) {
return ErrCannonAndOutputCannonConflict
}
if c.TraceTypeEnabled(TraceTypeCannon) || c.TraceTypeEnabled(TraceTypeOutputCannon) { if c.TraceTypeEnabled(TraceTypeCannon) || c.TraceTypeEnabled(TraceTypeOutputCannon) {
if c.CannonBin == "" { if c.CannonBin == "" {
return ErrMissingCannonBin return ErrMissingCannonBin
......
This diff is collapsed.
This diff is collapsed.
...@@ -115,8 +115,7 @@ func setupTestAgent(t *testing.T, agreeWithProposedOutput bool) (*Agent, *stubCl ...@@ -115,8 +115,7 @@ func setupTestAgent(t *testing.T, agreeWithProposedOutput bool) (*Agent, *stubCl
depth := 4 depth := 4
provider := alphabet.NewTraceProvider("abcd", uint64(depth)) provider := alphabet.NewTraceProvider("abcd", uint64(depth))
responder := &stubResponder{} responder := &stubResponder{}
updater := &stubUpdater{} agent := NewAgent(metrics.NoopMetrics, claimLoader, depth, trace.NewSimpleTraceAccessor(provider), responder, agreeWithProposedOutput, logger)
agent := NewAgent(metrics.NoopMetrics, claimLoader, depth, trace.NewSimpleTraceAccessor(provider), responder, updater, agreeWithProposedOutput, logger)
return agent, claimLoader, responder return agent, claimLoader, responder
} }
...@@ -166,10 +165,3 @@ func (s *stubResponder) ResolveClaim(ctx context.Context, clainIdx uint64) error ...@@ -166,10 +165,3 @@ func (s *stubResponder) ResolveClaim(ctx context.Context, clainIdx uint64) error
func (s *stubResponder) PerformAction(ctx context.Context, response types.Action) error { func (s *stubResponder) PerformAction(ctx context.Context, response types.Action) error {
return nil return nil
} }
type stubUpdater struct {
}
func (s *stubUpdater) UpdateOracle(ctx context.Context, data *types.PreimageOracleData) error {
panic("Not implemented")
}
...@@ -13,6 +13,10 @@ import ( ...@@ -13,6 +13,10 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
var (
factoryAddr = common.HexToAddress("0x24112842371dFC380576ebb09Ae16Cb6B6caD7CB")
)
func TestDisputeGameFactorySimpleGetters(t *testing.T) { func TestDisputeGameFactorySimpleGetters(t *testing.T) {
blockNum := uint64(23) blockNum := uint64(23)
tests := []struct { tests := []struct {
...@@ -35,7 +39,7 @@ func TestDisputeGameFactorySimpleGetters(t *testing.T) { ...@@ -35,7 +39,7 @@ func TestDisputeGameFactorySimpleGetters(t *testing.T) {
test := test test := test
t.Run(test.method, func(t *testing.T) { t.Run(test.method, func(t *testing.T) {
stubRpc, factory := setupDisputeGameFactoryTest(t) stubRpc, factory := setupDisputeGameFactoryTest(t)
stubRpc.SetResponse(test.method, batching.BlockByNumber(blockNum), nil, []interface{}{test.result}) stubRpc.SetResponse(factoryAddr, test.method, batching.BlockByNumber(blockNum), nil, []interface{}{test.result})
status, err := test.call(factory) status, err := test.call(factory)
require.NoError(t, err) require.NoError(t, err)
expected := test.expected expected := test.expected
...@@ -76,6 +80,7 @@ func TestLoadGame(t *testing.T) { ...@@ -76,6 +80,7 @@ func TestLoadGame(t *testing.T) {
func expectGetGame(stubRpc *batchingTest.AbiBasedRpc, idx int, blockNum uint64, game types.GameMetadata) { func expectGetGame(stubRpc *batchingTest.AbiBasedRpc, idx int, blockNum uint64, game types.GameMetadata) {
stubRpc.SetResponse( stubRpc.SetResponse(
factoryAddr,
methodGameAtIndex, methodGameAtIndex,
batching.BlockByNumber(blockNum), batching.BlockByNumber(blockNum),
[]interface{}{big.NewInt(int64(idx))}, []interface{}{big.NewInt(int64(idx))},
...@@ -89,11 +94,10 @@ func expectGetGame(stubRpc *batchingTest.AbiBasedRpc, idx int, blockNum uint64, ...@@ -89,11 +94,10 @@ func expectGetGame(stubRpc *batchingTest.AbiBasedRpc, idx int, blockNum uint64,
func setupDisputeGameFactoryTest(t *testing.T) (*batchingTest.AbiBasedRpc, *DisputeGameFactoryContract) { func setupDisputeGameFactoryTest(t *testing.T) (*batchingTest.AbiBasedRpc, *DisputeGameFactoryContract) {
fdgAbi, err := bindings.DisputeGameFactoryMetaData.GetAbi() fdgAbi, err := bindings.DisputeGameFactoryMetaData.GetAbi()
require.NoError(t, err) require.NoError(t, err)
address := common.HexToAddress("0x24112842371dFC380576ebb09Ae16Cb6B6caD7CB")
stubRpc := batchingTest.NewAbiBasedRpc(t, fdgAbi, address) stubRpc := batchingTest.NewAbiBasedRpc(t, factoryAddr, fdgAbi)
caller := batching.NewMultiCaller(stubRpc, 100) caller := batching.NewMultiCaller(stubRpc, 100)
factory, err := NewDisputeGameFactoryContract(address, caller) factory, err := NewDisputeGameFactoryContract(factoryAddr, caller)
require.NoError(t, err) require.NoError(t, err)
return stubRpc, factory return stubRpc, factory
} }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -33,6 +33,6 @@ func (a *alphabetWithProofProvider) GetStepData(ctx context.Context, i types.Pos ...@@ -33,6 +33,6 @@ func (a *alphabetWithProofProvider) GetStepData(ctx context.Context, i types.Pos
return nil, nil, nil, err return nil, nil, nil, err
} }
traceIndex := i.TraceIndex(int(a.depth)).Uint64() traceIndex := i.TraceIndex(int(a.depth)).Uint64()
data := types.NewPreimageOracleData(0, []byte{byte(traceIndex)}, []byte{byte(traceIndex - 1)}, uint32(traceIndex-1)) data := types.NewPreimageOracleData(types.NoLocalContext, []byte{byte(traceIndex)}, []byte{byte(traceIndex - 1)}, uint32(traceIndex-1))
return preimage, []byte{byte(traceIndex - 1)}, data, nil return preimage, []byte{byte(traceIndex - 1)}, data, nil
} }
This diff is collapsed.
This diff is collapsed.
...@@ -17,12 +17,10 @@ func TestFetchLocalInputs(t *testing.T) { ...@@ -17,12 +17,10 @@ func TestFetchLocalInputs(t *testing.T) {
contract := &mockGameInputsSource{ contract := &mockGameInputsSource{
l1Head: common.Hash{0xcc}, l1Head: common.Hash{0xcc},
starting: contracts.Proposal{ starting: contracts.Proposal{
Index: big.NewInt(6),
L2BlockNumber: big.NewInt(2222), L2BlockNumber: big.NewInt(2222),
OutputRoot: common.Hash{0xdd}, OutputRoot: common.Hash{0xdd},
}, },
disputed: contracts.Proposal{ disputed: contracts.Proposal{
Index: big.NewInt(7),
L2BlockNumber: big.NewInt(3333), L2BlockNumber: big.NewInt(3333),
OutputRoot: common.Hash{0xee}, OutputRoot: common.Hash{0xee},
}, },
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
package outputs package split
import ( import (
"context" "context"
...@@ -16,7 +16,7 @@ var ( ...@@ -16,7 +16,7 @@ var (
type ProviderCreator func(ctx context.Context, pre types.Claim, post types.Claim) (types.TraceProvider, error) type ProviderCreator func(ctx context.Context, pre types.Claim, post types.Claim) (types.TraceProvider, error)
func newSplitProviderSelector(topProvider types.TraceProvider, topDepth int, bottomProviderCreator ProviderCreator) trace.ProviderSelector { func NewSplitProviderSelector(topProvider types.TraceProvider, topDepth int, bottomProviderCreator ProviderCreator) trace.ProviderSelector {
return func(ctx context.Context, game types.Game, ref types.Claim, pos types.Position) (types.TraceProvider, error) { return func(ctx context.Context, game types.Game, ref types.Claim, pos types.Position) (types.TraceProvider, error) {
if pos.Depth() <= topDepth { if pos.Depth() <= topDepth {
return topProvider, nil return topProvider, nil
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"errors" "errors"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/txpool/blobpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/ethconfig"
...@@ -51,6 +52,11 @@ func NewL1Replica(t Testing, log log.Logger, genesis *core.Genesis) *L1Replica { ...@@ -51,6 +52,11 @@ func NewL1Replica(t Testing, log log.Logger, genesis *core.Genesis) *L1Replica {
NetworkId: genesis.Config.ChainID.Uint64(), NetworkId: genesis.Config.ChainID.Uint64(),
Genesis: genesis, Genesis: genesis,
RollupDisableTxPoolGossip: true, RollupDisableTxPoolGossip: true,
BlobPool: blobpool.Config{
Datadir: t.TempDir(),
Datacap: blobpool.DefaultConfig.Datacap,
PriceBump: blobpool.DefaultConfig.PriceBump,
},
} }
nodeCfg := &node.Config{ nodeCfg := &node.Config{
Name: "l1-geth", Name: "l1-geth",
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/txpool/blobpool"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/catalyst" "github.com/ethereum/go-ethereum/eth/catalyst"
"github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/ethconfig"
...@@ -21,10 +22,15 @@ import ( ...@@ -21,10 +22,15 @@ import (
_ "github.com/ethereum/go-ethereum/eth/tracers/native" _ "github.com/ethereum/go-ethereum/eth/tracers/native"
) )
func InitL1(chainID uint64, blockTime uint64, genesis *core.Genesis, c clock.Clock, opts ...GethOption) (*node.Node, *eth.Ethereum, error) { func InitL1(chainID uint64, blockTime uint64, genesis *core.Genesis, c clock.Clock, blobPoolDir string, beaconSrv Beacon, opts ...GethOption) (*node.Node, *eth.Ethereum, error) {
ethConfig := &ethconfig.Config{ ethConfig := &ethconfig.Config{
NetworkId: chainID, NetworkId: chainID,
Genesis: genesis, Genesis: genesis,
BlobPool: blobpool.Config{
Datadir: blobPoolDir,
Datacap: blobpool.DefaultConfig.Datacap,
PriceBump: blobpool.DefaultConfig.PriceBump,
},
} }
nodeConfig := &node.Config{ nodeConfig := &node.Config{
Name: "l1-geth", Name: "l1-geth",
...@@ -53,6 +59,7 @@ func InitL1(chainID uint64, blockTime uint64, genesis *core.Genesis, c clock.Clo ...@@ -53,6 +59,7 @@ func InitL1(chainID uint64, blockTime uint64, genesis *core.Genesis, c clock.Clo
finalizedDistance: 8, finalizedDistance: 8,
safeDistance: 4, safeDistance: 4,
engineAPI: catalyst.NewConsensusAPI(l1Eth), engineAPI: catalyst.NewConsensusAPI(l1Eth),
beacon: beaconSrv,
}) })
return l1Node, l1Eth, nil return l1Node, l1Eth, nil
......
...@@ -24,6 +24,8 @@ type ExternalRunner struct { ...@@ -24,6 +24,8 @@ type ExternalRunner struct {
BinPath string BinPath string
Genesis *core.Genesis Genesis *core.Genesis
JWTPath string JWTPath string
// 4844: a datadir specifically for tx-pool blobs
BlobPoolPath string
} }
type ExternalEthClient struct { type ExternalEthClient struct {
......
This diff is collapsed.
This diff is collapsed.
...@@ -290,7 +290,8 @@ func testFaultProofProgramScenario(t *testing.T, ctx context.Context, sys *Syste ...@@ -290,7 +290,8 @@ func testFaultProofProgramScenario(t *testing.T, ctx context.Context, sys *Syste
t.Log("Shutting down network") t.Log("Shutting down network")
// Shutdown the nodes from the actual chain. Should now be able to run using only the pre-fetched data. // Shutdown the nodes from the actual chain. Should now be able to run using only the pre-fetched data.
require.NoError(t, sys.BatchSubmitter.Kill()) require.NoError(t, sys.BatchSubmitter.Kill())
sys.L2OutputSubmitter.Stop() err = sys.L2OutputSubmitter.Driver().StopL2OutputSubmitting()
require.NoError(t, err)
sys.L2OutputSubmitter = nil sys.L2OutputSubmitter = nil
for _, node := range sys.EthInstances { for _, node := range sys.EthInstances {
node.Close() node.Close()
......
This diff is collapsed.
...@@ -30,7 +30,7 @@ func main() { ...@@ -30,7 +30,7 @@ func main() {
app.Name = "op-proposer" app.Name = "op-proposer"
app.Usage = "L2Output Submitter" app.Usage = "L2Output Submitter"
app.Description = "Service for generating and submitting L2 Output checkpoints to the L2OutputOracle contract" app.Description = "Service for generating and submitting L2 Output checkpoints to the L2OutputOracle contract"
app.Action = curryMain(Version) app.Action = cliapp.LifecycleCmd(proposer.Main(Version))
app.Commands = []*cli.Command{ app.Commands = []*cli.Command{
{ {
Name: "doc", Name: "doc",
...@@ -43,11 +43,3 @@ func main() { ...@@ -43,11 +43,3 @@ func main() {
log.Crit("Application failed", "message", err) log.Crit("Application failed", "message", err)
} }
} }
// curryMain transforms the proposer.Main function into an app.Action
// This is done to capture the Version of the proposer.
func curryMain(version string) func(ctx *cli.Context) error {
return func(ctx *cli.Context) error {
return proposer.Main(version, ctx)
}
}
This diff is collapsed.
This diff is collapsed.
...@@ -33,8 +33,11 @@ func setupL2OutputOracle() (common.Address, *bind.TransactOpts, *backends.Simula ...@@ -33,8 +33,11 @@ func setupL2OutputOracle() (common.Address, *bind.TransactOpts, *backends.Simula
backend, backend,
big.NewInt(10), big.NewInt(10),
big.NewInt(2), big.NewInt(2),
big.NewInt(100), big.NewInt(0),
) big.NewInt(0),
from,
common.Address{0xdd},
big.NewInt(100))
if err != nil { if err != nil {
return common.Address{}, nil, nil, nil, err return common.Address{}, nil, nil, nil, err
} }
......
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.
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