Skip to content

Commit

Permalink
test: add quote unit test (#927)
Browse files Browse the repository at this point in the history
  • Loading branch information
zakir-code authored Jan 21, 2025
1 parent 9addb51 commit 27b0c24
Show file tree
Hide file tree
Showing 17 changed files with 215 additions and 92 deletions.
12 changes: 8 additions & 4 deletions app/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@ import (
)

func initChainer(ctx sdk.Context, keepers keepers.AppKeepers) error {
delegations, err := keepers.StakingKeeper.GetAllDelegations(ctx)
validators, err := keepers.StakingKeeper.GetValidators(ctx, 1)
if err != nil {
return err
}
if len(delegations) == 0 {
return errors.New("no delegations found")
if len(validators) == 0 {
return errors.New("no validators found")
}
defValAddress, err := sdk.ValAddressFromBech32(validators[0].OperatorAddress)
if err != nil {
return err
}

bridgeDenoms := []contract.BridgeDenoms{
Expand All @@ -38,7 +42,7 @@ func initChainer(ctx sdk.Context, keepers keepers.AppKeepers) error {
bridgeDenoms,
moduleAddress,
moduleAddress,
common.BytesToAddress(sdk.MustAccAddressFromBech32(delegations[0].DelegatorAddress).Bytes()),
common.BytesToAddress(defValAddress.Bytes()),
); err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions app/upgrade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@ func getTestnetTokenAmount(ctx sdk.Context, coin sdk.Coin) sdk.Coin {
func checkBridgeFeeContract(t *testing.T, ctx sdk.Context, myApp *app.App) {
t.Helper()

bridgeFeeQuoteKeeper := contract.NewBridgeFeeQuoteKeeper(myApp.EvmKeeper, contract.BridgeFeeAddress)
bridgeFeeQuoteKeeper := contract.NewBridgeFeeQuoteKeeper(myApp.EvmKeeper)

quote, err := bridgeFeeQuoteKeeper.GetDefaultOracleQuote(ctx, contract.MustStrToByte32("eth"), contract.MustStrToByte32("usdt"))
require.NoError(t, err)
Expand Down Expand Up @@ -611,7 +611,7 @@ func checkBridgeFeeContract(t *testing.T, ctx sdk.Context, myApp *app.App) {
require.Len(t, tokens, len(bridgeTokens))
}

bridgeFeeOracleKeeper := contract.NewBridgeFeeOracleKeeper(myApp.EvmKeeper, contract.BridgeFeeOracleAddress)
bridgeFeeOracleKeeper := contract.NewBridgeFeeOracleKeeper(myApp.EvmKeeper)
oracle, err := bridgeFeeOracleKeeper.DefaultOracle(ctx)
require.NoError(t, err)
require.Equal(t, oracle, common.HexToAddress("0x9c079e86be639076809620CBFaa3784649F5ee81"))
Expand Down
6 changes: 4 additions & 2 deletions contract/bridge_fee.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"github.com/ethereum/go-ethereum/common"
)

const DefaultMaxQuoteCap = 3

func DeployBridgeFeeContract(
ctx sdk.Context,
evmKeeper EvmKeeper,
Expand Down Expand Up @@ -33,11 +35,11 @@ func DeployBridgeFeeContract(
return err
}

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

Expand Down
7 changes: 5 additions & 2 deletions contract/bridge_fee_oracle.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ type BridgeFeeOracleKeeper struct {
contract common.Address
}

func NewBridgeFeeOracleKeeper(caller Caller, contract string) BridgeFeeOracleKeeper {
func NewBridgeFeeOracleKeeper(caller Caller, contract ...string) BridgeFeeOracleKeeper {
if len(contract) == 0 {
contract = append(contract, BridgeFeeOracleAddress)
}
return BridgeFeeOracleKeeper{
Caller: caller,
abi: GetBridgeFeeOracle().ABI,
from: common.BytesToAddress(authtypes.NewModuleAddress(types.ModuleName).Bytes()),
contract: common.HexToAddress(contract),
contract: common.HexToAddress(contract[0]),
}
}

Expand Down
32 changes: 30 additions & 2 deletions contract/bridge_fee_quote.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package contract

import (
"context"
"fmt"
"math/big"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -91,22 +93,48 @@ func (k BridgeFeeQuoteKeeper) GetUpgradeRole(ctx context.Context) (common.Hash,
return res.Role, nil
}

func (k BridgeFeeQuoteKeeper) Quote(ctx context.Context, from common.Address, inputs []IBridgeFeeQuoteQuoteInput) (*types.MsgEthereumTxResponse, error) {
res, err := k.ApplyContract(ctx, from, k.contract, nil, k.abi, "quote", inputs)
if err != nil {
return k.unpackError(res, err)
}
var ret struct{ QuoteIds []*big.Int }
if err = k.abi.UnpackIntoInterface(&ret, "quote", res.Ret); err != nil {
return res, sdkerrors.ErrInvalidType.Wrapf("failed to unpack %s: %s", "quote", err.Error())
}
if len(ret.QuoteIds) == 0 {
return res, sdkerrors.ErrInvalidRequest.Wrapf("quote ids not found")
}
return res, nil
}

func (k BridgeFeeQuoteKeeper) 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 BridgeFeeQuoteKeeper) RegisterChain(ctx context.Context, chainName common.Hash, tokenNames ...common.Hash) (*types.MsgEthereumTxResponse, error) {
res, err := k.ApplyContract(ctx, k.from, k.contract, nil, k.abi, "registerChain", chainName, tokenNames)
if err != nil {
return nil, err
return k.unpackError(res, err)
}
return unpackRetIsOk(k.abi, "registerChain", res)
}

func (k BridgeFeeQuoteKeeper) AddToken(ctx context.Context, chainName common.Hash, tokenNames []common.Hash) (*types.MsgEthereumTxResponse, error) {
res, err := k.ApplyContract(ctx, k.from, k.contract, nil, k.abi, "addToken", chainName, tokenNames)
if err != nil {
return nil, err
return k.unpackError(res, err)
}
return unpackRetIsOk(k.abi, "addToken", res)
}

func (k BridgeFeeQuoteKeeper) unpackError(res *types.MsgEthereumTxResponse, err error) (*types.MsgEthereumTxResponse, error) {
if err == nil {
return res, nil
}
revertInfo, unpackErr := UnpackRevertError(k.abi, res.Ret)
if unpackErr != nil {
return res, err
}
return res, fmt.Errorf("reverted: %s, vmErr: %s", revertInfo, err.Error())
}
30 changes: 30 additions & 0 deletions contract/contract.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package contract

import (
"bytes"
"context"
"errors"
"fmt"
"math/big"
"strings"

Expand All @@ -28,6 +31,9 @@ const (

const DefaultGasCap uint64 = 30000000

// TransferModuleRole is keccak256("TRANSFER_MODULE_ROLE")
const TransferModuleRole = "0x4845f2571489e4ee59e15b11b74598e4330ef896ebb57513ebdbdb3b260a4671"

var (
erc20Init = Contract{
Address: common.HexToAddress(ERC20LogicAddress),
Expand Down Expand Up @@ -91,6 +97,11 @@ type Caller interface {
ExecuteEVM(ctx sdk.Context, from common.Address, contract *common.Address, value *big.Int, gasLimit uint64, data []byte) (*evmtypes.MsgEthereumTxResponse, error)
}

type BridgeDenoms struct {
ChainName common.Hash
Denoms []common.Hash
}

type Contract struct {
Address common.Address
ABI abi.ABI
Expand Down Expand Up @@ -212,3 +223,22 @@ func unpackRetIsOk(abi abi.ABI, method string, res *evmtypes.MsgEthereumTxRespon
}
return res, nil
}

func UnpackRevertError(abi abi.ABI, ret []byte) (string, error) {
if len(ret) < 4 {
return "", errors.New("invalid data for unpacking")
}
for _, e := range abi.Errors {
if bytes.Equal(e.ID[:4], ret[:4]) {
if len(ret) == 4 {
return e.Name, nil
}
unpack, err := e.Unpack(ret[4:])
if err != nil {
return "", err
}
return fmt.Sprintf("%s: %v", e.Name, unpack), nil
}
}
return "", errors.New("invalid data for unpacking")
}
11 changes: 11 additions & 0 deletions contract/contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,14 @@ func replayCodeAddress(codeBase64, addr, addrNew string) (code, codeNew []byte)

return bzZero, bzNew
}

func TestUnpackRevertError(t *testing.T) {
bridgeFeeQuoteABI := contract.GetBridgeFeeQuote().ABI

errSigs := make([]string, 0, len(bridgeFeeQuoteABI.Errors))
for _, e := range bridgeFeeQuoteABI.Errors {
errSig := hex.EncodeToString(e.ID[:4])
require.NotContains(t, errSigs, errSig)
errSigs = append(errSigs, errSig)
}
}
17 changes: 0 additions & 17 deletions contract/types.go

This file was deleted.

22 changes: 13 additions & 9 deletions testutil/helpers/base_suite.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package helpers

import (
"bytes"
"fmt"
"time"

Expand Down Expand Up @@ -34,7 +35,7 @@ type BaseSuite struct {
suite.Suite
MintValNumber int
ValSet *tmtypes.ValidatorSet
ValAddr []sdk.ValAddress
ValPrivs []*Signer
App *app.App
Ctx sdk.Context
}
Expand All @@ -44,18 +45,21 @@ func (s *BaseSuite) SetupTest() {
if valNumber <= 0 {
valNumber = tmrand.Intn(10) + 1
}
valSet, valAccounts, valBalances := generateGenesisValidator(valNumber, sdk.Coins{})
s.ValSet = valSet
s.ValAddr = make([]sdk.ValAddress, valNumber)
for i := 0; i < valNumber; i++ {
s.ValAddr[i] = valAccounts[i].GetAddress().Bytes()
}

s.App = setupWithGenesisValSet(s.T(), valSet, valAccounts, valBalances...)
s.ValSet, s.ValPrivs = generateGenesisValidator(valNumber)
s.App = setupWithGenesisValSet(s.T(), s.ValSet, s.ValPrivs)
s.Ctx = s.App.GetContextForFinalizeBlock(nil)
s.Ctx = s.Ctx.WithProposer(s.ValSet.Proposer.Address.Bytes())
}

func (s *BaseSuite) HasValAddr(address []byte) bool {
for i := 0; i < len(s.ValPrivs); i++ {
if bytes.Equal(s.ValPrivs[i].Address().Bytes(), address) {
return true
}
}
return false
}

func (s *BaseSuite) AddTestSigner(amount ...int64) *Signer {
signer := NewSigner(NewEthPrivKey())
defAmount := int64(10000)
Expand Down
Loading

0 comments on commit 27b0c24

Please sign in to comment.