Files
evm/params/precompile_config_test.go
2024-01-03 09:44:09 +01:00

344 lines
9.8 KiB
Go

// (c) 2022-2024 Lux Partners Limited. All rights reserved.
// See the file LICENSE for licensing terms.
package params
import (
"encoding/json"
"math/big"
"testing"
"github.com/luxdefi/evm/commontype"
"github.com/luxdefi/evm/precompile/contracts/deployerallowlist"
"github.com/luxdefi/evm/precompile/contracts/feemanager"
"github.com/luxdefi/evm/precompile/contracts/nativeminter"
"github.com/luxdefi/evm/precompile/contracts/rewardmanager"
"github.com/luxdefi/evm/precompile/contracts/txallowlist"
"github.com/luxdefi/evm/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
func TestVerifyWithChainConfig(t *testing.T) {
admins := []common.Address{{1}}
baseConfig := *TestChainConfig
config := &baseConfig
config.GenesisPrecompiles = Precompiles{
txallowlist.ConfigKey: txallowlist.NewConfig(utils.NewUint64(2), nil, nil, nil),
}
config.PrecompileUpgrades = []PrecompileUpgrade{
{
// disable TxAllowList at timestamp 4
txallowlist.NewDisableConfig(utils.NewUint64(4)),
},
{
// re-enable TxAllowList at timestamp 5
txallowlist.NewConfig(utils.NewUint64(5), admins, nil, nil),
},
}
// check this config is valid
err := config.Verify()
require.NoError(t, err)
// same precompile cannot be configured twice for the same timestamp
badConfig := *config
badConfig.PrecompileUpgrades = append(
badConfig.PrecompileUpgrades,
PrecompileUpgrade{
Config: txallowlist.NewDisableConfig(utils.NewUint64(5)),
},
)
err = badConfig.Verify()
require.ErrorContains(t, err, "config block timestamp (5) <= previous timestamp (5) of same key")
// cannot enable a precompile without disabling it first.
badConfig = *config
badConfig.PrecompileUpgrades = append(
badConfig.PrecompileUpgrades,
PrecompileUpgrade{
Config: txallowlist.NewConfig(utils.NewUint64(5), admins, nil, nil),
},
)
err = badConfig.Verify()
require.ErrorContains(t, err, "disable should be [true]")
}
func TestVerifyWithChainConfigAtNilTimestamp(t *testing.T) {
admins := []common.Address{{0}}
baseConfig := *TestChainConfig
config := &baseConfig
config.PrecompileUpgrades = []PrecompileUpgrade{
// this does NOT enable the precompile, so it should be upgradeable.
{Config: txallowlist.NewConfig(nil, nil, nil, nil)},
}
require.False(t, config.IsPrecompileEnabled(txallowlist.ContractAddress, 0)) // check the precompile is not enabled.
config.PrecompileUpgrades = []PrecompileUpgrade{
{
// enable TxAllowList at timestamp 5
Config: txallowlist.NewConfig(utils.NewUint64(5), admins, nil, nil),
},
}
// check this config is valid
require.NoError(t, config.Verify())
}
func TestVerifyPrecompileUpgrades(t *testing.T) {
admins := []common.Address{{1}}
tests := []struct {
name string
upgrades []PrecompileUpgrade
expectedError string
}{
{
name: "enable and disable tx allow list",
upgrades: []PrecompileUpgrade{
{
Config: txallowlist.NewConfig(utils.NewUint64(1), admins, nil, nil),
},
{
Config: txallowlist.NewDisableConfig(utils.NewUint64(2)),
},
},
expectedError: "",
},
{
name: "invalid allow list config in tx allowlist",
upgrades: []PrecompileUpgrade{
{
Config: txallowlist.NewConfig(utils.NewUint64(1), admins, nil, nil),
},
{
Config: txallowlist.NewDisableConfig(utils.NewUint64(2)),
},
{
Config: txallowlist.NewConfig(utils.NewUint64(3), admins, admins, admins),
},
},
expectedError: "cannot set address",
},
{
name: "invalid initial fee manager config",
upgrades: []PrecompileUpgrade{
{
Config: feemanager.NewConfig(utils.NewUint64(3), admins, nil, nil,
func() *commontype.FeeConfig {
feeConfig := DefaultFeeConfig
feeConfig.GasLimit = big.NewInt(-1)
return &feeConfig
}()),
},
},
expectedError: "gasLimit = -1 cannot be less than or equal to 0",
},
{
name: "invalid initial fee manager config gas limit 0",
upgrades: []PrecompileUpgrade{
{
Config: feemanager.NewConfig(utils.NewUint64(3), admins, nil, nil,
func() *commontype.FeeConfig {
feeConfig := DefaultFeeConfig
feeConfig.GasLimit = common.Big0
return &feeConfig
}()),
},
},
expectedError: "gasLimit = 0 cannot be less than or equal to 0",
},
{
name: "different upgrades are allowed to configure same timestamp for different precompiles",
upgrades: []PrecompileUpgrade{
{
Config: txallowlist.NewConfig(utils.NewUint64(1), admins, nil, nil),
},
{
Config: feemanager.NewConfig(utils.NewUint64(1), admins, nil, nil, nil),
},
},
expectedError: "",
},
{
name: "different upgrades must be monotonically increasing",
upgrades: []PrecompileUpgrade{
{
Config: txallowlist.NewConfig(utils.NewUint64(2), admins, nil, nil),
},
{
Config: feemanager.NewConfig(utils.NewUint64(1), admins, nil, nil, nil),
},
},
expectedError: "config block timestamp (1) < previous timestamp (2)",
},
{
name: "upgrades with same keys are not allowed to configure same timestamp for same precompiles",
upgrades: []PrecompileUpgrade{
{
Config: txallowlist.NewConfig(utils.NewUint64(1), admins, nil, nil),
},
{
Config: txallowlist.NewDisableConfig(utils.NewUint64(1)),
},
},
expectedError: "config block timestamp (1) <= previous timestamp (1) of same key",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require := require.New(t)
baseConfig := *TestChainConfig
config := &baseConfig
config.PrecompileUpgrades = tt.upgrades
err := config.Verify()
if tt.expectedError == "" {
require.NoError(err)
} else {
require.ErrorContains(err, tt.expectedError)
}
})
}
}
func TestVerifyPrecompiles(t *testing.T) {
admins := []common.Address{{1}}
tests := []struct {
name string
precompiles Precompiles
expectedError string
}{
{
name: "invalid allow list config in tx allowlist",
precompiles: Precompiles{
txallowlist.ConfigKey: txallowlist.NewConfig(utils.NewUint64(3), admins, admins, admins),
},
expectedError: "cannot set address",
},
{
name: "invalid initial fee manager config",
precompiles: Precompiles{
feemanager.ConfigKey: feemanager.NewConfig(utils.NewUint64(3), admins, nil, nil,
func() *commontype.FeeConfig {
feeConfig := DefaultFeeConfig
feeConfig.GasLimit = big.NewInt(-1)
return &feeConfig
}()),
},
expectedError: "gasLimit = -1 cannot be less than or equal to 0",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require := require.New(t)
baseConfig := *TestChainConfig
config := &baseConfig
config.GenesisPrecompiles = tt.precompiles
err := config.Verify()
if tt.expectedError == "" {
require.NoError(err)
} else {
require.ErrorContains(err, tt.expectedError)
}
})
}
}
func TestVerifyRequiresSortedTimestamps(t *testing.T) {
admins := []common.Address{{1}}
baseConfig := *TestChainConfig
config := &baseConfig
config.PrecompileUpgrades = []PrecompileUpgrade{
{
Config: txallowlist.NewConfig(utils.NewUint64(2), admins, nil, nil),
},
{
Config: deployerallowlist.NewConfig(utils.NewUint64(1), admins, nil, nil),
},
}
// block timestamps must be monotonically increasing, so this config is invalid
err := config.Verify()
require.ErrorContains(t, err, "config block timestamp (1) < previous timestamp (2)")
}
func TestGetPrecompileConfig(t *testing.T) {
require := require.New(t)
baseConfig := *TestChainConfig
config := &baseConfig
config.GenesisPrecompiles = Precompiles{
deployerallowlist.ConfigKey: deployerallowlist.NewConfig(utils.NewUint64(10), nil, nil, nil),
}
deployerConfig := config.getActivePrecompileConfig(deployerallowlist.ContractAddress, 0)
require.Nil(deployerConfig)
deployerConfig = config.getActivePrecompileConfig(deployerallowlist.ContractAddress, 10)
require.NotNil(deployerConfig)
deployerConfig = config.getActivePrecompileConfig(deployerallowlist.ContractAddress, 11)
require.NotNil(deployerConfig)
txAllowListConfig := config.getActivePrecompileConfig(txallowlist.ContractAddress, 0)
require.Nil(txAllowListConfig)
}
func TestPrecompileUpgradeUnmarshalJSON(t *testing.T) {
require := require.New(t)
upgradeBytes := []byte(`
{
"precompileUpgrades": [
{
"rewardManagerConfig": {
"blockTimestamp": 1671542573,
"adminAddresses": [
"0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC"
],
"initialRewardConfig": {
"allowFeeRecipients": true
}
}
},
{
"contractNativeMinterConfig": {
"blockTimestamp": 1671543172,
"disable": false
}
}
]
}
`)
var upgradeConfig UpgradeConfig
err := json.Unmarshal(upgradeBytes, &upgradeConfig)
require.NoError(err)
require.Len(upgradeConfig.PrecompileUpgrades, 2)
rewardManagerConf := upgradeConfig.PrecompileUpgrades[0]
require.Equal(rewardManagerConf.Key(), rewardmanager.ConfigKey)
testRewardManagerConfig := rewardmanager.NewConfig(
utils.NewUint64(1671542573),
[]common.Address{common.HexToAddress("0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC")},
nil,
nil,
&rewardmanager.InitialRewardConfig{
AllowFeeRecipients: true,
})
require.True(rewardManagerConf.Equal(testRewardManagerConfig))
nativeMinterConfig := upgradeConfig.PrecompileUpgrades[1]
require.Equal(nativeMinterConfig.Key(), nativeminter.ConfigKey)
expectedNativeMinterConfig := nativeminter.NewConfig(utils.NewUint64(1671543172), nil, nil, nil, nil)
require.True(nativeMinterConfig.Equal(expectedNativeMinterConfig))
// Marshal and unmarshal again and check that the result is the same
upgradeBytes2, err := json.Marshal(upgradeConfig)
require.NoError(err)
var upgradeConfig2 UpgradeConfig
err = json.Unmarshal(upgradeBytes2, &upgradeConfig2)
require.NoError(err)
require.Equal(upgradeConfig, upgradeConfig2)
}