Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions op-bindings/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ monorepo-base := $(shell dirname $(realpath .))
contracts-dir := $(monorepo-base)/packages/contracts-bedrock
contracts-list := ./artifacts.json
log-level := info
ETHERSCAN_APIKEY_ETH ?=
ETHERSCAN_APIKEY_OP ?=

all: version mkdir bindings

Expand All @@ -21,6 +23,21 @@ bindings: bindgen-local

bindings-build: bindgen-generate-local

bindgen: compile bindgen-generate-all

bindgen-generate-all:
go run ./bindgen/ \
generate \
--metadata-out ./$(pkg) \
--bindings-package $(pkg) \
--contracts-list $(contracts-list) \
--log.level $(log-level) \
all \
--source-maps-list MIPS,PreimageOracle \
--forge-artifacts $(contracts-dir)/forge-artifacts \
--etherscan.apikey.eth $(ETHERSCAN_APIKEY_ETH) \
--etherscan.apikey.op $(ETHERSCAN_APIKEY_OP)

bindgen-local: compile bindgen-generate-local

bindgen-generate-local:
Expand All @@ -34,6 +51,17 @@ bindgen-generate-local:
--source-maps-list MIPS,PreimageOracle \
--forge-artifacts $(contracts-dir)/forge-artifacts

bindgen-remote:
go run ./bindgen/ \
generate \
--metadata-out ./$(pkg) \
--bindings-package $(pkg) \
--contracts-list $(contracts-list) \
--log.level $(log-level) \
remote \
--etherscan.apikey.eth $(ETHERSCAN_APIKEY_ETH) \
--etherscan.apikey.op $(ETHERSCAN_APIKEY_OP)

mkdir:
mkdir -p $(pkg)

Expand Down
99 changes: 99 additions & 0 deletions op-bindings/artifacts.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,104 @@
"ISemver",
"StorageSetter",
"SuperchainConfig"
],
"remote": [
{
"name": "MultiCall3",
"verified": true,
"deployments": {
"eth": "0xcA11bde05977b3631167028862bE2a173976CA11",
"op": "0xcA11bde05977b3631167028862bE2a173976CA11"
}
},
{
"name": "Create2Deployer",
"verified": true,
"deployments": {
"eth": "0xF49600926c7109BD66Ab97a2c036bf696e58Dbc2"
}
},
{
"name": "Safe_v130",
"verified": true,
"deployments": {
"eth": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552",
"op": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938"
},
"deploymentSalt": "0000000000000000000000000000000000000000000000000000000000000000"
},
{
"name": "SafeL2_v130",
"verified": true,
"deployments": {
"eth": "0x3E5c63644E683549055b9Be8653de26E0B4CD36E",
"op": "0xfb1bffC9d739B8D520DaF37dF666da4C687191EA"
},
"deploymentSalt": "0000000000000000000000000000000000000000000000000000000000000000"
},
{
"name": "MultiSendCallOnly_v130",
"verified": true,
"deployments": {
"eth": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D",
"op": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B"
},
"deploymentSalt": "0000000000000000000000000000000000000000000000000000000000000000"
},
{
"name": "SafeSingletonFactory",
"verified": false,
"deployments": {
"eth": "0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7",
"op": "0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7"
},
"abi": "[{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\",\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"creationCode\",\"type\":\"bytes\"}]}]"
},
{
"name": "DeterministicDeploymentProxy",
"verified": false,
"deployments": {
"eth": "0x4e59b44847b379578588920cA78FbF26c0B4956C",
"op": "0x4e59b44847b379578588920cA78FbF26c0B4956C"
},
"abi": "[{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\",\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"creationCode\",\"type\":\"bytes\"}]}]"
},
{
"name": "MultiSend_v130",
"verified": true,
"deployments": {
"op": "0x998739BFdAAdde7C933B942a68053933098f9EDa"
},
"deploymentSalt": "0000000000000000000000000000000000000000000000000000000000000000"
},
{
"name": "Permit2",
"verified": true,
"deployments": {
"eth": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
"op": "0x000000000022D473030F116dDEE9F6B43aC78BA3"
},
"deploymentSalt": "0000000000000000000000000000000000000000d3af2663da51c10215000000",
"deployer": "0x4e59b44847b379578588920cA78FbF26c0B4956C"
},
{
"name": "SenderCreator",
"verified": false,
"deployments": {
"eth": "0x7fc98430eaedbb6070b35b39d798725049088348",
"op": "0x7fc98430eaedbb6070b35b39d798725049088348"
},
"initBytecode": "0x6080806040523461001657610210908161001c8239f35b600080fdfe6080604052600436101561001257600080fd5b6000803560e01c63570e1a361461002857600080fd5b346100c95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100c95760043567ffffffffffffffff918282116100c957366023830112156100c95781600401359283116100c95736602484840101116100c9576100c561009e84602485016100fc565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b80fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90806014116101bb5767ffffffffffffffff917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec82018381116101cd575b604051937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81600b8701160116850190858210908211176101c0575b604052808452602084019036848401116101bb576020946000600c819682946014880187378301015251923560601c5af19060005191156101b557565b60009150565b600080fd5b6101c86100cc565b610178565b6101d56100cc565b61013a56fea26469706673582212201927e80b76ab9b71c952137dd676621a9fdf520c25928815636594036eb1c40364736f6c63430008110033",
"abi": "[{\"inputs\": [{\"internalType\": \"bytes\",\"name\": \"initCode\",\"type\": \"bytes\"}],\"name\": \"createSender\",\"outputs\": [{\"internalType\": \"address\",\"name\": \"sender\",\"type\": \"address\"}],\"stateMutability\": \"nonpayable\",\"type\": \"function\"}]"
},
{
"name": "EntryPoint",
"verified": true,
"deployments": {
"eth": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
"op": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"
},
"deploymentSalt": "0000000000000000000000000000000000000000000000000000000000000000"
}
]
}
124 changes: 124 additions & 0 deletions op-bindings/bindgen/generator_remote.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package main

