Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
d94f788
feat: add test precompiled contract
fbac Aug 14, 2024
b9878a6
feat: add test stateful contract
fbac Aug 14, 2024
40ff210
feat: enable contracts granularly
fbac Aug 14, 2024
83457fc
feat: allow passing the app ctx to contracts
fbac Aug 14, 2024
d13079a
revert ctx changes
fbac Aug 14, 2024
e58c783
format ABI
fbac Aug 14, 2024
eaac523
add first e2e test
fbac Aug 15, 2024
fadf37a
add RegularCaller contract to e2e
fbac Aug 15, 2024
8ad612b
add signer to deployment
fbac Aug 15, 2024
a717f01
fix e2e, use regular abi
fbac Aug 16, 2024
5c88cf1
minor rewording
fbac Aug 16, 2024
f32ff32
use idiomatic errors
fbac Aug 16, 2024
ddee0c5
remove unused files
fbac Aug 19, 2024
c1d41e2
rename and generate bindings automatically
fbac Aug 19, 2024
797dbc4
create a new e2e section for precompiles
fbac Aug 19, 2024
bb69a61
add bindings generator and makefile target
fbac Aug 19, 2024
53098a1
add GetGasStabilityPoolBalance as prototype contract function
fbac Aug 19, 2024
dbe971c
include getGasStabilityPoolBalance function
fbac Aug 19, 2024
906c438
apply code review fixes
fbac Aug 20, 2024
cefb8d2
include tests for precompiles package
fbac Aug 20, 2024
1750644
delete regularcaller
fbac Aug 20, 2024
0f0a517
ignore bindings from codecov
fbac Aug 20, 2024
ee52f66
introduce more unit testing
fbac Aug 20, 2024
3fa0cab
add unit testing for prototype.go
fbac Aug 20, 2024
3a31ddb
minor linting fixes
fbac Aug 20, 2024
fe78f69
remove ctx, keep fungible keeper private
fbac Aug 20, 2024
b62a99e
increase unit tests coverage
fbac Aug 20, 2024
d2bcc79
add keys for new user_precompile
fbac Aug 20, 2024
adbc0a6
add init unit test
fbac Aug 20, 2024
de401aa
switch to double quotes
fbac Aug 20, 2024
f49ac43
avoid go:embed
fbac Aug 20, 2024
ac48e29
fixes derived from code review
fbac Aug 20, 2024
9cbc274
refactor some parts of bech32 functions
fbac Aug 21, 2024
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
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,13 @@ mocks:
@bash ./scripts/mocks-generate.sh
.PHONY: mocks

precompiles:
@echo "--> Generating bindings for precompiled contracts"
@bash ./scripts/bindings-stateful-precompiles.sh
.PHONY: precompiles

# generate also includes Go code formatting
generate: proto-gen openapi specs typescript docs-zetacored mocks fmt
generate: proto-gen openapi specs typescript docs-zetacored mocks precompiles fmt
.PHONY: generate


