@@ -2,16 +2,112 @@ package keeper
22
33import (
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"
11+ "google.golang.org/grpc/codes"
12+ "google.golang.org/grpc/status"
813)
914
1015func (k msgServer ) LockTokens (goCtx context.Context , msg * types.MsgLockTokens ) (* types.MsgLockTokensResponse , error ) {
1116 ctx := sdk .UnwrapSDKContext (goCtx )
1217
13- // TODO: Handling the message
14- _ = ctx
18+ // Validate creator address
19+ creatorAddr , err := sdk .AccAddressFromBech32 (msg .Creator )
20+ if err != nil {
21+ return nil , status .Error (codes .InvalidArgument , fmt .Sprintf ("invalid creator address: %s" , err ))
22+ }
23+
24+ // Validate amount
25+ if msg .Amount == "" {
26+ return nil , status .Error (codes .InvalidArgument , "amount is required" )
27+ }
28+
29+ // Parse amount as coins
30+ amount , err := sdk .ParseCoinsNormalized (msg .Amount )
31+ if err != nil {
32+ return nil , types .ErrInvalidAmount .Wrap (err .Error ())
33+ }
34+
35+ if ! amount .IsValid () || amount .IsZero () {
36+ return nil , types .ErrInvalidAmount .Wrap ("amount must be positive" )
37+ }
38+
39+ // Validate EVM address format
40+ if err := k .validateEVMAddress (msg .ToAddress ); err != nil {
41+ return nil , err
42+ }
43+
44+ // Check if user has sufficient balance
45+ userBalance := k .bankKeeper .SpendableCoins (ctx , creatorAddr )
46+ if ! userBalance .IsAllGTE (amount ) {
47+ return nil , types .ErrInsufficientFunds .Wrapf ("required: %s, available: %s" , amount .String (), userBalance .String ())
48+ }
49+ // Get module account
50+ moduleAccount := k .accountKeeper .GetModuleAccount (ctx , types .ModuleName )
51+ if moduleAccount == nil {
52+ return nil , types .ErrModuleAccount .Wrap ("module account not found" )
53+ }
54+
55+ // Transfer tokens from user to module account (this locks them)
56+ if err := k .bankKeeper .SendCoinsFromAccountToModule (ctx , creatorAddr , types .ModuleName , amount ); err != nil {
57+ return nil , types .ErrFailedToLockTokens .Wrap (err .Error ())
58+ }
59+
60+ // Get current block info
61+ sdkCtx := sdk .UnwrapSDKContext (ctx )
62+ blockHeight := sdkCtx .BlockHeight ()
63+ blockTime := sdkCtx .BlockTime ()
64+
65+ amountUint64 , err := strconv .ParseUint (msg .Amount , 10 , 64 )
66+ if err != nil {
67+ return nil , status .Error (codes .InvalidArgument , fmt .Sprintf ("invalid amount: %s" , err ))
68+ }
69+
70+ if err := k .SetAddressLockedAmount (ctx , msg .Creator , amountUint64 ); err != nil {
71+ return nil , types .ErrFailedToLockTokens .Wrap (err .Error ())
72+ }
73+
74+ // Emit simple event for bridge relayer
75+ sdkCtx .EventManager ().EmitEvent (
76+ sdk .NewEvent (
77+ types .EventTypeTokensLocked ,
78+ sdk .NewAttribute (types .AttributeKeyCreator , msg .Creator ),
79+ sdk .NewAttribute (types .AttributeKeyAmount , amount .String ()),
80+ sdk .NewAttribute (types .AttributeKeyToAddress , msg .ToAddress ),
81+ sdk .NewAttribute (types .AttributeKeyBlockHeight , fmt .Sprintf ("%d" , blockHeight )),
82+ sdk .NewAttribute (types .AttributeKeyTimestamp , blockTime .Format (time .RFC3339 )),
83+ ),
84+ )
1585
1686 return & types.MsgLockTokensResponse {}, nil
1787}
88+
89+ // validateEVMAddress performs basic EVM address validation
90+ func (k msgServer ) validateEVMAddress (address string ) error {
91+ if address == "" {
92+ return types .ErrInvalidEVMAddr .Wrap ("address cannot be empty" )
93+ }
94+
95+ // Basic EVM address validation (0x prefix + 40 hex chars)
96+ if len (address ) != 42 {
97+ return types .ErrInvalidEVMAddr .Wrap ("address must be 42 characters long" )
98+ }
99+
100+ if address [:2 ] != "0x" {
101+ return types .ErrInvalidEVMAddr .Wrap ("address must start with 0x" )
102+ }
103+
104+ // Validate hex characters
105+ for i := 2 ; i < len (address ); i ++ {
106+ c := address [i ]
107+ if ! ((c >= '0' && c <= '9' ) || (c >= 'a' && c <= 'f' ) || (c >= 'A' && c <= 'F' )) {
108+ return types .ErrInvalidEVMAddr .Wrap ("address contains invalid hex characters" )
109+ }
110+ }
111+
112+ return nil
113+ }
0 commit comments