Skip to content

Commit

Permalink
Problem: no command to enable/disable bridge (#775)
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas-nguy authored Dec 5, 2022
1 parent c9789da commit be8d53d
Show file tree
Hide file tree
Showing 11 changed files with 642 additions and 56 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- [cronos#742](https://github.com/crypto-org-chain/cronos/pull/742) Add upgrade handler for v0.8.0-gravity-alpha2.
- [cronos#750](https://github.com/crypto-org-chain/cronos/pull/750) Add upgrade handler for v0.8.0-gravity-alpha3.
- [cronos#769](https://github.com/crypto-org-chain/cronos/pull/769) Prevent cancellation function to be called outside the scope of the contract that manage it.
- [cronos#775](https://github.com/crypto-org-chain/cronos/pull/775) Support turnbridge transaction.

### Improvements

Expand Down
26 changes: 26 additions & 0 deletions integration_tests/cosmoscli.py
Original file line number Diff line number Diff line change
Expand Up @@ -1404,3 +1404,29 @@ def query_grant(self, granter, grantee):
home=self.data_dir,
)
)

def query_batches(self):
"query all gravity batches"
return json.loads(
self.raw(
"query",
"gravity",
"batch-txs",
home=self.data_dir,
)
)

def turn_bridge(self, enable, **kwargs):
kwargs.setdefault("gas_prices", DEFAULT_GAS_PRICE)
kwargs.setdefault("gas", DEFAULT_GAS)
return json.loads(
self.raw(
"tx",
"cronos",
"turn-bridge",
enable,
"-y",
home=self.data_dir,
**kwargs,
)
)
71 changes: 71 additions & 0 deletions integration_tests/test_gravity.py
Original file line number Diff line number Diff line change
Expand Up @@ -795,3 +795,74 @@ def check():
gravity.contract.functions.redeemVoucher(
old_nonce, ADDRS["signer2"]
).build_transaction({"from": ADDRS["signer1"]})


def test_gravity_turn_bridge(gravity):
geth = gravity.geth
cli = gravity.cronos.cosmos_cli()
cronos_w3 = gravity.cronos.w3

# deploy test erc20 contract
erc20 = deploy_contract(
geth,
CONTRACTS["TestERC20A"],
)

balance = erc20.caller.balanceOf(ADDRS["validator"])
assert balance == 100000000000000000000000000
amount = 1000

print("send to cronos crc20")
recipient = HexBytes(ADDRS["community"])
txreceipt = send_to_cosmos(
gravity.contract, erc20, geth, recipient, amount, KEYS["validator"]
)
assert txreceipt.status == 1, "should success"
assert erc20.caller.balanceOf(ADDRS["validator"]) == balance - amount

denom = f"gravity{erc20.address}"

def check_gravity_native_tokens():
"check the balance of gravity native token"
return cli.balance(eth_to_bech32(recipient), denom=denom) == amount

if gravity.cronos.enable_auto_deployment:
crc21_contract = None

def local_check_auto_deployment():
nonlocal crc21_contract
crc21_contract = check_auto_deployment(
cli, denom, cronos_w3, recipient, amount
)
return crc21_contract

wait_for_fn("send-to-crc21", local_check_auto_deployment)
else:
wait_for_fn("send-to-gravity-native", check_gravity_native_tokens)

# turn off bridge
rsp = cli.turn_bridge("false", from_="community")
assert rsp["code"] != 0, "should not have the permission"

rsp = cli.turn_bridge("false", from_="validator")
assert rsp["code"] == 0, rsp["raw_log"]
wait_for_new_blocks(cli, 1)

if gravity.cronos.enable_auto_deployment:
# send it back to erc20, should fail
tx = crc21_contract.functions.send_to_evm_chain(
ADDRS["validator"], amount, 1, 0, b""
).build_transaction({"from": ADDRS["community"]})
txreceipt = send_transaction(cronos_w3, tx, KEYS["community"])
assert txreceipt.status == 0, "should fail"
else:
# send back the gravity native tokens, should fail
rsp = cli.send_to_ethereum(
ADDRS["validator"], f"{amount}{denom}", f"0{denom}", from_="community"
)
assert rsp["code"] == 3, rsp["raw_log"]

wait_for_new_blocks(cli, 10)
# check no new batch is created
rsp = cli.query_batches()
assert len(rsp["batches"]) == 0
66 changes: 43 additions & 23 deletions proto/cronos/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,43 @@ option go_package = "github.com/crypto-org-chain/cronos/x/cronos/types";

// Msg defines the Cronos Msg service
service Msg {
// this line is used by starport scaffolding # proto/tx/rpc
// this line is used by starport scaffolding # proto/tx/rpc

// ConvertVouchers defines a method for converting ibc voucher to cronos evm coins.
rpc ConvertVouchers(MsgConvertVouchers) returns (MsgConvertVouchersResponse);
// ConvertVouchers defines a method for converting ibc voucher to cronos evm
// coins.
rpc ConvertVouchers(MsgConvertVouchers) returns (MsgConvertVouchersResponse);

// TransferTokens defines a method to transfer cronos evm coins to another chain through IBC
rpc TransferTokens(MsgTransferTokens) returns (MsgTransferTokensResponse);
// 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);
// UpdateTokenMapping defines a method to update token mapping
rpc UpdateTokenMapping(MsgUpdateTokenMapping)
returns (MsgUpdateTokenMappingResponse);

// TurnBridge defines a method to disable or enable the gravity bridge
rpc TurnBridge(MsgTurnBridge) returns (MsgTurnBridgeResponse);
}

// MsgConvertVouchers represents a message to convert ibc voucher coins to cronos evm coins.
// MsgConvertVouchers represents a message to convert ibc voucher coins to
// cronos evm coins.
message MsgConvertVouchers {
string address = 1;
repeated cosmos.base.v1beta1.Coin coins = 2
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
string address = 1;
repeated cosmos.base.v1beta1.Coin coins = 2 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
}

// MsgTransferTokens represents a message to transfer cronos evm coins through ibc.
// MsgTransferTokens represents a message to transfer cronos evm coins through
// ibc.
message MsgTransferTokens {
string from = 1;
string to = 2;
repeated cosmos.base.v1beta1.Coin coins = 3
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
string from = 1;
string to = 2;
repeated cosmos.base.v1beta1.Coin coins = 3 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
}

// MsgConvertVouchersResponse defines the ConvertVouchers response type.
Expand All @@ -45,16 +57,24 @@ message MsgTransferTokensResponse {}

// MsgUpdateTokenMapping defines the request type
message MsgUpdateTokenMapping {
string sender = 1;
string denom = 2;
string contract = 3;
// only when updating cronos (source) tokens
string symbol = 4;
uint32 decimal = 5;
string sender = 1;
string denom = 2;
string contract = 3;
// only when updating cronos (source) tokens
string symbol = 4;
uint32 decimal = 5;
}

// MsgUpdateTokenMappingResponse defines the response type
message MsgUpdateTokenMappingResponse {
message MsgUpdateTokenMappingResponse {}

// MsgTurnBridge defines the request type
message MsgTurnBridge {
string sender = 1;
bool enable = 2;
}

// MsgTurnBridgegResponse defines the response type
message MsgTurnBridgeResponse {}

// this line is used by starport scaffolding # proto/tx/message
30 changes: 30 additions & 0 deletions x/cronos/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cli

import (
"fmt"
"strconv"
"strings"

"github.com/cosmos/cosmos-sdk/client/flags"
Expand Down Expand Up @@ -34,6 +35,7 @@ func GetTxCmd() *cobra.Command {
cmd.AddCommand(CmdConvertTokens())
cmd.AddCommand(CmdSendToCryptoOrg())
cmd.AddCommand(CmdUpdateTokenMapping())
cmd.AddCommand(CmdTurnBridge())

return cmd
}
Expand Down Expand Up @@ -249,3 +251,31 @@ func CmdUpdateTokenMapping() *cobra.Command {

return cmd
}

// CmdTurnBridge returns a CLI command handler for enable or disable the bridge
func CmdTurnBridge() *cobra.Command {
cmd := &cobra.Command{
Use: "turn-bridge [true/false]",
Short: "Turn Bridge",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

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

flags.AddTxFlagsToCmd(cmd)
return cmd
}
4 changes: 3 additions & 1 deletion x/cronos/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
case *types.MsgConvertVouchers:
res, err := msgServer.ConvertVouchers(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)

case *types.MsgTransferTokens:
res, err := msgServer.TransferTokens(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *types.MsgUpdateTokenMapping:
res, err := msgServer.UpdateTokenMapping(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *types.MsgTurnBridge:
res, err := msgServer.TurnBridge(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
default:
errMsg := fmt.Sprintf("unrecognized %s message type: %T", types.ModuleName, msg)
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg)
Expand Down
16 changes: 16 additions & 0 deletions x/cronos/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,19 @@ func (k msgServer) UpdateTokenMapping(goCtx context.Context, msg *types.MsgUpdat
}
return &types.MsgUpdateTokenMappingResponse{}, nil
}

// TurnBridge implements the grpc method
func (k msgServer) TurnBridge(goCtx context.Context, msg *types.MsgTurnBridge) (*types.MsgTurnBridgeResponse, 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")
}

gravityParams := k.gravityKeeper.GetParams(ctx)
gravityParams.BridgeActive = msg.Enable
k.gravityKeeper.SetParams(ctx, gravityParams)

return &types.MsgTurnBridgeResponse{}, nil
}
2 changes: 1 addition & 1 deletion x/cronos/types/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const (
)

// NewConvertVouchersEvent constructs a new voucher convert sdk.Event
//nolint: interfacer
// nolint: interfacer
func NewConvertVouchersEvent(sender string, amount fmt.Stringer) sdk.Event {
return sdk.NewEvent(
EventTypeConvertVouchers,
Expand Down
1 change: 1 addition & 0 deletions x/cronos/types/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type GravityKeeper interface {
ERC20ToDenomLookup(ctx sdk.Context, tokenContract common.Address) (bool, string)
IterateUnbatchedSendToEthereums(ctx sdk.Context, cb func(*gravitytypes.SendToEthereum) bool)
GetParams(ctx sdk.Context) (params gravitytypes.Params)
SetParams(ctx sdk.Context, params gravitytypes.Params)
}

// EvmLogHandler defines the interface for evm log handler
Expand Down
46 changes: 46 additions & 0 deletions x/cronos/types/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const (
TypeMsgConvertVouchers = "ConvertVouchers"
TypeMsgTransferTokens = "TransferTokens"
TypeMsgUpdateTokenMapping = "UpdateTokenMapping"
TypeTurnBridge = "TurnBridge"
)

var _ sdk.Msg = &MsgConvertVouchers{}
Expand Down Expand Up @@ -171,3 +172,48 @@ func (msg *MsgUpdateTokenMapping) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(msg)
return sdk.MustSortJSON(bz)
}

var _ sdk.Msg = &MsgTurnBridge{}

// NewMsgTurnBridge ...
func NewMsgTurnBridge(admin string, enable bool) *MsgTurnBridge {
return &MsgTurnBridge{
Sender: admin,
Enable: enable,
}
}

// GetSigners ...
func (msg *MsgTurnBridge) GetSigners() []sdk.AccAddress {
sender, err := sdk.AccAddressFromBech32(msg.Sender)
if err != nil {
panic(err)
}
return []sdk.AccAddress{sender}
}

// ValidateBasic ...
func (msg *MsgTurnBridge) ValidateBasic() error {
_, err := sdk.AccAddressFromBech32(msg.Sender)
if err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid sender address (%s)", err)
}

return nil
}

// Route ...
func (msg MsgTurnBridge) Route() string {
return RouterKey
}

// Type ...
func (msg MsgTurnBridge) Type() string {
return TypeTurnBridge
}

// GetSignBytes ...
func (msg *MsgTurnBridge) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(msg)
return sdk.MustSortJSON(bz)
}
Loading

0 comments on commit be8d53d

Please sign in to comment.