Skip to content

Commit

Permalink
add tests for lockable coin
Browse files Browse the repository at this point in the history
  • Loading branch information
fish-sammy committed Sep 26, 2024
1 parent 4f29cce commit 2812f34
Showing 1 changed file with 255 additions and 0 deletions.
255 changes: 255 additions & 0 deletions x/nexus/keeper/lockable_coin_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
package keeper

import (
"fmt"
"testing"

"github.com/axelarnetwork/axelar-core/testutils/fake"
"github.com/axelarnetwork/axelar-core/testutils/rand"
axelarnet "github.com/axelarnetwork/axelar-core/x/axelarnet/exported"
"github.com/axelarnetwork/axelar-core/x/axelarnet/types/testutils"
"github.com/axelarnetwork/axelar-core/x/nexus/exported"
"github.com/axelarnetwork/axelar-core/x/nexus/types"
"github.com/axelarnetwork/axelar-core/x/nexus/types/mock"
"github.com/axelarnetwork/utils/funcs"
. "github.com/axelarnetwork/utils/test"
sdk "github.com/cosmos/cosmos-sdk/types"
ibctypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types"
"github.com/stretchr/testify/assert"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
)

func TestLockableCoin(t *testing.T) {
var (
ctx sdk.Context
nexus *mock.NexusMock
ibc *mock.IBCKeeperMock
bank *mock.BankKeeperMock

coin sdk.Coin
trace ibctypes.DenomTrace
)

givenKeeper := Given("the nexus keeper", func() {
ctx = sdk.NewContext(fake.NewMultiStore(), tmproto.Header{}, false, log.TestingLogger())

nexus = &mock.NexusMock{}
ibc = &mock.IBCKeeperMock{}
bank = &mock.BankKeeperMock{}
})

whenCoinIsNative := When("coin is native", func() {
coin = sdk.NewCoin(rand.Denom(5, 10), sdk.NewInt(rand.PosI64()))
nexus.GetChainByNativeAssetFunc = func(ctx sdk.Context, asset string) (exported.Chain, bool) {
if asset == coin.Denom {
return axelarnet.Axelarnet, true
}

return exported.Chain{}, false
}
})

whenCoinIsExternal := When("coin is external", func() {
coin = sdk.NewCoin(rand.Denom(5, 10), sdk.NewInt(rand.PosI64()))
nexus.GetChainByNativeAssetFunc = func(ctx sdk.Context, asset string) (exported.Chain, bool) {
return exported.Chain{}, false
}
nexus.IsAssetRegisteredFunc = func(ctx sdk.Context, chain exported.Chain, asset string) bool {
return chain == axelarnet.Axelarnet && asset == coin.Denom
}
})

whenCoinIsICS20 := When("coin is ICS20", func() {
path := testutils.RandomIBCPath()
trace = ibctypes.DenomTrace{
Path: path,
BaseDenom: rand.Denom(5, 10),
}

ibc.ParseIBCDenomFunc = func(ctx sdk.Context, ibcDenom string) (ibctypes.DenomTrace, error) {
if ibcDenom == coin.Denom {
return trace, nil
}

return ibctypes.DenomTrace{}, fmt.Errorf("denom not found")
}
ibc.GetIBCPathFunc = func(ctx sdk.Context, chain exported.ChainName) (string, bool) {
if chain == axelarnet.Axelarnet.Name {
return path, true
}

return "", false
}
nexus.GetChainByNativeAssetFunc = func(ctx sdk.Context, asset string) (exported.Chain, bool) {
if asset == trace.BaseDenom {
return axelarnet.Axelarnet, true
}

return exported.Chain{}, false
}

coin = sdk.NewCoin(trace.IBCDenom(), sdk.NewInt(rand.PosI64()))
})

t.Run("NewLockableCoin, GetCoin and GetOriginalCoin", func(t *testing.T) {
givenKeeper.
When2(whenCoinIsICS20).
Then("should create a new lockable coin of type ICS20", func(t *testing.T) {
lockableCoin, err := newLockableCoin(ctx, nexus, ibc, bank, coin)

assert.NoError(t, err)
assert.Equal(t, types.CoinType(types.ICS20), lockableCoin.coinType)
assert.Equal(t, sdk.NewCoin(trace.GetBaseDenom(), coin.Amount), lockableCoin.GetCoin())
assert.Equal(t, coin, lockableCoin.GetOriginalCoin(ctx))
}).
Run(t)

givenKeeper.
When2(whenCoinIsNative).
Then("should create a new lockable coin of type native", func(t *testing.T) {
lockableCoin, err := newLockableCoin(ctx, nexus, ibc, bank, coin)

assert.NoError(t, err)
assert.Equal(t, types.CoinType(types.Native), lockableCoin.coinType)
assert.Equal(t, coin, lockableCoin.GetCoin())
assert.Equal(t, coin, lockableCoin.GetOriginalCoin(ctx))
}).
Run(t)

givenKeeper.
When2(whenCoinIsExternal).
Then("should create a new lockable coin of type external", func(t *testing.T) {
lockableCoin, err := newLockableCoin(ctx, nexus, ibc, bank, coin)

assert.NoError(t, err)
assert.Equal(t, types.CoinType(types.External), lockableCoin.coinType)
assert.Equal(t, coin, lockableCoin.GetCoin())
assert.Equal(t, coin, lockableCoin.GetOriginalCoin(ctx))
}).
Run(t)
})

t.Run("Lock", func(t *testing.T) {
givenKeeper.
When2(whenCoinIsICS20).
Then("should lock the coin", func(t *testing.T) {
bank.SendCoinsFunc = func(ctx sdk.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error { return nil }

lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin))
fromAddr := rand.AccAddr()

err := lockableCoin.Lock(ctx, fromAddr)

assert.NoError(t, err)
assert.Len(t, bank.SendCoinsCalls(), 1)
assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.SendCoinsCalls()[0].Amt)
assert.Equal(t, fromAddr, bank.SendCoinsCalls()[0].FromAddr)
assert.Equal(t, exported.GetEscrowAddress(lockableCoin.GetOriginalCoin(ctx).Denom), bank.SendCoinsCalls()[0].ToAddr)
}).
Run(t)

givenKeeper.
When2(whenCoinIsNative).
Then("should lock the coin", func(t *testing.T) {
bank.SendCoinsFunc = func(ctx sdk.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error { return nil }

lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin))
fromAddr := rand.AccAddr()

err := lockableCoin.Lock(ctx, fromAddr)

assert.NoError(t, err)
assert.Len(t, bank.SendCoinsCalls(), 1)
assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.SendCoinsCalls()[0].Amt)
assert.Equal(t, fromAddr, bank.SendCoinsCalls()[0].FromAddr)
assert.Equal(t, exported.GetEscrowAddress(lockableCoin.GetOriginalCoin(ctx).Denom), bank.SendCoinsCalls()[0].ToAddr)
}).
Run(t)

