diff --git a/CHANGELOG.md b/CHANGELOG.md index d79ceea3..cf135437 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,8 +37,13 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## Unreleased +### API Breaking + +* (types) [\#503](https://github.com/ChainSafe/ethermint/pull/503) The `types.DenomDefault` constant for `"aphoton"` has been renamed to `types.AttoPhoton`. + ### Improvements +* (types) [\#503](https://github.com/ChainSafe/ethermint/pull/503) Add `--coin-denom` flag to testnet command that sets the given coin denomination to SDK and Ethermint parameters. * (types) [\#502](https://github.com/ChainSafe/ethermint/pull/502) `EthAccount` now also exposes the Ethereum hex address in `string` format to clients. * (types) [\#494](https://github.com/ChainSafe/ethermint/pull/494) Update `EthAccount` public key JSON type to `string`. * (app) [\#471](https://github.com/ChainSafe/ethermint/pull/471) Add `x/upgrade` module for managing software updates. diff --git a/app/ante/ante_test.go b/app/ante/ante_test.go index 4288bb63..0bb85d05 100644 --- a/app/ante/ante_test.go +++ b/app/ante/ante_test.go @@ -257,7 +257,7 @@ func (suite *AnteTestSuite) TestEthInvalidMempoolFees() { suite.app.EvmKeeper.SetParams(suite.ctx, evmtypes.DefaultParams()) suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.EvmKeeper, suite.app.SupplyKeeper) - suite.ctx = suite.ctx.WithMinGasPrices(sdk.NewDecCoins(sdk.NewDecCoin(types.DenomDefault, sdk.NewInt(500000)))) + suite.ctx = suite.ctx.WithMinGasPrices(sdk.NewDecCoins(types.NewPhotonDecCoin(sdk.NewInt(500000)))) addr1, priv1 := newTestAddrKey() addr2, _ := newTestAddrKey() diff --git a/app/ante/utils_test.go b/app/ante/utils_test.go index 30fbcbd5..d81c55e9 100644 --- a/app/ante/utils_test.go +++ b/app/ante/utils_test.go @@ -14,7 +14,7 @@ import ( "github.com/cosmos/ethermint/app" ante "github.com/cosmos/ethermint/app/ante" "github.com/cosmos/ethermint/crypto" - emint "github.com/cosmos/ethermint/types" + ethermint "github.com/cosmos/ethermint/types" evmtypes "github.com/cosmos/ethermint/x/evm/types" ethcrypto "github.com/ethereum/go-ethereum/crypto" @@ -52,11 +52,11 @@ func newTestMsg(addrs ...sdk.AccAddress) *sdk.TestMsg { } func newTestCoins() sdk.Coins { - return sdk.NewCoins(sdk.NewInt64Coin(emint.DenomDefault, 500000000)) + return sdk.NewCoins(ethermint.NewPhotonCoinInt64(500000000)) } func newTestStdFee() auth.StdFee { - return auth.NewStdFee(220000, sdk.NewCoins(sdk.NewInt64Coin(emint.DenomDefault, 150))) + return auth.NewStdFee(220000, sdk.NewCoins(ethermint.NewPhotonCoinInt64(150))) } // GenerateAddress generates an Ethereum address. diff --git a/client/testnet.go b/client/testnet.go index ab708b7c..9202772b 100644 --- a/client/testnet.go +++ b/client/testnet.go @@ -38,6 +38,7 @@ import ( "github.com/cosmos/ethermint/crypto" "github.com/cosmos/ethermint/types" + evmtypes "github.com/cosmos/ethermint/x/evm/types" ) var ( @@ -47,6 +48,7 @@ var ( flagNodeDaemonHome = "node-daemon-home" flagNodeCLIHome = "node-cli-home" flagStartingIPAddress = "starting-ip-address" + flagCoinDenom = "coin-denom" flagKeyAlgo = "algo" ) @@ -77,10 +79,11 @@ Note, strict routability for addresses is turned off in the config file.`, nodeCLIHome, _ := cmd.Flags().GetString(flagNodeCLIHome) startingIPAddress, _ := cmd.Flags().GetString(flagStartingIPAddress) numValidators, _ := cmd.Flags().GetInt(flagNumValidators) + coinDenom, _ := cmd.Flags().GetString(flagCoinDenom) algo, _ := cmd.Flags().GetString(flagKeyAlgo) return InitTestnet( - cmd, config, cdc, mbm, genAccIterator, outputDir, chainID, minGasPrices, + cmd, config, cdc, mbm, genAccIterator, outputDir, chainID, coinDenom, minGasPrices, nodeDirPrefix, nodeDaemonHome, nodeCLIHome, startingIPAddress, keyringBackend, algo, numValidators, ) }, @@ -93,7 +96,8 @@ Note, strict routability for addresses is turned off in the config file.`, cmd.Flags().String(flagNodeCLIHome, "ethermintcli", "Home directory of the node's cli configuration") cmd.Flags().String(flagStartingIPAddress, "192.168.0.1", "Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)") cmd.Flags().String(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created") - cmd.Flags().String(server.FlagMinGasPrices, fmt.Sprintf("0.000006%s", types.DenomDefault), "Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01aphoton,0.001stake)") + cmd.Flags().String(flagCoinDenom, types.AttoPhoton, "Coin denomination used for staking, governance, mint, crisis and evm parameters") + cmd.Flags().String(server.FlagMinGasPrices, fmt.Sprintf("0.000006%s", types.AttoPhoton), "Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01aphoton,0.001stake)") cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)") cmd.Flags().String(flagKeyAlgo, string(crypto.EthSecp256k1), "Key signing algorithm to generate keys for") return cmd @@ -108,6 +112,7 @@ func InitTestnet( genAccIterator authtypes.GenesisAccountIterator, outputDir, chainID, + coinDenom, minGasPrices, nodeDirPrefix, nodeDaemonHome, @@ -122,6 +127,10 @@ func InitTestnet( chainID = fmt.Sprintf("%d", tmrand.Int63()) } + if err := sdk.ValidateDenom(coinDenom); err != nil { + return err + } + nodeIDs := make([]string, numValidators) valPubKeys := make([]tmcrypto.PubKey, numValidators) @@ -205,11 +214,9 @@ func InitTestnet( return err } - accTokens := sdk.TokensFromConsensusPower(1000) accStakingTokens := sdk.TokensFromConsensusPower(5000) coins := sdk.NewCoins( - sdk.NewCoin(sdk.DefaultBondDenom, accTokens), - sdk.NewCoin(types.DenomDefault, accStakingTokens), + sdk.NewCoin(coinDenom, accStakingTokens), ) genAccounts = append(genAccounts, types.EthAccount{ @@ -221,7 +228,7 @@ func InitTestnet( msg := stakingtypes.NewMsgCreateValidator( sdk.ValAddress(addr), valPubKeys[i], - sdk.NewCoin(types.DenomDefault, valTokens), + sdk.NewCoin(coinDenom, valTokens), stakingtypes.NewDescription(nodeDirName, "", "", "", ""), stakingtypes.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()), sdk.OneInt(), @@ -251,7 +258,7 @@ func InitTestnet( srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config/app.toml"), simappConfig) } - if err := initGenFiles(cdc, mbm, chainID, genAccounts, genFiles, numValidators); err != nil { + if err := initGenFiles(cdc, mbm, chainID, coinDenom, genAccounts, genFiles, numValidators); err != nil { return err } @@ -268,7 +275,8 @@ func InitTestnet( } func initGenFiles( - cdc *codec.Codec, mbm module.BasicManager, chainID string, + cdc *codec.Codec, mbm module.BasicManager, + chainID, coinDenom string, genAccounts []authexported.GenesisAccount, genFiles []string, numValidators int, ) error { @@ -285,27 +293,33 @@ func initGenFiles( var stakingGenState stakingtypes.GenesisState cdc.MustUnmarshalJSON(appGenState[stakingtypes.ModuleName], &stakingGenState) - stakingGenState.Params.BondDenom = types.DenomDefault + stakingGenState.Params.BondDenom = coinDenom appGenState[stakingtypes.ModuleName] = cdc.MustMarshalJSON(stakingGenState) var govGenState govtypes.GenesisState cdc.MustUnmarshalJSON(appGenState[govtypes.ModuleName], &govGenState) - govGenState.DepositParams.MinDeposit[0].Denom = types.DenomDefault + govGenState.DepositParams.MinDeposit[0].Denom = coinDenom appGenState[govtypes.ModuleName] = cdc.MustMarshalJSON(govGenState) var mintGenState mint.GenesisState cdc.MustUnmarshalJSON(appGenState[mint.ModuleName], &mintGenState) - mintGenState.Params.MintDenom = types.DenomDefault + mintGenState.Params.MintDenom = coinDenom appGenState[mint.ModuleName] = cdc.MustMarshalJSON(mintGenState) var crisisGenState crisis.GenesisState cdc.MustUnmarshalJSON(appGenState[crisis.ModuleName], &crisisGenState) - crisisGenState.ConstantFee.Denom = types.DenomDefault + crisisGenState.ConstantFee.Denom = coinDenom appGenState[crisis.ModuleName] = cdc.MustMarshalJSON(crisisGenState) + var evmGenState evmtypes.GenesisState + cdc.MustUnmarshalJSON(appGenState[evmtypes.ModuleName], &evmGenState) + + evmGenState.Params.EvmDenom = coinDenom + appGenState[evmtypes.ModuleName] = cdc.MustMarshalJSON(evmGenState) + appGenStateJSON, err := codec.MarshalJSONIndent(cdc, appGenState) if err != nil { return err diff --git a/importer/importer_test.go b/importer/importer_test.go index 9aebb305..85fb8e6b 100644 --- a/importer/importer_test.go +++ b/importer/importer_test.go @@ -150,7 +150,7 @@ func createAndTestGenesis(t *testing.T, cms sdk.CommitMultiStore, ak auth.Accoun genAcc := ak.GetAccount(ctx, sdk.AccAddress(genInvestor.Bytes())) require.NotNil(t, genAcc) - balance := sdk.NewCoin(types.DenomDefault, genAcc.GetCoins().AmountOf(types.DenomDefault)) + balance := types.NewPhotonCoin(genAcc.GetCoins().AmountOf(types.AttoPhoton)) require.Equal(t, sdk.NewIntFromBigInt(b), balance.Amount) } diff --git a/types/account.go b/types/account.go index 494445c6..b5b48009 100644 --- a/types/account.go +++ b/types/account.go @@ -51,20 +51,20 @@ func (acc EthAccount) EthAddress() ethcmn.Address { // Balance returns the balance of an account. func (acc EthAccount) Balance() sdk.Int { - return acc.GetCoins().AmountOf(DenomDefault) + return acc.GetCoins().AmountOf(AttoPhoton) } // SetBalance sets an account's balance of aphotons func (acc *EthAccount) SetBalance(amt sdk.Int) { coins := acc.GetCoins() - diff := amt.Sub(coins.AmountOf(DenomDefault)) + diff := amt.Sub(coins.AmountOf(AttoPhoton)) switch { case diff.IsPositive(): // Increase coins to amount - coins = coins.Add(sdk.NewCoin(DenomDefault, diff)) + coins = coins.Add(NewPhotonCoin(diff)) case diff.IsNegative(): // Decrease coins to amount - coins = coins.Sub(sdk.NewCoins(sdk.NewCoin(DenomDefault, diff.Neg()))) + coins = coins.Sub(sdk.NewCoins(NewPhotonCoin(diff.Neg()))) default: return } diff --git a/types/account_test.go b/types/account_test.go index 201bfe7d..976e9a46 100644 --- a/types/account_test.go +++ b/types/account_test.go @@ -24,7 +24,7 @@ func init() { func TestEthermintAccountJSON(t *testing.T) { pubkey := secp256k1.GenPrivKey().PubKey() addr := sdk.AccAddress(pubkey.Address()) - balance := sdk.NewCoins(sdk.NewCoin(DenomDefault, sdk.OneInt())) + balance := sdk.NewCoins(NewPhotonCoin(sdk.OneInt())) baseAcc := auth.NewBaseAccount(addr, balance, pubkey, 10, 50) ethAcc := EthAccount{BaseAccount: baseAcc, CodeHash: []byte{1, 2}} @@ -63,7 +63,7 @@ func TestSecpPubKeyJSON(t *testing.T) { func TestEthermintAccount_String(t *testing.T) { pubkey := secp256k1.GenPrivKey().PubKey() addr := sdk.AccAddress(pubkey.Address()) - balance := sdk.NewCoins(sdk.NewCoin(DenomDefault, sdk.OneInt())) + balance := sdk.NewCoins(NewPhotonCoin(sdk.OneInt())) baseAcc := auth.NewBaseAccount(addr, balance, pubkey, 10, 50) ethAcc := EthAccount{BaseAccount: baseAcc, CodeHash: []byte{1, 2}} @@ -100,7 +100,7 @@ func TestEthermintAccount_String(t *testing.T) { func TestEthermintAccount_MarshalJSON(t *testing.T) { pubkey := secp256k1.GenPrivKey().PubKey() addr := sdk.AccAddress(pubkey.Address()) - balance := sdk.NewCoins(sdk.NewCoin(DenomDefault, sdk.OneInt())) + balance := sdk.NewCoins(NewPhotonCoin(sdk.OneInt())) baseAcc := auth.NewBaseAccount(addr, balance, pubkey, 10, 50) ethAcc := &EthAccount{BaseAccount: baseAcc, CodeHash: []byte{1, 2}} diff --git a/types/coin.go b/types/coin.go new file mode 100644 index 00000000..d7e396ed --- /dev/null +++ b/types/coin.go @@ -0,0 +1,38 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + // AttoPhoton defines the default coin denomination used in Ethermint in: + // + // - Staking parameters: denomination used as stake in the dPoS chain + // - Mint parameters: denomination minted due to fee distribution rewards + // - Governance parameters: denomination used for spam prevention in proposal deposits + // - Crisis parameters: constant fee denomination used for spam prevention to check broken invariant + // - EVM parameters: denomination used for running EVM state transitions in Ethermint. + AttoPhoton string = "aphoton" + + // BaseDenomUnit defines the base denomination unit for Photons. + // 1 photon = 1x10^{BaseDenomUnit} aphoton + BaseDenomUnit = 18 +) + +// NewPhotonCoin is a utility function that returns an "aphoton" coin with the given sdk.Int amount. +// The function will panic if the provided amount is negative. +func NewPhotonCoin(amount sdk.Int) sdk.Coin { + return sdk.NewCoin(AttoPhoton, amount) +} + +// NewPhotonDecCoin is a utility function that returns an "aphoton" decimal coin with the given sdk.Int amount. +// The function will panic if the provided amount is negative. +func NewPhotonDecCoin(amount sdk.Int) sdk.DecCoin { + return sdk.NewDecCoin(AttoPhoton, amount) +} + +// NewPhotonCoinInt64 is a utility function that returns an "aphoton" coin with the given int64 amount. +// The function will panic if the provided amount is negative. +func NewPhotonCoinInt64(amount int64) sdk.Coin { + return sdk.NewInt64Coin(AttoPhoton, amount) +} diff --git a/types/params.go b/types/params.go index 020452ad..de577b1b 100644 --- a/types/params.go +++ b/types/params.go @@ -5,8 +5,4 @@ const ( DefaultGasPrice = 20 // DefaultRPCGasLimit is default gas limit for RPC call operations DefaultRPCGasLimit = 10000000 - - // DenomDefault defines the single coin type/denomination supported in - // Ethermint. - DenomDefault = "aphoton" ) diff --git a/x/evm/keeper/keeper_test.go b/x/evm/keeper/keeper_test.go index 2483ff06..09943fe9 100644 --- a/x/evm/keeper/keeper_test.go +++ b/x/evm/keeper/keeper_test.go @@ -46,7 +46,7 @@ func (suite *KeeperTestSuite) SetupTest() { suite.querier = keeper.NewQuerier(suite.app.EvmKeeper) suite.address = ethcmn.HexToAddress(addrHex) - balance := sdk.NewCoins(sdk.NewCoin(ethermint.DenomDefault, sdk.NewInt(0))) + balance := sdk.NewCoins(ethermint.NewPhotonCoin(sdk.ZeroInt())) acc := ðermint.EthAccount{ BaseAccount: auth.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), balance, nil, 0, 0), CodeHash: ethcrypto.Keccak256(nil), diff --git a/x/evm/types/journal_test.go b/x/evm/types/journal_test.go index 5be019b7..5c5fc7c2 100644 --- a/x/evm/types/journal_test.go +++ b/x/evm/types/journal_test.go @@ -57,7 +57,7 @@ func (suite *JournalTestSuite) SetupTest() { suite.address = ethcmn.BytesToAddress(privkey.PubKey().Address().Bytes()) suite.journal = newJournal() - balance := sdk.NewCoins(sdk.NewCoin(ethermint.DenomDefault, sdk.NewInt(100))) + balance := sdk.NewCoins(ethermint.NewPhotonCoin(sdk.NewInt(100))) acc := ðermint.EthAccount{ BaseAccount: auth.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), balance, nil, 0, 0), CodeHash: ethcrypto.Keccak256(nil), diff --git a/x/evm/types/params.go b/x/evm/types/params.go index 59d837d9..a6c5ad3d 100644 --- a/x/evm/types/params.go +++ b/x/evm/types/params.go @@ -41,7 +41,7 @@ func NewParams(evmDenom string) Params { // DefaultParams returns default evm parameters func DefaultParams() Params { return Params{ - EvmDenom: ethermint.DenomDefault, + EvmDenom: ethermint.AttoPhoton, } } diff --git a/x/evm/types/state_transition_test.go b/x/evm/types/state_transition_test.go index 9196469b..f096c610 100644 --- a/x/evm/types/state_transition_test.go +++ b/x/evm/types/state_transition_test.go @@ -17,7 +17,7 @@ func (suite *StateDBTestSuite) TestTransitionDb() { suite.stateDB.SetNonce(suite.address, 123) addr := sdk.AccAddress(suite.address.Bytes()) - balance := sdk.NewCoin(ethermint.DenomDefault, sdk.NewInt(5000)) + balance := ethermint.NewPhotonCoin(sdk.NewInt(5000)) acc := suite.app.AccountKeeper.GetAccount(suite.ctx, addr) _ = acc.SetCoins(sdk.NewCoins(balance)) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) @@ -108,7 +108,7 @@ func (suite *StateDBTestSuite) TestTransitionDb() { "nil gas price", func() { invalidGas := sdk.DecCoins{ - {Denom: ethermint.DenomDefault}, + {Denom: ethermint.AttoPhoton}, } suite.ctx = suite.ctx.WithMinGasPrices(invalidGas) }, diff --git a/x/evm/types/statedb_test.go b/x/evm/types/statedb_test.go index 455da85d..8904e7a2 100644 --- a/x/evm/types/statedb_test.go +++ b/x/evm/types/statedb_test.go @@ -48,7 +48,7 @@ func (suite *StateDBTestSuite) SetupTest() { suite.address = ethcmn.BytesToAddress(privkey.PubKey().Address().Bytes()) - balance := sdk.NewCoins(sdk.NewCoin(ethermint.DenomDefault, sdk.NewInt(0))) + balance := sdk.NewCoins(ethermint.NewPhotonCoin(sdk.ZeroInt())) acc := ðermint.EthAccount{ BaseAccount: auth.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), balance, nil, 0, 0), CodeHash: ethcrypto.Keccak256(nil),