Skip to content

Commit

Permalink
feat(bridgecall): implement pre-compilation for ibc transfer
Browse files Browse the repository at this point in the history
  • Loading branch information
nulnut authored and zakir-code committed Oct 11, 2024
1 parent ebd652f commit f27bf64
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 26 deletions.
27 changes: 14 additions & 13 deletions x/crosschain/precompile/bridge_call.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ import (
"errors"
"math/big"

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

fxtypes "github.com/functionx/fx-core/v8/types"
crosschaintypes "github.com/functionx/fx-core/v8/x/crosschain/types"
ethtypes "github.com/functionx/fx-core/v8/x/eth/types"
evmtypes "github.com/functionx/fx-core/v8/x/evm/types"
)

Expand Down Expand Up @@ -49,48 +52,46 @@ func (m *BridgeCallMethod) Run(evm *vm.EVM, contract *vm.Contract) ([]byte, erro
return nil, err
}

route, has := m.router.GetRoute(args.DstChain)
if !has {
return nil, errors.New("invalid dstChain")
}
stateDB := evm.StateDB.(evmtypes.ExtStateDB)
var result []byte
err = stateDB.ExecuteNativeAction(contract.Address(), nil, func(ctx sdk.Context) error {
sender := contract.Caller()
baseCoins := make([]sdk.Coin, 0, len(args.Tokens)+1)
value := contract.Value()
originTokenAmount := sdkmath.ZeroInt()
if value.Cmp(big.NewInt(0)) == 1 {
coin, err := m.handlerOriginToken(ctx, evm, sender, value)
if err != nil {
return err
}
baseCoins = append(baseCoins, coin)
originTokenAmount = coin.Amount
}
crosschainKeeper, ok := m.router.GetRoute(ethtypes.ModuleName)
if !ok {
return errors.New("invalid router")
}
for i, token := range args.Tokens {
crosschainKeeper, ok := m.router.GetRoute(args.DstChain)
if !ok {
return errors.New("invalid dstChain")
}
coin, err := crosschainKeeper.EvmToBaseCoin(ctx, token.String(), args.Amounts[i], sender)
if err != nil {
return err
}
baseCoins = append(baseCoins, coin)
}

bridgeCallNonce, err := route.AddOutgoingBridgeCall(ctx, sender, args.Refund, baseCoins, args.To, args.Data, args.Memo, 0)
fxTarget := fxtypes.ParseFxTarget(args.DstChain)
nonce, err := m.handlerBridgeCall(ctx, sender, args.Refund, args.To, baseCoins, args.Data, args.Memo, fxTarget, originTokenAmount)
if err != nil {
return err
}

emitNonce := new(big.Int).SetUint64(bridgeCallNonce)
data, topic, err := m.NewBridgeCallEvent(args, sender, evm.Origin, emitNonce)
eventNonce := new(big.Int).SetUint64(nonce)
data, topic, err := m.NewBridgeCallEvent(args, sender, evm.Origin, eventNonce)
if err != nil {
return err
}
EmitEvent(evm, data, topic)

result, err = m.PackOutput(emitNonce)
result, err = m.PackOutput(eventNonce)
return err
})
return result, err
Expand Down
47 changes: 38 additions & 9 deletions x/crosschain/precompile/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ func (c *Keeper) handlerCrossChain(
originToken bool,
) error {
if fxTarget.IsIBC() {
return c.ibcTransfer(ctx, from.Bytes(), receipt, amount, fee, fxTarget, memo, originToken)
_, err := c.ibcTransfer(ctx, from.Bytes(), receipt, amount, fee, fxTarget, memo, originToken)
return err
}

return c.outgoingTransfer(ctx, from.Bytes(), receipt, amount, fee, fxTarget, originToken)
Expand Down Expand Up @@ -151,29 +152,29 @@ func (c *Keeper) ibcTransfer(
fxTarget fxtypes.FxTarget,
memo string,
originToken bool,
) error {
) (uint64, error) {
if !fee.IsZero() {
return fmt.Errorf("ibc transfer fee must be zero: %s", fee.String())
return 0, fmt.Errorf("ibc transfer fee must be zero: %s", fee.String())
}
if strings.ToLower(fxTarget.Prefix) == contract.EthereumAddressPrefix {
if err := contract.ValidateEthereumAddress(to); err != nil {
return fmt.Errorf("invalid to address: %s", to)
return 0, fmt.Errorf("invalid to address: %s", to)
}
} else {
if _, err := sdk.GetFromBech32(to, fxTarget.Prefix); err != nil {
return fmt.Errorf("invalid to address: %s", to)
return 0, fmt.Errorf("invalid to address: %s", to)
}
}

if !originToken {
var err error
crossChainKeeper, found := c.router.GetRoute(ethtypes.ModuleName)
if !found {
return sdkerrors.ErrInvalidRequest.Wrap("crosschain not found")
return 0, sdkerrors.ErrInvalidRequest.Wrap("crosschain not found")
}
amount, err = crossChainKeeper.BaseCoinToIBCCoin(ctx, amount, from, fxTarget.String())
if err != nil {
return err
return 0, err
}
}

Expand All @@ -191,11 +192,39 @@ func (c *Keeper) ibcTransfer(
),
)
if err != nil {
return fmt.Errorf("ibc transfer error: %s", err.Error())
return 0, fmt.Errorf("ibc transfer error: %s", err.Error())
}

if !originToken {
c.erc20Keeper.SetIBCTransferRelation(ctx, fxTarget.SourceChannel, transferResponse.Sequence)
}
return nil
return transferResponse.Sequence, nil
}

