Skip to content

Commit

Permalink
Merge branch 'develop' into blame-index-update
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinssgh authored Oct 10, 2023
2 parents 1ed3477 + 996f35d commit 476832b
Show file tree
Hide file tree
Showing 9 changed files with 474 additions and 140 deletions.
14 changes: 13 additions & 1 deletion cmd/zetacored/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func NewRootCmd() (*cobra.Command, appparams.EncodingConfig) {

customAppTemplate, customAppConfig := initAppConfig()

return server.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig, tmcfg.DefaultConfig())
return server.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig, initTmConfig())
},
}

Expand All @@ -107,6 +107,18 @@ func initAppConfig() (string, interface{}) {
return servercfg.AppConfig(zetacoredconfig.BaseDenom)
}

// initTmConfig overrides the default Tendermint config
func initTmConfig() *tmcfg.Config {
cfg := tmcfg.DefaultConfig()

// use mempool version 1 to enable tx priority
if cfg.Mempool != nil {
cfg.Mempool.Version = tmcfg.MempoolV1
}

return cfg
}

func initRootCmd(rootCmd *cobra.Command, encodingConfig appparams.EncodingConfig) {
rootCmd.AddCommand(
ethermintclient.ValidateChainID(
Expand Down
5 changes: 5 additions & 0 deletions docs/openapi/openapi.swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50449,6 +50449,11 @@ definitions:
type: object
crosschainMsgWhitelistERC20Response:
type: object
properties:
zrc20_address:
type: string
cctx_index:
type: string
crosschainOutTxTracker:
type: object
properties:
Expand Down
3 changes: 3 additions & 0 deletions docs/spec/crosschain/messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ message MsgVoteOnObservedInboundTx {

## MsgWhitelistERC20

WhitelistERC20 deploys a new zrc20, create a foreign coin object for the ERC20
and emit a crosschain tx to whitelist the ERC20 on the external chain

```proto
message MsgWhitelistERC20 {
string creator = 1;
Expand Down
5 changes: 4 additions & 1 deletion proto/crosschain/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ message MsgWhitelistERC20 {
int64 gas_limit = 7;
}

message MsgWhitelistERC20Response {}
message MsgWhitelistERC20Response {
string zrc20_address = 1;
string cctx_index = 2;
}

message MsgAddToOutTxTracker {
string creator = 1;
Expand Down
10 changes: 5 additions & 5 deletions x/crosschain/keeper/cctx_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import (
"errors"
"fmt"

cosmoserrors "cosmossdk.io/errors"
"cosmossdk.io/math"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/zeta-chain/zetacore/common"
"github.com/zeta-chain/zetacore/x/crosschain/types"
Expand All @@ -24,24 +24,24 @@ func (k Keeper) UpdateNonce(ctx sdk.Context, receiveChainID int64, cctx *types.C

nonce, found := k.GetChainNonces(ctx, chain.ChainName.String())
if !found {
return sdkerrors.Wrap(types.ErrCannotFindReceiverNonce, fmt.Sprintf("Chain(%s) | Identifiers : %s ", chain.ChainName.String(), cctx.LogIdentifierForCCTX()))
return cosmoserrors.Wrap(types.ErrCannotFindReceiverNonce, fmt.Sprintf("Chain(%s) | Identifiers : %s ", chain.ChainName.String(), cctx.LogIdentifierForCCTX()))
}

// SET nonce
cctx.GetCurrentOutTxParam().OutboundTxTssNonce = nonce.Nonce
tss, found := k.GetTSS(ctx)
if !found {
return sdkerrors.Wrap(types.ErrCannotFindTSSKeys, fmt.Sprintf("Chain(%s) | Identifiers : %s ", chain.ChainName.String(), cctx.LogIdentifierForCCTX()))
return cosmoserrors.Wrap(types.ErrCannotFindTSSKeys, fmt.Sprintf("Chain(%s) | Identifiers : %s ", chain.ChainName.String(), cctx.LogIdentifierForCCTX()))
}

p, found := k.GetPendingNonces(ctx, tss.TssPubkey, receiveChainID)
if !found {
return sdkerrors.Wrap(types.ErrCannotFindPendingNonces, fmt.Sprintf("chain_id %d, nonce %d", receiveChainID, nonce.Nonce))
return cosmoserrors.Wrap(types.ErrCannotFindPendingNonces, fmt.Sprintf("chain_id %d, nonce %d", receiveChainID, nonce.Nonce))
}

// #nosec G701 always in range
if p.NonceHigh != int64(nonce.Nonce) {
return sdkerrors.Wrap(types.ErrNonceMismatch, fmt.Sprintf("chain_id %d, high nonce %d, current nonce %d", receiveChainID, p.NonceHigh, nonce.Nonce))
return cosmoserrors.Wrap(types.ErrNonceMismatch, fmt.Sprintf("chain_id %d, high nonce %d, current nonce %d", receiveChainID, p.NonceHigh, nonce.Nonce))
}

nonce.Nonce++
Expand Down
72 changes: 51 additions & 21 deletions x/crosschain/keeper/msg_server_whitelist_erc20.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,58 @@ import (
"math/big"

errorsmod "cosmossdk.io/errors"
"cosmossdk.io/math"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
tmtypes "github.com/tendermint/tendermint/types"

"github.com/zeta-chain/zetacore/common"
"github.com/zeta-chain/zetacore/x/crosschain/types"
fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types"
zetaObserverTypes "github.com/zeta-chain/zetacore/x/observer/types"
)

// WhitelistERC20 deploys a new zrc20, create a foreign coin object for the ERC20
// and emit a crosschain tx to whitelist the ERC20 on the external chain
func (k Keeper) WhitelistERC20(goCtx context.Context, msg *types.MsgWhitelistERC20) (*types.MsgWhitelistERC20Response, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
if msg.Creator != k.zetaObserverKeeper.GetParams(ctx).GetAdminPolicyAccount(zetaObserverTypes.Policy_Type_group1) {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Deploy can only be executed by the correct policy account")
return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "Deploy can only be executed by the correct policy account")
}
erc20Addr := ethcommon.HexToAddress(msg.Erc20Address)
if erc20Addr == (ethcommon.Address{}) {
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid ERC20 contract address (%s)", msg.Erc20Address)
return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidAddress, "invalid ERC20 contract address (%s)", msg.Erc20Address)
}

// check if it's already whitelisted
// check if the erc20 is already whitelisted
foreignCoins := k.fungibleKeeper.GetAllForeignCoins(ctx)
for _, fcoin := range foreignCoins {
assetAddr := ethcommon.HexToAddress(fcoin.Asset)
if assetAddr == erc20Addr && fcoin.ForeignChainId == msg.ChainId {
return nil, sdkerrors.Wrapf(types.ErrInvalidAddress, "ERC20 contract address (%s) already whitelisted on chain (%d)", msg.Erc20Address, msg.ChainId)
for _, fCoin := range foreignCoins {
assetAddr := ethcommon.HexToAddress(fCoin.Asset)
if assetAddr == erc20Addr && fCoin.ForeignChainId == msg.ChainId {
return nil, errorsmod.Wrapf(
fungibletypes.ErrForeignCoinAlreadyExist,
"ERC20 contract address (%s) already whitelisted on chain (%d)",
msg.Erc20Address,
msg.ChainId,
)
}
}

tss, found := k.GetTSS(ctx)
if !found {
return nil, errorsmod.Wrapf(types.ErrCannotFindTSSKeys, "Cannot create new admin cmd of type whitelistERC20")
}

chain := k.zetaObserverKeeper.GetParams(ctx).GetChainFromChainID(msg.ChainId)
if chain == nil {
return nil, sdkerrors.Wrapf(types.ErrInvalidChainID, "chain id (%d) not supported", msg.ChainId)
return nil, errorsmod.Wrapf(types.ErrInvalidChainID, "chain id (%d) not supported", msg.ChainId)
}

// use a temporary context for the zrc20 deployment
tmpCtx, commit := ctx.CacheContext()

// add to the foreign coins. Deploy ZRC20 contract for it.
zrc20Addr, err := k.fungibleKeeper.DeployZRC20Contract(
tmpCtx,
Expand All @@ -60,29 +71,43 @@ func (k Keeper) WhitelistERC20(goCtx context.Context, msg *types.MsgWhitelistERC
big.NewInt(msg.GasLimit),
)
if err != nil {
return nil, sdkerrors.Wrapf(types.ErrDeployContract, "failed to deploy ZRC20 contract for ERC20 contract address (%s) on chain (%d)", msg.Erc20Address, msg.ChainId)
return nil, errorsmod.Wrapf(
types.ErrDeployContract,
"failed to deploy ZRC20 contract for ERC20 contract address (%s) on chain (%d)",
msg.Erc20Address,
msg.ChainId,
)
}
if zrc20Addr == (ethcommon.Address{}) {
return nil, sdkerrors.Wrapf(types.ErrDeployContract, "deployed ZRC20 return 0 address for ERC20 contract address (%s) on chain (%d)", msg.Erc20Address, msg.ChainId)
return nil, errorsmod.Wrapf(
types.ErrDeployContract,
"deployed ZRC20 return 0 address for ERC20 contract address (%s) on chain (%d)",
msg.Erc20Address,
msg.ChainId,
)
}

// get necessary parameters to create the cctx
param, found := k.zetaObserverKeeper.GetCoreParamsByChainID(ctx, msg.ChainId)
if !found {
return nil, sdkerrors.Wrapf(types.ErrInvalidChainID, "core params not found for chain id (%d)", msg.ChainId)
return nil, errorsmod.Wrapf(types.ErrInvalidChainID, "core params not found for chain id (%d)", msg.ChainId)
}

medianGasPrice, isFound := k.GetMedianGasPriceInUint(ctx, msg.ChainId)
if !isFound {
return nil, sdkerrors.Wrapf(types.ErrUnableToGetGasPrice, "median gas price not found for chain id (%d)", msg.ChainId)
return nil, errorsmod.Wrapf(types.ErrUnableToGetGasPrice, "median gas price not found for chain id (%d)", msg.ChainId)
}
medianGasPrice = medianGasPrice.MulUint64(2) // overpays gas price by 2x

hash := tmbytes.HexBytes(tmtypes.Tx(ctx.TxBytes()).Hash())
// calculate the cctx index
// we use the deployed zrc20 contract address to generate a unique index
// since other parts of the system may use the zrc20 for the index, we add a message specific suffix
hash := crypto.Keccak256Hash(zrc20Addr.Bytes(), []byte("WhitelistERC20"))
index := hash.Hex()

index := crypto.Keccak256Hash(hash.Bytes())
// create a cmd cctx to whitelist the erc20 on the external chain
cctx := types.CrossChainTx{
Creator: msg.Creator,
Index: index.String(),
Index: index,
ZetaFees: sdk.NewUint(0),
RelayedMessage: fmt.Sprintf("%s:%s", common.CmdWhitelistERC20, msg.Erc20Address),
CctxStatus: &types.Status{
Expand All @@ -96,7 +121,7 @@ func (k Keeper) WhitelistERC20(goCtx context.Context, msg *types.MsgWhitelistERC
TxOrigin: "",
CoinType: common.CoinType_Cmd,
Asset: "",
Amount: sdk.Uint{},
Amount: math.Uint{},
InboundTxObservedHash: hash.String(), // all Upper case Cosmos TX HEX, with no 0x prefix
InboundTxObservedExternalHeight: 0,
InboundTxBallotIndex: "",
Expand All @@ -107,7 +132,7 @@ func (k Keeper) WhitelistERC20(goCtx context.Context, msg *types.MsgWhitelistERC
Receiver: param.Erc20CustodyContractAddress,
ReceiverChainId: msg.ChainId,
CoinType: common.CoinType_Cmd,
Amount: sdk.NewUint(0),
Amount: math.NewUint(0),
OutboundTxTssNonce: 0,
OutboundTxGasLimit: 100_000,
OutboundTxGasPrice: medianGasPrice.String(),
Expand Down Expand Up @@ -137,6 +162,11 @@ func (k Keeper) WhitelistERC20(goCtx context.Context, msg *types.MsgWhitelistERC
}
k.fungibleKeeper.SetForeignCoins(ctx, foreignCoin)
k.SetCctxAndNonceToCctxAndInTxHashToCctx(ctx, cctx)

commit()
return &types.MsgWhitelistERC20Response{}, nil

return &types.MsgWhitelistERC20Response{
Zrc20Address: zrc20Addr.Hex(),
CctxIndex: index,
}, nil
}
Loading

0 comments on commit 476832b

Please sign in to comment.