Skip to content

Commit

Permalink
Add initial total supply to native erc20 tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
goran-ethernal committed Jun 15, 2023
1 parent 24c73e7 commit 32bae84
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 71 deletions.
24 changes: 13 additions & 11 deletions consensus/polybft/contractsapi/contractsapi.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 29 additions & 29 deletions consensus/polybft/contractsapi/gen_sc_data.go

Large diffs are not rendered by default.

36 changes: 25 additions & 11 deletions consensus/polybft/polybft.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/json"
"errors"
"fmt"
"math/big"
"path/filepath"
"time"

Expand Down Expand Up @@ -125,6 +126,17 @@ func GenesisPostHookFactory(config *chain.Chain, engineName string) func(txn *st
return err
}

// calculate initial total supply of native erc20 token
// we skip zero address, since its a special case address
initialTotalSupply := big.NewInt(0)
for addr, alloc := range config.Genesis.Alloc {
if addr == types.ZeroAddress {
continue
}

initialTotalSupply.Add(initialTotalSupply, alloc.Balance)
}

bridgeCfg := polyBFTConfig.Bridge
if bridgeCfg == nil {
return errMissingBridgeConfig
Expand Down Expand Up @@ -308,12 +320,13 @@ func GenesisPostHookFactory(config *chain.Chain, engineName string) func(txn *st
if polyBFTConfig.NativeTokenConfig.IsMintable {
// initialize NativeERC20Mintable SC
params := &contractsapi.InitializeNativeERC20MintableFn{
Predicate_: contracts.ChildERC20PredicateContract,
Owner_: polyBFTConfig.NativeTokenConfig.Owner,
RootToken_: polyBFTConfig.Bridge.RootNativeERC20Addr,
Name_: polyBFTConfig.NativeTokenConfig.Name,
Symbol_: polyBFTConfig.NativeTokenConfig.Symbol,
Decimals_: polyBFTConfig.NativeTokenConfig.Decimals,
Predicate_: contracts.ChildERC20PredicateContract,
Owner_: polyBFTConfig.NativeTokenConfig.Owner,
RootToken_: polyBFTConfig.Bridge.RootNativeERC20Addr,
Name_: polyBFTConfig.NativeTokenConfig.Name,
Symbol_: polyBFTConfig.NativeTokenConfig.Symbol,
Decimals_: polyBFTConfig.NativeTokenConfig.Decimals,
TokenSupply_: initialTotalSupply,
}

input, err := params.EncodeAbi()
Expand All @@ -328,11 +341,12 @@ func GenesisPostHookFactory(config *chain.Chain, engineName string) func(txn *st
} else {
// initialize NativeERC20 SC
params := &contractsapi.InitializeNativeERC20Fn{
Name_: polyBFTConfig.NativeTokenConfig.Name,
Symbol_: polyBFTConfig.NativeTokenConfig.Symbol,
Decimals_: polyBFTConfig.NativeTokenConfig.Decimals,
RootToken_: polyBFTConfig.Bridge.RootNativeERC20Addr,
Predicate_: contracts.ChildERC20PredicateContract,
Name_: polyBFTConfig.NativeTokenConfig.Name,
Symbol_: polyBFTConfig.NativeTokenConfig.Symbol,
Decimals_: polyBFTConfig.NativeTokenConfig.Decimals,
RootToken_: polyBFTConfig.Bridge.RootNativeERC20Addr,
Predicate_: contracts.ChildERC20PredicateContract,
TokenSupply_: initialTotalSupply,
}

input, err := params.EncodeAbi()
Expand Down
83 changes: 63 additions & 20 deletions e2e-polybft/e2e/consensus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/umbracle/ethgo/abi"
"github.com/umbracle/ethgo/wallet"

"github.com/0xPolygon/polygon-edge/command"
"github.com/0xPolygon/polygon-edge/command/genesis"
"github.com/0xPolygon/polygon-edge/command/sidechain"
"github.com/0xPolygon/polygon-edge/consensus/polybft"
Expand All @@ -24,13 +25,28 @@ import (
"github.com/0xPolygon/polygon-edge/types"
)

var uint256ABIType = abi.MustNewType("tuple(uint256)")

func TestE2E_Consensus_Basic_WithNonValidators(t *testing.T) {
const epochSize = 4

cluster := framework.NewTestCluster(t, 5,
framework.WithEpochSize(epochSize), framework.WithNonValidators(2))
defer cluster.Stop()

cluster.WaitForReady(t)

// initialize tx relayer
relayer, err := txrelayer.NewTxRelayer(txrelayer.WithClient(cluster.Servers[0].JSONRPC()))
require.NoError(t, err)

// because we are using native token as reward wallet, and it has default premine balance
initialTotalSupply := new(big.Int).Set(command.DefaultPremineBalance)

// check if initial total supply of native ERC20 token is the same as expected
totalSupply := queryNativeERC20Metadata(t, "totalSupply", uint256ABIType, relayer)
require.True(t, initialTotalSupply.Cmp(totalSupply.(*big.Int)) == 0) //nolint:forcetypeassert

t.Run("consensus protocol", func(t *testing.T) {
require.NoError(t, cluster.WaitForBlock(2*epochSize+1, 1*time.Minute))
})
Expand Down Expand Up @@ -449,41 +465,30 @@ func TestE2E_Consensus_MintableERC20NativeToken(t *testing.T) {
decimals = uint8(5)
)

nativeTokenAddr := ethgo.Address(contracts.NativeERC20TokenContract)

queryNativeERC20Metadata := func(funcName string, abiType *abi.Type, relayer txrelayer.TxRelayer) interface{} {
valueHex, err := ABICall(relayer, contractsapi.NativeERC20Mintable, nativeTokenAddr, ethgo.ZeroAddress, funcName)
require.NoError(t, err)

valueRaw, err := hex.DecodeHex(valueHex)
require.NoError(t, err)

var decodedResult map[string]interface{}

err = abiType.DecodeStruct(valueRaw, &decodedResult)
require.NoError(t, err)

return decodedResult["0"]
}

validatorsAddrs := make([]types.Address, validatorCount)
initValidatorsBalance := ethgo.Ether(1)
initMinterBalance := ethgo.Ether(100000)

minter, err := wallet.GenerateKey()
require.NoError(t, err)

// because we are using native token as reward wallet, and it has default premine balance
initialTotalSupply := new(big.Int).Set(command.DefaultPremineBalance)

cluster := framework.NewTestCluster(t,
validatorCount,
framework.WithNativeTokenConfig(
fmt.Sprintf("%s:%s:%d:true:%s", tokenName, tokenSymbol, decimals, minter.Address())),
framework.WithEpochSize(epochSize),
framework.WithSecretsCallback(func(addrs []types.Address, config *framework.TestClusterConfig) {
config.Premine = append(config.Premine, fmt.Sprintf("%s:%d", minter.Address(), initMinterBalance))
initialTotalSupply.Add(initialTotalSupply, initMinterBalance)

for i, addr := range addrs {
config.Premine = append(config.Premine, fmt.Sprintf("%s:%d", addr, initValidatorsBalance))
config.StakeAmounts = append(config.StakeAmounts, new(big.Int).Set(initValidatorsBalance))
validatorsAddrs[i] = addr
initialTotalSupply.Add(initialTotalSupply, initValidatorsBalance)
}
}))
defer cluster.Stop()
Expand All @@ -500,20 +505,25 @@ func TestE2E_Consensus_MintableERC20NativeToken(t *testing.T) {
stringABIType := abi.MustNewType("tuple(string)")
uint8ABIType := abi.MustNewType("tuple(uint8)")

name := queryNativeERC20Metadata("name", stringABIType, relayer)
totalSupply := queryNativeERC20Metadata(t, "totalSupply", uint256ABIType, relayer)
require.True(t, initialTotalSupply.Cmp(totalSupply.(*big.Int)) == 0) //nolint:forcetypeassert

// check if initial total supply of native ERC20 token is the same as expected
name := queryNativeERC20Metadata(t, "name", stringABIType, relayer)
require.Equal(t, tokenName, name)

symbol := queryNativeERC20Metadata("symbol", stringABIType, relayer)
symbol := queryNativeERC20Metadata(t, "symbol", stringABIType, relayer)
require.Equal(t, tokenSymbol, symbol)

decimalsCount := queryNativeERC20Metadata("decimals", uint8ABIType, relayer)
decimalsCount := queryNativeERC20Metadata(t, "decimals", uint8ABIType, relayer)
require.Equal(t, decimals, decimalsCount)

// send mint transactions
mintFn, exists := contractsapi.NativeERC20Mintable.Abi.Methods["mint"]
require.True(t, exists)

mintAmount := ethgo.Ether(10)
nativeTokenAddr := ethgo.Address(contracts.NativeERC20TokenContract)

// make sure minter account can mint tokens
for _, addr := range validatorsAddrs {
Expand Down Expand Up @@ -570,6 +580,20 @@ func TestE2E_Consensus_CustomRewardToken(t *testing.T) {
)
defer cluster.Stop()

cluster.WaitForReady(t)

// initialize tx relayer
relayer, err := txrelayer.NewTxRelayer(txrelayer.WithClient(cluster.Servers[0].JSONRPC()))
require.NoError(t, err)

// because we are not using native token as reward wallet, and have no premine
// initial token supply should be 0
initialTotalSupply := big.NewInt(0)

// check if initial total supply of native ERC20 token is the same as expected
totalSupply := queryNativeERC20Metadata(t, "totalSupply", uint256ABIType, relayer)
require.True(t, initialTotalSupply.Cmp(totalSupply.(*big.Int)) == 0) //nolint:forcetypeassert

// wait for couple of epochs to accumulate some rewards
require.NoError(t, cluster.WaitForBlock(epochSize*3, 3*time.Minute))

Expand All @@ -595,3 +619,22 @@ func TestE2E_Consensus_CustomRewardToken(t *testing.T) {
require.NoError(t, err)
require.True(t, validatorInfo.WithdrawableRewards.Cmp(big.NewInt(0)) > 0)
}

func queryNativeERC20Metadata(t *testing.T, funcName string, abiType *abi.Type, relayer txrelayer.TxRelayer) interface{} {
t.Helper()

valueHex, err := ABICall(relayer, contractsapi.NativeERC20Mintable,
ethgo.Address(contracts.NativeERC20TokenContract),
ethgo.ZeroAddress, funcName)
require.NoError(t, err)

valueRaw, err := hex.DecodeHex(valueHex)
require.NoError(t, err)

var decodedResult map[string]interface{}

err = abiType.DecodeStruct(valueRaw, &decodedResult)
require.NoError(t, err)

return decodedResult["0"]
}

0 comments on commit 32bae84

Please sign in to comment.