Skip to content

Commit

Permalink
test: refactor crosschain precompile test suite (#794)
Browse files Browse the repository at this point in the history
  • Loading branch information
zakir-code authored Oct 31, 2024
1 parent 506ae27 commit 1c1d733
Show file tree
Hide file tree
Showing 18 changed files with 353 additions and 282 deletions.
63 changes: 13 additions & 50 deletions x/crosschain/types/contract.go → contract/crosschain.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package types
package contract

import (
"errors"
"math/big"

"github.com/ethereum/go-ethereum/common"

"github.com/functionx/fx-core/v8/contract"
)

type BridgeCoinAmountArgs struct {
Expand All @@ -21,21 +19,7 @@ func (args *BridgeCoinAmountArgs) Validate() error {
return nil
}

type CancelSendToExternalArgs struct {
Chain string `abi:"_chain"`
TxID *big.Int `abi:"_txID"`
}

func (args *CancelSendToExternalArgs) Validate() error {
if err := ValidateModuleName(args.Chain); err != nil {
return err
}
if args.TxID == nil || args.TxID.Sign() <= 0 {
return errors.New("invalid tx id")
}
return nil
}

// Deprecated: After the upgrade to v8
type CrosschainArgs struct {
Token common.Address `abi:"_token"`
Receipt string `abi:"_receipt"`
Expand All @@ -61,27 +45,6 @@ func (args *CrosschainArgs) Validate() error {
return nil
}

type IncreaseBridgeFeeArgs struct {
Chain string `abi:"_chain"`
TxID *big.Int `abi:"_txID"`
Token common.Address `abi:"_token"`
Fee *big.Int `abi:"_fee"`
}

func (args *IncreaseBridgeFeeArgs) Validate() error {
if err := ValidateModuleName(args.Chain); err != nil {
return err
}

if args.TxID == nil || args.TxID.Sign() <= 0 {
return errors.New("invalid tx id")
}
if args.Fee == nil || args.Fee.Sign() <= 0 {
return errors.New("invalid add bridge fee")
}
return nil
}

type BridgeCallArgs struct {
DstChain string `abi:"_dstChain"`
Refund common.Address `abi:"_refund"`
Expand All @@ -94,16 +57,16 @@ type BridgeCallArgs struct {
}

func (args *BridgeCallArgs) Validate() error {
if err := ValidateModuleName(args.DstChain); err != nil {
return err
if args.DstChain == "" {
return errors.New("empty chain")
}
if args.Value.Sign() != 0 {
return errors.New("value must be zero")
}
if len(args.Tokens) != len(args.Amounts) {
return errors.New("tokens and amounts do not match")
}
if len(args.Amounts) > 0 && contract.IsZeroEthAddress(args.Refund) {
if len(args.Amounts) > 0 && IsZeroEthAddress(args.Refund) {
return errors.New("refund cannot be empty")
}
return nil
Expand All @@ -115,8 +78,8 @@ type ExecuteClaimArgs struct {
}

func (args *ExecuteClaimArgs) Validate() error {
if err := ValidateModuleName(args.Chain); err != nil {
return err
if args.Chain == "" {
return errors.New("empty chain")
}
if args.EventNonce == nil || args.EventNonce.Sign() <= 0 {
return errors.New("invalid event nonce")
Expand All @@ -130,10 +93,10 @@ type HasOracleArgs struct {
}

func (args *HasOracleArgs) Validate() error {
if err := ValidateModuleName(args.Chain); err != nil {
return err
if args.Chain == "" {
return errors.New("empty chain")
}
if contract.IsZeroEthAddress(args.ExternalAddress) {
if IsZeroEthAddress(args.ExternalAddress) {
return errors.New("invalid external address")
}
return nil
Expand All @@ -145,10 +108,10 @@ type IsOracleOnlineArgs struct {
}

func (args *IsOracleOnlineArgs) Validate() error {
if err := ValidateModuleName(args.Chain); err != nil {
return err
if args.Chain == "" {
return errors.New("empty chain")
}
if contract.IsZeroEthAddress(args.ExternalAddress) {
if IsZeroEthAddress(args.ExternalAddress) {
return errors.New("invalid external address")
}
return nil
Expand Down
77 changes: 77 additions & 0 deletions contract/crosschain_precompile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package contract

import (
"context"
"math/big"

sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
evmtypes "github.com/evmos/ethermint/x/evm/types"
)

type CrosschainPrecompileKeeper struct {
Caller
abi abi.ABI
contractAddr common.Address
}

func NewCrosschainPrecompileKeeper(caller Caller, contractAddr common.Address) CrosschainPrecompileKeeper {
if IsZeroEthAddress(contractAddr) {
contractAddr = common.HexToAddress(CrosschainAddress)
}
return CrosschainPrecompileKeeper{
Caller: caller,
abi: MustABIJson(ICrosschainMetaData.ABI),
contractAddr: contractAddr,
}
}

func (k CrosschainPrecompileKeeper) BridgeCoinAmount(ctx context.Context, args BridgeCoinAmountArgs) (*big.Int, error) {
res := struct{ Amount *big.Int }{}
err := k.QueryContract(ctx, common.Address{}, k.contractAddr, k.abi, "bridgeCoinAmount", &res, args.Token, args.Target)
if err != nil {
return nil, err
}
return res.Amount, nil
}

func (k CrosschainPrecompileKeeper) HasOracle(ctx context.Context, args HasOracleArgs) (bool, error) {
res := struct{ HasOracle bool }{}
err := k.QueryContract(ctx, common.Address{}, k.contractAddr, k.abi, "hasOracle", &res, args.Chain, args.ExternalAddress)
if err != nil {
return false, err
}
return res.HasOracle, nil
}

func (k CrosschainPrecompileKeeper) IsOracleOnline(ctx context.Context, args IsOracleOnlineArgs) (bool, error) {
res := struct{ IsOracleOnline bool }{}
err := k.QueryContract(ctx, common.Address{}, k.contractAddr, k.abi, "isOracleOnline", &res, args.Chain, args.ExternalAddress)
if err != nil {
return false, err
}
return res.IsOracleOnline, nil
}

func (k CrosschainPrecompileKeeper) BridgeCall(ctx context.Context, from common.Address, args BridgeCallArgs) (*evmtypes.MsgEthereumTxResponse, *big.Int, error) {
res, err := k.ApplyContract(ctx, from, k.contractAddr, nil, k.abi, "bridgeCall",
args.DstChain, args.Refund, args.Tokens, args.Amounts, args.To, args.Data, args.Value, args.Memo)
if err != nil {
return nil, nil, err
}
ret := struct{ EventNonce *big.Int }{}
if err = k.abi.UnpackIntoInterface(&ret, "bridgeCall", res.Ret); err != nil {
return res, nil, sdkerrors.ErrInvalidType.Wrapf("failed to unpack bridgeCall: %s", err.Error())
}
return res, ret.EventNonce, nil
}

func (k CrosschainPrecompileKeeper) ExecuteClaim(ctx context.Context, from common.Address, args ExecuteClaimArgs) (*evmtypes.MsgEthereumTxResponse, error) {
res, err := k.ApplyContract(ctx, from, k.contractAddr, nil, k.abi, "executeClaim",
args.Chain, args.EventNonce)
if err != nil {
return nil, err
}
return unpackRetIsOk(k.abi, "executeClaim", res)
}
30 changes: 30 additions & 0 deletions solidity/contracts/test/CrosschainTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,34 @@ contract CrosschainTest {
_memo
);
}

function executeClaim(
string memory _chain,
uint256 _eventNonce
) external returns (bool _result) {
return
ICrosschain(CROSS_CHAIN_ADDRESS).executeClaim(_chain, _eventNonce);
}

function hasOracle(
string memory _chain,
address _externalAddress
) external view returns (bool _result) {
return
ICrosschain(CROSS_CHAIN_ADDRESS).hasOracle(
_chain,
_externalAddress
);
}

function isOracleOnline(
string memory _chain,
address _externalAddress
) external view returns (bool _result) {
return
ICrosschain(CROSS_CHAIN_ADDRESS).isOracleOnline(
_chain,
_externalAddress
);
}
}
Loading

0 comments on commit 1c1d733

Please sign in to comment.