Skip to content

Commit

Permalink
refactor(fungible): set default liquidity cap for new ZRC20s (#2802)
Browse files Browse the repository at this point in the history
* default liquidity cap

* fix test

* changelog

* set cap in e2e tests
  • Loading branch information
lumtis authored Sep 10, 2024
1 parent d335f2d commit 3c2da19
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 24 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
* [2615](https://github.com/zeta-chain/node/pull/2615) - Refactor cleanup of outbound trackers
* [2749](https://github.com/zeta-chain/node/pull/2749) - fix all lint errors from govet
* [2725](https://github.com/zeta-chain/node/pull/2725) - refactor SetCctxAndNonceToCctxAndInboundHashToCctx to receive tsspubkey as an argument
* [2802](https://github.com/zeta-chain/node/pull/2802) - set default liquidity cap for new ZRC20s

### Tests

Expand Down
65 changes: 57 additions & 8 deletions e2e/txserver/zeta_tx_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (

"github.com/zeta-chain/node/app"
"github.com/zeta-chain/node/cmd/zetacored/config"
"github.com/zeta-chain/node/e2e/utils"
"github.com/zeta-chain/node/pkg/chains"
"github.com/zeta-chain/node/pkg/coin"
authoritytypes "github.com/zeta-chain/node/x/authority/types"
Expand Down Expand Up @@ -441,7 +442,7 @@ func (zts ZetaTxServer) DeployZRC20s(
}

// deploy eth zrc20
_, err = zts.BroadcastTx(deployerAccount, fungibletypes.NewMsgDeployFungibleCoinZRC20(
res, err := zts.BroadcastTx(deployerAccount, fungibletypes.NewMsgDeployFungibleCoinZRC20(
deployerAddr,
"",
chains.GoerliLocalnet.ChainId,
Expand All @@ -454,9 +455,16 @@ func (zts ZetaTxServer) DeployZRC20s(
if err != nil {
return "", fmt.Errorf("failed to deploy eth zrc20: %s", err.Error())
}
zrc20, err := fetchZRC20FromDeployResponse(res)
if err != nil {
return "", err
}
if err := zts.initializeLiquidityCap(zrc20); err != nil {
return "", err
}

// deploy btc zrc20
_, err = zts.BroadcastTx(deployerAccount, fungibletypes.NewMsgDeployFungibleCoinZRC20(
res, err = zts.BroadcastTx(deployerAccount, fungibletypes.NewMsgDeployFungibleCoinZRC20(
deployerAddr,
"",
chains.BitcoinRegtest.ChainId,
Expand All @@ -469,9 +477,16 @@ func (zts ZetaTxServer) DeployZRC20s(
if err != nil {
return "", fmt.Errorf("failed to deploy btc zrc20: %s", err.Error())
}
zrc20, err = fetchZRC20FromDeployResponse(res)
if err != nil {
return "", err
}
if err := zts.initializeLiquidityCap(zrc20); err != nil {
return "", err
}

// deploy sol zrc20
_, err = zts.BroadcastTx(deployerAccount, fungibletypes.NewMsgDeployFungibleCoinZRC20(
res, err = zts.BroadcastTx(deployerAccount, fungibletypes.NewMsgDeployFungibleCoinZRC20(
deployerAddr,
"",
chains.SolanaLocalnet.ChainId,
Expand All @@ -484,9 +499,16 @@ func (zts ZetaTxServer) DeployZRC20s(
if err != nil {
return "", fmt.Errorf("failed to deploy sol zrc20: %s", err.Error())
}
zrc20, err = fetchZRC20FromDeployResponse(res)
if err != nil {
return "", err
}
if err := zts.initializeLiquidityCap(zrc20); err != nil {
return "", err
}

// deploy erc20 zrc20
res, err := zts.BroadcastTx(deployerAccount, fungibletypes.NewMsgDeployFungibleCoinZRC20(
res, err = zts.BroadcastTx(deployerAccount, fungibletypes.NewMsgDeployFungibleCoinZRC20(
deployerAddr,
erc20Addr,
chains.GoerliLocalnet.ChainId,
Expand All @@ -501,12 +523,12 @@ func (zts ZetaTxServer) DeployZRC20s(
}

// fetch the erc20 zrc20 contract address and remove the quotes
erc20zrc20Addr, err := FetchAttributeFromTxResponse(res, "Contract")
erc20zrc20Addr, err := fetchZRC20FromDeployResponse(res)
if err != nil {
return "", fmt.Errorf("failed to fetch erc20 zrc20 contract address: %s, %s", err.Error(), res.String())
return "", err
}
if !ethcommon.IsHexAddress(erc20zrc20Addr) {
return "", fmt.Errorf("invalid address in event: %s", erc20zrc20Addr)
if err := zts.initializeLiquidityCap(erc20zrc20Addr); err != nil {
return "", err
}

return erc20zrc20Addr, nil
Expand Down Expand Up @@ -557,6 +579,33 @@ func (zts *ZetaTxServer) SetAuthorityClient(authorityClient authoritytypes.Query
zts.authorityClient = authorityClient
}

// initializeLiquidityCap initializes the liquidity cap for the given coin with a large value
func (zts ZetaTxServer) initializeLiquidityCap(zrc20 string) error {
liquidityCap := sdktypes.NewUint(1e18).MulUint64(1e12)

msg := fungibletypes.NewMsgUpdateZRC20LiquidityCap(
zts.MustGetAccountAddressFromName(utils.OperationalPolicyName),
zrc20,
liquidityCap,
)
_, err := zts.BroadcastTx(utils.OperationalPolicyName, msg)
return err
}

// fetchZRC20FromDeployResponse fetches the zrc20 address from the response
func fetchZRC20FromDeployResponse(res *sdktypes.TxResponse) (string, error) {
// fetch the erc20 zrc20 contract address and remove the quotes
zrc20Addr, err := FetchAttributeFromTxResponse(res, "Contract")
if err != nil {
return "", fmt.Errorf("failed to fetch zrc20 contract address: %s, %s", err.Error(), res.String())
}
if !ethcommon.IsHexAddress(zrc20Addr) {
return "", fmt.Errorf("invalid address in event: %s", zrc20Addr)
}

return zrc20Addr, nil
}

// fetchMessagePermissions fetches the message permissions for a given message
// return a bool preV19 to indicate the node is preV19 and the query doesn't exist
func (zts ZetaTxServer) fetchMessagePermissions(msg sdktypes.Msg) (authoritytypes.PolicyType, bool, error) {
Expand Down
30 changes: 14 additions & 16 deletions x/fungible/keeper/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,10 @@ import (
observertypes "github.com/zeta-chain/node/x/observer/types"
)

// TODO USE string constant
var (
BigIntZero = big.NewInt(0)
ZEVMGasLimitDepositAndCall = big.NewInt(1_000_000)

ZEVMGasLimitConnectorCall = big.NewInt(1_000_000)
ZEVMGasLimitConnectorCall = big.NewInt(1_000_000)
)

// DeployContract deploys a new contract in the ZEVM
Expand Down Expand Up @@ -98,9 +96,6 @@ func (k Keeper) DeployContract(

// DeployZRC20Contract creates and deploys an ERC20 contract on the EVM with the
// erc20 module account as owner. Also adds itself to ForeignCoins fungible module state variable
// TODO Unit test for these functions
// https://github.com/zeta-chain/node/issues/864
// TODO Remove repetitive code
func (k Keeper) DeployZRC20Contract(
ctx sdk.Context,
name, symbol string,
Expand Down Expand Up @@ -154,17 +149,20 @@ func (k Keeper) DeployZRC20Contract(
err.Error(),
)
}
coin, _ := k.GetForeignCoins(ctx, contractAddr.Hex())
coin.CoinType = coinType
coin.Name = name
coin.Symbol = symbol

// create and set in the store the new foreign coin object
newCoin, _ := k.GetForeignCoins(ctx, contractAddr.Hex())
newCoin.CoinType = coinType
newCoin.Name = name
newCoin.Symbol = symbol
// #nosec G115 uint8 -> uint32 false positive
coin.Decimals = uint32(decimals)
coin.Asset = erc20Contract
coin.Zrc20ContractAddress = contractAddr.Hex()
coin.ForeignChainId = chain.ChainId
coin.GasLimit = gasLimit.Uint64()
k.SetForeignCoins(ctx, coin)
newCoin.Decimals = uint32(decimals)
newCoin.Asset = erc20Contract
newCoin.Zrc20ContractAddress = contractAddr.Hex()
newCoin.ForeignChainId = chain.ChainId
newCoin.GasLimit = gasLimit.Uint64()
newCoin.LiquidityCap = sdk.NewUint(types.DefaultLiquidityCap).MulUint64(uint64(newCoin.Decimals))
k.SetForeignCoins(ctx, newCoin)

return contractAddr, nil
}
Expand Down
1 change: 1 addition & 0 deletions x/fungible/keeper/evm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ func TestKeeper_DeployZRC20Contract(t *testing.T) {
require.Equal(t, "bar", foreignCoins.Symbol)
require.Equal(t, coin.CoinType_Gas, foreignCoins.CoinType)
require.Equal(t, uint64(1000), foreignCoins.GasLimit)
require.True(t, foreignCoins.LiquidityCap.Equal(sdk.NewUint(types.DefaultLiquidityCap).MulUint64(8)))

// can get the zrc20 data
zrc20Data, err := k.QueryZRC20Data(ctx, addr)
Expand Down
14 changes: 14 additions & 0 deletions x/fungible/keeper/gas_coin_and_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ func setupGasCoin(
)
require.NoError(t, err)
assertContractDeployment(t, evmk, ctx, addr)

// increase the default liquidity cap
foreignCoin, found := k.GetForeignCoins(ctx, addr.Hex())
require.True(t, found)
foreignCoin.LiquidityCap = sdk.NewUint(1e18).MulUint64(1e12)
k.SetForeignCoins(ctx, foreignCoin)

return addr
}

Expand All @@ -68,6 +75,13 @@ func deployZRC20(
)
require.NoError(t, err)
assertContractDeployment(t, evmk, ctx, addr)

// increase the default liquidity cap
foreignCoin, found := k.GetForeignCoins(ctx, addr.Hex())
require.True(t, found)
foreignCoin.LiquidityCap = sdk.NewUint(1e18).MulUint64(1e12)
k.SetForeignCoins(ctx, foreignCoin)

return addr
}

Expand Down
5 changes: 5 additions & 0 deletions x/fungible/types/zrc20.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ package types

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

// DefaultLiquidityCap is the default value set for the liquidity cap of a new ZRC20 when deployed
// for security reason, this value is low. An arbitrary value should be set during the process of deploying a new ZRC20
// The value is represented in the base unit of the ZRC20, final value is calculated by multiplying this value by 10^decimals
const DefaultLiquidityCap = uint64(1000)

// ZRC20Data represents the ZRC4 token details used to map
// the token to a Cosmos Coin
type ZRC20Data struct {
Expand Down

0 comments on commit 3c2da19

Please sign in to comment.