Skip to content

Commit

Permalink
add some unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas-nguy committed Jul 26, 2022
1 parent d7dc2ca commit 2f3a349
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 5 deletions.
53 changes: 53 additions & 0 deletions x/cronos/keeper/evm_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package keeper_test

import (
"github.com/crypto-org-chain/cronos/x/cronos/types"
"math/big"

sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -66,3 +67,55 @@ func (suite *KeeperTestSuite) TestTokenConversion() {
coin := suite.app.BankKeeper.GetBalance(suite.ctx, cosmosAddress, denom)
suite.Require().Equal(amount, coin.Amount.BigInt())
}

func (suite *KeeperTestSuite) TestSourceTokenConversion() {
suite.SetupTest()
keeper := suite.app.CronosKeeper

// generate test address
priv, err := ethsecp256k1.GenerateKey()
suite.Require().NoError(err)
address := common.BytesToAddress(priv.PubKey().Address().Bytes())
cosmosAddress := sdk.AccAddress(address.Bytes())

// Deploy CRC21 token
contractAddress, err := keeper.DeployModuleCRC21(suite.ctx, "Test")
suite.Require().NoError(err)

// Register the token
denom := "cronos" + contractAddress.Hex()
msgUpdateTokenMapping := types.MsgUpdateTokenMapping{
Sender: cosmosAddress.String(),
Denom: denom,
Contract: contractAddress.Hex(),
Symbol: "Test",
Decimal: 0,
}
err = keeper.RegisterOrUpdateTokenMapping(suite.ctx, &msgUpdateTokenMapping)
suite.Require().NoError(err)

// Mint some CRC21 token
amount := big.NewInt(100)
_, err = suite.app.CronosKeeper.CallModuleCRC21(suite.ctx, contractAddress, "mint_by_cronos_module", address, amount)
suite.Require().NoError(err)

// Convert CRC21 to native
err = keeper.ConvertCoinFromCRC21ToNative(suite.ctx, contractAddress, address, sdk.NewIntFromBigInt(amount))
suite.Require().NoError(err)

// Check balance
coin := suite.app.BankKeeper.GetBalance(suite.ctx, cosmosAddress, denom)
suite.Require().Equal(amount, coin.Amount.BigInt())

// Convert native to CRC21
coins := sdk.NewCoins(sdk.NewCoin(denom, sdk.NewIntFromBigInt(amount)))
err = keeper.ConvertCoinsFromNativeToCRC21(suite.ctx, address, coins, false)
suite.Require().NoError(err)

// check balance
coin = suite.app.BankKeeper.GetBalance(suite.ctx, cosmosAddress, denom)
suite.Require().Equal(big.NewInt(0), coin.Amount.BigInt())
ret, err := keeper.CallModuleCRC21(suite.ctx, contractAddress, "balanceOf", address)
suite.Require().NoError(err)
suite.Require().Equal(0, big.NewInt(100).Cmp(big.NewInt(0).SetBytes(ret)))
}
11 changes: 9 additions & 2 deletions x/cronos/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,12 +214,16 @@ func (k Keeper) GetAccount(ctx sdk.Context, addr sdk.AccAddress) authtypes.Accou
// RegisterOrUpdateTokenMapping update the token mapping, register a coin metadata if needed
func (k Keeper) RegisterOrUpdateTokenMapping(ctx sdk.Context, msg *types.MsgUpdateTokenMapping) error {
if types.IsSourceCoin(msg.Denom) {
contract := types.GetContractAddressFromDenom(msg.Denom)
contract, err := types.GetContractAddressFromDenom(msg.Denom)
if err != nil {
return err
}
// we check that denom use the same contract address in checksum format
if contract != common.HexToAddress(msg.Contract).Hex() {
return sdkerrors.Wrapf(
sdkerrors.ErrInvalidRequest,
"coin denom %s does not match with contract address %s", msg.Denom, msg.Contract)
"coin denom %s does not match with contract address %s",
msg.Denom, common.HexToAddress(msg.Contract).Hex())
}

// check that the coin is registered, otherwise register it
Expand Down Expand Up @@ -264,6 +268,9 @@ func (k Keeper) RegisterOrUpdateTokenMapping(ctx sdk.Context, msg *types.MsgUpda
// delete existing mapping
k.DeleteExternalContractForDenom(ctx, msg.Denom)
} else {
if !common.IsHexAddress(msg.Contract) {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid contract address (%s)", msg.Contract)
}
// update the mapping
contract := common.HexToAddress(msg.Contract)
if err := k.SetExternalContractForDenom(ctx, msg.Denom, contract); err != nil {
Expand Down
160 changes: 160 additions & 0 deletions x/cronos/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,18 @@ func (suite *KeeperTestSuite) MintCoins(address sdk.AccAddress, coins sdk.Coins)
return nil
}

func (suite *KeeperTestSuite) RegisterSourceToken(
contractAddress, symbol string, decimal uint32) error {
denom := "cronos" + contractAddress
msg := types.MsgUpdateTokenMapping{
Denom: denom,
Contract: contractAddress,
Symbol: symbol,
Decimal: decimal,
}
return suite.app.CronosKeeper.RegisterOrUpdateTokenMapping(suite.ctx, &msg)
}

func (suite *KeeperTestSuite) TestDenomContractMap() {
denom1 := "testdenom1"
denom2 := "testdenom2"
Expand Down Expand Up @@ -269,3 +281,151 @@ func (suite *KeeperTestSuite) TestOnRecvVouchers() {
})
}
}

func (suite *KeeperTestSuite) TestRegisterOrUpdateTokenMapping() {
contractAddress := "0xF6D4FeCB1a6fb7C2CA350169A050D483bd87b883"

testCases := []struct {
name string
msg types.MsgUpdateTokenMapping
malleate func()
error bool
}{
{
"Non source token, no error",
types.MsgUpdateTokenMapping{
Sender: "",
Denom: "gravity0xf6d4fecb1a6fb7c2ca350169a050d483bd87b883",
Contract: contractAddress,
Symbol: "",
Decimal: 0,
},
func() {
},
false,
},
{
"No hex contract address, error",
types.MsgUpdateTokenMapping{
Sender: "",
Denom: "gravity0xf6d4fecb1a6fb7c2ca350169a050d483bd87b883",
Contract: "test",
Symbol: "",
Decimal: 0,
},
func() {
},
true,
},
{
"Non source token, no hex contract address, error",
types.MsgUpdateTokenMapping{
Sender: "",
Denom: "cronos0xtest",
Contract: "test",
Symbol: "",
Decimal: 0,
},
func() {
},
true,
},
{
"Non source token, already exists, no error",
types.MsgUpdateTokenMapping{
Sender: "",
Denom: "gravity0xf6d4fecb1a6fb7c2ca350169a050d483bd87b883",
Contract: "",
Symbol: "",
Decimal: 0,
},
func() {
err := suite.app.CronosKeeper.SetExternalContractForDenom(
suite.ctx,
"gravity0xf6d4fecb1a6fb7c2ca350169a050d483bd87b883",
common.HexToAddress(contractAddress))
suite.Require().NoError(err)
},
false,
},
{
"Source token, denom not match",
types.MsgUpdateTokenMapping{
Sender: "",
Denom: "cronos0xA6d4fecb1a6fb7c2ca350169a050d483bd87b883",
Contract: contractAddress,
Symbol: "",
Decimal: 0,
},
func() {
},
true,
},
{
"Source token, denom not checksum, error",
types.MsgUpdateTokenMapping{
Sender: "",
Denom: "cronos0xf6d4fecb1a6fb7c2ca350169a050d483bd87b883",
Contract: contractAddress,
Symbol: "",
Decimal: 0,
},
func() {
},
true,
},
{
"Source token, denom correct, no error",
types.MsgUpdateTokenMapping{
Sender: "",
Denom: "cronos0xF6D4FeCB1a6fb7C2CA350169A050D483bd87b883",
Contract: contractAddress,
Symbol: "",
Decimal: 0,
},
func() {
},
false,
},
{
"Source token, denom correct with decimal, no error",
types.MsgUpdateTokenMapping{
Sender: "",
Denom: "cronos0xF6D4FeCB1a6fb7C2CA350169A050D483bd87b883",
Contract: contractAddress,
Symbol: "Test",
Decimal: 6,
},
func() {
},
false,
},
}

for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.SetupTest() // reset
// Create Cronos Keeper with mock transfer keeper
cronosKeeper := *cronosmodulekeeper.NewKeeper(
app.MakeEncodingConfig().Marshaler,
suite.app.GetKey(types.StoreKey),
suite.app.GetKey(types.MemStoreKey),
suite.app.GetSubspace(types.ModuleName),
suite.app.BankKeeper,
keepertest.IbcKeeperMock{},
suite.app.GravityKeeper,
suite.app.EvmKeeper,
suite.app.AccountKeeper,
)
suite.app.CronosKeeper = cronosKeeper

tc.malleate()
err := suite.app.CronosKeeper.RegisterOrUpdateTokenMapping(suite.ctx, &tc.msg)
if tc.error {
suite.Require().Error(err)
} else {
suite.Require().NoError(err)
}
})
}
}
12 changes: 9 additions & 3 deletions x/cronos/types/types.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package types

import (
"fmt"
"math/big"
"strings"

"github.com/ethereum/go-ethereum/common"
)

var (
Expand Down Expand Up @@ -45,12 +48,15 @@ func IsValidCoinDenom(denom string) bool {
}

// GetContractAddressFromDenom get the contract address from the coin denom
func GetContractAddressFromDenom(denom string) string {
func GetContractAddressFromDenom(denom string) (string, error) {
contractAddress := ""
if strings.HasPrefix(denom, gravityDenomPrefix) {
contractAddress = denom[7:]
} else if strings.HasPrefix(denom, cronosDenomPrefix) {
contractAddress = denom[5:]
contractAddress = denom[6:]
}
if !common.IsHexAddress(contractAddress) {
return "", fmt.Errorf("invalid contract address (%s)", contractAddress)
}
return contractAddress
return contractAddress, nil
}

0 comments on commit 2f3a349

Please sign in to comment.