Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add token factory module #1318

Merged
merged 9 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
66 changes: 44 additions & 22 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ import (
skywayclient "github.com/palomachain/paloma/v2/x/skyway/client"
skywaymodulekeeper "github.com/palomachain/paloma/v2/x/skyway/keeper"
skywaymoduletypes "github.com/palomachain/paloma/v2/x/skyway/types"
"github.com/palomachain/paloma/v2/x/tokenfactory"
tokenfactorymodulekeeper "github.com/palomachain/paloma/v2/x/tokenfactory/keeper"
tokenfactorymoduletypes "github.com/palomachain/paloma/v2/x/tokenfactory/types"
treasurymodule "github.com/palomachain/paloma/v2/x/treasury"
treasuryclient "github.com/palomachain/paloma/v2/x/treasury/client"
treasurymodulekeeper "github.com/palomachain/paloma/v2/x/treasury/keeper"
Expand Down Expand Up @@ -178,19 +181,20 @@ var (

// module account permissions
maccPerms = map[string][]string{
authtypes.FeeCollectorName: nil,
distrtypes.ModuleName: nil,
minttypes.ModuleName: {authtypes.Minter},
stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking},
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
govtypes.ModuleName: {authtypes.Burner},
skywaymoduletypes.ModuleName: {authtypes.Minter, authtypes.Burner},
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
ibcfeetypes.ModuleName: nil,
icatypes.ModuleName: nil,
wasmtypes.ModuleName: {authtypes.Burner},
treasurymoduletypes.ModuleName: {authtypes.Burner, authtypes.Minter},
palomamoduletypes.ModuleName: nil,
authtypes.FeeCollectorName: nil,
distrtypes.ModuleName: nil,
minttypes.ModuleName: {authtypes.Minter},
stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking},
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
govtypes.ModuleName: {authtypes.Burner},
skywaymoduletypes.ModuleName: {authtypes.Minter, authtypes.Burner},
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
ibcfeetypes.ModuleName: nil,
icatypes.ModuleName: nil,
wasmtypes.ModuleName: {authtypes.Burner},
treasurymoduletypes.ModuleName: {authtypes.Burner, authtypes.Minter},
palomamoduletypes.ModuleName: nil,
tokenfactorymoduletypes.ModuleName: {authtypes.Minter, authtypes.Burner},
}
)

