Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: deploy fee contract for transaction processing #807

Merged
merged 2 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package app

import (
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
Expand Down Expand Up @@ -55,6 +56,7 @@ import (

fxante "github.com/functionx/fx-core/v8/ante"
"github.com/functionx/fx-core/v8/app/keepers"
"github.com/functionx/fx-core/v8/contract"
_ "github.com/functionx/fx-core/v8/docs/statik"
fxcfg "github.com/functionx/fx-core/v8/server/config"
fxauth "github.com/functionx/fx-core/v8/server/grpc/auth"
Expand All @@ -64,6 +66,7 @@ import (
"github.com/functionx/fx-core/v8/x/crosschain"
"github.com/functionx/fx-core/v8/x/crosschain/keeper"
crosschaintypes "github.com/functionx/fx-core/v8/x/crosschain/types"
ethtypes "github.com/functionx/fx-core/v8/x/eth/types"
fxevmtypes "github.com/functionx/fx-core/v8/x/evm/types"
ibcmiddlewaretypes "github.com/functionx/fx-core/v8/x/ibc/middleware/types"
)
Expand Down Expand Up @@ -345,6 +348,36 @@ func (app *App) InitChainer(ctx sdk.Context, req *abci.RequestInitChain) (*abci.
panic(err)
}

bridgeFeeQuoteKeeper := contract.NewBridgeFeeQuoteKeeper(app.EvmKeeper, contract.BridgeFeeAddress)
bridgeFeeOracleKeeper := contract.NewBridgeFeeOracleKeeper(app.EvmKeeper, contract.BridgeFeeOracleAddress)

acc := app.AccountKeeper.GetModuleAddress(evmtypes.ModuleName)
moduleAddress := common.BytesToAddress(acc.Bytes())

delegations, err := app.StakingKeeper.GetAllDelegations(ctx)
if err != nil {
return nil, err
}
if len(delegations) == 0 {
return nil, errors.New("no delegations found")
}
bridgeDenoms := []contract.BridgeDenoms{
{
ChainName: ethtypes.ModuleName,
Denoms: []string{fxtypes.DefaultDenom},
},
}
if err = contract.DeployBridgeFeeContract(
ctx,
app.EvmKeeper,
bridgeFeeQuoteKeeper,
bridgeFeeOracleKeeper,
bridgeDenoms,
moduleAddress, moduleAddress,
common.BytesToAddress(sdk.MustAccAddressFromBech32(delegations[0].DelegatorAddress).Bytes()),
); err != nil {
return nil, err
}
return response, nil
}

Expand Down
42 changes: 42 additions & 0 deletions app/upgrades/v8/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package v8

import (
"context"
"errors"
"strings"

storetypes "cosmossdk.io/store/types"
Expand All @@ -17,10 +18,12 @@ import (
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
ibctransfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types"
ibcchanneltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types"
"github.com/ethereum/go-ethereum/common"
evmtypes "github.com/evmos/ethermint/x/evm/types"

"github.com/functionx/fx-core/v8/app/keepers"
"github.com/functionx/fx-core/v8/app/upgrades/store"
"github.com/functionx/fx-core/v8/contract"
fxtypes "github.com/functionx/fx-core/v8/types"
crosschaintypes "github.com/functionx/fx-core/v8/x/crosschain/types"
erc20keeper "github.com/functionx/fx-core/v8/x/erc20/keeper"
Expand Down Expand Up @@ -72,6 +75,45 @@ func CreateUpgradeHandler(cdc codec.Codec, mm *module.Manager, configurator modu

store.RemoveStoreKeys(cacheCtx, app.GetKey(erc20types.StoreKey), erc20v8.GetRemovedStoreKeys())

quoteKeeper := contract.NewBridgeFeeQuoteKeeper(app.EvmKeeper, contract.BridgeFeeAddress)
oracleKeeper := contract.NewBridgeFeeOracleKeeper(app.EvmKeeper, contract.BridgeFeeOracleAddress)
chains := crosschaintypes.GetSupportChains()
bridgeDenoms := make([]contract.BridgeDenoms, len(chains))
for index, chain := range chains {
denoms := make([]string, 0)
bridgeTokens, err := app.Erc20Keeper.GetBridgeTokens(cacheCtx, chain)
if err != nil {
return fromVM, err
}
for _, token := range bridgeTokens {
denoms = append(denoms, token.GetDenom())
}
bridgeDenoms[index] = contract.BridgeDenoms{
ChainName: chain,
Denoms: denoms,
}
}
acc := app.AccountKeeper.GetModuleAddress(evmtypes.ModuleName)
moduleAddress := common.BytesToAddress(acc.Bytes())

oracles := app.CrosschainKeepers.EthKeeper.GetAllOracles(cacheCtx, true)
if oracles.Len() <= 0 {
return fromVM, errors.New("no oracle found")
}

if err = contract.DeployBridgeFeeContract(
cacheCtx,
app.EvmKeeper,
quoteKeeper,
oracleKeeper,
bridgeDenoms,
moduleAddress,
// TODO set bridge fee contract owner address before mainnet upgrade
moduleAddress,
fx0x55 marked this conversation as resolved.
Show resolved Hide resolved
common.HexToAddress(oracles[0].ExternalAddress),
); err != nil {
return fromVM, err
}
commit()
cacheCtx.Logger().Info("upgrade complete", "module", "upgrade")
return toVM, nil
Expand Down
4 changes: 2 additions & 2 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ func (suite *rpcTestSuite) TestClient_Tx() {
// 0. initAccount
// 1.fee_collector + 2.distribution + 3.bonded_tokens_pool + 4.not_bonded_tokens_pool + 5.gov + 6.mint + 7.autytypes.NewModuleAddress(crosschain)
// 8.evm 9.0x..1001 10.0x..1002 11.erc20 12.wfx-contract
suite.Equal(authtypes.NewBaseAccount(toAddress, nil, uint64(15+i), 0), account)
suite.Equal(authtypes.NewBaseAccount(toAddress, nil, uint64(19+i), 0), account)
}

ethPrivKey := suite.GetPrivKeyByIndex(hd2.EthSecp256k1Type, 0)
Expand Down Expand Up @@ -224,7 +224,7 @@ func (suite *rpcTestSuite) TestClient_Tx() {

account, err := cli.QueryAccount(ethAddress.String())
suite.Require().NoError(err)
suite.Equal(authtypes.NewBaseAccount(ethAddress, nil, uint64(18), 0), account)
suite.Equal(authtypes.NewBaseAccount(ethAddress, nil, uint64(22), 0), account)
}

for i := 0; i < len(clients); i++ {
Expand Down
130 changes: 130 additions & 0 deletions contract/bridge_fee.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package contract

import (
"math/big"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
)

func DeployBridgeFeeContract(
ctx sdk.Context,
evmKeeper EvmKeeper,
bridgeFeeQuoteKeeper BridgeFeeQuoteKeeper,
bridgeFeeOracleKeeper BridgeFeeOracleKeeper,
bridgeDenoms []BridgeDenoms,
evmModuleAddress, owner, defaultOracleAddress common.Address,
) error {
if err := deployBridgeProxy(
ctx,
evmKeeper,
GetBridgeFeeQuote().ABI,
GetBridgeFeeQuote().Bin,
common.HexToAddress(BridgeFeeAddress),
evmModuleAddress,
); err != nil {
return err
}
if err := deployBridgeProxy(
ctx,
evmKeeper,
GetBridgeFeeOracle().ABI,
GetBridgeFeeOracle().Bin,
common.HexToAddress(BridgeFeeOracleAddress),
evmModuleAddress,
); err != nil {
return err
}

if err := initBridgeFeeOracle(ctx, bridgeFeeOracleKeeper, owner, defaultOracleAddress); err != nil {
return err
}
return initBridgeFeeQuote(ctx, bridgeFeeQuoteKeeper, bridgeDenoms, owner)
}

func deployBridgeProxy(
ctx sdk.Context,
evmKeeper EvmKeeper,
logicABI abi.ABI,
logicBin []byte,
proxyAddress, evmModuleAddress common.Address,
) error {
logicContract, err := evmKeeper.DeployContract(ctx, evmModuleAddress, logicABI, logicBin)
if err != nil {
return err
}
if err = evmKeeper.CreateContractWithCode(ctx, proxyAddress, GetBridgeProxy().Code); err != nil {
return err
}
if _, err = evmKeeper.ApplyContract(ctx, evmModuleAddress, proxyAddress, nil, GetBridgeProxy().ABI, "init", logicContract); err != nil {
return err
}
return nil
}

func initBridgeFeeOracle(
ctx sdk.Context,
bridgeFeeOracleKeeper BridgeFeeOracleKeeper,
owner, defaultOracleAddress common.Address,
) error {
if _, err := bridgeFeeOracleKeeper.Initialize(ctx); err != nil {
return err
}
role, err := bridgeFeeOracleKeeper.GetQuoteRole(ctx)
if err != nil {
return err
}
if _, err = bridgeFeeOracleKeeper.GrantRole(ctx, role, common.HexToAddress(BridgeFeeAddress)); err != nil {
return err
}
ownerRole, err := bridgeFeeOracleKeeper.GetOwnerRole(ctx)
if err != nil {
return err
}
if _, err = bridgeFeeOracleKeeper.GrantRole(ctx, ownerRole, owner); err != nil {
return err
}
upgradeRole, err := bridgeFeeOracleKeeper.GetUpgradeRole(ctx)
if err != nil {
return err
}
if _, err = bridgeFeeOracleKeeper.GrantRole(ctx, upgradeRole, owner); err != nil {
return err
}
if _, err = bridgeFeeOracleKeeper.SetDefaultOracle(ctx, defaultOracleAddress); err != nil {
return err
}
return nil
}

func initBridgeFeeQuote(
ctx sdk.Context,
bridgeFeeQuoteKeeper BridgeFeeQuoteKeeper,
bridgeDenoms []BridgeDenoms,
owner common.Address,
) error {
if _, err := bridgeFeeQuoteKeeper.Initialize(ctx, common.HexToAddress(BridgeFeeOracleAddress), big.NewInt(DefaultMaxQuoteIndex)); err != nil {
return err
}
ownerRole, err := bridgeFeeQuoteKeeper.GetOwnerRole(ctx)
if err != nil {
return err
}
if _, err = bridgeFeeQuoteKeeper.GrantRole(ctx, ownerRole, owner); err != nil {
return err
}
upgradeRole, err := bridgeFeeQuoteKeeper.GetUpgradeRole(ctx)
if err != nil {
return err
}
if _, err = bridgeFeeQuoteKeeper.GrantRole(ctx, upgradeRole, owner); err != nil {
return err
}
for _, bridgeDenom := range bridgeDenoms {
if _, err = bridgeFeeQuoteKeeper.RegisterChain(ctx, bridgeDenom.ChainName, bridgeDenom.Denoms...); err != nil {
return err
}
}
return nil
}
63 changes: 63 additions & 0 deletions contract/bridge_fee_oracle.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package contract

import (
"context"

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 BridgeFeeOracleKeeper struct {
Caller
abi abi.ABI
from common.Address
contract common.Address
}

func NewBridgeFeeOracleKeeper(caller Caller, contract string) BridgeFeeOracleKeeper {
return BridgeFeeOracleKeeper{
Caller: caller,
abi: GetBridgeFeeOracle().ABI,
from: common.BytesToAddress(authtypes.NewModuleAddress(types.ModuleName).Bytes()),
contract: common.HexToAddress(contract),
}
}

func (k BridgeFeeOracleKeeper) Initialize(ctx context.Context) (*types.MsgEthereumTxResponse, error) {
return k.Caller.ApplyContract(ctx, k.from, k.contract, nil, k.abi, "initialize", common.HexToAddress(CrosschainAddress))
zakir-code marked this conversation as resolved.
Show resolved Hide resolved
}

func (k BridgeFeeOracleKeeper) GetOwnerRole(ctx context.Context) (common.Hash, error) {
var res struct{ Role common.Hash }
if err := k.QueryContract(sdk.UnwrapSDKContext(ctx), k.from, k.contract, k.abi, "OWNER_ROLE", &res); err != nil {
return common.Hash{}, err
}
return res.Role, nil
}

func (k BridgeFeeOracleKeeper) GetUpgradeRole(ctx context.Context) (common.Hash, error) {
var res struct{ Role common.Hash }
if err := k.QueryContract(sdk.UnwrapSDKContext(ctx), k.from, k.contract, k.abi, "UPGRADE_ROLE", &res); err != nil {
return common.Hash{}, err
}
return res.Role, nil
}

func (k BridgeFeeOracleKeeper) GetQuoteRole(ctx context.Context) (common.Hash, error) {
var res struct{ Role common.Hash }
if err := k.QueryContract(sdk.UnwrapSDKContext(ctx), k.from, k.contract, k.abi, "QUOTE_ROLE", &res); err != nil {
return common.Hash{}, err
}
return res.Role, nil
}

func (k BridgeFeeOracleKeeper) GrantRole(ctx context.Context, role common.Hash, account common.Address) (*types.MsgEthereumTxResponse, error) {
return k.ApplyContract(ctx, k.from, k.contract, nil, k.abi, "grantRole", role, account)
}

func (k BridgeFeeOracleKeeper) SetDefaultOracle(ctx context.Context, oracle common.Address) (*types.MsgEthereumTxResponse, error) {
return k.ApplyContract(ctx, k.from, k.contract, nil, k.abi, "setDefaultOracle", oracle)
}
1,821 changes: 1,821 additions & 0 deletions contract/bridge_fee_oracle.sol.go

Large diffs are not rendered by default.

Loading
Loading