Skip to content

Commit

Permalink
Problem: external token mapping not manageable directly
Browse files Browse the repository at this point in the history
Closes: #119

Solution:
- add native message to update token mapping

unit tests

Update x/cronos/keeper/msg_server.go

fix lint

fix msgs
  • Loading branch information
yihuang committed Sep 30, 2021
1 parent 47ce47c commit eb25147
Show file tree
Hide file tree
Showing 17 changed files with 886 additions and 63 deletions.
9 changes: 8 additions & 1 deletion app/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
cronostypes "github.com/crypto-org-chain/cronos/x/cronos/types"
)

const (
Expand Down Expand Up @@ -67,8 +68,14 @@ func setup(withGenesis bool, invCheckPeriod uint) (*App, GenesisState) {
}

// Setup initializes a new App. A Nop logger is set in App.
func Setup(isCheckTx bool) *App {
func Setup(isCheckTx bool, cronosAdmin string) *App {
app, genesisState := setup(!isCheckTx, 5)

// set cronos_admin for test
cronosGen := cronostypes.DefaultGenesis()
cronosGen.Params.CronosAdmin = cronosAdmin
genesisState["cronos"] = app.cdc.MustMarshalJSON(cronosGen)

if !isCheckTx {
// init chain must be called to stop deliverState from being nil
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
Expand Down
31 changes: 30 additions & 1 deletion docs/api/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
- [MsgConvertVouchersResponse](#cronos.MsgConvertVouchersResponse)
- [MsgTransferTokens](#cronos.MsgTransferTokens)
- [MsgTransferTokensResponse](#cronos.MsgTransferTokensResponse)
- [MsgUpdateTokenMapping](#cronos.MsgUpdateTokenMapping)
- [MsgUpdateTokenMappingResponse](#cronos.MsgUpdateTokenMappingResponse)

- [Msg](#cronos.Msg)

Expand All @@ -49,6 +51,7 @@ Params defines the parameters for the cronos module.
| ----- | ---- | ----- | ----------- |
| `ibc_cro_denom` | [string](#string) | | |
| `ibc_timeout` | [uint64](#uint64) | | |
| `cronos_admin` | [string](#string) | | the admin address who can update token mapping |



Expand Down Expand Up @@ -274,7 +277,32 @@ MsgTransferTokens represents a message to transfer cronos evm coins through ibc.
### MsgTransferTokensResponse
MsgTransferTokensResponse defines the TransferTokens response type.

this line is used by starport scaffolding # proto/tx/message





<a name="cronos.MsgUpdateTokenMapping"></a>

### MsgUpdateTokenMapping
MsgUpdateTokenMapping defines the request type


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `sender` | [string](#string) | | |
| `denom` | [string](#string) | | |
| `contract` | [string](#string) | | |






<a name="cronos.MsgUpdateTokenMappingResponse"></a>

### MsgUpdateTokenMappingResponse
MsgUpdateTokenMappingResponse defines the response type



Expand All @@ -296,6 +324,7 @@ Msg defines the Cronos Msg service
| ----------- | ------------ | ------------- | ------------| ------- | -------- |
| `ConvertVouchers` | [MsgConvertVouchers](#cronos.MsgConvertVouchers) | [MsgConvertVouchersResponse](#cronos.MsgConvertVouchersResponse) | ConvertVouchers defines a method for converting ibc voucher to cronos evm coins. | |
| `TransferTokens` | [MsgTransferTokens](#cronos.MsgTransferTokens) | [MsgTransferTokensResponse](#cronos.MsgTransferTokensResponse) | TransferTokens defines a method to transfer cronos evm coins to another chain through IBC | |
| `UpdateTokenMapping` | [MsgUpdateTokenMapping](#cronos.MsgUpdateTokenMapping) | [MsgUpdateTokenMappingResponse](#cronos.MsgUpdateTokenMappingResponse) | UpdateTokenMapping defines a method to update token mapping | |

<!-- end services -->

Expand Down
14 changes: 14 additions & 0 deletions integration_tests/cosmoscli.py
Original file line number Diff line number Diff line change
Expand Up @@ -983,3 +983,17 @@ def gov_propose_token_mapping_change(self, denom, contract, **kwargs):
**kwargs,
)
)

def update_token_mapping(self, denom, contract, **kwargs):
return json.loads(
self.raw(
"tx",
"cronos",
"update-token-mapping",
denom,
contract,
"-y",
home=self.data_dir,
**kwargs,
)
)
57 changes: 57 additions & 0 deletions integration_tests/test_gravity.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,3 +271,60 @@ def check():
return balance == 10

wait_for_fn("check balance on cronos", check)


def test_direct_token_mapping(gravity):
"""
Test adding a token mapping directly
- deploy test erc20 contract on geth
- deploy corresponding contract on cronos
- add the token mapping on cronos using gov module
- do a gravity transfer, check the balances
"""
geth = gravity.geth
cli = gravity.cronos.cosmos_cli()
cronos_w3 = gravity.cronos.w3

# deploy test erc20 contract
erc20 = deploy_contract(
geth,
Path(__file__).parent
/ "contracts/artifacts/contracts/TestERC20A.sol/TestERC20A.json",
)
print("erc20 contract", erc20.address)
crc20 = deploy_contract(
cronos_w3,
Path(__file__).parent
/ "contracts/artifacts/contracts/TestERC20Utility.sol/TestERC20Utility.json",
)
print("crc20 contract", crc20.address)
denom = f"gravity{erc20.address}"

print("check the contract mapping not exists yet")
with pytest.raises(AssertionError):
cli.query_contract_by_denom(denom)

rsp = cli.update_token_mapping(denom, crc20.address, from_="community")
assert rsp["code"] != 0, "should not have the permission"

rsp = cli.update_token_mapping(denom, crc20.address, from_="validator")
assert rsp["code"] == 0, rsp["raw_log"]
wait_for_new_blocks(cli, 1)

print("check the contract mapping exists now")
rsp = cli.query_contract_by_denom(denom)
print("contract", rsp)
assert rsp["contract"] == crc20.address

print("try to send token from ethereum to cronos")
txreceipt = send_to_cosmos(
gravity.contract, erc20, ADDRS["community"], 10, KEYS["validator"]
)
assert txreceipt.status == 1

def check():
balance = crc20.caller.balanceOf(ADDRS["community"])
print("crc20 balance", balance)
return balance == 10

wait_for_fn("check balance on cronos", check)
2 changes: 2 additions & 0 deletions proto/cronos/cronos.proto
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ message Params {
string ibc_cro_denom = 1
[ (gogoproto.moretags) = "yaml:\"ibc_cro_denom,omitempty\"" ];
uint64 ibc_timeout = 2;
// the admin address who can update token mapping
string cronos_admin = 3;
}

// TokenMappingChangeProposal defines a proposal to change one token mapping.
Expand Down
15 changes: 15 additions & 0 deletions proto/cronos/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ service Msg {

// TransferTokens defines a method to transfer cronos evm coins to another chain through IBC
rpc TransferTokens(MsgTransferTokens) returns (MsgTransferTokensResponse);

// UpdateTokenMapping defines a method to update token mapping
rpc UpdateTokenMapping(MsgUpdateTokenMapping) returns (MsgUpdateTokenMappingResponse);
}

// MsgConvertVouchers represents a message to convert ibc voucher coins to cronos evm coins.
Expand All @@ -39,4 +42,16 @@ message MsgConvertVouchersResponse {}

// MsgTransferTokensResponse defines the TransferTokens response type.
message MsgTransferTokensResponse {}

// MsgUpdateTokenMapping defines the request type
message MsgUpdateTokenMapping {
string sender = 1;
string denom = 2;
string contract = 3;
}

// MsgUpdateTokenMappingResponse defines the response type
message MsgUpdateTokenMappingResponse {
}

// this line is used by starport scaffolding # proto/tx/message
3 changes: 3 additions & 0 deletions scripts/cronos-devnet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ cronos_777-1:
evm:
params:
evm_denom: basetcro
cronos:
params:
cronos_admin: crc12luku6uxehhak02py4rcz65zu0swh7wjsrw0pp
gov:
voting_params:
voting_period: "10s"
Expand Down
26 changes: 26 additions & 0 deletions x/cronos/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func GetTxCmd() *cobra.Command {

cmd.AddCommand(CmdConvertTokens())
cmd.AddCommand(CmdSendToCryptoOrg())
cmd.AddCommand(CmdUpdateTokenMapping())

return cmd
}
Expand Down Expand Up @@ -174,3 +175,28 @@ $ %s tx gov submit-proposal token-mapping-change gravity0x0000...0000 0x0000...0

return cmd
}

// CmdUpdateTokenMapping returns a CLI command handler for update token mapping
func CmdUpdateTokenMapping() *cobra.Command {
cmd := &cobra.Command{
Use: "update-token-mapping [denom] [contract]",
Short: "Update token mapping",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

msg := types.NewMsgUpdateTokenMapping(clientCtx.GetFromAddress().String(), args[0], args[1])
if err := msg.ValidateBasic(); err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}
9 changes: 5 additions & 4 deletions x/cronos/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package cronos_test

import (
"errors"
"strings"
"testing"
"time"

"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
Expand All @@ -11,9 +15,6 @@ import (
"github.com/stretchr/testify/suite"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/tharsis/ethermint/crypto/ethsecp256k1"
"strings"
"testing"
"time"
)

type CronosTestSuite struct {
Expand All @@ -31,7 +32,7 @@ func TestCronosTestSuite(t *testing.T) {

func (suite *CronosTestSuite) SetupTest() {
checkTx := false
suite.app = app.Setup(false)
suite.app = app.Setup(false, "")
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1, ChainID: app.TestAppChainID, Time: time.Now().UTC()})
suite.handler = cronos.NewHandler(suite.app.CronosKeeper)

Expand Down
13 changes: 8 additions & 5 deletions x/cronos/keeper/keeper_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package keeper_test

import (
evmtypes "github.com/tharsis/ethermint/x/evm/types"
"math/big"
"testing"
"time"

evmtypes "github.com/tharsis/ethermint/x/evm/types"

sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
Expand Down Expand Up @@ -36,6 +37,8 @@ type KeeperTestSuite struct {

// EVM helpers
evmParam evmtypes.Params

address common.Address
}

func (suite *KeeperTestSuite) DoSetupTest(t require.TestingT) {
Expand All @@ -44,14 +47,14 @@ func (suite *KeeperTestSuite) DoSetupTest(t require.TestingT) {
// account key
priv, err := ethsecp256k1.GenerateKey()
require.NoError(t, err)
address := common.BytesToAddress(priv.PubKey().Address().Bytes())
suite.address = common.BytesToAddress(priv.PubKey().Address().Bytes())

// consensus key
priv, err = ethsecp256k1.GenerateKey()
require.NoError(t, err)
consAddress := sdk.ConsAddress(priv.PubKey().Address())

suite.app = app.Setup(checkTx)
suite.app = app.Setup(checkTx, sdk.AccAddress(suite.address.Bytes()).String())
suite.ctx = suite.app.NewContext(checkTx, tmproto.Header{
Height: 1,
ChainID: app.TestAppChainID,
Expand Down Expand Up @@ -79,13 +82,13 @@ func (suite *KeeperTestSuite) DoSetupTest(t require.TestingT) {

// initialize the validator
acc := &ethermint.EthAccount{
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(address.Bytes()), nil, 0, 0),
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0),
CodeHash: common.BytesToHash(ethcrypto.Keccak256(nil)).String(),
}

suite.app.AccountKeeper.SetAccount(suite.ctx, acc)

valAddr := sdk.ValAddress(address.Bytes())
valAddr := sdk.ValAddress(suite.address.Bytes())
validator, err := stakingtypes.NewValidator(valAddr, priv.PubKey(), stakingtypes.Description{})
err = suite.app.StakingKeeper.SetValidatorByConsAddr(suite.ctx, validator)
require.NoError(t, err)
Expand Down
15 changes: 15 additions & 0 deletions x/cronos/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"context"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/crypto-org-chain/cronos/x/cronos/types"
"github.com/ethereum/go-ethereum/common"
)

type msgServer struct {
Expand Down Expand Up @@ -55,3 +57,16 @@ func (k msgServer) TransferTokens(goCtx context.Context, msg *types.MsgTransferT
)
return &types.MsgTransferTokensResponse{}, nil
}

// UpdateTokenMapping implements the grpc method
func (k msgServer) UpdateTokenMapping(goCtx context.Context, msg *types.MsgUpdateTokenMapping) (*types.MsgUpdateTokenMappingResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
admin := k.Keeper.GetParams(ctx).CronosAdmin
// if admin is empty, no sender could be equal to it
if admin != msg.Sender {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "msg sender is authorized")
}
// msg is already validated
k.Keeper.SetExternalContractForDenom(ctx, msg.Denom, common.HexToAddress(msg.Contract))
return &types.MsgUpdateTokenMappingResponse{}, nil
}
22 changes: 22 additions & 0 deletions x/cronos/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
@@ -1 +1,23 @@
package keeper_test

import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/crypto-org-chain/cronos/x/cronos/keeper"
"github.com/crypto-org-chain/cronos/x/cronos/types"
)

func (suite *KeeperTestSuite) TestUpdateTokenMapping() {
suite.SetupTest()

denom := "gravity0x6E7eef2b30585B2A4D45Ba9312015d5354FDB067"
contract := "0x57f96e6B86CdeFdB3d412547816a82E3E0EbF9D2"

msg := types.NewMsgUpdateTokenMapping(sdk.AccAddress(suite.address.Bytes()).String(), denom, contract)
msgServer := keeper.NewMsgServerImpl(suite.app.CronosKeeper)
_, err := msgServer.UpdateTokenMapping(sdk.WrapSDKContext(suite.ctx), msg)
suite.Require().NoError(err)

contractAddr, found := suite.app.CronosKeeper.GetContractByDenom(suite.ctx, denom)
suite.Require().True(found)
suite.Require().Equal(contract, contractAddr.Hex())
}
Loading

0 comments on commit eb25147

Please sign in to comment.