Expand Down Expand Up @@ -250,15 +254,16 @@ type App struct {
ICAHostKeeper icahostkeeper.Keeper
TransferKeeper ibctransferkeeper.Keeper

SchedulerKeeper schedulermodulekeeper.Keeper
ConsensusKeeper consensusmodulekeeper.Keeper
ValsetKeeper valsetmodulekeeper.Keeper
PalomaKeeper palomamodulekeeper.Keeper
TreasuryKeeper treasurymodulekeeper.Keeper
EvmKeeper evmmodulekeeper.Keeper
SkywayKeeper skywaymodulekeeper.Keeper
wasmKeeper wasmkeeper.Keeper
MetrixKeeper metrixmodulekeeper.Keeper
SchedulerKeeper schedulermodulekeeper.Keeper
ConsensusKeeper consensusmodulekeeper.Keeper
ValsetKeeper valsetmodulekeeper.Keeper
PalomaKeeper palomamodulekeeper.Keeper
TreasuryKeeper treasurymodulekeeper.Keeper
EvmKeeper evmmodulekeeper.Keeper
SkywayKeeper skywaymodulekeeper.Keeper
wasmKeeper wasmkeeper.Keeper
MetrixKeeper metrixmodulekeeper.Keeper
TokenFactoryKeeper tokenfactorymodulekeeper.Keeper

// ModuleManager is the module manager
ModuleManager *module.Manager
Expand Down Expand Up @@ -342,6 +347,7 @@ func New(
wasmtypes.StoreKey,
palomamoduletypes.StoreKey,
authzkeeper.StoreKey,
tokenfactorymoduletypes.StoreKey,
)
tkeys := storetypes.NewTransientStoreKeys(paramstypes.TStoreKey)
memKeys := storetypes.NewMemoryStoreKeys(
Expand All @@ -353,6 +359,7 @@ func New(
treasurymoduletypes.MemStoreKey,
palomamoduletypes.MemStoreKey,
metrixmoduletypes.MemStoreKey,
tokenfactorymoduletypes.MemStoreKey,
)

app := &App{
Expand Down Expand Up @@ -618,6 +625,14 @@ func New(
app.EvmKeeper,
}

app.TokenFactoryKeeper = tokenfactorymodulekeeper.NewKeeper(
keys[tokenfactorymoduletypes.StoreKey],
app.GetSubspace(tokenfactorymoduletypes.ModuleName),
app.AccountKeeper,
app.BankKeeper,
app.DistrKeeper,
authorityAddress)

app.SkywayKeeper = skywaymodulekeeper.NewKeeper(
appCodec,
app.AccountKeeper,
Expand All @@ -629,6 +644,7 @@ func New(
app.EvmKeeper,
app.ConsensusKeeper,
app.PalomaKeeper,
app.TokenFactoryKeeper,
skywaymodulekeeper.NewSkywayStoreGetter(keys[skywaymoduletypes.StoreKey]),
authorityAddress,
authcodec.NewBech32Codec(chainparams.ValidatorAddressPrefix),
Expand Down Expand Up @@ -804,6 +820,7 @@ func New(
skywayModule := skywaymodule.NewAppModule(appCodec, app.SkywayKeeper, app.BankKeeper, app.GetSubspace(skywaymoduletypes.ModuleName), libcons.New(app.ValsetKeeper.GetCurrentSnapshot, appCodec))
treasuryModule := treasurymodule.NewAppModule(appCodec, app.TreasuryKeeper, app.AccountKeeper, app.BankKeeper)
metrixModule := metrix.NewAppModule(appCodec, app.MetrixKeeper)
tokenfactorymodule := tokenfactory.NewAppModule(app.TokenFactoryKeeper, app.AccountKeeper, app.BankKeeper)

stakingAppModule := staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName))

Expand Down Expand Up @@ -836,6 +853,7 @@ func New(
palomaModule,
treasuryModule,
metrixModule,
tokenfactorymodule,
wasm.NewAppModule(appCodec, &app.wasmKeeper, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.MsgServiceRouter(), app.GetSubspace(wasmtypes.ModuleName)),
ibc.NewAppModule(app.IBCKeeper),
transfer.NewAppModule(app.TransferKeeper),
Expand Down Expand Up @@ -894,6 +912,7 @@ func New(
ibcfeetypes.ModuleName,
consensusparamtypes.ModuleName,
metrixmoduletypes.ModuleName,
tokenfactorymoduletypes.ModuleName,
)

app.ModuleManager.SetOrderEndBlockers(
Expand Down Expand Up @@ -927,6 +946,7 @@ func New(
treasurymoduletypes.ModuleName,
consensusparamtypes.ModuleName,
metrixmoduletypes.ModuleName,
tokenfactorymoduletypes.ModuleName,
)

// NOTE: The genutils module must occur after staking so that pools are
Expand Down Expand Up @@ -966,6 +986,7 @@ func New(
treasurymoduletypes.ModuleName,
consensusparamtypes.ModuleName,
metrixmoduletypes.ModuleName,
tokenfactorymoduletypes.ModuleName,
)

app.configurator = module.NewConfigurator(appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())
Expand Down Expand Up @@ -1238,6 +1259,7 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino
paramsKeeper.Subspace(evmmoduletypes.ModuleName)
paramsKeeper.Subspace(skywaymoduletypes.ModuleName).WithKeyTable(skywaymoduletypes.ParamKeyTable())
paramsKeeper.Subspace(metrixmoduletypes.ModuleName)
paramsKeeper.Subspace(tokenfactorymoduletypes.ModuleName)

paramsKeeper.Subspace(ibcexported.ModuleName).WithKeyTable(keyTable)
paramsKeeper.Subspace(ibctransfertypes.ModuleName).WithKeyTable(ibctransfertypes.ParamKeyTable())
Expand Down
12 changes: 12 additions & 0 deletions app/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
metrixmoduletypes "github.com/palomachain/paloma/v2/x/metrix/types"
palomamoduletypes "github.com/palomachain/paloma/v2/x/paloma/types"
skywaymoduletypes "github.com/palomachain/paloma/v2/x/skyway/types"
tokenfactorymoduletypes "github.com/palomachain/paloma/v2/x/tokenfactory/types"
)

var minCommissionRate = math.LegacyMustNewDecFromStr("0.05")
Expand Down Expand Up @@ -172,6 +173,17 @@ func (app *App) RegisterUpgradeHandlers(semverVersion string) {
app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades))
}

if upgradeInfo.Name == "v2.4.0" && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) {
storeUpgrades := storetypes.StoreUpgrades{
Added: []string{
tokenfactorymoduletypes.StoreKey,
},
}

// configure store loader that checks if version == upgradeHeight and applies store upgrades
app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades))
}