givenKeeper.
When2(whenCoinIsExternal).
Then("should burn the coin", func(t *testing.T) {
bank.SendCoinsFromAccountToModuleFunc = func(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error {
return nil
}
bank.BurnCoinsFunc = func(ctx sdk.Context, moduleName string, amt sdk.Coins) error { return nil }

lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin))
fromAddr := rand.AccAddr()

err := lockableCoin.Lock(ctx, fromAddr)

assert.NoError(t, err)
assert.Len(t, bank.SendCoinsFromAccountToModuleCalls(), 1)
assert.Equal(t, fromAddr, bank.SendCoinsFromAccountToModuleCalls()[0].SenderAddr)
assert.Equal(t, types.ModuleName, bank.SendCoinsFromAccountToModuleCalls()[0].RecipientModule)
assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.SendCoinsFromAccountToModuleCalls()[0].Amt)
assert.Len(t, bank.BurnCoinsCalls(), 1)
assert.Equal(t, types.ModuleName, bank.BurnCoinsCalls()[0].ModuleName)
assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.BurnCoinsCalls()[0].Amt)
}).
Run(t)
})

t.Run("Unlock", func(t *testing.T) {
givenKeeper.
When2(whenCoinIsICS20).
Then("should unlock the coin", func(t *testing.T) {
bank.SendCoinsFunc = func(ctx sdk.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error { return nil }

lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin))
toAddr := rand.AccAddr()

err := lockableCoin.Unlock(ctx, toAddr)

assert.NoError(t, err)
assert.Len(t, bank.SendCoinsCalls(), 1)
assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.SendCoinsCalls()[0].Amt)
assert.Equal(t, exported.GetEscrowAddress(lockableCoin.GetOriginalCoin(ctx).Denom), bank.SendCoinsCalls()[0].FromAddr)
assert.Equal(t, toAddr, bank.SendCoinsCalls()[0].ToAddr)
}).
Run(t)

givenKeeper.
When2(whenCoinIsNative).
Then("should unlock the coin", func(t *testing.T) {
bank.SendCoinsFunc = func(ctx sdk.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error { return nil }

lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin))
toAddr := rand.AccAddr()

err := lockableCoin.Unlock(ctx, toAddr)

assert.NoError(t, err)
assert.Len(t, bank.SendCoinsCalls(), 1)
assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.SendCoinsCalls()[0].Amt)
assert.Equal(t, exported.GetEscrowAddress(lockableCoin.GetOriginalCoin(ctx).Denom), bank.SendCoinsCalls()[0].FromAddr)
assert.Equal(t, toAddr, bank.SendCoinsCalls()[0].ToAddr)
}).
Run(t)

givenKeeper.
When2(whenCoinIsExternal).
Then("should mint the coin", func(t *testing.T) {
bank.MintCoinsFunc = func(ctx sdk.Context, moduleName string, amt sdk.Coins) error { return nil }
bank.SendCoinsFromModuleToAccountFunc = func(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error {
return nil
}

lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin))
toAddr := rand.AccAddr()

err := lockableCoin.Unlock(ctx, toAddr)

assert.NoError(t, err)
assert.Len(t, bank.MintCoinsCalls(), 1)
assert.Equal(t, types.ModuleName, bank.MintCoinsCalls()[0].ModuleName)
assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.MintCoinsCalls()[0].Amt)
assert.Len(t, bank.SendCoinsFromModuleToAccountCalls(), 1)
assert.Equal(t, types.ModuleName, bank.SendCoinsFromModuleToAccountCalls()[0].SenderModule)
assert.Equal(t, toAddr, bank.SendCoinsFromModuleToAccountCalls()[0].RecipientAddr)
}).
Run(t)
})
}

0 comments on commit 2812f34

Please sign in to comment.