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  }