Skip to content

Commit

Permalink
refactor: max supply check (#3073)
Browse files Browse the repository at this point in the history
  • Loading branch information
lumtis authored Oct 31, 2024
1 parent c39b60d commit 70a0e40
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 0 deletions.
18 changes: 18 additions & 0 deletions testutil/keeper/mocks/fungible/bank.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions x/fungible/keeper/deposits_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,10 @@ func TestKeeper_DepositCoinZeta(t *testing.T) {
b := sdkk.BankKeeper.GetBalance(ctx, zetaToAddress, config.BaseDenom)
require.Equal(t, int64(0), b.Amount.Int64())
errorMint := errors.New("", 1, "error minting coins")

bankMock.On("GetSupply", ctx, mock.Anything, mock.Anything).
Return(sdk.NewCoin(config.BaseDenom, sdk.NewInt(0))).
Once()
bankMock.On("MintCoins", ctx, types.ModuleName, mock.Anything).Return(errorMint).Once()
err := k.DepositCoinZeta(ctx, to, amount)
require.ErrorIs(t, err, errorMint)
Expand Down
27 changes: 27 additions & 0 deletions x/fungible/keeper/zeta.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package keeper

import (
"errors"
"math/big"

sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -9,9 +10,24 @@ import (
"github.com/zeta-chain/node/x/fungible/types"
)

// ZETAMaxSupplyStr is the maximum mintable ZETA in the fungible module
// 1.85 billion ZETA
const ZETAMaxSupplyStr = "1850000000000000000000000000"

// MintZetaToEVMAccount mints ZETA (gas token) to the given address
// NOTE: this method should be used with a temporary context, and it should not be committed if the method returns an error
func (k *Keeper) MintZetaToEVMAccount(ctx sdk.Context, to sdk.AccAddress, amount *big.Int) error {
zetaMaxSupply, ok := sdk.NewIntFromString(ZETAMaxSupplyStr)
if !ok {
return errors.New("failed to parse ZETA max supply")
}

// Check if the max supply is reached
supply := k.bankKeeper.GetSupply(ctx, config.BaseDenom)
if supply.Amount.Add(sdk.NewIntFromBigInt(amount)).GT(zetaMaxSupply) {
return types.ErrMaxSupplyReached
}

coins := sdk.NewCoins(sdk.NewCoin(config.BaseDenom, sdk.NewIntFromBigInt(amount)))
// Mint coins
if err := k.bankKeeper.MintCoins(ctx, types.ModuleName, coins); err != nil {
Expand All @@ -23,6 +39,17 @@ func (k *Keeper) MintZetaToEVMAccount(ctx sdk.Context, to sdk.AccAddress, amount
}

func (k *Keeper) MintZetaToFungibleModule(ctx sdk.Context, amount *big.Int) error {
zetaMaxSupply, ok := sdk.NewIntFromString(ZETAMaxSupplyStr)
if !ok {
return errors.New("failed to parse ZETA max supply")
}

// Check if the max supply is reached
supply := k.bankKeeper.GetSupply(ctx, config.BaseDenom)
if supply.Amount.Add(sdk.NewIntFromBigInt(amount)).GT(zetaMaxSupply) {
return types.ErrMaxSupplyReached
}

coins := sdk.NewCoins(sdk.NewCoin(config.BaseDenom, sdk.NewIntFromBigInt(amount)))
// Mint coins
return k.bankKeeper.MintCoins(ctx, types.ModuleName, coins)
Expand Down
78 changes: 78 additions & 0 deletions x/fungible/keeper/zeta_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keeper_test

import (
"errors"
"github.com/stretchr/testify/mock"
"math/big"
"testing"

Expand All @@ -11,6 +12,7 @@ import (
"github.com/zeta-chain/node/cmd/zetacored/config"
testkeeper "github.com/zeta-chain/node/testutil/keeper"
"github.com/zeta-chain/node/testutil/sample"
"github.com/zeta-chain/node/x/fungible/keeper"
"github.com/zeta-chain/node/x/fungible/types"
)

Expand All @@ -29,13 +31,56 @@ func TestKeeper_MintZetaToEVMAccount(t *testing.T) {
require.True(t, bal.Amount.Equal(sdk.NewInt(42)))
})

t.Run("mint the token to reach max supply", func(t *testing.T) {
k, ctx, sdkk, _ := testkeeper.FungibleKeeper(t)
k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName)

acc := sample.Bech32AccAddress()
bal := sdkk.BankKeeper.GetBalance(ctx, acc, config.BaseDenom)
require.True(t, bal.IsZero())

zetaMaxSupply, ok := sdk.NewIntFromString(keeper.ZETAMaxSupplyStr)
require.True(t, ok)

supply := sdkk.BankKeeper.GetSupply(ctx, config.BaseDenom).Amount

newAmount := zetaMaxSupply.Sub(supply)

err := k.MintZetaToEVMAccount(ctx, acc, newAmount.BigInt())
require.NoError(t, err)
bal = sdkk.BankKeeper.GetBalance(ctx, acc, config.BaseDenom)
require.True(t, bal.Amount.Equal(newAmount))
})

t.Run("can't mint more than max supply", func(t *testing.T) {
k, ctx, sdkk, _ := testkeeper.FungibleKeeper(t)
k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName)

acc := sample.Bech32AccAddress()
bal := sdkk.BankKeeper.GetBalance(ctx, acc, config.BaseDenom)
require.True(t, bal.IsZero())

zetaMaxSupply, ok := sdk.NewIntFromString(keeper.ZETAMaxSupplyStr)
require.True(t, ok)

supply := sdkk.BankKeeper.GetSupply(ctx, config.BaseDenom).Amount

newAmount := zetaMaxSupply.Sub(supply).Add(sdk.NewInt(1))

err := k.MintZetaToEVMAccount(ctx, acc, newAmount.BigInt())
require.ErrorIs(t, err, types.ErrMaxSupplyReached)
})

coins42 := sdk.NewCoins(sdk.NewCoin(config.BaseDenom, sdk.NewInt(42)))

t.Run("should fail if minting fail", func(t *testing.T) {
k, ctx := testkeeper.FungibleKeeperAllMocks(t)

mockBankKeeper := testkeeper.GetFungibleBankMock(t, k)

mockBankKeeper.On("GetSupply", ctx, mock.Anything, mock.Anything).
Return(sdk.NewCoin(config.BaseDenom, sdk.NewInt(0))).
Once()
mockBankKeeper.On(
"MintCoins",
ctx,
Expand All @@ -55,6 +100,9 @@ func TestKeeper_MintZetaToEVMAccount(t *testing.T) {

mockBankKeeper := testkeeper.GetFungibleBankMock(t, k)

mockBankKeeper.On("GetSupply", ctx, mock.Anything, mock.Anything).
Return(sdk.NewCoin(config.BaseDenom, sdk.NewInt(0))).
Once()
mockBankKeeper.On(
"MintCoins",
ctx,
Expand All @@ -76,3 +124,33 @@ func TestKeeper_MintZetaToEVMAccount(t *testing.T) {
mockBankKeeper.AssertExpectations(t)
})
}

func TestKeeper_MintZetaToFungibleModule(t *testing.T) {
t.Run("should mint the token in the specified balance", func(t *testing.T) {
k, ctx, sdkk, _ := testkeeper.FungibleKeeper(t)
acc := k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName).GetAddress()

bal := sdkk.BankKeeper.GetBalance(ctx, acc, config.BaseDenom)
require.True(t, bal.IsZero())

err := k.MintZetaToEVMAccount(ctx, acc, big.NewInt(42))
require.NoError(t, err)
bal = sdkk.BankKeeper.GetBalance(ctx, acc, config.BaseDenom)
require.True(t, bal.Amount.Equal(sdk.NewInt(42)))
})

t.Run("can't mint more than max supply", func(t *testing.T) {
k, ctx, sdkk, _ := testkeeper.FungibleKeeper(t)
k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName)

zetaMaxSupply, ok := sdk.NewIntFromString(keeper.ZETAMaxSupplyStr)
require.True(t, ok)

supply := sdkk.BankKeeper.GetSupply(ctx, config.BaseDenom).Amount

newAmount := zetaMaxSupply.Sub(supply).Add(sdk.NewInt(1))

err := k.MintZetaToFungibleModule(ctx, newAmount.BigInt())
require.ErrorIs(t, err, types.ErrMaxSupplyReached)
})
}
6 changes: 6 additions & 0 deletions x/fungible/keeper/zevm_message_passing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ func TestKeeper_ZEVMDepositAndCallContract(t *testing.T) {
})
require.NoError(t, err)
errorMint := errors.New("", 10, "error minting coins")
bankMock.On("GetSupply", ctx, mock.Anything, mock.Anything).
Return(sdk.NewCoin(config.BaseDenom, sdk.NewInt(0))).
Once()
bankMock.On("MintCoins", ctx, types.ModuleName, mock.Anything).Return(errorMint).Once()

_, err = k.ZETADepositAndCallContract(
Expand Down Expand Up @@ -296,6 +299,9 @@ func TestKeeper_ZEVMRevertAndCallContract(t *testing.T) {
})
require.NoError(t, err)
errorMint := errors.New("", 101, "error minting coins")
bankMock.On("GetSupply", ctx, mock.Anything, mock.Anything).
Return(sdk.NewCoin(config.BaseDenom, sdk.NewInt(0))).
Once()
bankMock.On("MintCoins", ctx, types.ModuleName, mock.Anything).Return(errorMint).Once()

_, err = k.ZETARevertAndCallContract(
Expand Down
1 change: 1 addition & 0 deletions x/fungible/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ var (
ErrZRC20NilABI = cosmoserrors.Register(ModuleName, 1132, "ZRC20 ABI is nil")
ErrZeroAddress = cosmoserrors.Register(ModuleName, 1133, "address cannot be zero")
ErrInvalidAmount = cosmoserrors.Register(ModuleName, 1134, "invalid amount")
ErrMaxSupplyReached = cosmoserrors.Register(ModuleName, 1135, "max supply reached")
)
1 change: 1 addition & 0 deletions x/fungible/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type BankKeeper interface {
amt sdk.Coins,
) error
MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
GetSupply(ctx sdk.Context, denom string) sdk.Coin
}

type ObserverKeeper interface {
Expand Down

0 comments on commit 70a0e40

Please sign in to comment.