Expand Down
13 changes: 12 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ import (
"github.com/zeta-chain/zetacore/app/ante"
"github.com/zeta-chain/zetacore/docs/openapi"
zetamempool "github.com/zeta-chain/zetacore/pkg/mempool"
"github.com/zeta-chain/zetacore/precompiles"
srvflags "github.com/zeta-chain/zetacore/server/flags"
authoritymodule "github.com/zeta-chain/zetacore/x/authority"
authoritykeeper "github.com/zeta-chain/zetacore/x/authority/keeper"
Expand Down Expand Up @@ -566,7 +567,7 @@ func New(
&app.FeeMarketKeeper,
tracer,
evmSs,
[]evmkeeper.CustomContractFn{},
precompiles.StatefulContracts(&app.FungibleKeeper, appCodec, storetypes.TransientGasConfig()),
app.ConsensusParamsKeeper,
aggregateAllKeys(keys, tKeys, memKeys),
)
Expand Down Expand Up @@ -1049,10 +1050,20 @@ func (app *App) SimulationManager() *module.SimulationManager {

func (app *App) BlockedAddrs() map[string]bool {
blockList := make(map[string]bool)

for k, v := range blockedReceivingModAcc {
addr := authtypes.NewModuleAddress(k)
blockList[addr.String()] = v
}

// Each enabled precompiled stateful contract should be added as a BlockedAddrs.
// That way it's marked as non payable by the bank keeper.
for addr, enabled := range precompiles.EnabledStatefulContracts {
if enabled {
blockList[addr.String()] = enabled
}
}

return blockList
}

Expand Down
6 changes: 5 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* [2634](https://github.com/zeta-chain/node/pull/2634) - add support for EIP-1559 gas fees
* [2597](https://github.com/zeta-chain/node/pull/2597) - Add generic rpc metrics to zetaclient
* [2538](https://github.com/zeta-chain/node/pull/2538) - add background worker routines to shutdown zetaclientd when needed for tss migration
* [2633](https://github.com/zeta-chain/node/pull/2633) - support for stateful precompiled contracts.

### Refactor

Expand All @@ -17,6 +18,10 @@

* [2654](https://github.com/zeta-chain/node/pull/2654) - add validation for authorization list in when validating genesis state for authorization module

### Tests

* [2703](https://github.com/zeta-chain/node/pull/2703) - add e2e tests for stateful precompiled contracts

## v19.0.0

### Breaking Changes
Expand Down Expand Up @@ -57,7 +62,6 @@
* [2524](https://github.com/zeta-chain/node/pull/2524) - add inscription envelop parsing
* [2560](https://github.com/zeta-chain/node/pull/2560) - add support for Solana SOL token withdraw
* [2533](https://github.com/zeta-chain/node/pull/2533) - parse memo from both OP_RETURN and inscription
* [2633](https://github.com/zeta-chain/node/pull/2633) - support for stateful precompiled contracts.

### Refactor

Expand Down
3 changes: 2 additions & 1 deletion cmd/zetae2e/config/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/ethereum/go-ethereum/ethclient"
"github.com/gagliardetto/solana-go/rpc"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

"github.com/zeta-chain/zetacore/e2e/config"
authoritytypes "github.com/zeta-chain/zetacore/x/authority/types"
Expand Down Expand Up @@ -156,7 +157,7 @@ func getZetaClients(rpc string) (
zetaChainClients,
error,
) {
grpcConn, err := grpc.Dial(rpc, grpc.WithInsecure())
grpcConn, err := grpc.Dial(rpc, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
return zetaChainClients{}, err
}
Expand Down
7 changes: 5 additions & 2 deletions cmd/zetae2e/config/localnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ additional_accounts:
bech32_address: "zeta1pvtxa708yvdmszn687nne6nl8qn704daf420xz"
evm_address: "0x0B166ef9e7231Bb80A7A3FA73CEA7F3827E7D5BD"
private_key: "0bcc2fa28b526f90e1d54648d612db901e860bf68248555593f91ea801c6b482"
user_precompile:
bech32_address: "zeta1k4f0l2e9qqjccxnstwj0uaarxvn44lj990she9"
evm_address: "0xb552FFAb2500258C1A705Ba4Fe77A333275AFE45"
private_key: "bd6b74387f11b31d21e87c2ae7a23ec269aee08a355dad6c508a6fceb79d1f48"
policy_accounts:
emergency_policy_account:
bech32_address: "zeta16m2cnrdwtgweq4njc6t470vl325gw4kp6s7tap"
Expand All @@ -67,5 +71,4 @@ rpcs:
solana: "http://solana:8899"
zetacore_grpc: "zetacore0:9090"
zetacore_rpc: "http://zetacore0:26657"

# contracts will be populated on first run
# contracts will be populated on first run
4 changes: 4 additions & 0 deletions cmd/zetae2e/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,9 @@ func localE2ETest(cmd *cobra.Command, _ []string) {
erc20AdvancedTests := []string{
e2etests.TestERC20DepositRestrictedName,
}
precompiledContractTests := []string{
e2etests.TestZetaPrecompilesPrototypeName,
}
zetaTests := []string{
e2etests.TestZetaWithdrawName,
e2etests.TestMessagePassingExternalChainsName,
Expand Down Expand Up @@ -283,6 +286,7 @@ func localE2ETest(cmd *cobra.Command, _ []string) {
ethereumTests = append(ethereumTests, ethereumAdvancedTests...)
}

eg.Go(statefulPrecompilesTestRoutine(conf, deployerRunner, verbose, precompiledContractTests...))
eg.Go(erc20TestRoutine(conf, deployerRunner, verbose, erc20Tests...))
eg.Go(zetaTestRoutine(conf, deployerRunner, verbose, zetaTests...))
eg.Go(zevmMPTestRoutine(conf, deployerRunner, verbose, zevmMPTests...))
Expand Down
54 changes: 54 additions & 0 deletions cmd/zetae2e/local/precompiles.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package local

import (
"fmt"
"time"

"github.com/fatih/color"

"github.com/zeta-chain/zetacore/e2e/config"
"github.com/zeta-chain/zetacore/e2e/e2etests"
"github.com/zeta-chain/zetacore/e2e/runner"
)

// statefulPrecompilesTestRoutine runs steateful precompiles related e2e tests
func statefulPrecompilesTestRoutine(
conf config.Config,
deployerRunner *runner.E2ERunner,
verbose bool,
testNames ...string,
) func() error {
return func() (err error) {
account := conf.AdditionalAccounts.UserPrecompile

precompileRunner, err := initTestRunner(
"precompiles",
conf,
deployerRunner,
account,
runner.NewLogger(verbose, color.FgRed, "precompiles"),
)
if err != nil {
return err
}

precompileRunner.Logger.Print("🏃 starting stateful precompiled contracts tests")
startTime := time.Now()

testsToRun, err := precompileRunner.GetE2ETestsToRunByName(
e2etests.AllE2ETests,
testNames...,
)
if err != nil {
return fmt.Errorf("precompiled contracts tests failed: %v", err)
}

if err := precompileRunner.RunE2ETests(testsToRun); err != nil {
return fmt.Errorf("precompiled contracts tests failed: %v", err)
}

precompileRunner.Logger.Print("🍾 precompiled contracts tests completed in %s", time.Since(startTime).String())

return err
}
}
7 changes: 6 additions & 1 deletion codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,9 @@ ignore:
- "server"
- "testutil"
- "tool"
- "typescript/**/*"
- "typescript/**/*"
- "precompiles/**/bindings.go"
- "precompiles/**/*.abi"
- "precompiles/**/*.json"
- "precompiles/**/*.sol"
- "precompiles/prototype/IPrototype.go"
6 changes: 6 additions & 0 deletions e2e/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ type AdditionalAccounts struct {
UserMisc Account `yaml:"user_misc"`
UserAdmin Account `yaml:"user_admin"`
UserMigration Account `yaml:"user_migration"`
UserPrecompile Account `yaml:"user_precompile"`
}

type PolicyAccounts struct {
Expand Down Expand Up @@ -212,6 +213,7 @@ func (a AdditionalAccounts) AsSlice() []Account {
a.UserMisc,
a.UserAdmin,
a.UserMigration,
a.UserPrecompile,
}
}

Expand Down Expand Up @@ -304,6 +306,10 @@ func (c *Config) GenerateKeys() error {
if err != nil {
return err
}
c.AdditionalAccounts.UserPrecompile, err = generateAccount()
if err != nil {
return err
}

c.PolicyAccounts.EmergencyPolicyAccount, err = generateAccount()
if err != nil {
Expand Down
14 changes: 14 additions & 0 deletions e2e/e2etests/e2etests.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ const (
Not used to test functionalities but do various interactions with the netwoks
*/
TestDeploy = "deploy"

/*
Stateful precompiled contracts tests
*/
TestZetaPrecompilesPrototypeName = "precompile_contracts_prototype"
)

// AllE2ETests is an ordered list of all e2e tests
Expand Down Expand Up @@ -589,4 +594,13 @@ var AllE2ETests = []runner.E2ETest{
[]runner.ArgDefinition{},
TestMigrateTSS,
),
/*
Stateful precompiled contracts tests
*/
runner.NewE2ETest(
TestZetaPrecompilesPrototypeName,
"test stateful precompiled contracts prototype",
[]runner.ArgDefinition{},
TestPrecompilesRegular,
),
}
36 changes: 36 additions & 0 deletions e2e/e2etests/test_precompiles_prototype.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package e2etests

import (
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"

"github.com/zeta-chain/zetacore/e2e/runner"
"github.com/zeta-chain/zetacore/precompiles/prototype"
)

func TestPrecompilesRegular(r *runner.E2ERunner, args []string) {
require.Len(r, args, 0, "No arguments expected")

iPrototype, err := prototype.NewIPrototype(prototype.ContractAddress, r.ZEVMClient)
require.NoError(r, err, "Failed to create prototype contract caller")

res, err := iPrototype.Bech32ify(nil, "zeta", common.HexToAddress("0xB9Dbc229Bf588A613C00BEE8e662727AB8121cfE"))
require.NoError(r, err, "Error calling Bech32ify")
require.Equal(r, "zeta1h8duy2dltz9xz0qqhm5wvcnj02upy887fyn43u", res, "Failed to validate Bech32ify result")

addr, err := iPrototype.Bech32ToHexAddr(nil, "zeta1h8duy2dltz9xz0qqhm5wvcnj02upy887fyn43u")
require.NoError(r, err, "Error calling Bech32ToHexAddr")
require.Equal(
r,
"0xB9Dbc229Bf588A613C00BEE8e662727AB8121cfE",
addr.String(),
"Failed to validate Bech32ToHexAddr result",
)

chainID, err := r.EVMClient.ChainID(r.Ctx)
require.NoError(r, err, "Error retrieving ChainID")

balance, err := iPrototype.GetGasStabilityPoolBalance(nil, chainID.Int64())
require.NoError(r, err, "Error calling GetGasStabilityPoolBalance")
require.NotNil(r, balance, "GetGasStabilityPoolBalance returned balance is nil")
}
43 changes: 43 additions & 0 deletions precompiles/precompiles.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package precompiles

import (
"github.com/cosmos/cosmos-sdk/codec"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdktypes "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
ethparams "github.com/ethereum/go-ethereum/params"
evmkeeper "github.com/zeta-chain/ethermint/x/evm/keeper"

"github.com/zeta-chain/zetacore/precompiles/prototype"
"github.com/zeta-chain/zetacore/x/fungible/keeper"
)

// EnabledStatefulContracts contains the list of all enabled stateful precompiles.
// This is useful for listing and reading from other packages, such as BlockedAddrs() function.
// Setting to false a contract here will disable it, not being included in the blockchain.
var EnabledStatefulContracts = map[common.Address]bool{
prototype.ContractAddress: true,
}

// StatefulContracts returns all the registered precompiled contracts.
func StatefulContracts(
fungibleKeeper *keeper.Keeper,
cdc codec.Codec,
gasConfig storetypes.GasConfig,
) (precompiledContracts []evmkeeper.CustomContractFn) {
// Initialize at 0 the custom compiled contracts and the addresses.
precompiledContracts = make([]evmkeeper.CustomContractFn, 0)

// Define the regular contract function.
if EnabledStatefulContracts[prototype.ContractAddress] {
prototype := func(_ sdktypes.Context, _ ethparams.Rules) vm.PrecompiledContract {
return prototype.NewIPrototypeContract(fungibleKeeper, cdc, gasConfig)
}

// Append the regular contract to the precompiledContracts slice.
precompiledContracts = append(precompiledContracts, prototype)
}

return precompiledContracts
}
39 changes: 39 additions & 0 deletions precompiles/precompiles_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package precompiles

import (
"testing"

storetypes "github.com/cosmos/cosmos-sdk/store/types"
ethparams "github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
ethermint "github.com/zeta-chain/ethermint/types"
"github.com/zeta-chain/zetacore/testutil/keeper"
)

func Test_StatefulContracts(t *testing.T) {
k, ctx, _, _ := keeper.FungibleKeeper(t)
gasConfig := storetypes.TransientGasConfig()

var encoding ethermint.EncodingConfig
appCodec := encoding.Codec

var expectedContracts int
for _, enabled := range EnabledStatefulContracts {
if enabled {
expectedContracts++
}
}

// StatefulContracts() should return all the enabled contracts.
contracts := StatefulContracts(k, appCodec, gasConfig)
require.NotNil(t, contracts, "StatefulContracts() should not return a nil slice")
require.Len(t, contracts, expectedContracts, "StatefulContracts() should return all the enabled contracts")

// Extract the contract function from the first contract.
customContractFn := contracts[0]
contract := customContractFn(ctx, ethparams.Rules{})

// Check the contract function returns a valid address.
contractAddr := contract.Address()
require.NotNil(t, contractAddr, "The called contract should have a valid address")
}
Loading