Skip to content

Commit 4f16b10

Browse files
committed
Refactor MsgUnlockTokens in EVM bridge module to replace toAddress with fromEvmAddress, updating related protobuf and Go files. Enhance address mapping functionality by adding methods for setting and retrieving mappings between EVM and Cosmos addresses. Implement validation for authorized workers and improve error handling in UnlockTokens method.
1 parent 2a21efe commit 4f16b10

File tree

11 files changed

+267
-141
lines changed

11 files changed

+267
-141
lines changed

api/junction/evmbridge/tx.pulsar.go

Lines changed: 74 additions & 74 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

proto/junction/evmbridge/tx.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ message MsgLockTokensResponse {}
5050
message MsgUnlockTokens {
5151
option (cosmos.msg.v1.signer) = "creator";
5252
string creator = 1;
53-
string toAddress = 2;
53+
string fromEvmAddress = 2;
5454
string amount = 3;
5555
string evmTxHash = 4;
5656
}

x/evmbridge/keeper/ledger.go

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,24 @@ import (
1414
"google.golang.org/grpc/status"
1515
)
1616

17-
func (k Keeper) GetAddressLockedAmount(ctx sdk.Context, address string) (uint64, error) {
17+
func (k Keeper) GetAddressLockedAmount(ctx sdk.Context, cosmos_address string) (uint64, error) {
1818
storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
19-
rollupRegistryStore := prefix.NewStore(storeAdapter, types.KeyPrefix(types.EVMLedgerKey))
19+
ledgerStore := prefix.NewStore(storeAdapter, types.KeyPrefix(types.EVMLedgerKey))
2020

21-
amountBytes := rollupRegistryStore.Get([]byte(address))
21+
amountBytes := ledgerStore.Get([]byte(cosmos_address))
2222
if amountBytes == nil {
2323
return 0, nil
2424
}
2525
amount := binary.BigEndian.Uint64(amountBytes)
2626
return amount, nil
2727
}
2828

29-
func (k Keeper) AddAddressLockedAmount(ctx sdk.Context, address string, amountToAdd uint64) (uint64, error) {
29+
func (k Keeper) AddAddressLockedAmount(ctx sdk.Context, cosmos_address string, amountToAdd uint64) (uint64, error) {
3030
storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
31-
rollupRegistryStore := prefix.NewStore(storeAdapter, types.KeyPrefix(types.EVMLedgerKey))
31+
ledgerStore := prefix.NewStore(storeAdapter, types.KeyPrefix(types.EVMLedgerKey))
3232

3333
// Get current amount
34-
currentAmount, err := k.GetAddressLockedAmount(ctx, address)
34+
currentAmount, err := k.GetAddressLockedAmount(ctx, cosmos_address)
3535
if err != nil {
3636
return 0, err
3737
}
@@ -42,17 +42,17 @@ func (k Keeper) AddAddressLockedAmount(ctx sdk.Context, address string, amountTo
4242
// Convert to bytes and store
4343
amountBytes := make([]byte, 8)
4444
binary.BigEndian.PutUint64(amountBytes, newAmount)
45-
rollupRegistryStore.Set([]byte(address), amountBytes)
45+
ledgerStore.Set([]byte(cosmos_address), amountBytes)
4646

4747
return newAmount, nil
4848
}
4949

50-
func (k Keeper) SubtractAddressLockedAmount(ctx sdk.Context, address string, amountToSubtract uint64) (uint64, error) {
50+
func (k Keeper) SubtractAddressLockedAmount(ctx sdk.Context, cosmos_address string, amountToSubtract uint64) (uint64, error) {
5151
storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
52-
rollupRegistryStore := prefix.NewStore(storeAdapter, types.KeyPrefix(types.EVMLedgerKey))
52+
ledgerStore := prefix.NewStore(storeAdapter, types.KeyPrefix(types.EVMLedgerKey))
5353

5454
// Get current amount
55-
currentAmount, err := k.GetAddressLockedAmount(ctx, address)
55+
currentAmount, err := k.GetAddressLockedAmount(ctx, cosmos_address)
5656
if err != nil {
5757
return 0, err
5858
}
@@ -68,19 +68,39 @@ func (k Keeper) SubtractAddressLockedAmount(ctx sdk.Context, address string, amo
6868
// Convert to bytes and store
6969
amountBytes := make([]byte, 8)
7070
binary.BigEndian.PutUint64(amountBytes, newAmount)
71-
rollupRegistryStore.Set([]byte(address), amountBytes)
71+
ledgerStore.Set([]byte(cosmos_address), amountBytes)
7272

7373
return newAmount, nil
7474
}
7575

76-
func (k Keeper) SetAddressLockedAmount(ctx sdk.Context, address string, amount uint64) error {
76+
func (k Keeper) SetAddressLockedAmount(ctx sdk.Context, cosmos_address string, amount uint64) error {
7777
storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
78-
rollupRegistryStore := prefix.NewStore(storeAdapter, types.KeyPrefix(types.EVMLedgerKey))
78+
ledgerStore := prefix.NewStore(storeAdapter, types.KeyPrefix(types.EVMLedgerKey))
7979

8080
// Convert to bytes and store
8181
amountBytes := make([]byte, 8)
8282
binary.BigEndian.PutUint64(amountBytes, amount)
83-
rollupRegistryStore.Set([]byte(address), amountBytes)
83+
ledgerStore.Set([]byte(cosmos_address), amountBytes)
8484

8585
return nil
8686
}
87+
88+
// Store address mapping (evm address -> cosmos address)
89+
func (k Keeper) SetAddressMapping(ctx sdk.Context, evm_address string, cosmos_address string) error {
90+
storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
91+
ledgerMappingStore := prefix.NewStore(storeAdapter, types.KeyPrefix(types.EVMMappingKey))
92+
93+
ledgerMappingStore.Set([]byte(evm_address), []byte(cosmos_address))
94+
return nil
95+
}
96+
97+
func (k Keeper) GetCosmosAddressMapping(ctx sdk.Context, evm_address string) (string, error) {
98+
storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
99+
ledgerMappingStore := prefix.NewStore(storeAdapter, types.KeyPrefix(types.EVMMappingKey))
100+
101+
cosmos_address := ledgerMappingStore.Get([]byte(evm_address))
102+
if cosmos_address == nil {
103+
return "", status.Error(codes.NotFound, "address mapping not found")
104+
}
105+
return string(cosmos_address), nil
106+
}

x/evmbridge/keeper/msg_server_lock_tokens.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ func (k msgServer) LockTokens(goCtx context.Context, msg *types.MsgLockTokens) (
7070
if err := k.SetAddressLockedAmount(ctx, msg.Creator, amountUint64); err != nil {
7171
return nil, types.ErrFailedToLockTokens.Wrap(err.Error())
7272
}
73+
if err := k.SetAddressMapping(ctx, msg.ToAddress, msg.Creator); err != nil {
74+
return nil, types.ErrFailedToMapAddress.Wrap(err.Error())
75+
}
7376

7477
// Emit simple event for bridge relayer
7578
sdkCtx.EventManager().EmitEvent(

x/evmbridge/keeper/msg_server_unlock_tokens.go

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ package keeper
22

33
import (
44
"context"
5+
"fmt"
6+
"strconv"
7+
"time"
58

69
"github.com/airchains-network/junction/x/evmbridge/types"
710
sdk "github.com/cosmos/cosmos-sdk/types"
@@ -10,8 +13,99 @@ import (
1013
func (k msgServer) UnlockTokens(goCtx context.Context, msg *types.MsgUnlockTokens) (*types.MsgUnlockTokensResponse, error) {
1114
ctx := sdk.UnwrapSDKContext(goCtx)
1215

13-
// TODO: Handling the message
14-
_ = ctx
16+
allowedWorkers := k.GetParams(ctx).BridgeWorkers
17+
var isAllowedWorker bool
18+
for _, worker := range allowedWorkers {
19+
if worker == msg.Creator {
20+
isAllowedWorker = true
21+
break
22+
}
23+
}
24+
if !isAllowedWorker {
25+
return nil, types.ErrUnauthorized.Wrapf("creator %s is not authorized to unlock tokens", msg.Creator)
26+
}
27+
28+
// get the cosmos address from the evm address
29+
cosmosAddress, err := k.GetCosmosAddressMapping(ctx, msg.FromEvmAddress)
30+
if err != nil {
31+
return nil, types.ErrInvalidAddress.Wrap(err.Error())
32+
}
33+
34+
// check if the to address is a valid cosmos address
35+
_, err = sdk.AccAddressFromBech32(cosmosAddress)
36+
if err != nil {
37+
return nil, types.ErrInvalidAddress.Wrapf("invalid to address: %s", err)
38+
}
39+
40+
// Validate evm tx hash
41+
if msg.EvmTxHash == "" {
42+
return nil, types.ErrInvalidEvmTxHash.Wrap("evm tx hash is required")
43+
}
44+
45+
// we need to check if the passed amount is a valid number or not
46+
_, err = strconv.ParseUint(msg.Amount, 10, 64)
47+
if err != nil {
48+
return nil, types.ErrInvalidAmount.Wrapf("invalid amount: %s", err)
49+
}
50+
// now we need to check if the amount is less than or equal to the locked amount
51+
lockedAmount, err := k.GetAddressLockedAmount(ctx, cosmosAddress)
52+
if err != nil {
53+
return nil, types.ErrInvalidAddress.Wrap(err.Error())
54+
}
55+
// Parse string amount to sdk.Coins first
56+
amount, err := sdk.ParseCoinsNormalized(msg.Amount)
57+
if err != nil {
58+
return nil, types.ErrInvalidAmount.Wrap(err.Error())
59+
}
60+
amountUint64, err := strconv.ParseUint(msg.Amount, 10, 64)
61+
if err != nil {
62+
return nil, types.ErrInvalidAmount.Wrapf("invalid amount: %s", err)
63+
}
64+
if amountUint64 > lockedAmount {
65+
return nil, types.ErrInsufficientUserBalance.Wrapf("insufficient locked amount: %d", amountUint64)
66+
}
67+
68+
// Get module account
69+
moduleAccount := k.accountKeeper.GetModuleAccount(ctx, types.ModuleName)
70+
if moduleAccount == nil {
71+
return nil, types.ErrModuleAccount.Wrap("module account not found")
72+
}
73+
74+
// Check if module has sufficient balance
75+
moduleBalance := k.bankKeeper.SpendableCoins(ctx, moduleAccount.GetAddress())
76+
if !moduleBalance.IsAllGTE(amount) {
77+
return nil, types.ErrInsufficientFunds.Wrapf("module insufficient funds: required %s, available %s", amount.String(), moduleBalance.String())
78+
}
79+
80+
// transfer the amount from the module account to the to address
81+
err = k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, sdk.MustAccAddressFromBech32(cosmosAddress), amount)
82+
if err != nil {
83+
return nil, types.ErrFailedToUnlockTokens.Wrap(err.Error())
84+
}
85+
86+
// now we need to subtract the amount from the locked amount
87+
_, err = k.SubtractAddressLockedAmount(ctx, cosmosAddress, amountUint64)
88+
if err != nil {
89+
return nil, types.ErrFailedToUnlockTokens.Wrap(err.Error())
90+
}
91+
92+
// Get current block info for event
93+
sdkCtx := sdk.UnwrapSDKContext(ctx)
94+
blockHeight := sdkCtx.BlockHeight()
95+
blockTime := sdkCtx.BlockTime()
96+
97+
// Emit simple unlock event
98+
sdkCtx.EventManager().EmitEvent(
99+
sdk.NewEvent(
100+
types.EventTypeTokensUnlocked,
101+
sdk.NewAttribute(types.AttributeKeyRecipient, cosmosAddress),
102+
sdk.NewAttribute(types.AttributeKeyFromEvmAddress, msg.FromEvmAddress),
103+
sdk.NewAttribute(types.AttributeKeyAmount, amount.String()),
104+
sdk.NewAttribute(types.AttributeKeyEVMTxHash, msg.EvmTxHash),
105+
sdk.NewAttribute(types.AttributeKeyBlockHeight, fmt.Sprintf("%d", blockHeight)),
106+
sdk.NewAttribute(types.AttributeKeyTimestamp, blockTime.Format(time.RFC3339)),
107+
),
108+
)
15109

16110
return &types.MsgUnlockTokensResponse{}, nil
17111
}

x/evmbridge/module/autocli.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
3636
},
3737
{
3838
RpcMethod: "UnlockTokens",
39-
Use: "unlock-tokens [to-address] [amount] [evm-tx-hash]",
39+
Use: "unlock-tokens [from-evm-address] [amount] [evm-tx-hash]",
4040
Short: "Send a unlock-tokens tx",
41-
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "toAddress"}, {ProtoField: "amount"}, {ProtoField: "evmTxHash"}},
41+
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "fromEvmAddress"}, {ProtoField: "amount"}, {ProtoField: "evmTxHash"}},
4242
},
4343
// this line is used by ignite scaffolding # autocli/tx
4444
},

x/evmbridge/types/errors.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,8 @@ var (
1818
ErrInvalidRecipient = sdkerrors.Register(ModuleName, 1106, "invalid recipient address")
1919
ErrInsufficientUserBalance = sdkerrors.Register(ModuleName, 1107, "user has insufficient locked balance")
2020
ErrFailedToLockTokens = sdkerrors.Register(ModuleName, 1108, "failed to lock tokens")
21+
ErrFailedToMapAddress = sdkerrors.Register(ModuleName, 1109, "failed to map address")
22+
ErrInvalidAddress = sdkerrors.Register(ModuleName, 1109, "invalid address")
23+
ErrInvalidEvmTxHash = sdkerrors.Register(ModuleName, 1110, "invalid evm tx hash")
24+
ErrFailedToUnlockTokens = sdkerrors.Register(ModuleName, 1111, "failed to unlock tokens")
2125
)

x/evmbridge/types/events.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,6 @@ const (
2424
AttributeKeyRecipient = "recipient"
2525
// AttributeKeyEVMTxHash is the EVM transaction hash that triggered the unlock
2626
AttributeKeyEVMTxHash = "evm_tx_hash"
27+
// AttributeKeyFromEvmAddress is the EVM address that triggered the unlock
28+
AttributeKeyFromEvmAddress = "from_evm_address"
2729
)

x/evmbridge/types/keys.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ const (
1111
MemStoreKey = "mem_evmbridge"
1212

1313
EVMLedgerKey = "evm_ledger"
14+
15+
EVMMappingKey = "evm_mapping"
1416
)
1517

1618
var (

x/evmbridge/types/message_unlock_tokens.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import (
88

99
var _ sdk.Msg = &MsgUnlockTokens{}
1010

11-
func NewMsgUnlockTokens(creator string, toAddress string, amount string, evmTxHash string) *MsgUnlockTokens {
11+
func NewMsgUnlockTokens(creator string, fromEvmAddress string, amount string, evmTxHash string) *MsgUnlockTokens {
1212
return &MsgUnlockTokens{
1313
Creator: creator,
14-
ToAddress: toAddress,
14+
FromEvmAddress: fromEvmAddress,
1515
Amount: amount,
1616
EvmTxHash: evmTxHash,
1717
}

0 commit comments

Comments
 (0)