Skip to content

Commit

Permalink
feat: get bridge fee quote in BuildOutgoingTxBatch (#788)
Browse files Browse the repository at this point in the history
  • Loading branch information
zakir-code authored Oct 29, 2024
1 parent eac095a commit 046e565
Show file tree
Hide file tree
Showing 12 changed files with 171 additions and 50 deletions.
8 changes: 8 additions & 0 deletions app/keepers/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ func NewAppKeeper(
appKeepers.Erc20Keeper,
appKeepers.AccountKeeper,
appKeepers.EvmKeeper,
contract.NewBridgeFeeQuoteKeeper(appKeepers.EvmKeeper, contract.BridgeFeeAddress),
authAddr,
)
appKeepers.PolygonKeeper = crosschainkeeper.NewKeeper(
Expand All @@ -394,6 +395,7 @@ func NewAppKeeper(
appKeepers.Erc20Keeper,
appKeepers.AccountKeeper,
appKeepers.EvmKeeper,
contract.NewBridgeFeeQuoteKeeper(appKeepers.EvmKeeper, contract.BridgeFeeAddress),
authAddr,
)
appKeepers.AvalancheKeeper = crosschainkeeper.NewKeeper(
Expand All @@ -408,6 +410,7 @@ func NewAppKeeper(
appKeepers.Erc20Keeper,
appKeepers.AccountKeeper,
appKeepers.EvmKeeper,
contract.NewBridgeFeeQuoteKeeper(appKeepers.EvmKeeper, contract.BridgeFeeAddress),
authAddr,
)
appKeepers.EthKeeper = crosschainkeeper.NewKeeper(
Expand All @@ -422,6 +425,7 @@ func NewAppKeeper(
appKeepers.Erc20Keeper,
appKeepers.AccountKeeper,
appKeepers.EvmKeeper,
contract.NewBridgeFeeQuoteKeeper(appKeepers.EvmKeeper, contract.BridgeFeeAddress),
authAddr,
)
appKeepers.ArbitrumKeeper = crosschainkeeper.NewKeeper(
Expand All @@ -436,6 +440,7 @@ func NewAppKeeper(
appKeepers.Erc20Keeper,
appKeepers.AccountKeeper,
appKeepers.EvmKeeper,
contract.NewBridgeFeeQuoteKeeper(appKeepers.EvmKeeper, contract.BridgeFeeAddress),
authAddr,
)
appKeepers.OptimismKeeper = crosschainkeeper.NewKeeper(
Expand All @@ -450,6 +455,7 @@ func NewAppKeeper(
appKeepers.Erc20Keeper,
appKeepers.AccountKeeper,
appKeepers.EvmKeeper,
contract.NewBridgeFeeQuoteKeeper(appKeepers.EvmKeeper, contract.BridgeFeeAddress),
authAddr,
)
appKeepers.Layer2Keeper = crosschainkeeper.NewKeeper(
Expand All @@ -464,6 +470,7 @@ func NewAppKeeper(
appKeepers.Erc20Keeper,
appKeepers.AccountKeeper,
appKeepers.EvmKeeper,
contract.NewBridgeFeeQuoteKeeper(appKeepers.EvmKeeper, contract.BridgeFeeAddress),
authAddr,
)
appKeepers.TronKeeper = crosschainkeeper.NewKeeper(
Expand All @@ -478,6 +485,7 @@ func NewAppKeeper(
appKeepers.Erc20Keeper,
appKeepers.AccountKeeper,
appKeepers.EvmKeeper,
contract.NewBridgeFeeQuoteKeeper(appKeepers.EvmKeeper, contract.BridgeFeeAddress),
authAddr,
)

Expand Down
45 changes: 45 additions & 0 deletions contract/bridge_fee_quote.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package contract

import (
"context"
"math/big"

sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/evmos/ethermint/x/evm/types"
)

type BrideFeeQuoteKeeper struct {
Caller
abi abi.ABI
from common.Address
contract common.Address
}

func NewBridgeFeeQuoteKeeper(caller Caller, contract string) BrideFeeQuoteKeeper {
return BrideFeeQuoteKeeper{
Caller: caller,
abi: bridgeFeeQuoteABI,
// evm module address
from: common.BytesToAddress(authtypes.NewModuleAddress(types.ModuleName).Bytes()),
contract: common.HexToAddress(contract),
}
}

func (k BrideFeeQuoteKeeper) GetQuotesByToken(ctx context.Context, chainName, tokenName string) ([]IBridgeFeeQuoteQuoteInfo, error) {
var res struct{ Quotes []IBridgeFeeQuoteQuoteInfo }
if err := k.QueryContract(sdk.UnwrapSDKContext(ctx), k.from, k.contract, k.abi, "getQuotesByToken", &res, chainName, tokenName); err != nil {
return nil, err
}
return res.Quotes, nil
}

func (k BrideFeeQuoteKeeper) GetQuoteById(ctx context.Context, id *big.Int) (IBridgeFeeQuoteQuoteInfo, error) {
var res struct{ Quote IBridgeFeeQuoteQuoteInfo }
if err := k.QueryContract(sdk.UnwrapSDKContext(ctx), k.from, k.contract, k.abi, "getQuoteById", &res, id); err != nil {
return IBridgeFeeQuoteQuoteInfo{}, err
}
return res.Quote, nil
}
2 changes: 2 additions & 0 deletions contract/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const (

StakingAddress = "0x0000000000000000000000000000000000001003"
CrosschainAddress = "0x0000000000000000000000000000000000001004"
BridgeFeeAddress = "0x0000000000000000000000000000000000001005"
)

const DefaultGasCap uint64 = 30000000
Expand Down Expand Up @@ -45,6 +46,7 @@ var (
fxBridgeABI = MustABIJson(IFxBridgeLogicMetaData.ABI)
bridgeCallbackABI = MustABIJson(IBridgeCallbackMetaData.ABI)
errorABI = MustABIJson(IErrorMetaData.ABI)
bridgeFeeQuoteABI = MustABIJson(IBridgeFeeQuoteMetaData.ABI)
)

type Caller interface {
Expand Down
50 changes: 25 additions & 25 deletions contract/ibridge_fee_quote.sol.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion solidity/contracts/bridge/BridgeFeeQuote.sol
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ contract BridgeFeeQuote is
* @param _tokenName The address of the token.
* @return QuoteInfo[] The quote list.
*/
function getQuoteByToken(
function getQuotesByToken(
string memory _chainName,
string memory _tokenName
) external view returns (QuoteInfo[] memory) {
Expand Down
2 changes: 1 addition & 1 deletion solidity/contracts/bridge/IBridgeFee.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ interface IBridgeFeeQuote {

function getQuoteById(uint256 _id) external view returns (QuoteInfo memory);

function getQuoteByToken(
function getQuotesByToken(
string memory _chainName,
string memory _tokenName
) external view returns (QuoteInfo[] memory quotes);
Expand Down
2 changes: 1 addition & 1 deletion solidity/test/bridge_fee_quote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ describe("BridgeFeeQuoteUpgradeable", function () {
},
]);

const quotes = await bridgeFeeQuote.getQuoteByToken(chainName, token1);
const quotes = await bridgeFeeQuote.getQuotesByToken(chainName, token1);
expect(quotes.length).to.equal(3);

for (let i = 0; i < 3; i++) {
Expand Down
41 changes: 22 additions & 19 deletions x/crosschain/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ type Keeper struct {
cdc codec.BinaryCodec // The wire codec for binary encoding/decoding.
storeKey storetypes.StoreKey // Unexposed key to access store from sdk.Context

stakingKeeper types.StakingKeeper
stakingMsgServer types.StakingMsgServer
distributionKeeper types.DistributionMsgServer
bankKeeper types.BankKeeper
ak types.AccountKeeper
ibcTransferKeeper types.IBCTransferKeeper
erc20Keeper types.Erc20Keeper
evmKeeper types.EVMKeeper
stakingKeeper types.StakingKeeper
stakingMsgServer types.StakingMsgServer
distributionKeeper types.DistributionMsgServer
bankKeeper types.BankKeeper
ak types.AccountKeeper
ibcTransferKeeper types.IBCTransferKeeper
erc20Keeper types.Erc20Keeper
evmKeeper types.EVMKeeper
brideFeeQuoteKeeper types.BridgeFeeQuoteKeeper

authority string
callbackFrom common.Address
Expand All @@ -37,7 +38,7 @@ type Keeper struct {
func NewKeeper(cdc codec.BinaryCodec, moduleName string, storeKey storetypes.StoreKey,
stakingKeeper types.StakingKeeper, stakingMsgServer types.StakingMsgServer, distributionKeeper types.DistributionMsgServer,
bankKeeper types.BankKeeper, ibcTransferKeeper types.IBCTransferKeeper, erc20Keeper types.Erc20Keeper, ak types.AccountKeeper,
evmKeeper types.EVMKeeper, authority string,
evmKeeper types.EVMKeeper, brideFeeQuoteKeeper types.BridgeFeeQuoteKeeper, authority string,
) Keeper {
if addr := ak.GetModuleAddress(moduleName); addr == nil {
panic(fmt.Sprintf("%s module account has not been set", moduleName))
Expand All @@ -48,16 +49,18 @@ func NewKeeper(cdc codec.BinaryCodec, moduleName string, storeKey storetypes.Sto
cdc: cdc,
storeKey: storeKey,

stakingKeeper: stakingKeeper,
stakingMsgServer: stakingMsgServer,
distributionKeeper: distributionKeeper,
bankKeeper: bankKeeper,
ak: ak,
ibcTransferKeeper: ibcTransferKeeper,
erc20Keeper: erc20Keeper,
evmKeeper: evmKeeper,
authority: authority,
callbackFrom: common.BytesToAddress(autytypes.NewModuleAddress(types.BridgeCallSender)),
stakingKeeper: stakingKeeper,
stakingMsgServer: stakingMsgServer,
distributionKeeper: distributionKeeper,
bankKeeper: bankKeeper,
ak: ak,
ibcTransferKeeper: ibcTransferKeeper,
erc20Keeper: erc20Keeper,
evmKeeper: evmKeeper,
brideFeeQuoteKeeper: brideFeeQuoteKeeper,

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

Expand Down
2 changes: 2 additions & 0 deletions x/crosschain/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/stretchr/testify/suite"
"go.uber.org/mock/gomock"

"github.com/functionx/fx-core/v8/contract"
"github.com/functionx/fx-core/v8/testutil"
"github.com/functionx/fx-core/v8/testutil/helpers"
arbitrumtypes "github.com/functionx/fx-core/v8/x/arbitrum/types"
Expand Down Expand Up @@ -111,6 +112,7 @@ func (s *KeeperMockSuite) SetupTest() {
s.erc20Keeper,
s.accountKeeper,
s.evmKeeper,
contract.NewBridgeFeeQuoteKeeper(nil, contract.BridgeFeeAddress),
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)

Expand Down
23 changes: 20 additions & 3 deletions x/crosschain/keeper/outgoing_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,36 @@ package keeper

import (
"fmt"
"math/big"

sdkmath "cosmossdk.io/math"
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/hashicorp/go-metrics"

"github.com/functionx/fx-core/v8/contract"
fxtelemetry "github.com/functionx/fx-core/v8/telemetry"
"github.com/functionx/fx-core/v8/x/crosschain/types"
)

func (k Keeper) BuildOutgoingTxBatch(ctx sdk.Context, sender sdk.AccAddress, receiver string, amount, fee sdk.Coin) (uint64, error) {
quoteInfos, err := k.brideFeeQuoteKeeper.GetQuotesByToken(ctx, k.moduleName, fee.Denom)
if err != nil {
return 0, err
}
var quoteInfo *contract.IBridgeFeeQuoteQuoteInfo
for _, quote := range quoteInfos {
if fee.Amount.GTE(sdkmath.NewIntFromBigInt(quote.Fee)) &&
new(big.Int).Sub(quote.Expiry, big.NewInt(ctx.BlockTime().UnixNano())).Sign() > 0 {
quoteInfo = &quote
break
}
}
if quoteInfo == nil {
return 0, types.ErrInvalid.Wrapf("bridge fee is too small or expired")
}

bridgeToken, err := k.BaseCoinToBridgeToken(ctx, sender, amount.Add(fee))
if err != nil {
return 0, err
Expand All @@ -21,8 +40,6 @@ func (k Keeper) BuildOutgoingTxBatch(ctx sdk.Context, sender sdk.AccAddress, rec
return 0, err
}

feeReceive := "" // todo: query feeReceive from quote contract

batchTimeout := k.CalExternalTimeoutHeight(ctx, GetExternalBatchTimeout)
if batchTimeout <= 0 {
return 0, types.ErrInvalid.Wrapf("batch timeout height")
Expand All @@ -40,7 +57,7 @@ func (k Keeper) BuildOutgoingTxBatch(ctx sdk.Context, sender sdk.AccAddress, rec
},
},
TokenContract: bridgeToken.Contract,
FeeReceive: feeReceive,
FeeReceive: quoteInfo.Oracle.String(),
Block: uint64(ctx.BlockHeight()), // set the current block height when storing the batch
}
if err = k.StoreBatch(ctx, batch); err != nil {
Expand Down
39 changes: 39 additions & 0 deletions x/crosschain/mock/expected_keepers_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions x/crosschain/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/evmos/ethermint/x/evm/types"

"github.com/functionx/fx-core/v8/contract"
erc20types "github.com/functionx/fx-core/v8/x/erc20/types"
)

Expand Down Expand Up @@ -85,3 +86,7 @@ type AccountKeeper interface {
NewAccountWithAddress(ctx context.Context, addr sdk.AccAddress) sdk.AccountI
GetModuleAccount(ctx context.Context, moduleName string) sdk.ModuleAccountI
}

type BridgeFeeQuoteKeeper interface {
GetQuotesByToken(ctx context.Context, chainName, denom string) ([]contract.IBridgeFeeQuoteQuoteInfo, error)
}

0 comments on commit 046e565

Please sign in to comment.