github.com/Finschia/finschia-sdk@v0.49.1/x/fbridge/keeper/transfer.go (about) 1 package keeper 2 3 import ( 4 "encoding/binary" 5 "encoding/hex" 6 "errors" 7 "fmt" 8 "regexp" 9 "strconv" 10 "strings" 11 12 "golang.org/x/crypto/sha3" 13 14 sdk "github.com/Finschia/finschia-sdk/types" 15 sdkerrors "github.com/Finschia/finschia-sdk/types/errors" 16 "github.com/Finschia/finschia-sdk/x/fbridge/types" 17 ) 18 19 func (k Keeper) handleBridgeTransfer(ctx sdk.Context, sender sdk.AccAddress, amount sdk.Int) (uint64, error) { 20 token := sdk.Coins{sdk.Coin{Denom: k.GetParams(ctx).TargetDenom, Amount: amount}} 21 if err := k.bankKeeper.IsSendEnabledCoins(ctx, token...); err != nil { 22 return 0, err 23 } 24 25 if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, sender, types.ModuleName, token); err != nil { 26 return 0, err 27 } 28 29 if err := k.bankKeeper.BurnCoins(ctx, types.ModuleName, token); err != nil { 30 panic(fmt.Errorf("cannot burn coins after a successful send to a module account: %w", err)) 31 } 32 33 seq := k.GetNextSequence(ctx) 34 k.setNextSequence(ctx, seq+1) 35 k.setSeqToBlocknum(ctx, seq, uint64(ctx.BlockHeight())) 36 37 return seq, nil 38 } 39 40 func (k Keeper) setSeqToBlocknum(ctx sdk.Context, seq, height uint64) { 41 store := ctx.KVStore(k.storeKey) 42 bz := make([]byte, 8) 43 binary.BigEndian.PutUint64(bz, height) 44 store.Set(types.SeqToBlocknumKey(seq), bz) 45 } 46 47 func (k Keeper) GetSeqToBlocknum(ctx sdk.Context, seq uint64) (uint64, error) { 48 store := ctx.KVStore(k.storeKey) 49 bz := store.Get(types.SeqToBlocknumKey(seq)) 50 if len(bz) == 0 { 51 return 0, sdkerrors.ErrNotFound.Wrapf("sequence %d not found", seq) 52 } 53 54 return binary.BigEndian.Uint64(bz), nil 55 } 56 57 func (k Keeper) GetNextSequence(ctx sdk.Context) uint64 { 58 store := ctx.KVStore(k.storeKey) 59 bz := store.Get(types.KeyNextSeqSend) 60 if len(bz) == 0 { 61 panic(errors.New("sending next sequence should have been set")) 62 } 63 64 return binary.BigEndian.Uint64(bz) 65 } 66 67 func (k Keeper) setNextSequence(ctx sdk.Context, seq uint64) { 68 store := ctx.KVStore(k.storeKey) 69 bz := make([]byte, 8) 70 binary.BigEndian.PutUint64(bz, seq) 71 store.Set(types.KeyNextSeqSend, bz) 72 } 73 74 func IsValidEthereumAddress(address string) error { 75 matched, err := regexp.MatchString(`^0x[a-fA-F0-9]{40}$`, address) 76 if err != nil || !matched { 77 return sdkerrors.ErrInvalidAddress.Wrapf("invalid eth address: %s", address) 78 } 79 80 address = address[2:] 81 addressLower := strings.ToLower(address) 82 83 hasher := sha3.NewLegacyKeccak256() 84 hasher.Write([]byte(addressLower)) 85 addressHash := hex.EncodeToString(hasher.Sum(nil)) 86 87 checksumAddress := "" 88 for i := 0; i < len(addressLower); i++ { 89 c, err := strconv.ParseUint(string(addressHash[i]), 16, 4) 90 if err != nil { 91 return err 92 } 93 if c < 8 { 94 checksumAddress += string(addressLower[i]) 95 } else { 96 checksumAddress += strings.ToUpper(string(addressLower[i])) 97 } 98 } 99 100 if address != checksumAddress { 101 return sdkerrors.ErrInvalidAddress.Wrapf("invalid checksum for eth address: %s", address) 102 } 103 104 return nil 105 }