diff --git a/accounts/abi/bind/precompilebind/precompile_config_template.go b/accounts/abi/bind/precompilebind/precompile_config_template.go index edab3ddb1b..4d8f9252de 100644 --- a/accounts/abi/bind/precompilebind/precompile_config_template.go +++ b/accounts/abi/bind/precompilebind/precompile_config_template.go @@ -8,51 +8,31 @@ const tmplSourcePrecompileConfigGo = ` // This file is a generated precompile contract config with stubbed abstract functions. // The file is generated by a template. Please inspect every code and comment in this file before use. -// There are some must-be-done changes waiting in the file. Each area requiring you to add your code is marked with CUSTOM CODE to make them easy to find and modify. -// Additionally there are other files you need to edit to activate your precompile. -// These areas are highlighted with comments "ADD YOUR PRECOMPILE HERE". -// For testing take a look at other precompile tests in contract_test.go and config_test.go in other precompile folders. -// See the tutorial in https://docs.avax.network/subnets/hello-world-precompile-tutorial for more information about precompile development. - -/* General guidelines for precompile development: -1- Read the comment and set a suitable contract address in generated module.go. E.g: - ContractAddress = common.HexToAddress("ASUITABLEHEXADDRESS") -2- Set a suitable config key in generated module.go. E.g: "yourPrecompileConfig" -3- It is recommended to only modify code in the highlighted areas marked with "CUSTOM CODE STARTS HERE". Typically, custom codes are required in only those areas. -Modifying code outside of these areas should be done with caution and with a deep understanding of how these changes may impact the EVM. -4- Set gas costs in generated contract.go -5- Add your config unit tests under generated package config_test.go -6- Add your contract unit tests undertgenerated package contract_test.go -7- Additionally you can add a full-fledged VM test for your precompile under plugin/vm/vm_test.go. See existing precompile tests for examples. -8- Add your solidity interface and test contract to contract-examples/contracts -9- Write solidity tests for your precompile in contract-examples/test -10- Create your genesis with your precompile enabled in tests/e2e/genesis/ -11- Create e2e test for your solidity test in tests/e2e/solidity/suites.go -12- Run your e2e precompile Solidity tests with 'E2E=true ./scripts/run.sh' -*/ - package {{.Package}} import ( "math/big" - "github.com/ava-labs/subnet-evm/precompile/config" + "github.com/ava-labs/subnet-evm/precompile/precompileconfig" {{- if .Contract.AllowList}} "github.com/ava-labs/subnet-evm/precompile/allowlist" - {{- end}} "github.com/ethereum/go-ethereum/common" + {{- end}} + ) -var _ config.Config = &Config{} +var _ precompileconfig.Config = &Config{} // Config implements the StatefulPrecompileConfig // interface while adding in the {{.Contract.Type}} specific precompile address. type Config struct { {{- if .Contract.AllowList}} - allowlist.Config + allowlist.AllowListConfig {{- end}} - config.Upgrade + precompileconfig.Upgrade + // CUSTOM CODE STARTS HERE + // Add your own custom fields for Config here } {{$structs := .Structs}} @@ -83,12 +63,12 @@ type {{capitalise .Normalized.Name}}Output struct{ func NewConfig(blockTimestamp *big.Int{{if .Contract.AllowList}}, admins []common.Address, enableds []common.Address,{{end}}) *Config { return &Config{ {{- if .Contract.AllowList}} - Config: allowlist.Config{ + AllowListConfig: allowlist.AllowListConfig{ AdminAddresses: admins, EnabledAddresses: enableds, }, {{- end}} - Upgrade: config.Upgrade{BlockTimestamp: blockTimestamp}, + Upgrade: precompileconfig.Upgrade{BlockTimestamp: blockTimestamp}, } } @@ -96,14 +76,14 @@ func NewConfig(blockTimestamp *big.Int{{if .Contract.AllowList}}, admins []commo // that disables {{.Contract.Type}}. func NewDisableConfig(blockTimestamp *big.Int) *Config { return &Config{ - Upgrade: config.Upgrade{ + Upgrade: precompileconfig.Upgrade{ BlockTimestamp: blockTimestamp, Disable: true, }, } } -// Key returns the key for the {{.Contract.Type}} config. +// Key returns the key for the {{.Contract.Type}} precompileconfig. // This should be the same key as used in the precompile module. func (*Config) Key() string { return ConfigKey } @@ -111,7 +91,7 @@ func (*Config) Key() string { return ConfigKey } func (c *Config) Verify() error { {{if .Contract.AllowList}} // Verify AllowList first - if err := c.Config.Verify(); err != nil { + if err := c.AllowListConfig.Verify(); err != nil { return err } {{end}} @@ -122,7 +102,7 @@ func (c *Config) Verify() error { } // Equal returns true if [s] is a [*Config] and it has been configured identical to [c]. -func (c *Config) Equal(s config.Config) bool { +func (c *Config) Equal(s precompileconfig.Config) bool { // typecast before comparison other, ok := (s).(*Config) if !ok { @@ -131,7 +111,7 @@ func (c *Config) Equal(s config.Config) bool { // CUSTOM CODE STARTS HERE // modify this boolean accordingly with your custom Config, to check if [other] and the current [c] are equal // if Config contains only Upgrade {{if .Contract.AllowList}} and AllowListConfig {{end}} you can skip modifying it. - equals := c.Upgrade.Equal(&other.Upgrade) {{if .Contract.AllowList}} && c.Config.Equal(&other.Config) {{end}} + equals := c.Upgrade.Equal(&other.Upgrade) {{if .Contract.AllowList}} && c.AllowListConfig.Equal(&other.AllowListConfig) {{end}} return equals } ` diff --git a/accounts/abi/bind/precompilebind/precompile_contract_template.go b/accounts/abi/bind/precompilebind/precompile_contract_template.go index d96b67e768..1c302d4b49 100644 --- a/accounts/abi/bind/precompilebind/precompile_contract_template.go +++ b/accounts/abi/bind/precompilebind/precompile_contract_template.go @@ -25,29 +25,6 @@ const tmplSourcePrecompileContractGo = ` // This file is a generated precompile contract config with stubbed abstract functions. // The file is generated by a template. Please inspect every code and comment in this file before use. -// There are some must-be-done changes waiting in the file. Each area requiring you to add your code is marked with CUSTOM CODE to make them easy to find and modify. -// Additionally there are other files you need to edit to activate your precompile. -// These areas are highlighted with comments "ADD YOUR PRECOMPILE HERE". -// For testing take a look at other precompile tests in contract_test.go and config_test.go in other precompile folders. -// See the tutorial in https://docs.avax.network/subnets/hello-world-precompile-tutorial for more information about precompile development. - -/* General guidelines for precompile development: -1- Read the comment and set a suitable contract address in generated module.go. E.g: - ContractAddress = common.HexToAddress("ASUITABLEHEXADDRESS") -2- Set a suitable config key in generated module.go. E.g: "yourPrecompileConfig" -3- It is recommended to only modify code in the highlighted areas marked with "CUSTOM CODE STARTS HERE". Typically, custom codes are required in only those areas. -Modifying code outside of these areas should be done with caution and with a deep understanding of how these changes may impact the EVM. -4- Set gas costs in generated contract.go -5- Add your config unit tests under generated package config_test.go -6- Add your contract unit tests undertgenerated package contract_test.go -7- Additionally you can add a full-fledged VM test for your precompile under plugin/vm/vm_test.go. See existing precompile tests for examples. -8- Add your solidity interface and test contract to contract-examples/contracts -9- Write solidity tests for your precompile in contract-examples/test -10- Create your genesis with your precompile enabled in tests/e2e/genesis/ -11- Create e2e test for your solidity test in tests/e2e/solidity/suites.go -12- Run your e2e precompile Solidity tests with 'E2E=true ./scripts/run.sh' -*/ - package {{.Package}} import ( diff --git a/accounts/abi/bind/precompilebind/precompile_module_template.go b/accounts/abi/bind/precompilebind/precompile_module_template.go index b0b8c7f184..0fa4975e5d 100644 --- a/accounts/abi/bind/precompilebind/precompile_module_template.go +++ b/accounts/abi/bind/precompilebind/precompile_module_template.go @@ -8,35 +8,12 @@ const tmplSourcePrecompileModuleGo = ` // This file is a generated precompile contract config with stubbed abstract functions. // The file is generated by a template. Please inspect every code and comment in this file before use. -// There are some must-be-done changes waiting in the file. Each area requiring you to add your code is marked with CUSTOM CODE to make them easy to find and modify. -// Additionally there are other files you need to edit to activate your precompile. -// These areas are highlighted with comments "ADD YOUR PRECOMPILE HERE". -// For testing take a look at other precompile tests in contract_test.go and config_test.go in other precompile folders. -// See the tutorial in https://docs.avax.network/subnets/hello-world-precompile-tutorial for more information about precompile development. - -/* General guidelines for precompile development: -1- Read the comment and set a suitable contract address in generated module.go. E.g: - ContractAddress = common.HexToAddress("ASUITABLEHEXADDRESS") -2- Set a suitable config key in generated module.go. E.g: "yourPrecompileConfig" -3- It is recommended to only modify code in the highlighted areas marked with "CUSTOM CODE STARTS HERE". Typically, custom codes are required in only those areas. -Modifying code outside of these areas should be done with caution and with a deep understanding of how these changes may impact the EVM. -4- Set gas costs in generated contract.go -5- Add your config unit tests under generated package config_test.go -6- Add your contract unit tests undertgenerated package contract_test.go -7- Additionally you can add a full-fledged VM test for your precompile under plugin/vm/vm_test.go. See existing precompile tests for examples. -8- Add your solidity interface and test contract to contract-examples/contracts -9- Write solidity tests for your precompile in contract-examples/test -10- Create your genesis with your precompile enabled in tests/e2e/genesis/ -11- Create e2e test for your solidity test in tests/e2e/solidity/suites.go -12- Run your e2e precompile Solidity tests with 'E2E=true ./scripts/run.sh' -*/ - package {{.Package}} import ( "fmt" - "github.com/ava-labs/subnet-evm/precompile/config" + "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/ava-labs/subnet-evm/precompile/contract" "github.com/ava-labs/subnet-evm/precompile/modules" @@ -45,7 +22,7 @@ import ( var _ contract.Configurator = &configurator{} -// ConfigKey is the key used in json config files to specify this precompile config. +// ConfigKey is the key used in json config files to specify this precompile precompileconfig. // must be unique across all precompiles. const ConfigKey = "{{decapitalise .Contract.Type}}Config" @@ -72,17 +49,17 @@ func init() { } } -// NewConfig returns a new precompile config. -// This is required for Marshal/Unmarshal the precompile config. -func (*configurator) NewConfig() config.Config { +// NewConfig returns a new precompile precompileconfig. +// This is required for Marshal/Unmarshal the precompile precompileconfig. +func (*configurator) NewConfig() precompileconfig.Config { return &Config{} } -// Configure configures [state] with the given [cfg] config. +// Configure configures [state] with the given [cfg] precompileconfig. // This function is called by the EVM once per precompile contract activation. // You can use this function to set up your precompile contract's initial state, // by using the [cfg] config and [state] stateDB. -func (*configurator) Configure(chainConfig contract.ChainConfig, cfg config.Config, state contract.StateDB, _ contract.BlockContext) error { +func (*configurator) Configure(chainConfig contract.ChainConfig, cfg precompileconfig.Config, state contract.StateDB, _ contract.BlockContext) error { config, ok := cfg.(*Config) if !ok { return fmt.Errorf("incorrect config %T: %v", config, config) @@ -90,7 +67,7 @@ func (*configurator) Configure(chainConfig contract.ChainConfig, cfg config.Conf // CUSTOM CODE STARTS HERE {{if .Contract.AllowList}} // AllowList is activated for this precompile. Configuring allowlist addresses here. - return config.Configure(state, ContractAddress) + return config.AllowListConfig.Configure(state, ContractAddress) {{else}} return nil {{end}} diff --git a/cmd/precompilegen/main.go b/cmd/precompilegen/main.go index 75606a9c87..a2545e3572 100644 --- a/cmd/precompilegen/main.go +++ b/cmd/precompilegen/main.go @@ -33,6 +33,8 @@ import ( "path/filepath" "strings" + _ "embed" + "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/precompilebind" "github.com/ava-labs/subnet-evm/internal/flags" @@ -47,25 +49,28 @@ var ( gitDate = "" app *cli.App + + //go:embed template-readme.md + readme string ) var ( // Flags needed by abigen abiFlag = &cli.StringFlag{ Name: "abi", - Usage: "Path to the Ethereum contract ABI json to bind, - for STDIN", + Usage: "Path to the contract ABI json to generate, - for STDIN", } typeFlag = &cli.StringFlag{ Name: "type", - Usage: "Struct name for the precompile (default = {ABI name})", + Usage: "Struct name for the precompile (default = {abi file name})", } pkgFlag = &cli.StringFlag{ Name: "pkg", - Usage: "Package name to generate the precompile into (default = {type})", + Usage: "Go package name to generate the precompile into (default = {type})", } outFlag = &cli.StringFlag{ Name: "out", - Usage: "Output folder for the generated precompile files, - for STDOUT (default = ./{pkg})", + Usage: "Output folder for the generated precompile files, - for STDOUT (default = ./precompile/contracts/{pkg})", } ) @@ -134,7 +139,7 @@ func precompilegen(c *cli.Context) error { } if outFlagStr == "" { - outFlagStr = filepath.Join("./", pkg) + outFlagStr = filepath.Join("./precompile/contracts", pkg) } abifilename := "" @@ -187,6 +192,12 @@ func precompilegen(c *cli.Context) error { utils.Fatalf("Failed to write ABI: %v", err) } + readmeOut := filepath.Join(outFlagStr, "README.md") + + if err := os.WriteFile(readmeOut, []byte(readme), 0o600); err != nil { + utils.Fatalf("Failed to write README: %v", err) + } + fmt.Println("Precompile files generated successfully at: ", outFlagStr) return nil } diff --git a/cmd/precompilegen/template-readme.md b/cmd/precompilegen/template-readme.md new file mode 100644 index 0000000000..883f41f105 --- /dev/null +++ b/cmd/precompilegen/template-readme.md @@ -0,0 +1,22 @@ +There are some must-be-done changes waiting in the generated file. Each area requiring you to add your code is marked with CUSTOM CODE to make them easy to find and modify. +Additionally there are other files you need to edit to activate your precompile. +These areas are highlighted with comments "ADD YOUR PRECOMPILE HERE". +For testing take a look at other precompile tests in contract_test.go and config_test.go in other precompile folders. +See the tutorial in for more information about precompile development. + +General guidelines for precompile development: +1- Set a suitable config key in generated module.go. E.g: "yourPrecompileConfig" +2- Read the comment and set a suitable contract address in generated module.go. E.g: +ContractAddress = common.HexToAddress("ASUITABLEHEXADDRESS") +3- It is recommended to only modify code in the highlighted areas marked with "CUSTOM CODE STARTS HERE". Typically, custom codes are required in only those areas. +Modifying code outside of these areas should be done with caution and with a deep understanding of how these changes may impact the EVM. +4- Set gas costs in generated contract.go +5- Force import your precompile package in precompile/registry/registry.go +6- Add your config unit tests under generated package config_test.go +7- Add your contract unit tests under generated package contract_test.go +8- Additionally you can add a full-fledged VM test for your precompile under plugin/vm/vm_test.go. See existing precompile tests for examples. +9- Add your solidity interface and test contract to contract-examples/contracts +10- Write solidity tests for your precompile in contract-examples/test +11- Create your genesis with your precompile enabled in tests/e2e/genesis/ +12- Create e2e test for your solidity test in tests/e2e/solidity/suites.go +13- Run your e2e precompile Solidity tests with 'E2E=true ./scripts/run.sh diff --git a/precompile/allowlist/test_allowlist.go b/precompile/allowlist/test_allowlist.go index 5abb39d5b9..70656dda3d 100644 --- a/precompile/allowlist/test_allowlist.go +++ b/precompile/allowlist/test_allowlist.go @@ -273,6 +273,7 @@ func SetDefaultRoles(contractAddress common.Address) func(t *testing.T, state co } func RunPrecompileWithAllowListTests(t *testing.T, module modules.Module, newStateDB func(t *testing.T) contract.StateDB, contractTests map[string]testutils.PrecompileTest) { + t.Helper() tests := AllowListTests(module) // Add the contract specific tests to the map of tests to run. for name, test := range contractTests {