Skip to content

Commit

Permalink
fix: transfer bridge fee
Browse files Browse the repository at this point in the history
  • Loading branch information
zakir-code committed Jan 8, 2025
1 parent fdf7355 commit b08a784
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 81 deletions.
38 changes: 6 additions & 32 deletions x/crosschain/keeper/bridge_call_in.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"math/big"
"strconv"

sdkmath "cosmossdk.io/math"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -42,7 +41,7 @@ func (k Keeper) BridgeCallHandler(ctx sdk.Context, msg *types.MsgBridgeCallClaim
baseCoins = baseCoins.Add(baseCoin)
}

if err := k.handleBridgeCallInQuote(ctx, msg.GetSenderAddr(), msg.QuoteId.BigInt(), msg.GasLimit.BigInt()); err != nil {
if err := k.handlerBridgeCallInFee(ctx, msg.GetSenderAddr(), msg.QuoteId.BigInt(), msg.GasLimit.BigInt()); err != nil {
return err
}

Expand Down Expand Up @@ -138,41 +137,16 @@ func (k Keeper) BridgeCallEvm(ctx sdk.Context, sender, refundAddr, to, receiverA
return nil
}

func (k Keeper) handleBridgeCallInQuote(ctx sdk.Context, from common.Address, quoteId, gasLimit *big.Int) error {
if quoteId == nil || quoteId.Sign() <= 0 || gasLimit == nil || gasLimit.Sign() <= 0 {
func (k Keeper) handlerBridgeCallInFee(ctx sdk.Context, from common.Address, quoteId, gasLimit *big.Int) error {
if quoteId == nil || quoteId.Sign() <= 0 {
// Allow free bridgeCall
return nil
}

contractQuote, err := k.validatorQuoteGasLimit(ctx, quoteId, gasLimit)
quote, err := k.ValidateQuote(ctx, quoteId, gasLimit)
if err != nil {
return err
}

// transfer fee to quote oracle
bridgeToken, err := k.erc20Keeper.GetBridgeToken(ctx, k.moduleName, contractQuote.TokenName)
if err != nil {
return err
}

if bridgeToken.IsOrigin() {
fees := sdk.NewCoins(sdk.NewCoin(fxtypes.DefaultDenom, sdkmath.NewIntFromBigInt(contractQuote.Fee)))
return k.bankKeeper.SendCoins(ctx, from.Bytes(), contractQuote.Oracle.Bytes(), fees)
}

_, err = k.erc20TokenKeeper.Transfer(ctx, bridgeToken.GetContractAddress(), from, contractQuote.Oracle, contractQuote.Fee)
return err
}

func (k Keeper) validatorQuoteGasLimit(ctx sdk.Context, quoteId, gasLimit *big.Int) (contract.IBridgeFeeQuoteQuoteInfo, error) {
contractQuote, err := k.bridgeFeeQuoteKeeper.GetQuoteById(ctx, quoteId)
if err != nil {
return contract.IBridgeFeeQuoteQuoteInfo{}, err
}
if contractQuote.IsTimeout(ctx.BlockTime()) {
return contract.IBridgeFeeQuoteQuoteInfo{}, types.ErrInvalid.Wrapf("quote has timed out")
}
if contractQuote.GasLimit.Cmp(gasLimit) < 0 {
return contract.IBridgeFeeQuoteQuoteInfo{}, types.ErrInvalid.Wrapf("quote gas limit is less than gas limit")
}
return contractQuote, nil
return k.TransferBridgeFee(ctx, from, quote.Oracle, quote.Fee, quote.TokenName)
}
53 changes: 13 additions & 40 deletions x/crosschain/keeper/bridge_call_out.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func (k Keeper) BridgeCallResultHandler(ctx sdk.Context, claim *types.MsgBridgeC
return err
}

if err := k.TransferQuoteFeeToRelayer(ctx, claim.Nonce); err != nil {
if err := k.TransferBridgeFeeToRelayer(ctx, claim.Nonce); err != nil {
return err
}
ctx.EventManager().EmitEvent(sdk.NewEvent(
Expand Down Expand Up @@ -318,7 +318,7 @@ func (k Keeper) BridgeCallBaseCoin(ctx sdk.Context, from, refund, to common.Addr
}
cacheKey = types.NewOriginTokenKey(k.moduleName, nonce)

if err = k.handleBridgeCallOutQuote(ctx, from, nonce, quoteId, gasLimit); err != nil {
if err = k.handlerBridgeCallOutFee(ctx, from, nonce, quoteId, gasLimit); err != nil {
return 0, err
}
}
Expand Down Expand Up @@ -383,63 +383,36 @@ func (k Keeper) IBCTransfer(
return transferResponse.Sequence, nil
}

func (k Keeper) handleBridgeCallOutQuote(ctx sdk.Context, from common.Address, bridgeCallNonce uint64, quoteId, gasLimit *big.Int) error {
if quoteId == nil || quoteId.Sign() <= 0 || gasLimit == nil || gasLimit.Sign() <= 0 {
func (k Keeper) handlerBridgeCallOutFee(ctx sdk.Context, from common.Address, bridgeCallNonce uint64, quoteId, gasLimit *big.Int) error {
if quoteId == nil || quoteId.Sign() <= 0 {
// Users can send submitBridgeCall by themselves without paying
return nil
}

contractQuote, err := k.validatorQuoteGasLimit(ctx, quoteId, gasLimit)
quote, err := k.ValidateQuote(ctx, quoteId, gasLimit)
if err != nil {
return err
}

// transfer fee to module
bridgeToken, err := k.erc20Keeper.GetBridgeToken(ctx, k.moduleName, contractQuote.TokenName)
if err != nil {
bridgeFeeAddr := common.BytesToAddress(k.bridgeFeeCollector)
if err = k.TransferBridgeFee(ctx, from, bridgeFeeAddr, quote.Fee, quote.TokenName); err != nil {
return err
}

if bridgeToken.IsOrigin() {
fees := sdk.NewCoins(sdk.NewCoin(fxtypes.DefaultDenom, sdkmath.NewIntFromBigInt(contractQuote.Fee)))
if err = k.bankKeeper.SendCoinsFromAccountToModule(ctx, from.Bytes(), k.moduleName, fees); err != nil {
return err
}
} else {
if _, err = k.erc20TokenKeeper.Transfer(ctx, bridgeToken.GetContractAddress(), from, k.GetModuleEvmAddress(), contractQuote.Fee); err != nil {
return err
}
}

k.SetOutgoingBridgeCallQuoteInfo(ctx, bridgeCallNonce, types.NewQuoteInfo(contractQuote))
k.SetOutgoingBridgeCallQuoteInfo(ctx, bridgeCallNonce, types.NewQuoteInfo(quote))
return nil
}

func (k Keeper) TransferQuoteFeeToRelayer(ctx sdk.Context, bridgeCallNonce uint64) error {
quoteInfo, found := k.GetOutgoingBridgeCallQuoteInfo(ctx, bridgeCallNonce)
func (k Keeper) TransferBridgeFeeToRelayer(ctx sdk.Context, bridgeCallNonce uint64) error {
quote, found := k.GetOutgoingBridgeCallQuoteInfo(ctx, bridgeCallNonce)
if !found {
return nil
}

k.DeleteOutgoingBridgeCallQuoteInfo(ctx, bridgeCallNonce)

bridgeToken, err := k.erc20Keeper.GetBridgeToken(ctx, k.moduleName, quoteInfo.Token)
if err != nil {
return err
}

quoteOracle := quoteInfo.OracleAddress()
if bridgeToken.IsOrigin() {
fees := sdk.NewCoins(sdk.NewCoin(fxtypes.DefaultDenom, quoteInfo.Fee))
if err = k.bankKeeper.SendCoinsFromModuleToAccount(ctx, k.moduleName, quoteOracle.Bytes(), fees); err != nil {
return err
}
} else {
if _, err = k.erc20TokenKeeper.Transfer(ctx, bridgeToken.GetContractAddress(), k.GetModuleEvmAddress(), quoteOracle, quoteInfo.Fee.BigInt()); err != nil {
return err
}
}

return nil
bridgeFeeAddr := common.BytesToAddress(k.bridgeFeeCollector)
return k.TransferBridgeFee(ctx, bridgeFeeAddr, quote.OracleAddress(), quote.Fee.BigInt(), quote.Token)
}

func (k Keeper) SetOutgoingBridgeCallQuoteInfo(ctx sdk.Context, nonce uint64, quoteInfo types.QuoteInfo) {
Expand Down
41 changes: 41 additions & 0 deletions x/crosschain/keeper/bridge_fee.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package keeper

import (
"math/big"
"strings"

sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"

"github.com/pundiai/fx-core/v8/contract"
fxtypes "github.com/pundiai/fx-core/v8/types"
"github.com/pundiai/fx-core/v8/x/crosschain/types"
)

func (k Keeper) ValidateQuote(ctx sdk.Context, quoteId, gasLimit *big.Int) (contract.IBridgeFeeQuoteQuoteInfo, error) {
quote, err := k.bridgeFeeQuoteKeeper.GetQuoteById(ctx, quoteId)
if err != nil {
return contract.IBridgeFeeQuoteQuoteInfo{}, err
}
if quote.IsTimeout(ctx.BlockTime()) {
return contract.IBridgeFeeQuoteQuoteInfo{}, types.ErrInvalid.Wrapf("quote has timed out")
}
if quote.GasLimit.Cmp(gasLimit) < 0 {
return contract.IBridgeFeeQuoteQuoteInfo{}, types.ErrInvalid.Wrapf("quote gas limit is less than gas limit")
}
return quote, nil
}

func (k Keeper) TransferBridgeFee(ctx sdk.Context, from, to common.Address, bridgeFee *big.Int, bridgeTokenName string) error {
if strings.ToUpper(bridgeTokenName) == fxtypes.DefaultDenom {
fees := sdk.NewCoins(sdk.NewCoin(fxtypes.DefaultDenom, sdkmath.NewIntFromBigInt(bridgeFee)))
return k.bankKeeper.SendCoins(ctx, from.Bytes(), to.Bytes(), fees)
}
erc20Token, err := k.erc20Keeper.GetERC20Token(ctx, bridgeTokenName)
if err != nil {
return err
}
_, err = k.erc20TokenKeeper.Transfer(ctx, erc20Token.GetERC20Contract(), from, to, bridgeFee)
return err
}
14 changes: 6 additions & 8 deletions x/crosschain/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ type Keeper struct {
bridgeFeeQuoteKeeper types.BridgeFeeQuoteKeeper
erc20TokenKeeper types.ERC20TokenKeeper

authority string
callbackFrom common.Address
authority string
callbackFrom common.Address
bridgeFeeCollector sdk.AccAddress
}

// NewKeeper returns a new instance of the gravity keeper
Expand Down Expand Up @@ -61,8 +62,9 @@ func NewKeeper(cdc codec.BinaryCodec, moduleName string, storeKey storetypes.Sto
bridgeFeeQuoteKeeper: bridgeFeeQuoteKeeper,
erc20TokenKeeper: evmErc20Keeper,

authority: authority,
callbackFrom: common.BytesToAddress(autytypes.NewModuleAddress(types.BridgeCallSender)),
authority: authority,
callbackFrom: common.BytesToAddress(autytypes.NewModuleAddress(types.BridgeCallSender)),
bridgeFeeCollector: autytypes.NewModuleAddress(types.BridgeFeeCollectorName),
}
}

Expand All @@ -74,10 +76,6 @@ func (k Keeper) GetCallbackFrom() common.Address {
return k.callbackFrom
}

func (k Keeper) GetModuleEvmAddress() common.Address {
return common.BytesToAddress(k.ak.GetModuleAddress(k.moduleName))
}

// Logger returns a module-specific logger.
func (k Keeper) Logger(ctx sdk.Context) log.Logger {
return ctx.Logger().With("module", "x/"+k.moduleName)
Expand Down
4 changes: 3 additions & 1 deletion x/crosschain/types/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ const (
// RouterKey is the module name router key
RouterKey = ModuleName

BridgeCallSender = "bridgecall"
BridgeCallSender = "bridge_call"

BridgeFeeCollectorName = "bridge_fee_collector"
)

var (
Expand Down

0 comments on commit b08a784

Please sign in to comment.