Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(fungible): set default liquidity cap for new ZRC20s #2802

Merged
merged 6 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,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)
lumtis marked this conversation as resolved.
Show resolved Hide resolved

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)
lumtis marked this conversation as resolved.
Show resolved Hide resolved

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)

lumtis marked this conversation as resolved.
Show resolved Hide resolved
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)

lumtis marked this conversation as resolved.
Show resolved Hide resolved
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
Loading