import (
"context"
"fmt"
"os"

"github.com/ethereum-optimism/optimism/op-bindings/etherscan"
"github.com/ethereum/go-ethereum/common"
)

type bindGenGeneratorRemote struct {
bindGenGeneratorBase
contractDataClients struct {
eth contractDataClient
op contractDataClient
}
tempArtifactsDir string
}

type contractDataClient interface {
FetchAbi(ctx context.Context, address string) (string, error)
FetchDeployedBytecode(ctx context.Context, address string) (string, error)
FetchDeploymentTxHash(ctx context.Context, address string) (string, error)
FetchDeploymentTx(ctx context.Context, txHash string) (etherscan.TxInfo, error)
}

type deployments struct {
Eth common.Address `json:"eth"`
Op common.Address `json:"op"`
}

type remoteContract struct {
Name string `json:"name"`
Verified bool `json:"verified"`
Deployments deployments `json:"deployments"`
DeploymentSalt string `json:"deploymentSalt"`
Deployer common.Address `json:"deployer"`
ABI string `json:"abi"`
InitBytecode string `json:"initBytecode"`
}

type remoteContractMetadata struct {
remoteContract
Package string
InitBin string
DeployedBin string
}

func (generator *bindGenGeneratorRemote) generateBindings() error {
contracts, err := readContractList(generator.logger, generator.contractsListPath)
if err != nil {
return fmt.Errorf("error reading contract list %s: %w", generator.contractsListPath, err)
}
if len(contracts.Remote) == 0 {
return fmt.Errorf("no contracts parsed from given contract list: %s", generator.contractsListPath)
}

return generator.processContracts(contracts.Remote)
}

func (generator *bindGenGeneratorRemote) processContracts(contracts []remoteContract) error {
var err error
generator.tempArtifactsDir, err = mkTempArtifactsDir(generator.logger)
if err != nil {
return err
}
defer func() {
err := os.RemoveAll(generator.tempArtifactsDir)
if err != nil {
generator.logger.Error("Error removing temporary artifact directory", "path", generator.tempArtifactsDir, "err", err.Error())
} else {
generator.logger.Debug("Successfully removed temporary artifact directory")
}
}()

for _, contract := range contracts {
generator.logger.Info("Generating bindings and metadata for remote contract", "contract", contract.Name)

contractMetadata := remoteContractMetadata{
remoteContract: remoteContract{
Name: contract.Name,
Deployments: contract.Deployments,
DeploymentSalt: contract.DeploymentSalt,
ABI: contract.ABI,
Verified: contract.Verified,
},
Package: generator.bindingsPackageName,
}

var err error
switch contract.Name {
case "MultiCall3", "Safe_v130", "SafeL2_v130", "MultiSendCallOnly_v130",
"EntryPoint", "SafeSingletonFactory", "DeterministicDeploymentProxy":
err = generator.standardHandler(&contractMetadata)
case "Create2Deployer":
err = generator.create2DeployerHandler(&contractMetadata)
case "MultiSend_v130":
err = generator.multiSendHandler(&contractMetadata)
case "SenderCreator":
// The SenderCreator contract is deployed by EntryPoint, so the transaction data
// from the deployment transaction is for the entire EntryPoint deployment.
// So, we're manually providing the initialization bytecode
contractMetadata.InitBin = contract.InitBytecode
err = generator.senderCreatorHandler(&contractMetadata)
case "Permit2":
// Permit2 has an immutable Solidity variable that resolves to block.chainid,
// so we can't use the deployed bytecode, and instead must generate it
// at some later point not handled by BindGen.
// DeployerAddress is intended to be used to help deploy Permit2 at it's deterministic address
// to a chain set with the required id to be able to obtain a diff minimized deployed bytecode
contractMetadata.Deployer = contract.Deployer
err = generator.permit2Handler(&contractMetadata)
default:
err = fmt.Errorf("unknown contract: %s, don't know how to handle it", contract.Name)
}

if err != nil {
return err
}
}

return nil
}
Loading