app.UpgradeKeeper.SetUpgradeHandler(semverVersion, func(ctx context.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
return app.ModuleManager.RunMigrations(ctx, app.configurator, fromVM)
})
Expand Down
22 changes: 22 additions & 0 deletions proto/palomachain/paloma/skyway/msgs.proto
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ service Msg {
"/palomachain/paloma/skyway/light-node-sale-claim";
}

rpc SetERC20ToTokenDenom(MsgSetERC20ToTokenDenom)
returns (google.protobuf.Empty) {
option (google.api.http).post =
"/palomachain/paloma/skyway/erc20-to-token-denom";
}

rpc OverrideNonceProposal(MsgNonceOverrideProposal) returns (google.protobuf.Empty);
}

Expand Down Expand Up @@ -303,3 +309,19 @@ message MsgEstimateBatchGas {
string eth_signer = 4;
uint64 estimate = 5;
}

// MsgSetERC20ToTokenDenom is a message to set the mapping between an ERC20 token
// and a denom created by the token factory.
// Needs admin rights on the token to set the mapping.
message MsgSetERC20ToTokenDenom {
option (cosmos.msg.v1.signer) = "metadata";

palomachain.paloma.valset.MsgMetadata metadata = 1
[
(gogoproto.moretags) = "yaml:\"metadata\"",
(gogoproto.nullable) = false
];
string denom = 2 [ (gogoproto.moretags) = "yaml:\"denom\"" ];
string chain_reference_id = 3 [ (gogoproto.moretags) = "yaml:\"chain_reference_id\"" ];
string erc20 = 4 [ (gogoproto.moretags) = "yaml:\"erc20\"" ];
}
21 changes: 21 additions & 0 deletions proto/palomachain/paloma/tokenfactory/authorityMetadata.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
syntax = "proto3";
package palomachain.paloma.tokenfactory;

import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";
import "cosmos_proto/cosmos.proto";

option go_package = "github.com/palomachain/paloma/v2/x/tokenfactory/types";

// DenomAuthorityMetadata specifies metadata for addresses that have specific
// capabilities over a token factory denom. Right now there is only one Admin
// permission, but is planned to be extended to the future.
message DenomAuthorityMetadata {
option (gogoproto.equal) = true;

// Can be empty for no admin, or a valid paloma address
string admin = 1 [
(gogoproto.moretags) = "yaml:\"admin\"",
(cosmos_proto.scalar) = "cosmos.AddressString"
];
}
32 changes: 32 additions & 0 deletions proto/palomachain/paloma/tokenfactory/genesis.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
syntax = "proto3";
package palomachain.paloma.tokenfactory;

import "gogoproto/gogo.proto";
import "palomachain/paloma/tokenfactory/authorityMetadata.proto";
import "palomachain/paloma/tokenfactory/params.proto";

option go_package = "github.com/palomachain/paloma/v2/x/tokenfactory/types";

// GenesisState defines the tokenfactory module's genesis state.
message GenesisState {
// params defines the paramaters of the module.
Params params = 1 [ (gogoproto.nullable) = false ];

repeated GenesisDenom factory_denoms = 2 [
(gogoproto.moretags) = "yaml:\"factory_denoms\"",
(gogoproto.nullable) = false
];
}

