Skip to content

Commit be8d53d

Browse files
authored
Problem: no command to enable/disable bridge (#775)
1 parent c9789da commit be8d53d

11 files changed

Lines changed: 642 additions & 56 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
- [cronos#742](https://github.com/crypto-org-chain/cronos/pull/742) Add upgrade handler for v0.8.0-gravity-alpha2.
99
- [cronos#750](https://github.com/crypto-org-chain/cronos/pull/750) Add upgrade handler for v0.8.0-gravity-alpha3.
1010
- [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.
11+
- [cronos#775](https://github.com/crypto-org-chain/cronos/pull/775) Support turnbridge transaction.
1112

1213
### Improvements
1314

integration_tests/cosmoscli.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,3 +1404,29 @@ def query_grant(self, granter, grantee):
14041404
home=self.data_dir,
14051405
)
14061406
)
1407+
1408+
def query_batches(self):
1409+
"query all gravity batches"
1410+
return json.loads(
1411+
self.raw(
1412+
"query",
1413+
"gravity",
1414+
"batch-txs",
1415+
home=self.data_dir,
1416+
)
1417+
)
1418+
1419+
def turn_bridge(self, enable, **kwargs):
1420+
kwargs.setdefault("gas_prices", DEFAULT_GAS_PRICE)
1421+
kwargs.setdefault("gas", DEFAULT_GAS)
1422+
return json.loads(
1423+
self.raw(
1424+
"tx",
1425+
"cronos",
1426+
"turn-bridge",
1427+
enable,
1428+
"-y",
1429+
home=self.data_dir,
1430+
**kwargs,
1431+
)
1432+
)

integration_tests/test_gravity.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,3 +795,74 @@ def check():
795795
gravity.contract.functions.redeemVoucher(
796796
old_nonce, ADDRS["signer2"]
797797
).build_transaction({"from": ADDRS["signer1"]})
798+
799+
800+
def test_gravity_turn_bridge(gravity):
801+
geth = gravity.geth
802+
cli = gravity.cronos.cosmos_cli()
803+
cronos_w3 = gravity.cronos.w3
804+
805+
# deploy test erc20 contract
806+
erc20 = deploy_contract(
807+
geth,
808+
CONTRACTS["TestERC20A"],
809+
)
810+
811+
balance = erc20.caller.balanceOf(ADDRS["validator"])
812+
assert balance == 100000000000000000000000000
813+
amount = 1000
814+
815+
print("send to cronos crc20")
816+
recipient = HexBytes(ADDRS["community"])
817+
txreceipt = send_to_cosmos(
818+
gravity.contract, erc20, geth, recipient, amount, KEYS["validator"]
819+
)
820+
assert txreceipt.status == 1, "should success"
821+
assert erc20.caller.balanceOf(ADDRS["validator"]) == balance - amount
822+
823+
denom = f"gravity{erc20.address}"
824+
825+
def check_gravity_native_tokens():
826+
"check the balance of gravity native token"
827+
return cli.balance(eth_to_bech32(recipient), denom=denom) == amount
828+
829+
if gravity.cronos.enable_auto_deployment:
830+
crc21_contract = None
831+
832+
def local_check_auto_deployment():
833+
nonlocal crc21_contract
834+
crc21_contract = check_auto_deployment(
835+
cli, denom, cronos_w3, recipient, amount
836+
)
837+
return crc21_contract
838+
839+
wait_for_fn("send-to-crc21", local_check_auto_deployment)
840+
else:
841+
wait_for_fn("send-to-gravity-native", check_gravity_native_tokens)
842+
843+
# turn off bridge
844+
rsp = cli.turn_bridge("false", from_="community")
845+
assert rsp["code"] != 0, "should not have the permission"
846+
847+
rsp = cli.turn_bridge("false", from_="validator")
848+
assert rsp["code"] == 0, rsp["raw_log"]
849+
wait_for_new_blocks(cli, 1)
850+
851+
if gravity.cronos.enable_auto_deployment:
852+
# send it back to erc20, should fail
853+
tx = crc21_contract.functions.send_to_evm_chain(
854+
ADDRS["validator"], amount, 1, 0, b""
855+
).build_transaction({"from": ADDRS["community"]})
856+
txreceipt = send_transaction(cronos_w3, tx, KEYS["community"])
857+
assert txreceipt.status == 0, "should fail"
858+
else:
859+
# send back the gravity native tokens, should fail
860+
rsp = cli.send_to_ethereum(
861+
ADDRS["validator"], f"{amount}{denom}", f"0{denom}", from_="community"
862+
)
863+
assert rsp["code"] == 3, rsp["raw_log"]
864+
865+
wait_for_new_blocks(cli, 10)
866+
# check no new batch is created
867+
rsp = cli.query_batches()
868+
assert len(rsp["batches"]) == 0

proto/cronos/tx.proto

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,43 @@ option go_package = "github.com/crypto-org-chain/cronos/x/cronos/types";
1010

1111
// Msg defines the Cronos Msg service
1212
service Msg {
13-
// this line is used by starport scaffolding # proto/tx/rpc
13+
// this line is used by starport scaffolding # proto/tx/rpc
1414

15-
// ConvertVouchers defines a method for converting ibc voucher to cronos evm coins.
16-
rpc ConvertVouchers(MsgConvertVouchers) returns (MsgConvertVouchersResponse);
15+
// ConvertVouchers defines a method for converting ibc voucher to cronos evm
16+
// coins.
17+
rpc ConvertVouchers(MsgConvertVouchers) returns (MsgConvertVouchersResponse);
1718

18-
// TransferTokens defines a method to transfer cronos evm coins to another chain through IBC
19-
rpc TransferTokens(MsgTransferTokens) returns (MsgTransferTokensResponse);
19+
// TransferTokens defines a method to transfer cronos evm coins to another
20+
// chain through IBC
21+
rpc TransferTokens(MsgTransferTokens) returns (MsgTransferTokensResponse);
2022

21-
// UpdateTokenMapping defines a method to update token mapping
22-
rpc UpdateTokenMapping(MsgUpdateTokenMapping) returns (MsgUpdateTokenMappingResponse);
23+
// UpdateTokenMapping defines a method to update token mapping
24+
rpc UpdateTokenMapping(MsgUpdateTokenMapping)
25+
returns (MsgUpdateTokenMappingResponse);
26+
27+
// TurnBridge defines a method to disable or enable the gravity bridge
28+
rpc TurnBridge(MsgTurnBridge) returns (MsgTurnBridgeResponse);
2329
}
2430

25-
// MsgConvertVouchers represents a message to convert ibc voucher coins to cronos evm coins.
31+
// MsgConvertVouchers represents a message to convert ibc voucher coins to
32+
// cronos evm coins.
2633
message MsgConvertVouchers {
27-
string address = 1;
28-
repeated cosmos.base.v1beta1.Coin coins = 2
29-
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
34+
string address = 1;
35+
repeated cosmos.base.v1beta1.Coin coins = 2 [
36+
(gogoproto.nullable) = false,
37+
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
38+
];
3039
}
3140

32-
// MsgTransferTokens represents a message to transfer cronos evm coins through ibc.
41+
// MsgTransferTokens represents a message to transfer cronos evm coins through
42+
// ibc.
3343
message MsgTransferTokens {
34-
string from = 1;
35-
string to = 2;
36-
repeated cosmos.base.v1beta1.Coin coins = 3
37-
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
44+
string from = 1;
45+
string to = 2;
46+
repeated cosmos.base.v1beta1.Coin coins = 3 [
47+
(gogoproto.nullable) = false,
48+
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
49+
];
3850
}
3951

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

4658
// MsgUpdateTokenMapping defines the request type
4759
message MsgUpdateTokenMapping {
48-
string sender = 1;
49-
string denom = 2;
50-
string contract = 3;
51-
// only when updating cronos (source) tokens
52-
string symbol = 4;
53-
uint32 decimal = 5;
60+
string sender = 1;
61+
string denom = 2;
62+
string contract = 3;
63+
// only when updating cronos (source) tokens
64+
string symbol = 4;
65+
uint32 decimal = 5;
5466
}
5567

5668
// MsgUpdateTokenMappingResponse defines the response type
57-
message MsgUpdateTokenMappingResponse {
69+
message MsgUpdateTokenMappingResponse {}
70+
71+
// MsgTurnBridge defines the request type
72+
message MsgTurnBridge {
73+
string sender = 1;
74+
bool enable = 2;
5875
}
5976

77+
// MsgTurnBridgegResponse defines the response type
78+
message MsgTurnBridgeResponse {}
79+
6080
// this line is used by starport scaffolding # proto/tx/message

x/cronos/client/cli/tx.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cli
22

33
import (
44
"fmt"
5+
"strconv"
56
"strings"
67

78
"github.com/cosmos/cosmos-sdk/client/flags"
@@ -34,6 +35,7 @@ func GetTxCmd() *cobra.Command {
3435
cmd.AddCommand(CmdConvertTokens())
3536
cmd.AddCommand(CmdSendToCryptoOrg())
3637
cmd.AddCommand(CmdUpdateTokenMapping())
38+
cmd.AddCommand(CmdTurnBridge())
3739

3840
return cmd
3941
}
@@ -249,3 +251,31 @@ func CmdUpdateTokenMapping() *cobra.Command {
249251

250252
return cmd
251253
}
254+
255+
// CmdTurnBridge returns a CLI command handler for enable or disable the bridge
256+
func CmdTurnBridge() *cobra.Command {
257+
cmd := &cobra.Command{
258+
Use: "turn-bridge [true/false]",
259+
Short: "Turn Bridge",
260+
Args: cobra.ExactArgs(1),
261+
RunE: func(cmd *cobra.Command, args []string) error {
262+
clientCtx, err := client.GetClientTxContext(cmd)
263+
if err != nil {
264+
return err
265+
}
266+
267+
enable, err := strconv.ParseBool(args[0])
268+
if err != nil {
269+
return err
270+
}
271+
msg := types.NewMsgTurnBridge(clientCtx.GetFromAddress().String(), enable)
272+
if err := msg.ValidateBasic(); err != nil {
273+
return err
274+
}
275+
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
276+
},
277+
}
278+
279+
flags.AddTxFlagsToCmd(cmd)
280+
return cmd
281+
}

x/cronos/handler.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
2222
case *types.MsgConvertVouchers:
2323
res, err := msgServer.ConvertVouchers(sdk.WrapSDKContext(ctx), msg)
2424
return sdk.WrapServiceResult(ctx, res, err)
25-
2625
case *types.MsgTransferTokens:
2726
res, err := msgServer.TransferTokens(sdk.WrapSDKContext(ctx), msg)
2827
return sdk.WrapServiceResult(ctx, res, err)
2928
case *types.MsgUpdateTokenMapping:
3029
res, err := msgServer.UpdateTokenMapping(sdk.WrapSDKContext(ctx), msg)
3130
return sdk.WrapServiceResult(ctx, res, err)
31+
case *types.MsgTurnBridge:
32+
res, err := msgServer.TurnBridge(sdk.WrapSDKContext(ctx), msg)
33+
return sdk.WrapServiceResult(ctx, res, err)
3234
default:
3335
errMsg := fmt.Sprintf("unrecognized %s message type: %T", types.ModuleName, msg)
3436
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg)

x/cronos/keeper/msg_server.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,19 @@ func (k msgServer) UpdateTokenMapping(goCtx context.Context, msg *types.MsgUpdat
7373
}
7474
return &types.MsgUpdateTokenMappingResponse{}, nil
7575
}
76+
77+
// TurnBridge implements the grpc method
78+
func (k msgServer) TurnBridge(goCtx context.Context, msg *types.MsgTurnBridge) (*types.MsgTurnBridgeResponse, error) {
79+
ctx := sdk.UnwrapSDKContext(goCtx)
80+
admin := k.Keeper.GetParams(ctx).CronosAdmin
81+
// if admin is empty, no sender could be equal to it
82+
if admin != msg.Sender {
83+
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "msg sender is authorized")
84+
}
85+
86+
gravityParams := k.gravityKeeper.GetParams(ctx)
87+
gravityParams.BridgeActive = msg.Enable
88+
k.gravityKeeper.SetParams(ctx, gravityParams)
89+
90+
return &types.MsgTurnBridgeResponse{}, nil
91+
}

x/cronos/types/events.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const (
2222
)
2323

2424
// NewConvertVouchersEvent constructs a new voucher convert sdk.Event
25-
//nolint: interfacer
25+
// nolint: interfacer
2626
func NewConvertVouchersEvent(sender string, amount fmt.Stringer) sdk.Event {
2727
return sdk.NewEvent(
2828
EventTypeConvertVouchers,

x/cronos/types/interfaces.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ type GravityKeeper interface {
5959
ERC20ToDenomLookup(ctx sdk.Context, tokenContract common.Address) (bool, string)
6060
IterateUnbatchedSendToEthereums(ctx sdk.Context, cb func(*gravitytypes.SendToEthereum) bool)
6161
GetParams(ctx sdk.Context) (params gravitytypes.Params)
62+
SetParams(ctx sdk.Context, params gravitytypes.Params)
6263
}
6364

6465
// EvmLogHandler defines the interface for evm log handler

x/cronos/types/messages.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const (
1010
TypeMsgConvertVouchers = "ConvertVouchers"
1111
TypeMsgTransferTokens = "TransferTokens"
1212
TypeMsgUpdateTokenMapping = "UpdateTokenMapping"
13+
TypeTurnBridge = "TurnBridge"
1314
)
1415

1516
var _ sdk.Msg = &MsgConvertVouchers{}
@@ -171,3 +172,48 @@ func (msg *MsgUpdateTokenMapping) GetSignBytes() []byte {
171172
bz := ModuleCdc.MustMarshalJSON(msg)
172173
return sdk.MustSortJSON(bz)
173174
}
175+
176+
var _ sdk.Msg = &MsgTurnBridge{}
177+
178+
// NewMsgTurnBridge ...
179+
func NewMsgTurnBridge(admin string, enable bool) *MsgTurnBridge {
180+
return &MsgTurnBridge{
181+
Sender: admin,
182+
Enable: enable,
183+
}
184+
}
185+
186+
// GetSigners ...
187+
func (msg *MsgTurnBridge) GetSigners() []sdk.AccAddress {
188+
sender, err := sdk.AccAddressFromBech32(msg.Sender)
189+
if err != nil {
190+
panic(err)
191+
}
192+
return []sdk.AccAddress{sender}
193+
}
194+
195+
// ValidateBasic ...
196+
func (msg *MsgTurnBridge) ValidateBasic() error {
197+
_, err := sdk.AccAddressFromBech32(msg.Sender)
198+
if err != nil {
199+
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid sender address (%s)", err)
200+
}
201+
202+
return nil
203+
}
204+
205+
// Route ...
206+
func (msg MsgTurnBridge) Route() string {
207+
return RouterKey
208+
}
209+
210+
// Type ...
211+
func (msg MsgTurnBridge) Type() string {
212+
return TypeTurnBridge
213+
}
214+
215+
// GetSignBytes ...
216+
func (msg *MsgTurnBridge) GetSignBytes() []byte {
217+
bz := ModuleCdc.MustMarshalJSON(msg)
218+
return sdk.MustSortJSON(bz)
219+
}

0 commit comments

Comments
 (0)