-
Notifications
You must be signed in to change notification settings - Fork 126
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4f29cce
commit 2812f34
Showing
1 changed file
with
255 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
}) | ||
} |