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
61 changes: 4 additions & 57 deletions op-deployer/pkg/deployer/opcm/espresso.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,77 +7,24 @@ import (
"github.com/ethereum/go-ethereum/common"
)

type DeployAWSNitroVerifierInput struct {
type DeployEspressoInput struct {
NitroEnclaveVerifier common.Address
TeeVerifierAddress common.Address
TeeBatcher common.Address
SystemConfig common.Address
ProxyAdminOwner common.Address
}

type DeployAWSNitroVerifierOutput struct {
NitroTEEVerifierProxy common.Address
NitroTEEVerifierImpl common.Address
ProxyAdmin common.Address
}

type DeployEspressoInput struct {
Salt common.Hash
NitroTEEVerifier common.Address
TeeBatcher common.Address
SystemConfig common.Address
ProxyAdminOwner common.Address
UseMockTEEVerifier bool
}

type DeployEspressoOutput struct {
BatchAuthenticatorAddress common.Address
TeeVerifierProxy common.Address
TeeVerifierImpl common.Address
TeeVerifierProxyAdmin common.Address
NitroTEEVerifier common.Address
}

type DeployEspressoScript struct {
Run func(input, output, deployerAddress common.Address) error
}

type DeployAWSNitroVerifierScript struct {
Run func(input, output common.Address) error
}

func DeployAWSNitroVerifier(
host *script.Host,
input DeployAWSNitroVerifierInput,
) (DeployAWSNitroVerifierOutput, error) {
var output DeployAWSNitroVerifierOutput
inputAddr := host.NewScriptAddress()
outputAddr := host.NewScriptAddress()

cleanupInput, err := script.WithPrecompileAtAddress[*DeployAWSNitroVerifierInput](host, inputAddr, &input)
if err != nil {
return output, fmt.Errorf("failed to insert DeployAWSNitroVerifierInput precompile: %w", err)
}
defer cleanupInput()

cleanupOutput, err := script.WithPrecompileAtAddress[*DeployAWSNitroVerifierOutput](host, outputAddr, &output,
script.WithFieldSetter[*DeployAWSNitroVerifierOutput])
if err != nil {
return output, fmt.Errorf("failed to insert DeployAWSNitroVerifierOutput precompile: %w", err)
}
defer cleanupOutput()

implContract := "DeployAWSNitroVerifier"
deployScript, cleanupDeploy, err := script.WithScript[DeployAWSNitroVerifierScript](host, "DeployAWSNitroVerifier.s.sol", implContract)
if err != nil {
return output, fmt.Errorf("failed to load %s script: %w", implContract, err)
}
defer cleanupDeploy()

if err := deployScript.Run(inputAddr, outputAddr); err != nil {
return output, fmt.Errorf("failed to run %s script: %w", implContract, err)
}

return output, nil
}

func DeployEspresso(
host *script.Host,
input DeployEspressoInput,
Expand Down
54 changes: 22 additions & 32 deletions op-deployer/pkg/deployer/pipeline/espresso.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,51 +28,41 @@ func DeployEspresso(env *Env, intent *state.Intent, st *state.State, chainID com
}

lgr.Info("deploying espresso contracts")
// read the nitro enclaver verifier address from environment variable, fallback to empty address

// Read the underlying AWS NitroEnclaveVerifier address (from Automata).
// If not set, address(0) triggers mock deployment — dev/test only.
var nitroEnclaveVerifierAddress common.Address
if envVar := os.Getenv("NITRO_ENCLAVE_VERIFIER_ADDRESS"); envVar != "" {
nitroEnclaveVerifierAddress = common.HexToAddress(envVar)
lgr.Info("Using nitro enclave verifier address from NITRO_ENCLAVE_VERIFIER_ADDRESS env var", "address", nitroEnclaveVerifierAddress.Hex())
lgr.Info("using nitro enclave verifier from NITRO_ENCLAVE_VERIFIER_ADDRESS", "address", nitroEnclaveVerifierAddress.Hex())
} else {
lgr.Info("NITRO_ENCLAVE_VERIFIER_ADDRESS env var not set, using empty address")
// this means we should deploy a mock verifier ( should only be used in dev / test environments
nitroEnclaveVerifierAddress = common.Address{}
}

var nvo opcm.DeployAWSNitroVerifierOutput
nvo, err = opcm.DeployAWSNitroVerifier(env.L1ScriptHost, opcm.DeployAWSNitroVerifierInput{
NitroEnclaveVerifier: nitroEnclaveVerifierAddress,
TeeVerifierAddress: common.Address{}, // Will be set after TEEVerifier deployment if needed
ProxyAdminOwner: env.Deployer,
})
if err != nil {
return fmt.Errorf("failed to deploy nitro verifier contracts: %w", err)
lgr.Info("NITRO_ENCLAVE_VERIFIER_ADDRESS not set — deploying mock TEE verifiers")
}

var eo opcm.DeployEspressoOutput
// Read batch authenticator owner address from environment variable, fallback to env.Deployer
var batchAuthenticatorOwnwerAddress common.Address
if batchAuthenticatorOwnerEnv := os.Getenv("BATCH_AUTHENTICATOR_OWNER_ADDRESS"); batchAuthenticatorOwnerEnv != "" {
batchAuthenticatorOwnwerAddress = common.HexToAddress(batchAuthenticatorOwnerEnv)
lgr.Info("Using batch authenticator owner address from BATCH_AUTHENTICATOR_OWNER_ADDRESS env var", "address", batchAuthenticatorOwnwerAddress.Hex())
var batchAuthOwner common.Address
if envVar := os.Getenv("BATCH_AUTHENTICATOR_OWNER_ADDRESS"); envVar != "" {
batchAuthOwner = common.HexToAddress(envVar)
lgr.Info("using batch authenticator owner from BATCH_AUTHENTICATOR_OWNER_ADDRESS", "address", batchAuthOwner.Hex())
} else {
batchAuthenticatorOwnwerAddress = env.Deployer
lgr.Info("Using deployer address from env.Deployer", "address", batchAuthenticatorOwnwerAddress.Hex())
batchAuthOwner = env.Deployer
lgr.Info("using deployer as batch authenticator owner", "address", batchAuthOwner.Hex())
}

eo, err = opcm.DeployEspresso(env.L1ScriptHost, opcm.DeployEspressoInput{
Salt: st.Create2Salt,
NitroTEEVerifier: nvo.NitroTEEVerifierProxy,
TeeBatcher: chainIntent.TeeBatcher,
SystemConfig: chainState.SystemConfigProxy,
ProxyAdminOwner: batchAuthenticatorOwnwerAddress,
UseMockTEEVerifier: nitroEnclaveVerifierAddress == common.Address{},
}, batchAuthenticatorOwnwerAddress)
eo, err := opcm.DeployEspresso(env.L1ScriptHost, opcm.DeployEspressoInput{
NitroEnclaveVerifier: nitroEnclaveVerifierAddress,
TeeBatcher: chainIntent.TeeBatcher,
SystemConfig: chainState.SystemConfigProxy,
ProxyAdminOwner: batchAuthOwner,
}, batchAuthOwner)
if err != nil {
return fmt.Errorf("failed to deploy espresso contracts: %w", err)
}

chainState.BatchAuthenticatorAddress = eo.BatchAuthenticatorAddress
lgr.Info("Espresso BatchAuthenticator deployed at", "address", eo.BatchAuthenticatorAddress)
lgr.Info("espresso contracts deployed",
"batchAuthenticator", eo.BatchAuthenticatorAddress,
"teeVerifier", eo.TeeVerifierProxy,
"nitroTEEVerifier", eo.NitroTEEVerifier,
)
return nil
}
4 changes: 3 additions & 1 deletion packages/contracts-bedrock/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@ evm_version = 'cancun'

remappings = [
# Espresso-tee-contracts context-specific remappings (must come before general @openzeppelin remappings)
'lib/espresso-tee-contracts/:@openzeppelin/contracts/=lib/espresso-tee-contracts/lib/openzeppelin-contracts/contracts',
'lib/espresso-tee-contracts/:@espresso-tee/=lib/espresso-tee-contracts/src/',
'lib/espresso-tee-contracts/:@openzeppelin/contracts/=lib/openzeppelin-contracts-v5/contracts',
'lib/espresso-tee-contracts/:@openzeppelin/contracts-upgradeable/=lib/espresso-tee-contracts/lib/openzeppelin-contracts-upgradeable/contracts',
'lib/espresso-tee-contracts/:aws-nitro-enclave-attestation/=lib/espresso-tee-contracts/lib/aws-nitro-enclave-attestation/contracts/src/',
'lib/espresso-tee-contracts/:solady/=lib/solady/src',
# General remappings
'@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts',
Expand Down
38 changes: 26 additions & 12 deletions packages/contracts-bedrock/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,33 @@ build-go-ffi:
clean:
rm -rf ./artifacts ./forge-artifacts ./cache ./scripts/go-ffi/go-ffi ./deployments/hardhat/*

# Fixes Proxy and ProxyAdmin artifact bytecode if empty or missing.
# Foundry generates .json files with empty bytecode when multiple compiler versions are used.
# Fixes Proxy and ProxyAdmin artifact bytecode when Foundry's unversioned .json is missing,
# empty, or overwritten by a third-party library (e.g. OZ v5 ProxyAdmin shadowing
# src/universal/ProxyAdmin.sol). Restores from the pinned src/universal versioned artifact.
fix-proxy-artifact:
@sh -c 'for contract in Proxy ProxyAdmin; do \
if [ -f "forge-artifacts/${contract}.sol/${contract}.0.8.15.json" ]; then \
if [ ! -f "forge-artifacts/${contract}.sol/${contract}.json" ]; then \
cp "forge-artifacts/${contract}.sol/${contract}.0.8.15.json" "forge-artifacts/${contract}.sol/${contract}.json"; \
echo "Created ${contract}.json from ${contract}.0.8.15.json"; \
else \
python3 -c "import json; main = json.load(open(\"forge-artifacts/${contract}.sol/${contract}.json\")); versioned = json.load(open(\"forge-artifacts/${contract}.sol/${contract}.0.8.15.json\")); bytecode_obj = main.get(\"bytecode\", {}).get(\"object\", \"0x\"); (main.update({\"bytecode\": versioned[\"bytecode\"], \"deployedBytecode\": versioned[\"deployedBytecode\"]}) or json.dump(main, open(\"forge-artifacts/${contract}.sol/${contract}.json\", \"w\"), indent=2) or print(\"Fixed ${contract}.json bytecode from ${contract}.0.8.15.json\")) if len(bytecode_obj) <= 2 else print(\"${contract}.json already has bytecode, skipping fix\")"; \
fi; \
fi; \
done'
#!/usr/bin/env python3
import json, os
FIXES = [("Proxy", "0.8.15"), ("ProxyAdmin", "0.8.25")]
for contract, ref_ver in FIXES:
ref_path = f"forge-artifacts/{contract}.sol/{contract}.{ref_ver}.json"
main_path = f"forge-artifacts/{contract}.sol/{contract}.json"
if not os.path.exists(ref_path):
continue
ref = json.load(open(ref_path))
if os.path.exists(main_path):
main = json.load(open(main_path))
bytecode = main.get("bytecode", {}).get("object", "0x")
src = main.get("ast", {}).get("absolutePath", "")
if len(bytecode) > 2 and "src/universal" in src:
print(f"{contract}.json already has correct OP bytecode, skipping fix")
continue
main["bytecode"] = ref["bytecode"]
main["deployedBytecode"] = ref["deployedBytecode"]
main["ast"] = ref["ast"]
json.dump(main, open(main_path, "w"), indent=2)
else:
json.dump(ref, open(main_path, "w"), indent=2)
print(f"Fixed {contract}.json from {contract}.{ref_ver}.json")


########################################################
Expand Down
Loading
Loading