From f7b7c2a4c78ba485094bd4e0e4b0a052e2970d41 Mon Sep 17 00:00:00 2001 From: Jean Gal Date: Wed, 1 Apr 2026 15:31:32 -0400 Subject: [PATCH 1/6] pin to different tee commit --- packages/contracts-bedrock/lib/espresso-tee-contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts-bedrock/lib/espresso-tee-contracts b/packages/contracts-bedrock/lib/espresso-tee-contracts index bcd4e337789..9e6e1bc5010 160000 --- a/packages/contracts-bedrock/lib/espresso-tee-contracts +++ b/packages/contracts-bedrock/lib/espresso-tee-contracts @@ -1 +1 @@ -Subproject commit bcd4e337789d67f4cc2af7b4dca64f33ef2041fd +Subproject commit 9e6e1bc50101d6fe1460ed99882c457ec832752b From 12587ec53f36620d60654ed22e6f4c3d83af48a3 Mon Sep 17 00:00:00 2001 From: Jean Gal Date: Wed, 1 Apr 2026 16:29:03 -0400 Subject: [PATCH 2/6] use updated tee contract scripts --- op-deployer/pkg/deployer/opcm/espresso.go | 61 +---- op-deployer/pkg/deployer/pipeline/espresso.go | 54 ++-- packages/contracts-bedrock/foundry.toml | 2 + .../deploy/DeployAWSNitroVerifier.s.sol | 204 --------------- .../scripts/deploy/DeployEspresso.s.sol | 243 ++++++++---------- 5 files changed, 131 insertions(+), 433 deletions(-) delete mode 100644 packages/contracts-bedrock/scripts/deploy/DeployAWSNitroVerifier.s.sol diff --git a/op-deployer/pkg/deployer/opcm/espresso.go b/op-deployer/pkg/deployer/opcm/espresso.go index 73aac449022..b83a882ece4 100644 --- a/op-deployer/pkg/deployer/opcm/espresso.go +++ b/op-deployer/pkg/deployer/opcm/espresso.go @@ -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, diff --git a/op-deployer/pkg/deployer/pipeline/espresso.go b/op-deployer/pkg/deployer/pipeline/espresso.go index cc7856038ee..ed5836afb36 100644 --- a/op-deployer/pkg/deployer/pipeline/espresso.go +++ b/op-deployer/pkg/deployer/pipeline/espresso.go @@ -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 } diff --git a/packages/contracts-bedrock/foundry.toml b/packages/contracts-bedrock/foundry.toml index 77a98b85394..0031abcf9dd 100644 --- a/packages/contracts-bedrock/foundry.toml +++ b/packages/contracts-bedrock/foundry.toml @@ -52,8 +52,10 @@ evm_version = 'cancun' remappings = [ # Espresso-tee-contracts context-specific remappings (must come before general @openzeppelin remappings) + 'lib/espresso-tee-contracts/:@espresso-tee/=lib/espresso-tee-contracts/src/', 'lib/espresso-tee-contracts/:@openzeppelin/contracts/=lib/espresso-tee-contracts/lib/openzeppelin-contracts/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', diff --git a/packages/contracts-bedrock/scripts/deploy/DeployAWSNitroVerifier.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployAWSNitroVerifier.s.sol deleted file mode 100644 index ad0023bf36f..00000000000 --- a/packages/contracts-bedrock/scripts/deploy/DeployAWSNitroVerifier.s.sol +++ /dev/null @@ -1,204 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import { IEspressoNitroTEEVerifier } from "@espresso-tee-contracts/interface/IEspressoNitroTEEVerifier.sol"; -import { EspressoNitroTEEVerifier } from "@espresso-tee-contracts/EspressoNitroTEEVerifier.sol"; -import { BaseDeployIO } from "scripts/deploy/BaseDeployIO.sol"; -import { Script } from "forge-std/Script.sol"; -import { Solarray } from "scripts/libraries/Solarray.sol"; -import { INitroEnclaveVerifier } from "aws-nitro-enclave-attestation/interfaces/INitroEnclaveVerifier.sol"; -import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; -import { Proxy } from "src/universal/Proxy.sol"; -import { MockEspressoNitroTEEVerifier } from "test/mocks/MockEspressoTEEVerifiers.sol"; - -contract DeployAWSNitroVerifierInput is BaseDeployIO { - address internal _nitroEnclaveVerifier; - address internal _teeVerifierAddress; - address internal _proxyAdminOwner; - - function set(bytes4 _sel, address _val) public { - if (_sel == this.nitroEnclaveVerifier.selector) { - _nitroEnclaveVerifier = _val; - } else if (_sel == this.teeVerifierAddress.selector) { - _teeVerifierAddress = _val; - } else if (_sel == this.proxyAdminOwner.selector) { - _proxyAdminOwner = _val; - } else { - revert("DeployAWSNitroVerifierInput: unknown selector"); - } - } - - function nitroEnclaveVerifier() public view returns (address) { - return _nitroEnclaveVerifier; - } - - /// @notice The address of the main EspressoTEEVerifier contract that controls admin functions. - /// Can be address(0) during initial deployment if TEEVerifier doesn't exist yet. - function teeVerifierAddress() public view returns (address) { - return _teeVerifierAddress; - } - - /// @notice The address that will own the ProxyAdmin. Defaults to msg.sender if not set. - function proxyAdminOwner() public view returns (address) { - return _proxyAdminOwner; - } -} - -contract DeployAWSNitroVerifierOutput is BaseDeployIO { - address internal _nitroTEEVerifierProxy; - address internal _nitroTEEVerifierImpl; - address internal _proxyAdmin; - - function set(bytes4 _sel, address _addr) public { - require(_addr != address(0), "DeployAWSNitroVerifierOutput: cannot set zero address"); - if (_sel == this.nitroTEEVerifierProxy.selector) { - _nitroTEEVerifierProxy = _addr; - } else if (_sel == this.nitroTEEVerifierImpl.selector) { - _nitroTEEVerifierImpl = _addr; - } else if (_sel == this.proxyAdmin.selector) { - _proxyAdmin = _addr; - } else { - revert("DeployAWSNitroVerifierOutput: unknown selector"); - } - } - - function nitroTEEVerifierProxy() public view returns (address) { - require(_nitroTEEVerifierProxy != address(0), "nitro TEE verifier proxy not set"); - return _nitroTEEVerifierProxy; - } - - function nitroTEEVerifierImpl() public view returns (address) { - require(_nitroTEEVerifierImpl != address(0), "nitro TEE verifier impl not set"); - return _nitroTEEVerifierImpl; - } - - function proxyAdmin() public view returns (address) { - require(_proxyAdmin != address(0), "proxy admin not set"); - return _proxyAdmin; - } - - /// @notice Alias for nitroTEEVerifierProxy for backward compatibility - function nitroTEEVerifierAddress() public view returns (address) { - return nitroTEEVerifierProxy(); - } -} - -contract DeployAWSNitroVerifier is Script { - struct ProxyDeployment { - ProxyAdmin proxyAdmin; - Proxy proxy; - } - - function run(DeployAWSNitroVerifierInput input, DeployAWSNitroVerifierOutput output) public { - deployNitroTEEVerifier(input, output); - checkOutput(output); - } - - /// @notice Deploys ProxyAdmin and Proxy contracts via CREATE using type().creationCode. - /// @param labelPrefix Prefix for vm.label (e.g., "Mock" or "") - /// @return deployment Struct containing the deployed ProxyAdmin and Proxy - function deployProxyInfrastructure(string memory labelPrefix) - internal - returns (ProxyDeployment memory deployment) - { - vm.broadcast(msg.sender); - deployment.proxyAdmin = _createProxyAdmin(msg.sender); - vm.label(address(deployment.proxyAdmin), string.concat(labelPrefix, "NitroTEEVerifierProxyAdmin")); - - vm.broadcast(msg.sender); - deployment.proxy = _createProxy(address(deployment.proxyAdmin)); - vm.label(address(deployment.proxy), string.concat(labelPrefix, "NitroTEEVerifierProxy")); - - vm.broadcast(msg.sender); - deployment.proxyAdmin.setProxyType(address(deployment.proxy), ProxyAdmin.ProxyType.ERC1967); - } - - function _createProxyAdmin(address owner) internal returns (ProxyAdmin) { - bytes memory initCode = abi.encodePacked(type(ProxyAdmin).creationCode, abi.encode(owner)); - address addr; - assembly { - addr := create(0, add(initCode, 0x20), mload(initCode)) - } - require(addr != address(0), "DeployAWSNitroVerifier: ProxyAdmin deployment failed"); - return ProxyAdmin(addr); - } - - function _createProxy(address admin) internal returns (Proxy) { - bytes memory initCode = abi.encodePacked(type(Proxy).creationCode, abi.encode(admin)); - address addr; - assembly { - addr := create(0, add(initCode, 0x20), mload(initCode)) - } - require(addr != address(0), "DeployAWSNitroVerifier: Proxy deployment failed"); - return Proxy(payable(addr)); - } - - function deployNitroTEEVerifier( - DeployAWSNitroVerifierInput input, - DeployAWSNitroVerifierOutput output - ) - public - returns (IEspressoNitroTEEVerifier) - { - address nitroEnclaveVerifier = input.nitroEnclaveVerifier(); - address proxyAdminOwner = input.proxyAdminOwner(); - if (proxyAdminOwner == address(0)) { - proxyAdminOwner = msg.sender; - } - - // Deploy proxy infrastructure - ProxyDeployment memory deployment = deployProxyInfrastructure(nitroEnclaveVerifier == address(0) ? "Mock" : ""); - - address implAddress; - - if (nitroEnclaveVerifier == address(0)) { - // Deploy mock implementation - vm.broadcast(msg.sender); - MockEspressoNitroTEEVerifier mockImpl = new MockEspressoNitroTEEVerifier(); - vm.label(address(mockImpl), "MockNitroTEEVerifierImpl"); - implAddress = address(mockImpl); - - // Upgrade proxy to point to mock implementation - vm.broadcast(msg.sender); - deployment.proxyAdmin.upgrade(payable(address(deployment.proxy)), implAddress); - } else { - // Deploy production implementation - address teeVerifierAddress = input.teeVerifierAddress(); - - vm.broadcast(msg.sender); - EspressoNitroTEEVerifier impl = new EspressoNitroTEEVerifier(); - vm.label(address(impl), "NitroTEEVerifierImpl"); - implAddress = address(impl); - - // Initialize the proxy - bytes memory initData = abi.encodeCall( - EspressoNitroTEEVerifier.initialize, (teeVerifierAddress, INitroEnclaveVerifier(nitroEnclaveVerifier)) - ); - vm.broadcast(msg.sender); - deployment.proxyAdmin.upgradeAndCall(payable(address(deployment.proxy)), implAddress, initData); - } - - // Transfer ownership if needed - if (proxyAdminOwner != msg.sender) { - vm.broadcast(msg.sender); - deployment.proxyAdmin.transferOwnership(proxyAdminOwner); - } - - // Set outputs - output.set(output.nitroTEEVerifierProxy.selector, address(deployment.proxy)); - output.set(output.nitroTEEVerifierImpl.selector, implAddress); - output.set(output.proxyAdmin.selector, address(deployment.proxyAdmin)); - - return IEspressoNitroTEEVerifier(address(deployment.proxy)); - } - - function checkOutput(DeployAWSNitroVerifierOutput output) public view { - address[] memory addresses = - Solarray.addresses(output.nitroTEEVerifierProxy(), output.nitroTEEVerifierImpl(), output.proxyAdmin()); - for (uint256 i = 0; i < addresses.length; i++) { - require( - addresses[i] != address(0) && addresses[i].code.length > 0, "DeployAWSNitroVerifier: invalid address" - ); - } - } -} diff --git a/packages/contracts-bedrock/scripts/deploy/DeployEspresso.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployEspresso.s.sol index 46cc0086756..31a8e89a387 100644 --- a/packages/contracts-bedrock/scripts/deploy/DeployEspresso.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/DeployEspresso.s.sol @@ -8,35 +8,24 @@ import { Solarray } from "scripts/libraries/Solarray.sol"; import { IBatchAuthenticator } from "interfaces/L1/IBatchAuthenticator.sol"; import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; import { IEspressoNitroTEEVerifier } from "@espresso-tee-contracts/interface/IEspressoNitroTEEVerifier.sol"; -import { IEspressoSGXTEEVerifier } from "@espresso-tee-contracts/interface/IEspressoSGXTEEVerifier.sol"; import { IEspressoTEEVerifier } from "@espresso-tee-contracts/interface/IEspressoTEEVerifier.sol"; -import { EspressoTEEVerifier } from "@espresso-tee-contracts/EspressoTEEVerifier.sol"; +import { DeployNitroTEEVerifier } from "lib/espresso-tee-contracts/scripts/DeployNitroTEEVerifier.s.sol"; +import { DeployTEEVerifier } from "lib/espresso-tee-contracts/scripts/DeployTEEVerifier.s.sol"; import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; import { Proxy } from "src/universal/Proxy.sol"; import { BatchAuthenticator } from "src/L1/BatchAuthenticator.sol"; import { MockEspressoTEEVerifier } from "test/mocks/MockEspressoTEEVerifiers.sol"; +import { MockEspressoNitroTEEVerifier } from "test/mocks/MockEspressoTEEVerifiers.sol"; contract DeployEspressoInput is BaseDeployIO { - bytes32 internal _salt; - address internal _nitroTEEVerifier; + address internal _nitroEnclaveVerifier; address internal _teeBatcher; address internal _systemConfig; address internal _proxyAdminOwner; - bool internal _useMockTEEVerifier; - - function set(bytes4 _sel, bytes32 _val) public { - if (_sel == this.salt.selector) _salt = _val; - else revert("DeployEspressoInput: unknown selector"); - } - - function set(bytes4 _sel, bool _val) public { - if (_sel == this.useMockTEEVerifier.selector) _useMockTEEVerifier = _val; - else revert("DeployEspressoInput: unknown selector"); - } function set(bytes4 _sel, address _val) public { - if (_sel == this.nitroTEEVerifier.selector) { - _nitroTEEVerifier = _val; + if (_sel == this.nitroEnclaveVerifier.selector) { + _nitroEnclaveVerifier = _val; } else if (_sel == this.teeBatcher.selector) { _teeBatcher = _val; } else if (_sel == this.systemConfig.selector) { @@ -48,14 +37,10 @@ contract DeployEspressoInput is BaseDeployIO { } } - function salt() public view returns (bytes32) { - require(_salt != 0, "DeployEspressoInput: salt not set"); - return _salt; - } - - /// @notice Address of the EspressoNitroTEEVerifier proxy (deployed via DeployAWSNitroVerifier) - function nitroTEEVerifier() public view returns (address) { - return _nitroTEEVerifier; + /// @notice Address of the underlying AWS NitroEnclaveVerifier (from Automata). + /// Set to address(0) to deploy mock verifiers (dev/test only). + function nitroEnclaveVerifier() public view returns (address) { + return _nitroEnclaveVerifier; } function teeBatcher() public view returns (address) { @@ -66,12 +51,6 @@ contract DeployEspressoInput is BaseDeployIO { return _systemConfig; } - /// @notice If true, deploy MockEspressoTEEVerifier instead of production EspressoTEEVerifier. - /// Defaults to false. Also uses mock if nitroTEEVerifier is address(0). - function useMockTEEVerifier() public view returns (bool) { - return _useMockTEEVerifier; - } - /// @notice The address that will own the ProxyAdmin contracts. Defaults to msg.sender if not set. function proxyAdminOwner() public view returns (address) { return _proxyAdminOwner; @@ -81,8 +60,8 @@ contract DeployEspressoInput is BaseDeployIO { contract DeployEspressoOutput is BaseDeployIO { address internal _batchAuthenticatorAddress; address internal _teeVerifierProxy; - address internal _teeVerifierImpl; address internal _teeVerifierProxyAdmin; + address internal _nitroTEEVerifier; function set(bytes4 _sel, address _addr) public { require(_addr != address(0), "DeployEspressoOutput: cannot set zero address"); @@ -90,10 +69,10 @@ contract DeployEspressoOutput is BaseDeployIO { _batchAuthenticatorAddress = _addr; } else if (_sel == this.teeVerifierProxy.selector) { _teeVerifierProxy = _addr; - } else if (_sel == this.teeVerifierImpl.selector) { - _teeVerifierImpl = _addr; } else if (_sel == this.teeVerifierProxyAdmin.selector) { _teeVerifierProxyAdmin = _addr; + } else if (_sel == this.nitroTEEVerifier.selector) { + _nitroTEEVerifier = _addr; } else { revert("DeployEspressoOutput: unknown selector"); } @@ -109,16 +88,16 @@ contract DeployEspressoOutput is BaseDeployIO { return _teeVerifierProxy; } - function teeVerifierImpl() public view returns (address) { - require(_teeVerifierImpl != address(0), "DeployEspressoOutput: tee verifier impl not set"); - return _teeVerifierImpl; - } - function teeVerifierProxyAdmin() public view returns (address) { require(_teeVerifierProxyAdmin != address(0), "DeployEspressoOutput: tee verifier proxy admin not set"); return _teeVerifierProxyAdmin; } + function nitroTEEVerifier() public view returns (address) { + require(_nitroTEEVerifier != address(0), "DeployEspressoOutput: nitro tee verifier proxy not set"); + return _nitroTEEVerifier; + } + /// @notice Alias for teeVerifierProxy for convenience function teeVerifierAddress() public view returns (address) { return teeVerifierProxy(); @@ -126,10 +105,14 @@ contract DeployEspressoOutput is BaseDeployIO { } contract DeployEspresso is Script { + /// @dev ERC-1967 admin slot: keccak256("eip1967.proxy.admin") - 1 + /// Used to read the ProxyAdmin address auto-deployed by OZ v5 TransparentUpgradeableProxy. + bytes32 internal constant ERC1967_ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; + function run(DeployEspressoInput input, DeployEspressoOutput output, address deployerAddress) public { - IEspressoTEEVerifier teeVerifier = deployTEEVerifier(input, output, deployerAddress); + IEspressoTEEVerifier teeVerifier = deployTEEContracts(input, output, deployerAddress); deployBatchAuthenticator(input, output, teeVerifier); - checkOutput(input, output); + checkOutput(output); } function deployBatchAuthenticator( @@ -140,9 +123,9 @@ contract DeployEspresso is Script { public returns (IBatchAuthenticator) { - // Deploy the proxy admin, the proxy, and the batch authenticator implementation. - // We create ProxyAdmin with msg.sender as the owner to ensure broadcasts come from - // the expected address, then transfer ownership to proxyAdminOwner afterward. + address proxyAdminOwner = input.proxyAdminOwner(); + if (proxyAdminOwner == address(0)) proxyAdminOwner = msg.sender; + vm.broadcast(msg.sender); ProxyAdmin proxyAdmin = new ProxyAdmin(msg.sender); vm.label(address(proxyAdmin), "BatchAuthenticatorProxyAdmin"); @@ -155,37 +138,31 @@ contract DeployEspresso is Script { BatchAuthenticator impl = new BatchAuthenticator(); vm.label(address(impl), "BatchAuthenticatorImpl"); - // Determine the desired BatchAuthenticator owner - address batchAuthenticatorOwner = input.proxyAdminOwner(); - if (batchAuthenticatorOwner == address(0)) { - batchAuthenticatorOwner = msg.sender; - } - - // Initialize the proxy with explicit owner parameter bytes memory initData = abi.encodeCall( BatchAuthenticator.initialize, - (teeVerifier, input.teeBatcher(), ISystemConfig(input.systemConfig()), batchAuthenticatorOwner) + (teeVerifier, input.teeBatcher(), ISystemConfig(input.systemConfig()), proxyAdminOwner) ); vm.broadcast(msg.sender); proxyAdmin.upgradeAndCall(payable(address(proxy)), address(impl), initData); - // Transfer ProxyAdmin ownership to the desired proxyAdminOwner if different from msg.sender. - address proxyAdminOwner = input.proxyAdminOwner(); - if (proxyAdminOwner == address(0)) { - proxyAdminOwner = msg.sender; - } if (proxyAdminOwner != msg.sender) { vm.broadcast(msg.sender); proxyAdmin.transferOwnership(proxyAdminOwner); } - // Return the proxied contract. - IBatchAuthenticator batchAuthenticator = IBatchAuthenticator(address(proxy)); - output.set(output.batchAuthenticatorAddress.selector, address(batchAuthenticator)); - return batchAuthenticator; + output.set(output.batchAuthenticatorAddress.selector, address(proxy)); + return IBatchAuthenticator(address(proxy)); } - function deployTEEVerifier( + /// @notice Deploys NitroTEEVerifier and TEEVerifier by calling the deployment scripts from + /// the espresso-tee-contracts repository directly. Deployment order follows + /// DeployAllTEEVerifiers.s.sol in that repo: + /// 1. Deploy TEEVerifier with placeholder nitro address + /// 2. Deploy NitroTEEVerifier pointing to the TEEVerifier + /// 3. Update TEEVerifier with the actual NitroTEEVerifier address + /// + /// If nitroEnclaveVerifier is address(0), deploys our local mocks (dev/test only). + function deployTEEContracts( DeployEspressoInput input, DeployEspressoOutput output, address deployerAddress @@ -193,102 +170,88 @@ contract DeployEspresso is Script { public returns (IEspressoTEEVerifier) { - IEspressoNitroTEEVerifier nitroTEEVerifier = IEspressoNitroTEEVerifier(input.nitroTEEVerifier()); - // OP only uses Nitro TEE, not SGX - IEspressoSGXTEEVerifier sgxTEEVerifier = IEspressoSGXTEEVerifier(address(0)); - - // Use mock if explicitly requested or if nitroTEEVerifier is not set - if (input.useMockTEEVerifier() || address(nitroTEEVerifier) == address(0)) { - vm.broadcast(msg.sender); - MockEspressoTEEVerifier mockImpl = new MockEspressoTEEVerifier(nitroTEEVerifier); - vm.label(address(mockImpl), "MockEspressoTEEVerifier"); - - // For mock deployments, we still need valid distinct addresses for the output. - // Deploy a minimal ProxyAdmin to satisfy the output requirements, even though - // the mock doesn't use it. This ensures checkOutput validation passes. - address mockProxyAdminOwner = input.proxyAdminOwner(); - if (mockProxyAdminOwner == address(0)) { - mockProxyAdminOwner = msg.sender; - } - vm.broadcast(msg.sender); - ProxyAdmin mockProxyAdmin = new ProxyAdmin(mockProxyAdminOwner); - vm.label(address(mockProxyAdmin), "MockTEEVerifierProxyAdmin"); - - output.set(output.teeVerifierProxy.selector, address(mockImpl)); - output.set(output.teeVerifierImpl.selector, address(mockImpl)); - output.set(output.teeVerifierProxyAdmin.selector, address(mockProxyAdmin)); - return IEspressoTEEVerifier(address(mockImpl)); + address nitroEnclaveVerifier = input.nitroEnclaveVerifier(); + if (nitroEnclaveVerifier == address(0)) { + return _deployMockTEEContracts(input, output); } + return _deployProductionTEEContracts(input, output, deployerAddress, nitroEnclaveVerifier); + } - // Production deployment: Proxy + ProxyAdmin pattern + function _deployMockTEEContracts( + DeployEspressoInput input, + DeployEspressoOutput output + ) + internal + returns (IEspressoTEEVerifier) + { + address proxyAdminOwner = input.proxyAdminOwner(); + if (proxyAdminOwner == address(0)) proxyAdminOwner = msg.sender; - // 1. Deploy the ProxyAdmin + // Use our local mocks — they carry OP-specific test behavior (permissive isSignerValid, + // test helper overrides, special address exceptions) that the submodule mocks don't have. vm.broadcast(msg.sender); - ProxyAdmin proxyAdmin = new ProxyAdmin(msg.sender); - vm.label(address(proxyAdmin), "TEEVerifierProxyAdmin"); + MockEspressoNitroTEEVerifier nitroMock = new MockEspressoNitroTEEVerifier(); + vm.label(address(nitroMock), "MockEspressoNitroTEEVerifier"); - // 2. Deploy the Proxy vm.broadcast(msg.sender); - Proxy proxy = new Proxy(address(proxyAdmin)); - vm.label(address(proxy), "TEEVerifierProxy"); + MockEspressoTEEVerifier teeMock = new MockEspressoTEEVerifier(IEspressoNitroTEEVerifier(address(nitroMock))); + vm.label(address(teeMock), "MockEspressoTEEVerifier"); - // 3. Set proxy type + // Deploy a dummy ProxyAdmin so the output proxy-admin field is a valid distinct address. vm.broadcast(msg.sender); - proxyAdmin.setProxyType(address(proxy), ProxyAdmin.ProxyType.ERC1967); + ProxyAdmin dummyAdmin = new ProxyAdmin(proxyAdminOwner); + vm.label(address(dummyAdmin), "MockTEEVerifierDummyProxyAdmin"); - // 4. Deploy the EspressoTEEVerifier implementation - vm.broadcast(msg.sender); - EspressoTEEVerifier impl = new EspressoTEEVerifier(); - vm.label(address(impl), "TEEVerifierImpl"); + output.set(output.nitroTEEVerifier.selector, address(nitroMock)); + output.set(output.teeVerifierProxy.selector, address(teeMock)); + output.set(output.teeVerifierProxyAdmin.selector, address(dummyAdmin)); + return IEspressoTEEVerifier(address(teeMock)); + } + + function _deployProductionTEEContracts( + DeployEspressoInput input, + DeployEspressoOutput output, + address deployerAddress, + address nitroEnclaveVerifier + ) + internal + returns (IEspressoTEEVerifier) + { + address proxyAdminOwner = input.proxyAdminOwner(); + if (proxyAdminOwner == address(0)) proxyAdminOwner = deployerAddress; + + // Deploy TEEVerifier with placeholder nitro address; wire it in after NitroTEEVerifier is deployed. + vm.startBroadcast(msg.sender); + (address teeProxy,) = new DeployTEEVerifier().deploy(proxyAdminOwner, address(0), address(0)); + vm.stopBroadcast(); + vm.label(teeProxy, "TEEVerifierProxy"); + + // NitroTEEVerifier is deployed without a proxy; it stores teeProxy for access control. + vm.startBroadcast(msg.sender); + address nitroVerifier = new DeployNitroTEEVerifier().deploy(teeProxy, nitroEnclaveVerifier); + vm.stopBroadcast(); + vm.label(nitroVerifier, "NitroTEEVerifier"); - // 5. Initialize the proxy - // Note: EspressoTEEVerifier.initialize takes (owner, sgxVerifier, nitroVerifier) - bytes memory initData = - abi.encodeCall(EspressoTEEVerifier.initialize, (deployerAddress, sgxTEEVerifier, nitroTEEVerifier)); vm.broadcast(msg.sender); - proxyAdmin.upgradeAndCall(payable(address(proxy)), address(impl), initData); + IEspressoTEEVerifier(teeProxy).setEspressoNitroTEEVerifier(IEspressoNitroTEEVerifier(nitroVerifier)); - // 6. Transfer ownership to the desired proxyAdminOwner if different from msg.sender - address proxyAdminOwner = input.proxyAdminOwner(); - if (proxyAdminOwner == address(0)) { - proxyAdminOwner = msg.sender; - } - if (proxyAdminOwner != msg.sender) { - vm.broadcast(msg.sender); - proxyAdmin.transferOwnership(proxyAdminOwner); - } + address teeProxyAdmin = address(uint160(uint256(vm.load(teeProxy, ERC1967_ADMIN_SLOT)))); - // 7. Set outputs - output.set(output.teeVerifierProxy.selector, address(proxy)); - output.set(output.teeVerifierImpl.selector, address(impl)); - output.set(output.teeVerifierProxyAdmin.selector, address(proxyAdmin)); + output.set(output.teeVerifierProxy.selector, teeProxy); + output.set(output.teeVerifierProxyAdmin.selector, teeProxyAdmin); + output.set(output.nitroTEEVerifier.selector, nitroVerifier); - return IEspressoTEEVerifier(address(proxy)); + return IEspressoTEEVerifier(teeProxy); } - function checkOutput(DeployEspressoInput input, DeployEspressoOutput output) public view { - // Check core addresses - address[] memory coreAddresses = - Solarray.addresses(output.batchAuthenticatorAddress(), output.teeVerifierProxy()); - DeployUtils.assertValidContractAddresses(coreAddresses); - - // Check that proxy admin is a valid, distinct address (applies to both mock and production) - address[] memory adminAddresses = Solarray.addresses(output.teeVerifierProxyAdmin()); - DeployUtils.assertValidContractAddresses(adminAddresses); + function checkOutput(DeployEspressoOutput output) public view { + address[] memory addresses = Solarray.addresses( + output.batchAuthenticatorAddress(), output.teeVerifierProxy(), output.nitroTEEVerifier() + ); + DeployUtils.assertValidContractAddresses(addresses); require( output.teeVerifierProxy() != output.teeVerifierProxyAdmin(), - "DeployEspresso: proxy and proxy admin should be different" + "DeployEspresso: tee proxy and proxy admin should be different" ); - - // For production deployment, also check impl is valid and distinct from proxy - if (!input.useMockTEEVerifier() && input.nitroTEEVerifier() != address(0)) { - address[] memory teeAddresses = - Solarray.addresses(output.teeVerifierProxy(), output.teeVerifierImpl(), output.teeVerifierProxyAdmin()); - DeployUtils.assertValidContractAddresses(teeAddresses); - require( - output.teeVerifierProxy() != output.teeVerifierImpl(), - "DeployEspresso: proxy and impl should be different" - ); - } } } From eb699f4f68cbd54ff91ea211e47f391c02078408 Mon Sep 17 00:00:00 2001 From: Jean Gal Date: Wed, 1 Apr 2026 16:37:48 -0400 Subject: [PATCH 3/6] point to latest tee contract --- packages/contracts-bedrock/lib/espresso-tee-contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts-bedrock/lib/espresso-tee-contracts b/packages/contracts-bedrock/lib/espresso-tee-contracts index 9e6e1bc5010..4e07c341a0d 160000 --- a/packages/contracts-bedrock/lib/espresso-tee-contracts +++ b/packages/contracts-bedrock/lib/espresso-tee-contracts @@ -1 +1 @@ -Subproject commit 9e6e1bc50101d6fe1460ed99882c457ec832752b +Subproject commit 4e07c341a0d55afdc0146b7743c7221a981273b8 From b1519bd97f544918f37ebe63fe49f23fc59043c5 Mon Sep 17 00:00:00 2001 From: Jean Gal Date: Thu, 2 Apr 2026 11:59:28 -0400 Subject: [PATCH 4/6] use proxy admin from OP repo --- packages/contracts-bedrock/foundry.toml | 2 +- .../lib/espresso-tee-contracts | 2 +- .../scripts/deploy/DeployEspresso.s.sol | 60 ++++++++++++------- 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/packages/contracts-bedrock/foundry.toml b/packages/contracts-bedrock/foundry.toml index 0031abcf9dd..4194e1a5eb1 100644 --- a/packages/contracts-bedrock/foundry.toml +++ b/packages/contracts-bedrock/foundry.toml @@ -53,7 +53,7 @@ evm_version = 'cancun' remappings = [ # Espresso-tee-contracts context-specific remappings (must come before general @openzeppelin remappings) 'lib/espresso-tee-contracts/:@espresso-tee/=lib/espresso-tee-contracts/src/', - 'lib/espresso-tee-contracts/:@openzeppelin/contracts/=lib/espresso-tee-contracts/lib/openzeppelin-contracts/contracts', + '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', diff --git a/packages/contracts-bedrock/lib/espresso-tee-contracts b/packages/contracts-bedrock/lib/espresso-tee-contracts index 4e07c341a0d..1c4344abe1b 160000 --- a/packages/contracts-bedrock/lib/espresso-tee-contracts +++ b/packages/contracts-bedrock/lib/espresso-tee-contracts @@ -1 +1 @@ -Subproject commit 4e07c341a0d55afdc0146b7743c7221a981273b8 +Subproject commit 1c4344abe1b3ff539db85e227a18255218f20c70 diff --git a/packages/contracts-bedrock/scripts/deploy/DeployEspresso.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployEspresso.s.sol index 31a8e89a387..abb659feefc 100644 --- a/packages/contracts-bedrock/scripts/deploy/DeployEspresso.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/DeployEspresso.s.sol @@ -9,8 +9,8 @@ import { IBatchAuthenticator } from "interfaces/L1/IBatchAuthenticator.sol"; import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; import { IEspressoNitroTEEVerifier } from "@espresso-tee-contracts/interface/IEspressoNitroTEEVerifier.sol"; import { IEspressoTEEVerifier } from "@espresso-tee-contracts/interface/IEspressoTEEVerifier.sol"; +import { DeployTEEVerifierImpl } from "lib/espresso-tee-contracts/scripts/DeployTEEVerifierImpl.s.sol"; import { DeployNitroTEEVerifier } from "lib/espresso-tee-contracts/scripts/DeployNitroTEEVerifier.s.sol"; -import { DeployTEEVerifier } from "lib/espresso-tee-contracts/scripts/DeployTEEVerifier.s.sol"; import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; import { Proxy } from "src/universal/Proxy.sol"; import { BatchAuthenticator } from "src/L1/BatchAuthenticator.sol"; @@ -105,10 +105,6 @@ contract DeployEspressoOutput is BaseDeployIO { } contract DeployEspresso is Script { - /// @dev ERC-1967 admin slot: keccak256("eip1967.proxy.admin") - 1 - /// Used to read the ProxyAdmin address auto-deployed by OZ v5 TransparentUpgradeableProxy. - bytes32 internal constant ERC1967_ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; - function run(DeployEspressoInput input, DeployEspressoOutput output, address deployerAddress) public { IEspressoTEEVerifier teeVerifier = deployTEEContracts(input, output, deployerAddress); deployBatchAuthenticator(input, output, teeVerifier); @@ -154,11 +150,9 @@ contract DeployEspresso is Script { return IBatchAuthenticator(address(proxy)); } - /// @notice Deploys NitroTEEVerifier and TEEVerifier by calling the deployment scripts from - /// the espresso-tee-contracts repository directly. Deployment order follows - /// DeployAllTEEVerifiers.s.sol in that repo: - /// 1. Deploy TEEVerifier with placeholder nitro address - /// 2. Deploy NitroTEEVerifier pointing to the TEEVerifier + /// @notice Deploys NitroTEEVerifier and TEEVerifier (behind an OP-style proxy). Order: + /// 1. Deploy TEEVerifier impl + OP ProxyAdmin + Proxy, initialize with placeholder nitro address + /// 2. Deploy NitroTEEVerifier pointing to the TEEVerifier proxy /// 3. Update TEEVerifier with the actual NitroTEEVerifier address /// /// If nitroEnclaveVerifier is address(0), deploys our local mocks (dev/test only). @@ -220,11 +214,38 @@ contract DeployEspresso is Script { address proxyAdminOwner = input.proxyAdminOwner(); if (proxyAdminOwner == address(0)) proxyAdminOwner = deployerAddress; - // Deploy TEEVerifier with placeholder nitro address; wire it in after NitroTEEVerifier is deployed. - vm.startBroadcast(msg.sender); - (address teeProxy,) = new DeployTEEVerifier().deploy(proxyAdminOwner, address(0), address(0)); - vm.stopBroadcast(); - vm.label(teeProxy, "TEEVerifierProxy"); + // Deploy EspressoTEEVerifier implementation via the submodule script (no proxy). + // We use DeployTEEVerifierImpl (not DeployTEEVerifier) to avoid importing OZ v5 + // TransparentUpgradeableProxy, which would compile OZ v5 ProxyAdmin and cause an + // artifact collision with src/universal/ProxyAdmin.sol. + vm.broadcast(msg.sender); + address teeVerifierImpl = new DeployTEEVerifierImpl().deploy(); + vm.label(teeVerifierImpl, "TEEVerifierImpl"); + + // Wrap in an OP-style proxy — same pattern used by deployBatchAuthenticator above. + vm.broadcast(msg.sender); + ProxyAdmin teeProxyAdmin = new ProxyAdmin(msg.sender); + vm.label(address(teeProxyAdmin), "TEEVerifierProxyAdmin"); + + vm.broadcast(msg.sender); + Proxy teeProxyRaw = new Proxy(address(teeProxyAdmin)); + vm.label(address(teeProxyRaw), "TEEVerifierProxy"); + + vm.broadcast(msg.sender); + teeProxyAdmin.setProxyType(address(teeProxyRaw), ProxyAdmin.ProxyType.ERC1967); + + // Initialize with placeholder verifier addresses; nitro address is wired in below. + bytes memory initData = + abi.encodeWithSignature("initialize(address,address,address)", proxyAdminOwner, address(0), address(0)); + vm.broadcast(msg.sender); + teeProxyAdmin.upgradeAndCall(payable(address(teeProxyRaw)), teeVerifierImpl, initData); + + if (proxyAdminOwner != msg.sender) { + vm.broadcast(msg.sender); + teeProxyAdmin.transferOwnership(proxyAdminOwner); + } + + address teeProxy = address(teeProxyRaw); // NitroTEEVerifier is deployed without a proxy; it stores teeProxy for access control. vm.startBroadcast(msg.sender); @@ -235,19 +256,16 @@ contract DeployEspresso is Script { vm.broadcast(msg.sender); IEspressoTEEVerifier(teeProxy).setEspressoNitroTEEVerifier(IEspressoNitroTEEVerifier(nitroVerifier)); - address teeProxyAdmin = address(uint160(uint256(vm.load(teeProxy, ERC1967_ADMIN_SLOT)))); - output.set(output.teeVerifierProxy.selector, teeProxy); - output.set(output.teeVerifierProxyAdmin.selector, teeProxyAdmin); + output.set(output.teeVerifierProxyAdmin.selector, address(teeProxyAdmin)); output.set(output.nitroTEEVerifier.selector, nitroVerifier); return IEspressoTEEVerifier(teeProxy); } function checkOutput(DeployEspressoOutput output) public view { - address[] memory addresses = Solarray.addresses( - output.batchAuthenticatorAddress(), output.teeVerifierProxy(), output.nitroTEEVerifier() - ); + address[] memory addresses = + Solarray.addresses(output.batchAuthenticatorAddress(), output.teeVerifierProxy(), output.nitroTEEVerifier()); DeployUtils.assertValidContractAddresses(addresses); require( output.teeVerifierProxy() != output.teeVerifierProxyAdmin(), From f188998c362878c8c8696f137b1a8319fc7f2147 Mon Sep 17 00:00:00 2001 From: Jean Gal Date: Thu, 2 Apr 2026 13:15:29 -0400 Subject: [PATCH 5/6] force ref path for proxy artifact --- packages/contracts-bedrock/justfile | 38 +++++++++---- .../lib/espresso-tee-contracts | 2 +- .../scripts/deploy/DeployEspresso.s.sol | 55 +++++++------------ 3 files changed, 46 insertions(+), 49 deletions(-) diff --git a/packages/contracts-bedrock/justfile b/packages/contracts-bedrock/justfile index 7af1c4aacc6..6519a6cc62e 100644 --- a/packages/contracts-bedrock/justfile +++ b/packages/contracts-bedrock/justfile @@ -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") ######################################################## diff --git a/packages/contracts-bedrock/lib/espresso-tee-contracts b/packages/contracts-bedrock/lib/espresso-tee-contracts index 1c4344abe1b..4e07c341a0d 160000 --- a/packages/contracts-bedrock/lib/espresso-tee-contracts +++ b/packages/contracts-bedrock/lib/espresso-tee-contracts @@ -1 +1 @@ -Subproject commit 1c4344abe1b3ff539db85e227a18255218f20c70 +Subproject commit 4e07c341a0d55afdc0146b7743c7221a981273b8 diff --git a/packages/contracts-bedrock/scripts/deploy/DeployEspresso.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployEspresso.s.sol index abb659feefc..5c2bfa6f98c 100644 --- a/packages/contracts-bedrock/scripts/deploy/DeployEspresso.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/DeployEspresso.s.sol @@ -9,7 +9,7 @@ import { IBatchAuthenticator } from "interfaces/L1/IBatchAuthenticator.sol"; import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; import { IEspressoNitroTEEVerifier } from "@espresso-tee-contracts/interface/IEspressoNitroTEEVerifier.sol"; import { IEspressoTEEVerifier } from "@espresso-tee-contracts/interface/IEspressoTEEVerifier.sol"; -import { DeployTEEVerifierImpl } from "lib/espresso-tee-contracts/scripts/DeployTEEVerifierImpl.s.sol"; +import { DeployTEEVerifier } from "lib/espresso-tee-contracts/scripts/DeployTEEVerifier.s.sol"; import { DeployNitroTEEVerifier } from "lib/espresso-tee-contracts/scripts/DeployNitroTEEVerifier.s.sol"; import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; import { Proxy } from "src/universal/Proxy.sol"; @@ -105,6 +105,11 @@ contract DeployEspressoOutput is BaseDeployIO { } contract DeployEspresso is Script { + /// @dev ERC-1967 admin slot: keccak256("eip1967.proxy.admin") - 1 + /// Used to read the ProxyAdmin address auto-deployed by the OZ v5 TransparentUpgradeableProxy + /// that DeployTEEVerifier deploys. + bytes32 internal constant ERC1967_ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; + function run(DeployEspressoInput input, DeployEspressoOutput output, address deployerAddress) public { IEspressoTEEVerifier teeVerifier = deployTEEContracts(input, output, deployerAddress); deployBatchAuthenticator(input, output, teeVerifier); @@ -150,8 +155,9 @@ contract DeployEspresso is Script { return IBatchAuthenticator(address(proxy)); } - /// @notice Deploys NitroTEEVerifier and TEEVerifier (behind an OP-style proxy). Order: - /// 1. Deploy TEEVerifier impl + OP ProxyAdmin + Proxy, initialize with placeholder nitro address + /// @notice Deploys NitroTEEVerifier and TEEVerifier via the canonical espresso-tee-contracts scripts. + /// Deployment order: + /// 1. Deploy TEEVerifier (impl + OZ v5 TUP proxy) with placeholder nitro address /// 2. Deploy NitroTEEVerifier pointing to the TEEVerifier proxy /// 3. Update TEEVerifier with the actual NitroTEEVerifier address /// @@ -214,38 +220,13 @@ contract DeployEspresso is Script { address proxyAdminOwner = input.proxyAdminOwner(); if (proxyAdminOwner == address(0)) proxyAdminOwner = deployerAddress; - // Deploy EspressoTEEVerifier implementation via the submodule script (no proxy). - // We use DeployTEEVerifierImpl (not DeployTEEVerifier) to avoid importing OZ v5 - // TransparentUpgradeableProxy, which would compile OZ v5 ProxyAdmin and cause an - // artifact collision with src/universal/ProxyAdmin.sol. - vm.broadcast(msg.sender); - address teeVerifierImpl = new DeployTEEVerifierImpl().deploy(); - vm.label(teeVerifierImpl, "TEEVerifierImpl"); - - // Wrap in an OP-style proxy — same pattern used by deployBatchAuthenticator above. - vm.broadcast(msg.sender); - ProxyAdmin teeProxyAdmin = new ProxyAdmin(msg.sender); - vm.label(address(teeProxyAdmin), "TEEVerifierProxyAdmin"); - - vm.broadcast(msg.sender); - Proxy teeProxyRaw = new Proxy(address(teeProxyAdmin)); - vm.label(address(teeProxyRaw), "TEEVerifierProxy"); - - vm.broadcast(msg.sender); - teeProxyAdmin.setProxyType(address(teeProxyRaw), ProxyAdmin.ProxyType.ERC1967); - - // Initialize with placeholder verifier addresses; nitro address is wired in below. - bytes memory initData = - abi.encodeWithSignature("initialize(address,address,address)", proxyAdminOwner, address(0), address(0)); - vm.broadcast(msg.sender); - teeProxyAdmin.upgradeAndCall(payable(address(teeProxyRaw)), teeVerifierImpl, initData); - - if (proxyAdminOwner != msg.sender) { - vm.broadcast(msg.sender); - teeProxyAdmin.transferOwnership(proxyAdminOwner); - } - - address teeProxy = address(teeProxyRaw); + // Deploy TEEVerifier (impl + OZ v5 TUP proxy) via the canonical submodule script. + // DeployImplementations uses vm.getCode("src/universal/ProxyAdmin.sol:ProxyAdmin") to avoid + // the artifact collision with the OZ v5 ProxyAdmin that this TUP auto-deploys. + vm.startBroadcast(msg.sender); + (address teeProxy,) = new DeployTEEVerifier().deploy(proxyAdminOwner, address(0), address(0)); + vm.stopBroadcast(); + vm.label(teeProxy, "TEEVerifierProxy"); // NitroTEEVerifier is deployed without a proxy; it stores teeProxy for access control. vm.startBroadcast(msg.sender); @@ -256,8 +237,10 @@ contract DeployEspresso is Script { vm.broadcast(msg.sender); IEspressoTEEVerifier(teeProxy).setEspressoNitroTEEVerifier(IEspressoNitroTEEVerifier(nitroVerifier)); + address teeProxyAdmin = address(uint160(uint256(vm.load(teeProxy, ERC1967_ADMIN_SLOT)))); + output.set(output.teeVerifierProxy.selector, teeProxy); - output.set(output.teeVerifierProxyAdmin.selector, address(teeProxyAdmin)); + output.set(output.teeVerifierProxyAdmin.selector, teeProxyAdmin); output.set(output.nitroTEEVerifier.selector, nitroVerifier); return IEspressoTEEVerifier(teeProxy); From 074aba49142cf924c3f7e6b1e0f19f5709279bde Mon Sep 17 00:00:00 2001 From: Jean Gal Date: Fri, 3 Apr 2026 10:07:57 -0400 Subject: [PATCH 6/6] Point to tee contracts commit at main --- packages/contracts-bedrock/lib/espresso-tee-contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts-bedrock/lib/espresso-tee-contracts b/packages/contracts-bedrock/lib/espresso-tee-contracts index 4e07c341a0d..25f87e1eb46 160000 --- a/packages/contracts-bedrock/lib/espresso-tee-contracts +++ b/packages/contracts-bedrock/lib/espresso-tee-contracts @@ -1 +1 @@ -Subproject commit 4e07c341a0d55afdc0146b7743c7221a981273b8 +Subproject commit 25f87e1eb464e9514a12ffcdf4925e8f88d69a74