diff --git a/.circleci/config.yml b/.circleci/config.yml index cd4c04363..1149a4c18 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,6 +11,7 @@ parameters: jobs: go-lint-test: + circleci_ip_ranges: true parameters: package: type: string diff --git a/ops/internal/validation/versions_test.go b/ops/internal/validation/versions_test.go new file mode 100644 index 000000000..f349850a7 --- /dev/null +++ b/ops/internal/validation/versions_test.go @@ -0,0 +1,135 @@ +package validation + +import ( + "context" + "os" + "reflect" + "testing" + "time" + + "github.com/ethereum-optimism/superchain-registry/validation" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/rpc" + "github.com/lmittmann/w3" + "github.com/lmittmann/w3/module/eth" + "github.com/stretchr/testify/require" +) + +// This test file tests the integrity of the standard versions files. However, it can't +// live in the validation package because the validation package can't import Geth. + +var ( + versionFn = w3.MustNewFunc("version()", "string") + implsFn = w3.MustNewFunc("implementations()", "(address superchainConfig,address protocolVersions,address l1ERC721Bridge,address optimismPortal,address systemConfig,address optimismMintableERC20Factory,address l1CrossDomainMessenger,address l1StandardBridge,address disputeGameFactory,address anchorStateRegistry,address delayedWeth,address mips)") + oracleFn = w3.MustNewFunc("oracle()", "address") +) + +type opcmImpls struct { + SuperchainConfig common.Address + ProtocolVersions common.Address + L1ERC721Bridge common.Address + OptimismPortal common.Address + SystemConfig common.Address + OptimismMintableERC20Factory common.Address + L1CrossDomainMessenger common.Address + L1StandardBridge common.Address + DisputeGameFactory common.Address + AnchorStateRegistry common.Address + DelayedWeth common.Address + Mips common.Address +} + +var rpcURLs = map[string]string{ + "sepolia": os.Getenv("SEPOLIA_RPC_URL"), + "mainnet": os.Getenv("MAINNET_RPC_URL"), +} + +var versionMappings = map[string]validation.Versions{ + "sepolia": validation.StandardVersionsSepolia, + "mainnet": validation.StandardVersionsMainnet, +} + +func TestVersionsIntegrity(t *testing.T) { + for _, network := range []string{"sepolia", "mainnet"} { + if network == "mainnet" { + t.Skipf("mainnet temporarily skipped since it isn't deployed yet") + } + + t.Run(network, func(t *testing.T) { + testVersionIntegrity(t, network) + }) + } +} + +func testVersionIntegrity(t *testing.T, network string) { + rpcURL := rpcURLs[network] + require.NotEmpty(t, rpcURL) + + versions := versionMappings[network] + require.NotEmpty(t, versions) + + rpcClient, err := rpc.Dial(rpcURL) + require.NoError(t, err) + + w3Client := w3.NewClient(rpcClient) + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + for _, semver := range []validation.Semver{"op-contracts/v2.0.0-rc.1"} { + stdVer, ok := versions[semver] + require.True(t, ok) + require.NotNil(t, stdVer.OPContractsManager) + opcmAddr := stdVer.OPContractsManager.Address + require.NotNil(t, opcmAddr) + + var impls opcmImpls + require.NoError(t, w3Client.CallCtx( + ctx, + eth.CallFunc(common.Address(*opcmAddr), implsFn).Returns(&impls), + )) + + vValue := reflect.ValueOf(&stdVer).Elem() + implsValue := reflect.ValueOf(impls) + + fields := []string{ + "SuperchainConfig", + "ProtocolVersions", + "L1ERC721Bridge", + "OptimismPortal", + "SystemConfig", + "OptimismMintableERC20Factory", + "L1CrossDomainMessenger", + "L1StandardBridge", + "DisputeGameFactory", + "AnchorStateRegistry", + "DelayedWeth", + "Mips", + } + + for _, field := range fields { + implsField := implsValue.FieldByName(field) + require.True(t, implsField.IsValid()) + + address := implsField.Interface().(common.Address) + contractData := vValue.FieldByName(field).Interface().(*validation.ContractData) + require.NotNil(t, contractData) + + if contractData.Address != nil { + require.Equal(t, common.Address(*contractData.Address), address, "invalid address for %s", field) + } else if contractData.ImplementationAddress != nil { + require.Equal(t, common.Address(*contractData.ImplementationAddress), address, "invalid implementation address for %s", field) + } else { + require.Empty(t, address, "address %s should be empty", field) + } + + var contractVer string + require.NoError(t, w3Client.CallCtx(ctx, eth.CallFunc(address, versionFn).Returns(&contractVer))) + require.Equal(t, contractData.Version, contractVer, "invalid version for %s", field) + } + + var oracleAddr common.Address + require.NoError(t, w3Client.CallCtx(ctx, eth.CallFunc(common.Address(*stdVer.Mips.Address), oracleFn).Returns(&oracleAddr))) + require.Equal(t, common.Address(*stdVer.PreimageOracle.Address), oracleAddr, "invalid oracle address") + } +} diff --git a/validation/standard/standard-versions-sepolia.toml b/validation/standard/standard-versions-sepolia.toml index 21d418f92..f204ff622 100644 --- a/validation/standard/standard-versions-sepolia.toml +++ b/validation/standard/standard-versions-sepolia.toml @@ -3,6 +3,25 @@ # * proxied : specify a standard "implementation_address" # * neither : specify neither a standard "address" nor "implementation_address" +# OPCM https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv2.0.0-rc.1 +["op-contracts/v2.0.0-rc.1"] +system_config = { version = "2.4.0", implementation_address = "0x760C48C62A85045A6B69f07F4a9f22868659CbCc" } +fault_dispute_game = { version = "1.4.1" } +permissioned_dispute_game = { version = "1.4.1" } +mips = { version = "1.3.0", address = "0xaa59a0777648bc75cd10364083e878c1ccd6112a" } +optimism_portal = { version = "3.13.0", implementation_address = "0x2D7e764a0D9919e16983a46595CfA81fc34fa7Cd" } +anchor_state_registry = { version = "2.2.2", implementation_address = "0x7b465370BB7A333f99edd19599EB7Fb1c2D3F8D2" } +delayed_weth = { version = "1.3.0", implementation_address = "0x5e40B9231B86984b5150507046e354dbFbeD3d9e" } +dispute_game_factory = { version = "1.0.1", implementation_address = "0x4bbA758F006Ef09402eF31724203F316ab74e4a0" } +preimage_oracle = { version = "1.1.4", address = "0x1fb8cdfc6831fc866ed9c51af8817da5c287add3" } +l1_cross_domain_messenger = { version = "2.5.0", implementation_address = "0x3eA6084748ED1b2A9B5D4426181F1ad8C93F6231" } +l1_erc721_bridge = { version = "2.3.1", implementation_address = "0x276d3730f219f7ec22274f7263180b8452b46d47" } +l1_standard_bridge = { version = "2.2.2", implementation_address = "0x78972E88Ab8BBB517a36cAea23b931BAB58AD3c6" } +optimism_mintable_erc20_factory = { version = "1.10.1", implementation_address = "0x5493f4677A186f64805fe7317D6993ba4863988F" } +op_contracts_manager = { version = "1.6.0", address = "0x1b25f566336f47bc5e0036d66e142237dcf4640b" } +superchain_config = { version = "1.2.0", implementation_address = "0x4da82a327773965b8d4D85Fa3dB8249b387458E7" } +protocol_versions = { version = "1.1.0", implementation_address = "0x37E15e4d6DFFa9e5E320Ee1eC036922E563CB76C" } + # Holocene https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.8.0 ["op-contracts/v1.8.0"] # Updated in this release @@ -21,7 +40,7 @@ l1_erc721_bridge = { version = "2.1.0", implementation_address = "0xae2af01232a6 l1_standard_bridge = { version = "2.1.0", implementation_address = "0x64b5a5ed26dcb17370ff4d33a8d503f0fbd06cff" } # l2_output_oracle -- This contract not used in fault proofs optimism_mintable_erc20_factory = { version = "1.9.0", implementation_address = "0xe01efbeb1089d1d1db9c6c8b135c934c0734c846" } -op_contracts_manager = { version = "1.0.0-beta.21", implementation_address = "0xefb0779120d9cc3582747e5eb787d859e3a53a5c" } +op_contracts_manager = { version = "1.0.0-beta.21", address = "0xefb0779120d9cc3582747e5eb787d859e3a53a5c" } # Holocene https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.8.0-rc.4 ["op-contracts/v1.8.0-rc.4"] @@ -59,4 +78,4 @@ l1_erc721_bridge = { version = "2.1.0", implementation_address = "0xae2af01232a6 l1_standard_bridge = { version = "2.1.0", implementation_address = "0x64b5a5ed26dcb17370ff4d33a8d503f0fbd06cff" } # l2_output_oracle -- This contract not used in fault proofs optimism_mintable_erc20_factory = { version = "1.9.0", implementation_address = "0xe01efbeb1089d1d1db9c6c8b135c934c0734c846" } -op_contracts_manager = { version = "1.0.0-beta.21", implementation_address = "0x760B1d2Dc68DC51fb6E8B2b8722B8ed08903540c" } +op_contracts_manager = { version = "1.0.0-beta.21", address = "0x760B1d2Dc68DC51fb6E8B2b8722B8ed08903540c" } diff --git a/validation/versions.go b/validation/versions.go index 3f4bc0089..b0e07cd66 100644 --- a/validation/versions.go +++ b/validation/versions.go @@ -54,6 +54,8 @@ type VersionConfig struct { L2OutputOracle *ContractData `toml:"l2_output_oracle,omitempty"` OptimismMintableERC20Factory *ContractData `toml:"optimism_mintable_erc20_factory,omitempty"` OPContractsManager *ContractData `toml:"op_contracts_manager,omitempty"` + SuperchainConfig *ContractData `toml:"superchain_config,omitempty"` + ProtocolVersions *ContractData `toml:"protocol_versions,omitempty"` } // Versions maps release tags to their contract configurations