// GenesisDenom defines a tokenfactory denom that is defined within genesis
// state. The structure contains DenomAuthorityMetadata which defines the
// denom's admin.
message GenesisDenom {
option (gogoproto.equal) = true;

string denom = 1 [ (gogoproto.moretags) = "yaml:\"denom\"" ];
DenomAuthorityMetadata authority_metadata = 2 [
(gogoproto.moretags) = "yaml:\"authority_metadata\"",
(gogoproto.nullable) = false
];
}
18 changes: 18 additions & 0 deletions proto/palomachain/paloma/tokenfactory/params.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
syntax = "proto3";
package palomachain.paloma.tokenfactory;

import "gogoproto/gogo.proto";
import "cosmos_proto/cosmos.proto";
import "cosmos/base/v1beta1/coin.proto";
import "palomachain/paloma/tokenfactory/authorityMetadata.proto";

option go_package = "github.com/palomachain/paloma/v2/x/tokenfactory/types";

// Params defines the parameters for the tokenfactory module.
message Params {
repeated cosmos.base.v1beta1.Coin denom_creation_fee = 1 [
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
(gogoproto.moretags) = "yaml:\"denom_creation_fee\"",
(gogoproto.nullable) = false
];
}
72 changes: 72 additions & 0 deletions proto/palomachain/paloma/tokenfactory/query.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
syntax = "proto3";
package palomachain.paloma.tokenfactory;

import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
import "cosmos/base/query/v1beta1/pagination.proto";
import "palomachain/paloma/tokenfactory/authorityMetadata.proto";
import "palomachain/paloma/tokenfactory/params.proto";

option go_package = "github.com/palomachain/paloma/v2/x/tokenfactory/types";

// Query defines the gRPC querier service.
service Query {
// Params defines a gRPC query method that returns the tokenfactory module's
// parameters.
rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
option (google.api.http).get = "/palomachain/paloma/tokenfactory/params";
}

// DenomAuthorityMetadata defines a gRPC query method for fetching
// DenomAuthorityMetadata for a particular denom.
rpc DenomAuthorityMetadata(QueryDenomAuthorityMetadataRequest)
returns (QueryDenomAuthorityMetadataResponse) {
option (google.api.http).get =
"/palomachain/paloma/tokenfactory/denoms/{denom}/authority_metadata";
}

// DenomsFromCreator defines a gRPC query method for fetching all
// denominations created by a specific admin/creator.
rpc DenomsFromCreator(QueryDenomsFromCreatorRequest)
returns (QueryDenomsFromCreatorResponse) {
option (google.api.http).get =
"/palomachain/paloma/tokenfactory/denoms_from_creator/{creator}";
}
}

// QueryParamsRequest is the request type for the Query/Params RPC method.
message QueryParamsRequest {}

// QueryParamsResponse is the response type for the Query/Params RPC method.
message QueryParamsResponse {
// params defines the parameters of the module.
Params params = 1 [ (gogoproto.nullable) = false ];
}

// QueryDenomAuthorityMetadataRequest defines the request structure for the
// DenomAuthorityMetadata gRPC query.
message QueryDenomAuthorityMetadataRequest {
string denom = 1 [ (gogoproto.moretags) = "yaml:\"denom\"" ];
}

// QueryDenomAuthorityMetadataResponse defines the response structure for the
// DenomAuthorityMetadata gRPC query.
message QueryDenomAuthorityMetadataResponse {
DenomAuthorityMetadata authority_metadata = 1 [
(gogoproto.moretags) = "yaml:\"authority_metadata\"",
(gogoproto.nullable) = false
];
}

// QueryDenomsFromCreatorRequest defines the request structure for the
// DenomsFromCreator gRPC query.
message QueryDenomsFromCreatorRequest {
string creator = 1 [ (gogoproto.moretags) = "yaml:\"creator\"" ];
}

// QueryDenomsFromCreatorRequest defines the response structure for the
// DenomsFromCreator gRPC query.
message QueryDenomsFromCreatorResponse {
repeated string denoms = 1 [ (gogoproto.moretags) = "yaml:\"denoms\"" ];
}

Loading
Loading