package wasm_test
import (
"fmt"
bindings "github.com/cybercongress/go-cyber/v7/x/tokenfactory/wasm/types"
"testing"
"github.com/stretchr/testify/require"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cybercongress/go-cyber/v7/x/tokenfactory/types"
wasmbinding "github.com/cybercongress/go-cyber/v7/x/tokenfactory/wasm"
)
func TestCreateDenom(t *testing.T) {
actor := RandomAccountAddress()
junoapp, ctx := SetupCustomApp(t, actor)
actorAmount := sdk.NewCoins(sdk.NewCoin(types.DefaultParams().DenomCreationFee[0].Denom, types.DefaultParams().DenomCreationFee[0].Amount.MulRaw(100)))
fundAccount(t, ctx, junoapp, actor, actorAmount)
specs := map[string]struct {
createDenom *bindings.CreateDenom
expErr bool
}{
"valid sub-denom": {
createDenom: &bindings.CreateDenom{
Subdenom: "MOON",
},
},
"empty sub-denom": {
createDenom: &bindings.CreateDenom{
Subdenom: "",
},
expErr: false,
},
"invalid sub-denom": {
createDenom: &bindings.CreateDenom{
Subdenom: "sub-denom_2",
},
expErr: false,
},
"null create denom": {
createDenom: nil,
expErr: true,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
_, gotErr := wasmbinding.PerformCreateDenom(&junoapp.AppKeepers.TokenFactoryKeeper, junoapp.AppKeepers.BankKeeper, ctx, actor, spec.createDenom)
if spec.expErr {
t.Logf("validate_msg_test got error: %v", gotErr)
require.Error(t, gotErr)
return
}
require.NoError(t, gotErr)
})
}
}
func TestChangeAdmin(t *testing.T) {
const validDenom = "validdenom"
tokenCreator := RandomAccountAddress()
specs := map[string]struct {
actor sdk.AccAddress
changeAdmin *bindings.ChangeAdmin
expErrMsg string
}{
"valid": {
changeAdmin: &bindings.ChangeAdmin{
Denom: fmt.Sprintf("factory/%s/%s", tokenCreator.String(), validDenom),
NewAdminAddress: RandomBech32AccountAddress(),
},
actor: tokenCreator,
},
"typo in factory in denom name": {
changeAdmin: &bindings.ChangeAdmin{
Denom: fmt.Sprintf("facory/%s/%s", tokenCreator.String(), validDenom),
NewAdminAddress: RandomBech32AccountAddress(),
},
actor: tokenCreator,
expErrMsg: "denom prefix is incorrect. Is: facory. Should be: factory: invalid denom",
},
"invalid address in denom": {
changeAdmin: &bindings.ChangeAdmin{
Denom: fmt.Sprintf("factory/%s/%s", RandomBech32AccountAddress(), validDenom),
NewAdminAddress: RandomBech32AccountAddress(),
},
actor: tokenCreator,
expErrMsg: "failed changing admin from message: unauthorized account",
},
"other denom name in 3 part name": {
changeAdmin: &bindings.ChangeAdmin{
Denom: fmt.Sprintf("factory/%s/%s", tokenCreator.String(), "invalid denom"),
NewAdminAddress: RandomBech32AccountAddress(),
},
actor: tokenCreator,
expErrMsg: fmt.Sprintf("invalid denom: factory/%s/invalid denom", tokenCreator.String()),
},
"empty denom": {
changeAdmin: &bindings.ChangeAdmin{
Denom: "",
NewAdminAddress: RandomBech32AccountAddress(),
},
actor: tokenCreator,
expErrMsg: "invalid denom: ",
},
"empty address": {
changeAdmin: &bindings.ChangeAdmin{
Denom: fmt.Sprintf("factory/%s/%s", tokenCreator.String(), validDenom),
NewAdminAddress: "",
},
actor: tokenCreator,
expErrMsg: "address from bech32: empty address string is not allowed",
},
"creator is a different address": {
changeAdmin: &bindings.ChangeAdmin{
Denom: fmt.Sprintf("factory/%s/%s", tokenCreator.String(), validDenom),
NewAdminAddress: RandomBech32AccountAddress(),
},
actor: RandomAccountAddress(),
expErrMsg: "failed changing admin from message: unauthorized account",
},
"change to the same address": {
changeAdmin: &bindings.ChangeAdmin{
Denom: fmt.Sprintf("factory/%s/%s", tokenCreator.String(), validDenom),
NewAdminAddress: tokenCreator.String(),
},
actor: tokenCreator,
},
"nil binding": {
actor: tokenCreator,
expErrMsg: "invalid request: changeAdmin is nil - original request: ",
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
junoapp, ctx := SetupCustomApp(t, tokenCreator)
actorAmount := sdk.NewCoins(sdk.NewCoin(types.DefaultParams().DenomCreationFee[0].Denom, types.DefaultParams().DenomCreationFee[0].Amount.MulRaw(100)))
fundAccount(t, ctx, junoapp, tokenCreator, actorAmount)
_, err := wasmbinding.PerformCreateDenom(&junoapp.AppKeepers.TokenFactoryKeeper, junoapp.AppKeepers.BankKeeper, ctx, tokenCreator, &bindings.CreateDenom{
Subdenom: validDenom,
})
require.NoError(t, err)
err = wasmbinding.ChangeAdmin(&junoapp.AppKeepers.TokenFactoryKeeper, ctx, spec.actor, spec.changeAdmin)
if len(spec.expErrMsg) > 0 {
require.Error(t, err)
actualErrMsg := err.Error()
require.Equal(t, spec.expErrMsg, actualErrMsg)
return
}
require.NoError(t, err)
})
}
}
func TestMint(t *testing.T) {
creator := RandomAccountAddress()
junoapp, ctx := SetupCustomApp(t, creator)
tokenCreationFeeAmt := sdk.NewCoins(sdk.NewCoin(types.DefaultParams().DenomCreationFee[0].Denom, types.DefaultParams().DenomCreationFee[0].Amount.MulRaw(100)))
fundAccount(t, ctx, junoapp, creator, tokenCreationFeeAmt)
validDenom := bindings.CreateDenom{
Subdenom: "MOON",
}
_, err := wasmbinding.PerformCreateDenom(&junoapp.AppKeepers.TokenFactoryKeeper, junoapp.AppKeepers.BankKeeper, ctx, creator, &validDenom)
require.NoError(t, err)
emptyDenom := bindings.CreateDenom{
Subdenom: "",
}
_, err = wasmbinding.PerformCreateDenom(&junoapp.AppKeepers.TokenFactoryKeeper, junoapp.AppKeepers.BankKeeper, ctx, creator, &emptyDenom)
require.NoError(t, err)
validDenomStr := fmt.Sprintf("factory/%s/%s", creator.String(), validDenom.Subdenom)
emptyDenomStr := fmt.Sprintf("factory/%s/%s", creator.String(), emptyDenom.Subdenom)
lucky := RandomAccountAddress()
balances := junoapp.AppKeepers.BankKeeper.GetAllBalances(ctx, lucky)
require.Empty(t, balances)
amount, ok := sdk.NewIntFromString("8080")
require.True(t, ok)
specs := map[string]struct {
mint *bindings.MintTokens
expErr bool
}{
"valid mint": {
mint: &bindings.MintTokens{
Denom: validDenomStr,
Amount: amount,
MintToAddress: lucky.String(),
},
},
"empty sub-denom": {
mint: &bindings.MintTokens{
Denom: emptyDenomStr,
Amount: amount,
MintToAddress: lucky.String(),
},
expErr: false,
},
"nonexistent sub-denom": {
mint: &bindings.MintTokens{
Denom: fmt.Sprintf("factory/%s/%s", creator.String(), "SUN"),
Amount: amount,
MintToAddress: lucky.String(),
},
expErr: true,
},
"invalid sub-denom": {
mint: &bindings.MintTokens{
Denom: "sub-denom_2",
Amount: amount,
MintToAddress: lucky.String(),
},
expErr: true,
},
"zero amount": {
mint: &bindings.MintTokens{
Denom: validDenomStr,
Amount: sdk.ZeroInt(),
MintToAddress: lucky.String(),
},
expErr: true,
},
"negative amount": {
mint: &bindings.MintTokens{
Denom: validDenomStr,
Amount: amount.Neg(),
MintToAddress: lucky.String(),
},
expErr: true,
},
"empty recipient": {
mint: &bindings.MintTokens{
Denom: validDenomStr,
Amount: amount,
MintToAddress: "",
},
expErr: true,
},
"invalid recipient": {
mint: &bindings.MintTokens{
Denom: validDenomStr,
Amount: amount,
MintToAddress: "invalid",
},
expErr: true,
},
"null mint": {
mint: nil,
expErr: true,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
gotErr := wasmbinding.PerformMint(&junoapp.AppKeepers.TokenFactoryKeeper, junoapp.AppKeepers.BankKeeper, ctx, creator, spec.mint)
if spec.expErr {
require.Error(t, gotErr)
return
}
require.NoError(t, gotErr)
})
}
}
func TestBurn(t *testing.T) {
creator := RandomAccountAddress()
junoapp, ctx := SetupCustomApp(t, creator)
tokenCreationFeeAmt := sdk.NewCoins(sdk.NewCoin(types.DefaultParams().DenomCreationFee[0].Denom, types.DefaultParams().DenomCreationFee[0].Amount.MulRaw(100)))
fundAccount(t, ctx, junoapp, creator, tokenCreationFeeAmt)
validDenom := bindings.CreateDenom{
Subdenom: "MOON",
}
_, err := wasmbinding.PerformCreateDenom(&junoapp.AppKeepers.TokenFactoryKeeper, junoapp.AppKeepers.BankKeeper, ctx, creator, &validDenom)
require.NoError(t, err)
emptyDenom := bindings.CreateDenom{
Subdenom: "",
}
_, err = wasmbinding.PerformCreateDenom(&junoapp.AppKeepers.TokenFactoryKeeper, junoapp.AppKeepers.BankKeeper, ctx, creator, &emptyDenom)
require.NoError(t, err)
lucky := RandomAccountAddress()
balances := junoapp.AppKeepers.BankKeeper.GetAllBalances(ctx, lucky)
require.Empty(t, balances)
validDenomStr := fmt.Sprintf("factory/%s/%s", creator.String(), validDenom.Subdenom)
emptyDenomStr := fmt.Sprintf("factory/%s/%s", creator.String(), emptyDenom.Subdenom)
mintAmount, ok := sdk.NewIntFromString("8080")
require.True(t, ok)
specs := map[string]struct {
burn *bindings.BurnTokens
expErr bool
}{
"valid burn": {
burn: &bindings.BurnTokens{
Denom: validDenomStr,
Amount: mintAmount,
BurnFromAddress: creator.String(),
},
expErr: false,
},
"non admin address": {
burn: &bindings.BurnTokens{
Denom: validDenomStr,
Amount: mintAmount,
BurnFromAddress: lucky.String(),
},
expErr: true,
},
"empty sub-denom": {
burn: &bindings.BurnTokens{
Denom: emptyDenomStr,
Amount: mintAmount,
BurnFromAddress: creator.String(),
},
expErr: false,
},
"invalid sub-denom": {
burn: &bindings.BurnTokens{
Denom: "sub-denom_2",
Amount: mintAmount,
BurnFromAddress: creator.String(),
},
expErr: true,
},
"non-minted denom": {
burn: &bindings.BurnTokens{
Denom: fmt.Sprintf("factory/%s/%s", creator.String(), "SUN"),
Amount: mintAmount,
BurnFromAddress: creator.String(),
},
expErr: true,
},
"zero amount": {
burn: &bindings.BurnTokens{
Denom: validDenomStr,
Amount: sdk.ZeroInt(),
BurnFromAddress: creator.String(),
},
expErr: true,
},
"negative amount": {
burn: nil,
expErr: true,
},
"null burn": {
burn: &bindings.BurnTokens{
Denom: validDenomStr,
Amount: mintAmount.Neg(),
BurnFromAddress: creator.String(),
},
expErr: true,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
mintBinding := &bindings.MintTokens{
Denom: validDenomStr,
Amount: mintAmount,
MintToAddress: creator.String(),
}
err := wasmbinding.PerformMint(&junoapp.AppKeepers.TokenFactoryKeeper, junoapp.AppKeepers.BankKeeper, ctx, creator, mintBinding)
require.NoError(t, err)
emptyDenomMintBinding := &bindings.MintTokens{
Denom: emptyDenomStr,
Amount: mintAmount,
MintToAddress: creator.String(),
}
err = wasmbinding.PerformMint(&junoapp.AppKeepers.TokenFactoryKeeper, junoapp.AppKeepers.BankKeeper, ctx, creator, emptyDenomMintBinding)
require.NoError(t, err)
gotErr := wasmbinding.PerformBurn(&junoapp.AppKeepers.TokenFactoryKeeper, ctx, creator, spec.burn)
if spec.expErr {
require.Error(t, gotErr)
return
}
require.NoError(t, gotErr)
})
}
}