From c53813ce374e9ee12fbbab1ac37d8e9a88cbe369 Mon Sep 17 00:00:00 2001 From: Chirantan Ekbote Date: Thu, 25 Aug 2022 17:24:14 +0900 Subject: [PATCH] wormchain: tokenbridge: Clean up coin handling Use `sdk.Coin` methods as much as possible rather than mixing with big.Int and uint256.Int. --- .../keeper/msg_server_execute_vaa.go | 59 ++++++++----------- .../tokenbridge/keeper/msg_server_transfer.go | 52 ++++++++-------- wormhole_chain/x/tokenbridge/types/asset.go | 17 +++--- 3 files changed, 58 insertions(+), 70 deletions(-) diff --git a/wormhole_chain/x/tokenbridge/keeper/msg_server_execute_vaa.go b/wormhole_chain/x/tokenbridge/keeper/msg_server_execute_vaa.go index c244407db..b1e58b7f9 100644 --- a/wormhole_chain/x/tokenbridge/keeper/msg_server_execute_vaa.go +++ b/wormhole_chain/x/tokenbridge/keeper/msg_server_execute_vaa.go @@ -109,42 +109,39 @@ func (k msgServer) ExecuteVAA(goCtx context.Context, msg *types.MsgExecuteVAA) ( } } - amount, err := types.Untruncate(unnormalizedAmount, meta) + amt := sdk.NewCoin(identifier, sdk.NewIntFromBigInt(unnormalizedAmount)) + if err := amt.Validate(); err != nil { + return nil, fmt.Errorf("%w: %s", types.ErrInvalidAmount, err) + } + amount, err := types.Untruncate(amt, meta) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to untruncate amount: %w", err) } - fee, err := types.Untruncate(unnormalizedFee, meta) - if err != nil { - return nil, err + f := sdk.NewCoin(identifier, sdk.NewIntFromBigInt(unnormalizedFee)) + if err := f.Validate(); err != nil { + return nil, fmt.Errorf("%w: %s", types.ErrInvalidFee, err) } - if fee.Sign() == -1 { - return nil, types.ErrNegativeFee + fee, err := types.Untruncate(f, meta) + if err != nil { + return nil, fmt.Errorf("failed to untruncate fee: %w", err) + } + + if amount.IsLT(fee) { + return nil, types.ErrFeeTooHigh } if wrapped { - err = k.bankKeeper.MintCoins(ctx, types.ModuleName, sdk.Coins{ - { - Denom: identifier, - Amount: sdk.NewIntFromBigInt(amount), - }, - }) - if err != nil { - return nil, err + if err := k.bankKeeper.MintCoins(ctx, types.ModuleName, sdk.Coins{amount}); err != nil { + return nil, fmt.Errorf("failed to mint coins (%s): %w", amount, err) } } moduleAccount := k.accountKeeper.GetModuleAddress(types.ModuleName) - amtLessFees := sdk.Coins{ - { - Denom: identifier, - Amount: sdk.NewIntFromBigInt(new(big.Int).Sub(amount, fee)), - }, - } + amtLessFees := amount.Sub(fee) - err = k.bankKeeper.SendCoins(ctx, moduleAccount, to[:], amtLessFees) - if err != nil { + if err := k.bankKeeper.SendCoins(ctx, moduleAccount, to[:], sdk.Coins{amtLessFees}); err != nil { return nil, err } @@ -153,15 +150,9 @@ func (k msgServer) ExecuteVAA(goCtx context.Context, msg *types.MsgExecuteVAA) ( return nil, err } // Transfer fee to tx sender if it is not 0 - if fee.Sign() == 1 { - err = k.bankKeeper.SendCoins(ctx, moduleAccount, txSender, sdk.Coins{ - { - Denom: identifier, - Amount: sdk.NewIntFromBigInt(fee), - }, - }) - if err != nil { - return nil, err + if fee.IsPositive() { + if err := k.bankKeeper.SendCoins(ctx, moduleAccount, txSender, sdk.Coins{fee}); err != nil { + return nil, fmt.Errorf("failed to send fees (%s) to tx sender: %w", fee, err) } } @@ -170,8 +161,8 @@ func (k msgServer) ExecuteVAA(goCtx context.Context, msg *types.MsgExecuteVAA) ( TokenAddress: tokenAddress[:], To: sdk.AccAddress(to[:]).String(), FeeRecipient: txSender.String(), - Amount: amount.String(), - Fee: fee.String(), + Amount: amount.Amount.String(), + Fee: fee.Amount.String(), LocalDenom: identifier, }) if err != nil { diff --git a/wormhole_chain/x/tokenbridge/keeper/msg_server_transfer.go b/wormhole_chain/x/tokenbridge/keeper/msg_server_transfer.go index e161f66a3..a18797cff 100644 --- a/wormhole_chain/x/tokenbridge/keeper/msg_server_transfer.go +++ b/wormhole_chain/x/tokenbridge/keeper/msg_server_transfer.go @@ -4,13 +4,13 @@ import ( "bytes" "context" "encoding/binary" + "fmt" "math/big" "github.com/certusone/wormhole-chain/x/tokenbridge/types" whtypes "github.com/certusone/wormhole-chain/x/wormhole/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/holiman/uint256" ) func (k msgServer) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) { @@ -49,31 +49,30 @@ func (k msgServer) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*typ } } - bridgeBalance := new(big.Int).Set(k.bankKeeper.GetBalance(ctx, k.accountKeeper.GetModuleAddress(types.ModuleName), msg.Amount.Denom).Amount.BigInt()) - amount := new(big.Int).Set(msg.Amount.Amount.BigInt()) - fees := new(big.Int).Set(msg.Fee.Amount.BigInt()) - - truncAmount, err := types.Truncate(amount, meta) + bridgeBalance, err := types.Truncate(k.bankKeeper.GetBalance(ctx, moduleAddress, msg.Amount.Denom), meta) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to truncate bridge balance: %w", err) + } + amount, err := types.Truncate(msg.Amount, meta) + if err != nil { + return nil, fmt.Errorf("%w: %s", types.ErrInvalidAmount, err) } - truncFees, err := types.Truncate(fees, meta) + fees, err := types.Truncate(msg.Fee, meta) if err != nil { - return nil, err + return nil, fmt.Errorf("%w: %s", types.ErrInvalidFee, err) } - truncBridgeBalance, err := types.Truncate(bridgeBalance, meta) - if err != nil { - return nil, err + if amount.IsLT(fees) { + return nil, types.ErrFeeTooHigh } - if !truncAmount.IsUint64() || !bridgeBalance.IsUint64() { + if !amount.Amount.IsUint64() || !bridgeBalance.Amount.IsUint64() { return nil, types.ErrAmountTooHigh } // Check that the total outflow of this asset does not exceed u64 - if !new(big.Int).Add(truncAmount, truncBridgeBalance).IsUint64() { + if !bridgeBalance.Add(amount).Amount.IsUint64() { return nil, types.ErrAmountTooHigh } @@ -81,11 +80,7 @@ func (k msgServer) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*typ // PayloadID buf.WriteByte(1) // Amount - tokenAmount, overflow := uint256.FromBig(truncAmount) - if overflow { - return nil, types.ErrInvalidAmount - } - tokenAmountBytes32 := tokenAmount.Bytes32() + tokenAmountBytes32 := bytes32(amount.Amount.BigInt()) buf.Write(tokenAmountBytes32[:]) tokenChain, tokenAddress, err := types.GetTokenMeta(wormholeConfig, msg.Amount.Denom) if err != nil { @@ -100,18 +95,9 @@ func (k msgServer) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*typ // ToChain MustWrite(buf, binary.BigEndian, uint16(msg.ToChain)) // Fee - fee, overflow := uint256.FromBig(truncFees) - if overflow { - return nil, types.ErrInvalidFee - } - feeBytes32 := fee.Bytes32() + feeBytes32 := bytes32(fees.Amount.BigInt()) buf.Write(feeBytes32[:]) - // Check that the amount is sufficient to cover the fee - if truncAmount.Cmp(truncFees) != 1 { - return nil, types.ErrFeeTooHigh - } - // Post message emitterAddress := whtypes.EmitterAddressFromAccAddress(moduleAddress) err = k.wormholeKeeper.PostMessage(ctx, emitterAddress, 0, buf.Bytes()) @@ -121,3 +107,11 @@ func (k msgServer) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*typ return &types.MsgTransferResponse{}, nil } + +func bytes32(i *big.Int) [32]byte { + var out [32]byte + + i.FillBytes(out[:]) + + return out +} diff --git a/wormhole_chain/x/tokenbridge/types/asset.go b/wormhole_chain/x/tokenbridge/types/asset.go index 2ac9528ab..3e924a2b0 100644 --- a/wormhole_chain/x/tokenbridge/types/asset.go +++ b/wormhole_chain/x/tokenbridge/types/asset.go @@ -9,27 +9,30 @@ import ( "strings" whtypes "github.com/certusone/wormhole-chain/x/wormhole/types" + sdk "github.com/cosmos/cosmos-sdk/types" btypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) // Truncate an amount -func Truncate(amount *big.Int, meta btypes.Metadata) (normalized *big.Int, err error) { +func Truncate(coin sdk.Coin, meta btypes.Metadata) (normalized sdk.Coin, err error) { factor, err := truncFactor(meta) if err != nil { - return new(big.Int), err + return normalized, err } - return new(big.Int).Div(amount, factor), nil + amt := new(big.Int).Div(coin.Amount.BigInt(), factor) + return sdk.NewCoin(coin.Denom, sdk.NewIntFromBigInt(amt)), nil } // Untruncate an amount -func Untruncate(amount *big.Int, meta btypes.Metadata) (normalized *big.Int, err error) { +func Untruncate(coin sdk.Coin, meta btypes.Metadata) (normalized sdk.Coin, err error) { factor, err := truncFactor(meta) if err != nil { - return new(big.Int), err + return normalized, err } - return new(big.Int).Mul(amount, factor), nil + amt := new(big.Int).Mul(coin.Amount.BigInt(), factor) + return sdk.NewCoin(coin.Denom, sdk.NewIntFromBigInt(amt)), nil } // Compute truncation factor for a given token meta. @@ -55,7 +58,7 @@ func truncFactor(meta btypes.Metadata) (factor *big.Int, err error) { if displayDenom.Exponent > 8 { return new(big.Int).SetInt64(int64(math.Pow10(int(displayDenom.Exponent - 8)))), nil } else { - return new(big.Int).SetInt64(1), nil + return big.NewInt(1), nil } }