func (c *Keeper) handlerBridgeCall(
ctx sdk.Context,
from, refund, to common.Address,
coins sdk.Coins,
data, memo []byte,
fxTarget fxtypes.FxTarget,
originTokenAmount sdkmath.Int,
) (nonce uint64, err error) {
if fxTarget.IsIBC() {
if !coins.IsValid() || len(coins) != 1 {
return 0, sdkerrors.ErrInvalidCoins.Wrapf("ibc transfer with coins: %s", coins.String())
}
amount := coins[0]
toAddr, err := fxTarget.ReceiveAddrToStr(to.Bytes())
if err != nil {
return 0, sdkerrors.ErrInvalidAddress.Wrapf("ibc transfer target %s to: %s", fxTarget.GetTarget(), to.String())
}
return c.ibcTransfer(ctx, from.Bytes(), toAddr, amount, sdk.NewCoin(amount.Denom, sdkmath.ZeroInt()), fxTarget, string(memo), !originTokenAmount.IsZero())
}

route, has := c.router.GetRoute(fxTarget.GetTarget())
if !has {
return 0, errors.New("invalid dstChain")
}
// todo record origin amount
return route.AddOutgoingBridgeCall(ctx, from, refund, coins, to, data, memo, 0)
}
8 changes: 4 additions & 4 deletions x/crosschain/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
bank "github.com/cosmos/cosmos-sdk/x/bank/types"
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
tranfsertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types"
transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types"
"github.com/ethereum/go-ethereum/common"
"github.com/evmos/ethermint/x/evm/types"

Expand Down Expand Up @@ -73,9 +73,9 @@ type EVMKeeper interface {
}

type IBCTransferKeeper interface {
Transfer(ctx context.Context, msg *tranfsertypes.MsgTransfer) (*tranfsertypes.MsgTransferResponse, error)
SetDenomTrace(ctx sdk.Context, denomTrace tranfsertypes.DenomTrace)
GetDenomTrace(ctx sdk.Context, denomTraceHash tmbytes.HexBytes) (tranfsertypes.DenomTrace, bool)
Transfer(ctx context.Context, msg *transfertypes.MsgTransfer) (*transfertypes.MsgTransferResponse, error)
SetDenomTrace(ctx sdk.Context, denomTrace transfertypes.DenomTrace)
GetDenomTrace(ctx sdk.Context, denomTraceHash tmbytes.HexBytes) (transfertypes.DenomTrace, bool)
}

type AccountKeeper interface {
Expand Down

0 comments on commit f27bf64

Please sign in to comment.