Add a new token and only allow fees in alnt (#68)

Part of https://www.notion.so/Multiple-tokens-support-and-disable-transfers-for-LSTAKE-1f2a6b22d47280269f87df3fe03e8d64
- Add base token with denoms `alps` and `lps` (`1 lps = 10^18 alps`)
- Keep `alnt` as the staking token and for laconic module ops
- Accept tx fees only in `alnt`

Reviewed-on: cerc-io/laconicd#68
Co-authored-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
Co-committed-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
This commit is contained in:
prathamesh authored and Nabarun committed 2025-05-13 18:17:38 +05:30
1 parent f4cf8ac744
commit 31ef3afb9a
8 files changed
+136 -26

No files matched your search

+79
View File
@@ -0,0 +1,79 @@
package app
import (
_ "embed"
"math"
errorsmod "cosmossdk.io/errors"
sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"git.vdb.to/cerc-io/laconicd/app/params"
)
// Reference: https://github.com/cosmos/cosmos-sdk/blob/v0.50.10/x/auth/ante/validator_tx_fee.go#L15
// checkTxFeeWithValidatorMinGasPrices implements the default fee logic, where the minimum price per
// unit of gas is fixed and set by each validator, can the tx priority is computed from the gas price.
func checkTxFeeWithValidatorMinGasPrices(ctx sdk.Context, tx sdk.Tx) (sdk.Coins, int64, error) {
feeTx, ok := tx.(sdk.FeeTx)
if !ok {
return nil, 0, errorsmod.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
}
feeCoins := feeTx.GetFee()
gas := feeTx.GetGas()
// Only allow alnt as a fee token
for _, coin := range feeCoins {
if coin.Denom != params.CoinUnit {
return nil, 0, errorsmod.Wrapf(sdkerrors.ErrInvalidCoins, "invalid fee denom %s, only %s is accepted", coin.Denom, params.CoinUnit)
}
}
// Ensure that the provided fees meet a minimum threshold for the validator,
// if this is a CheckTx. This is only for local mempool purposes, and thus
// is only ran on check tx.
if ctx.IsCheckTx() {
minGasPrices := ctx.MinGasPrices()
if !minGasPrices.IsZero() {
requiredFees := make(sdk.Coins, len(minGasPrices))
// Determine the required fees by multiplying each required minimum gas
// price by the gas limit, where fee = ceil(minGasPrice * gasLimit).
glDec := sdkmath.LegacyNewDec(int64(gas))
for i, gp := range minGasPrices {
fee := gp.Amount.Mul(glDec)
requiredFees[i] = sdk.NewCoin(gp.Denom, fee.Ceil().RoundInt())
}
if !feeCoins.IsAnyGTE(requiredFees) {
return nil, 0, errorsmod.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeCoins, requiredFees)
}
}
}
priority := getTxPriority(feeCoins, int64(gas))
return feeCoins, priority, nil
}
// getTxPriority returns a naive tx priority based on the amount of the smallest denomination of the gas price
// provided in a transaction.
// NOTE: This implementation should be used with a great consideration as it opens potential attack vectors
// where txs with multiple coins could not be prioritize as expected.
func getTxPriority(fee sdk.Coins, gas int64) int64 {
var priority int64
for _, c := range fee {
p := int64(math.MaxInt64)
gasPrice := c.Amount.QuoRaw(gas)
if gasPrice.IsInt64() {
p = gasPrice.Int64()
}
if priority == 0 || p < priority {
priority = p
}
}
return priority
}
+24
View File
@@ -27,6 +27,7 @@ import (
"github.com/cosmos/cosmos-sdk/server/config"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
consensuskeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper"
@@ -185,6 +186,9 @@ func NewLaconicApp(
app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, make(map[string]module.AppModuleSimulation, 0))
app.sm.RegisterStoreDecoders()
// set custom ante handlers
app.setCustomAnteHandler()
if err := app.Load(loadLatest); err != nil {
return nil, err
}
@@ -232,3 +236,23 @@ func (app *LaconicApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.AP
panic(err)
}
}
// setCustomAnteHandler overwrites default ante handlers with custom ante handlers
// Reference: https://github.com/cosmos/cosmos-sdk/blob/v0.50.10/x/auth/tx/config/config.go#L149
func (app *LaconicApp) setCustomAnteHandler() {
anteHandler, err := ante.NewAnteHandler(
ante.HandlerOptions{
AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
SignModeHandler: app.txConfig.SignModeHandler(),
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
TxFeeChecker: checkTxFeeWithValidatorMinGasPrices,
},
)
if err != nil {
panic(err)
}
// Set the AnteHandler for the app
app.SetAnteHandler(anteHandler)
}
+9 -7
View File
@@ -10,11 +10,14 @@ import (
)
const (
CoinUnit = "lnt"
BaseCoinUnit = "alnt"
LntExponent = 18
// Registered token
LpsCoinUnit = "lps"
LpsBaseCoinUnit = "alps"
LpsExponent = 18
DefaultBondDenom = BaseCoinUnit
// Native token, only denominated in alnt
// Used for staking, fees and laconic module ops
CoinUnit = "alnt"
// Bech32PrefixAccAddr defines the Bech32 prefix of an account's address.
Bech32PrefixAccAddr = "laconic"
@@ -39,12 +42,11 @@ func init() {
}
func RegisterDenoms() {
err := sdk.RegisterDenom(CoinUnit, math.LegacyOneDec())
err := sdk.RegisterDenom(LpsCoinUnit, math.LegacyOneDec())
if err != nil {
panic(err)
}
err = sdk.RegisterDenom(BaseCoinUnit, math.LegacyNewDecWithPrec(1, LntExponent))
err = sdk.RegisterDenom(LpsBaseCoinUnit, math.LegacyNewDecWithPrec(1, LpsExponent))
if err != nil {
panic(err)
}