diff --git a/CHANGELOG.md b/CHANGELOG.md index dbf2c4407..5d1978fd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,8 @@ ### Features * (IRISHub) [\#2908](https://github.com/irisnet/irishub/pull/2908) Add ICA module. -* (IRISHub) [\#2909](https://github.com/irisnet/irishub/pull/2909) Add cosmos LSM. +* (IRISHub) [\#2909](https://github.com/irisnet/irishub/pull/2909) Add Cosmos LSM module. +* (IRISHub) [\#2925](https://github.com/irisnet/irishub/pull/2925) Enhance token module. ### Improvements diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 6b65ec441..579d6ac3a 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -111,6 +111,7 @@ import ( mintkeeper "github.com/irisnet/irishub/v3/modules/mint/keeper" minttypes "github.com/irisnet/irishub/v3/modules/mint/types" iristypes "github.com/irisnet/irishub/v3/types" + "github.com/irisnet/irishub/v3/wrapper" ) // AppKeepers defines a structure used to consolidate all @@ -440,23 +441,6 @@ func New( appKeepers.keys[guardiantypes.StoreKey], ) - appKeepers.TokenKeeper = tokenkeeper.NewKeeper( - appCodec, - appKeepers.keys[tokentypes.StoreKey], - appKeepers.BankKeeper, - authtypes.FeeCollectorName, - authtypes.NewModuleAddress(govtypes.ModuleName).String(), - ).WithSwapRegistry(tokenv1.SwapRegistry{ - iristypes.NativeToken.MinUnit: tokenv1.SwapParams{ - MinUnit: iristypes.EvmToken.MinUnit, - Ratio: sdk.OneDec(), - }, - iristypes.EvmToken.MinUnit: tokenv1.SwapParams{ - MinUnit: iristypes.NativeToken.MinUnit, - Ratio: sdk.OneDec(), - }, - }) - appKeepers.RecordKeeper = recordkeeper.NewKeeper( appCodec, appKeepers.keys[recordtypes.StoreKey], @@ -534,7 +518,7 @@ func New( AddRoute(farmtypes.RouterKey, farm.NewCommunityPoolCreateFarmProposalHandler(appKeepers.FarmKeeper)) appKeepers.GovKeeper.SetHooks(govtypes.NewMultiGovHooks( - farmkeeper.NewGovHook(appKeepers.FarmKeeper), + wrapper.NewFarmGovHook(farmkeeper.NewGovHook(appKeepers.FarmKeeper)), )) appKeepers.GovKeeper.SetLegacyRouter(govRouter) @@ -561,6 +545,27 @@ func New( cast.ToString(appOpts.Get(srvflags.EVMTracer)), appKeepers.GetSubspace(evmtypes.ModuleName), ) + + appKeepers.TokenKeeper = tokenkeeper.NewKeeper( + appCodec, + appKeepers.keys[tokentypes.StoreKey], + appKeepers.BankKeeper, + appKeepers.AccountKeeper, + wrapper.NewEVMKeeper(appKeepers.EvmKeeper), + wrapper.NewICS20Keeper(appKeepers.IBCTransferKeeper), + authtypes.FeeCollectorName, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + ).WithSwapRegistry(tokenv1.SwapRegistry{ + iristypes.NativeToken.MinUnit: tokenv1.SwapParams{ + MinUnit: iristypes.EvmToken.MinUnit, + Ratio: sdk.OneDec(), + }, + iristypes.EvmToken.MinUnit: tokenv1.SwapParams{ + MinUnit: iristypes.NativeToken.MinUnit, + Ratio: sdk.OneDec(), + }, + }) + appKeepers.EvmKeeper = appKeepers.EvmKeeper.SetHooks(appKeepers.TokenKeeper.Hooks()) return appKeepers } diff --git a/app/upgrades/v300/constants.go b/app/upgrades/v300/constants.go index afb13b632..a97a83207 100644 --- a/app/upgrades/v300/constants.go +++ b/app/upgrades/v300/constants.go @@ -16,5 +16,8 @@ var ( // the portion of a chain's total stake can be liquid GlobalLiquidStakingCap = sdk.MustNewDecFromStr("0.25") // 25% + // BeaconContractAddress is the address of the beacon contract + BeaconContractAddress = "" + allowMessages = []string{"*"} ) diff --git a/app/upgrades/v300/upgrades.go b/app/upgrades/v300/upgrades.go index 736542743..b4d559ded 100644 --- a/app/upgrades/v300/upgrades.go +++ b/app/upgrades/v300/upgrades.go @@ -33,6 +33,10 @@ func upgradeHandlerConstructor( if err := mergeEVM(ctx, box); err != nil { return nil, err } + + if err := mergeToken(ctx, box); err != nil { + return nil, err + } // initialize ICS27 module initICAModule(ctx, m, fromVM) @@ -71,3 +75,12 @@ func mergeEVM(ctx sdk.Context, box upgrades.Toolbox) error { params.AllowUnprotectedTxs = true return box.EvmKeeper.SetParams(ctx, params) } + +func mergeToken(ctx sdk.Context, box upgrades.Toolbox) error { + ctx.Logger().Info("start to run token module migrations...") + + params := box.TokenKeeper.GetParams(ctx) + params.EnableErc20 = true + params.Beacon = BeaconContractAddress + return box.TokenKeeper.SetParams(ctx, params) +} diff --git a/cmd/iris/cmd/testnet.go b/cmd/iris/cmd/testnet.go index 5884edd9b..4022862f8 100644 --- a/cmd/iris/cmd/testnet.go +++ b/cmd/iris/cmd/testnet.go @@ -249,17 +249,13 @@ func InitTestnet( return err } - accTokens := sdk.TokensFromConsensusPower(1000, sdk.DefaultPowerReduction) - accStakingTokens := sdk.TokensFromConsensusPower(500, sdk.DefaultPowerReduction) - accEvmTokens := sdk.TokensFromConsensusPower(5000, PowerReduction) - accIrisTokens := sdk.TokensFromConsensusPower(5000, sdk.DefaultPowerReduction) + accStakingTokens := sdk.TokensFromConsensusPower(15e8, sdk.DefaultPowerReduction) + accEvmTokens := sdk.TokensFromConsensusPower(5e8, PowerReduction) - coins := sdk.Coins{ - sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), accTokens), + coins := sdk.NewCoins( sdk.NewCoin(sdk.DefaultBondDenom, accStakingTokens), sdk.NewCoin(iristypes.EvmToken.MinUnit, accEvmTokens), - sdk.NewCoin(nativeIrisMinUnit, accIrisTokens), - } + ) genBalances = append( genBalances, diff --git a/go.mod b/go.mod index e703ec7ac..31b84c3dd 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/cosmos/iavl v0.20.1 // indirect github.com/cosmos/ibc-go/v7 v7.3.0 github.com/evmos/ethermint v0.22.0 - github.com/irisnet/irismod v1.8.1-0.20240304075720-718d99d97674 //release/v1.8.0-lsm + github.com/irisnet/irismod v1.8.1-0.20240422082845-aafd2bd851f9 //release/v1.8.0-lsm ) require ( @@ -232,6 +232,6 @@ require ( replace github.com/zondax/hid => github.com/zondax/hid v0.9.0 // use bianjieai fork of ethermint -replace github.com/evmos/ethermint => github.com/bianjieai/ethermint v0.22.0-irishub-20231207.0.20240403080035-de4b07ecf255 //release/v0.2…20231207-lsm +replace github.com/evmos/ethermint => github.com/bianjieai/ethermint v0.22.0-irishub-20231207.0.20240419023144-3cea3d782107 //release/v0.2…20231207-lsm replace github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/go.sum b/go.sum index 37f0bf16d..2b3feea83 100644 --- a/go.sum +++ b/go.sum @@ -295,8 +295,8 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2gVpmOtVTJZNodLdLQLn/KsJqFvXwnd/s= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bianjieai/ethermint v0.22.0-irishub-20231207.0.20240403080035-de4b07ecf255 h1:Rngrww/saMItIkpSozg5poBQiRHsE52iZnio5zII8EQ= -github.com/bianjieai/ethermint v0.22.0-irishub-20231207.0.20240403080035-de4b07ecf255/go.mod h1:x9BFez6AUL9Yksv4zZd3QLmSazwOkyNd3h2zFV2B4RU= +github.com/bianjieai/ethermint v0.22.0-irishub-20231207.0.20240419023144-3cea3d782107 h1:ssrDDPlhLILV0UaQD+D/mRqAvQ5FeQrWB3lltaP5YTc= +github.com/bianjieai/ethermint v0.22.0-irishub-20231207.0.20240419023144-3cea3d782107/go.mod h1:x9BFez6AUL9Yksv4zZd3QLmSazwOkyNd3h2zFV2B4RU= github.com/bianjieai/nft-transfer v1.1.3-ibc-v7.3.0 h1:399lErsTpI+faTerw5Q4OuVlXAmAQSuibVvxHR3C6OY= github.com/bianjieai/nft-transfer v1.1.3-ibc-v7.3.0/go.mod h1:u2PNH4v8CD4AWU4Rf7yt8/qqQtrrwwHiw03qQSKERhg= github.com/bianjieai/tibc-go v0.5.0 h1:/J1OQe4gwUUkS3Q6+nm0EsTY7MNAOPNzfnpvgIWlvKM= @@ -846,8 +846,8 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= -github.com/irisnet/irismod v1.8.1-0.20240304075720-718d99d97674 h1:7fBGecB0olPrkoeY0Y7wn202BQ4Q2zF8o+KwYFzNYQs= -github.com/irisnet/irismod v1.8.1-0.20240304075720-718d99d97674/go.mod h1:kvPd2HckP0Mr4BZRtUa2RjDNH1EfOP3xHESHRIXayOY= +github.com/irisnet/irismod v1.8.1-0.20240422082845-aafd2bd851f9 h1:5uvIKhg55Y82su5FX3A4KT64sc89u0kEhacUMdhVIQc= +github.com/irisnet/irismod v1.8.1-0.20240422082845-aafd2bd851f9/go.mod h1:TQDhEmxqCIzo7OjyNy//UI0xKDuMtONjoy5LzUeRhVo= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= diff --git a/modules/evm/keeper.go b/modules/evm/keeper.go index 6d5028e76..860f3402b 100644 --- a/modules/evm/keeper.go +++ b/modules/evm/keeper.go @@ -21,7 +21,6 @@ import ( type Keeper struct { evmkeeper *evmkeeper.Keeper bankKeeper types.BankKeeper - hasHook bool } var _ types.MsgServer = &Keeper{} @@ -139,15 +138,10 @@ func (k *Keeper) EthereumTx( return response, nil } -// SetHooks sets the hooks for the EVM module -// It should be called only once during initialization, it panic if called more than once. -func (k *Keeper) SetHooks(eh types.EvmHooks) *Keeper { - return &Keeper{ - evmkeeper: k.evmkeeper.SetHooks(eh), - hasHook: true, - } -} - +// UpdateParams updates the parameters for the EVM module. +// +// It takes a context.Context object and a *types.MsgUpdateParams object as parameters. +// The function returns a *types.MsgUpdateParamsResponse object and an error. func (k *Keeper) UpdateParams( goCtx context.Context, msg *types.MsgUpdateParams, diff --git a/modules/evm/moudle.go b/modules/evm/moudle.go index 5117f75ce..7bbeb3478 100644 --- a/modules/evm/moudle.go +++ b/modules/evm/moudle.go @@ -30,7 +30,7 @@ func NewAppModule( ) AppModule { return AppModule{ AppModule: ethermint.NewAppModule(k, ak, ss), - k: &Keeper{k, bankKeeper, false}, + k: &Keeper{k, bankKeeper}, ss: ss, } } diff --git a/modules/evm/state_transition.go b/modules/evm/state_transition.go index 7c1156ae7..f710dc47d 100644 --- a/modules/evm/state_transition.go +++ b/modules/evm/state_transition.go @@ -59,7 +59,7 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction, fee // snapshot to contain the tx processing and post processing in same scope var commit func() tmpCtx := ctx - if k.hasHook { + if k.evmkeeper.Hooks() != nil { // Create a cache context to revert state when tx hooks fails, // the cache context is only committed when both tx and hooks executed successfully. // Didn't use `Snapshot` because the context stack has exponential complexity on certain operations, diff --git a/modules/mint/client/cli/cli_test.go b/modules/mint/client/cli/cli_test.go index a49c19842..001efbe85 100644 --- a/modules/mint/client/cli/cli_test.go +++ b/modules/mint/client/cli/cli_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/cosmos/cosmos-sdk/testutil/network" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/suite" @@ -52,6 +53,6 @@ func (s *IntegrationTestSuite) TestMint() { s.Require().NoError(err) s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(bz.Bytes(), respType)) params := respType.(*minttypes.Params) - s.Require().Equal("stake", params.MintDenom) + s.Require().Equal(sdk.DefaultBondDenom, params.MintDenom) s.Require().Equal("0.040000000000000000", params.Inflation.String()) } diff --git a/modules/mint/simulation/genesis.go b/modules/mint/simulation/genesis.go index 9d18523f4..6bbd698c8 100644 --- a/modules/mint/simulation/genesis.go +++ b/modules/mint/simulation/genesis.go @@ -32,7 +32,7 @@ func RandomizedGenState(simState *module.SimulationState) { func(r *rand.Rand) { inflation = GenInflation(r) }, ) - params := types.Params{Inflation: inflation, MintDenom: types.MintDenom} + params := types.Params{Inflation: inflation, MintDenom: sdk.DefaultBondDenom} mintGenesis := types.NewGenesisState(types.DefaultMinter(), params) bz, err := json.MarshalIndent(&mintGenesis, "", " ") diff --git a/modules/mint/types/params.go b/modules/mint/types/params.go index a7fb4505a..3882ccb70 100644 --- a/modules/mint/types/params.go +++ b/modules/mint/types/params.go @@ -22,7 +22,6 @@ var ( // params store for inflation params KeyInflation = []byte("Inflation") KeyMintDenom = []byte("MintDenom") - MintDenom = sdk.DefaultBondDenom ) // ParamTable for mint module @@ -41,7 +40,7 @@ func NewParams(mintDenom string, inflation sdk.Dec) Params { func DefaultParams() Params { return Params{ Inflation: sdk.NewDecWithPrec(4, 2), - MintDenom: MintDenom, + MintDenom: sdk.DefaultBondDenom, } } diff --git a/types/runtime.go b/types/runtime.go index fb04585c0..99a60c58c 100644 --- a/types/runtime.go +++ b/types/runtime.go @@ -62,6 +62,8 @@ func init() { Mintable: true, Owner: sdk.AccAddress(crypto.AddressHash([]byte(tokentypes.ModuleName))).String(), } + sdk.DefaultBondDenom = NativeToken.MinUnit + userHomeDir, err := os.UserHomeDir() if err != nil { diff --git a/wrapper/farm.go b/wrapper/farm.go new file mode 100644 index 000000000..624b29411 --- /dev/null +++ b/wrapper/farm.go @@ -0,0 +1,53 @@ +package wrapper + +import ( + "github.com/cosmos/cosmos-sdk/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + farmkeeper "github.com/irisnet/irismod/modules/farm/keeper" +) + +var _ govtypes.GovHooks = farmGovHook{} + +type farmGovHook struct { + gh farmkeeper.GovHook +} + +// NewFarmGovHook creates a new farmGovHook instance. +// +// It takes a parameter of type farmkeeper.GovHook and returns a farmGovHook. +func NewFarmGovHook(gh farmkeeper.GovHook) govtypes.GovHooks { + return farmGovHook{ + gh: gh, + } +} + +// AfterProposalDeposit implements types.GovHooks. +func (f farmGovHook) AfterProposalDeposit(ctx types.Context, proposalID uint64, depositorAddr types.AccAddress) error { + f.gh.AfterProposalDeposit(ctx, proposalID, depositorAddr) + return nil +} + +// AfterProposalFailedMinDeposit implements types.GovHooks. +func (f farmGovHook) AfterProposalFailedMinDeposit(ctx types.Context, proposalID uint64) error { + f.gh.AfterProposalFailedMinDeposit(ctx, proposalID) + return nil +} + +// AfterProposalSubmission implements types.GovHooks. +func (f farmGovHook) AfterProposalSubmission(ctx types.Context, proposalID uint64) error { + f.gh.AfterProposalSubmission(ctx, proposalID) + return nil +} + +// AfterProposalVote implements types.GovHooks. +func (f farmGovHook) AfterProposalVote(ctx types.Context, proposalID uint64, voterAddr types.AccAddress) error { + f.gh.AfterProposalVote(ctx, proposalID,voterAddr) + return nil +} + +// AfterProposalVotingPeriodEnded implements types.GovHooks. +func (f farmGovHook) AfterProposalVotingPeriodEnded(ctx types.Context, proposalID uint64) error { + f.gh.AfterProposalVotingPeriodEnded(ctx, proposalID) + return nil +} diff --git a/wrapper/token.go b/wrapper/token.go new file mode 100644 index 000000000..0ced2b5f0 --- /dev/null +++ b/wrapper/token.go @@ -0,0 +1,110 @@ +package wrapper + +import ( + "context" + "math/big" + "strings" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/vm" + + "github.com/evmos/ethermint/crypto/ethsecp256k1" + evmkeeper "github.com/evmos/ethermint/x/evm/keeper" + evmtypes "github.com/evmos/ethermint/x/evm/types" + + ibctransferkeeper "github.com/cosmos/ibc-go/v7/modules/apps/transfer/keeper" + ibctransfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + + tokentypes "github.com/irisnet/irismod/modules/token/types" + irismodtypes "github.com/irisnet/irismod/types" +) + +var ( + _ tokentypes.EVMKeeper = (*evmKeeper)(nil) + _ tokentypes.ICS20Keeper = (*ics20Keeper)(nil) +) + +// NewEVMKeeper wraps the given evmkeeper.Keeper and returns a new evmKeeper. +// +// ek: The evmkeeper.Keeper to be wrapped. +// Returns a pointer to the wrapped evmKeeper. +func NewEVMKeeper(ek *evmkeeper.Keeper) tokentypes.EVMKeeper { + return &evmKeeper{ek: ek} +} + +type evmKeeper struct { + ek *evmkeeper.Keeper +} + +// ApplyMessage implements types.EVMKeeper. +func (e *evmKeeper) ApplyMessage(ctx sdk.Context, msg core.Message, tracer vm.EVMLogger, commit bool) (*irismodtypes.Result, error) { + res, err := e.ek.ApplyMessage(ctx, msg, tracer, commit) + if err != nil { + return nil, err + } + return &irismodtypes.Result{ + Hash: res.Hash, + Logs: evmtypes.LogsToEthereum(res.Logs), + Ret: res.Ret, + VMError: res.VmError, + GasUsed: res.GasUsed, + }, nil +} + +// ChainID implements types.EVMKeeper. +func (e *evmKeeper) ChainID() *big.Int { + return e.ek.ChainID() +} + +// EstimateGas implements types.EVMKeeper. +func (e *evmKeeper) EstimateGas(ctx context.Context, req *irismodtypes.EthCallRequest) (uint64, error) { + res, err := e.ek.EstimateGas(ctx, &evmtypes.EthCallRequest{ + Args: req.Args, + GasCap: req.GasCap, + ProposerAddress: req.ProposerAddress, + ChainId: req.ChainID, + }) + if err != nil { + return 0, err + } + return res.Gas, nil +} + +// SupportedKey implements types.EVMKeeper. +func (e *evmKeeper) SupportedKey(pubKey cryptotypes.PubKey) bool { + // NOTICE: when the account has not executed native transactions, the pubkey is empty. + if pubKey == nil { + return true + } + + _, ok := pubKey.(*ethsecp256k1.PubKey) + return ok +} + +// NewICS20Keeper wraps the given ibctransferkeeper.Keeper into an ics20Keeper. +// +// Parameters: +// - ik: the ibctransferkeeper.Keeper to be wrapped. +// +// Return: +// - *ics20Keeper: the wrapped ics20Keeper. +func NewICS20Keeper(ik ibctransferkeeper.Keeper) tokentypes.ICS20Keeper { + return &ics20Keeper{ik: ik} +} + +type ics20Keeper struct { + ik ibctransferkeeper.Keeper +} + +// HasTrace implements types.ICS20Keeper. +func (i *ics20Keeper) HasTrace(ctx sdk.Context, denom string) bool { + hash, err := ibctransfertypes.ParseHexHash(strings.TrimPrefix(denom, "ibc/")) + if err != nil { + return false + } + _, has := i.ik.GetDenomTrace(ctx, hash) + return has +}