Skip to content

Commit

Permalink
Unable to fund relayer when using rootchain originated native token (#…
Browse files Browse the repository at this point in the history
…2002)

* Integrate SC changes (with SC logs)

Co-authored-by: Goran Rojovic <goran-ethernal@users.noreply.github.com>

* Fix lint and e2e tests

* Approve CustomSupernetManager for premine tx and remove SC logs

* Add AccountPremined event

* Add e2e tests

* Update README.md

* e2e fix

* fix e2e test

* Do not allow native ERC20 token to be used as reward token if it is non-mintable

* e2e fix

* e2e fix 2

* Code cleanup

* Integrate the most recent SC changes

* Update account address field when retrieving genesis set

* Test_validateRewardWallet expanded

* Fix address encoding when reading genesis balance

* Lint fix

* Update SCs

* Remove stake-manager flag from supernet command

* Add stake-manager back to supernet cmd and deprecation note

---------

Co-authored-by: Goran Rojovic <goran-ethernal@users.noreply.github.com>
Co-authored-by: Goran Rojovic <goran.rojovic@ethernal.tech>
  • Loading branch information
3 people authored Nov 3, 2023
1 parent 47f2d9b commit 9ace673
Show file tree
Hide file tree
Showing 36 changed files with 1,303 additions and 259 deletions.
1 change: 0 additions & 1 deletion .github/workflows/deploy.nightly.devnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ jobs:
polygon-edge polybft supernet \
--private-key aa75e9a7d427efc732f8e4f1a5b7646adcc61fd5bae40f80d13c8419c9f43d6d \
--supernet-manager $(cat genesis.json | jq -r '.params.engine.polybft.bridge.customSupernetManagerAddr') \
--stake-manager $(cat genesis.json | jq -r '.params.engine.polybft.bridge.stakeManagerAddr') \
--finalize-genesis-set \
--enable-staking \
--jsonrpc {{ rootchain_json_rpc }}
Expand Down
3 changes: 3 additions & 0 deletions command/bridge/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
depositERC20 "github.com/0xPolygon/polygon-edge/command/bridge/deposit/erc20"
depositERC721 "github.com/0xPolygon/polygon-edge/command/bridge/deposit/erc721"
"github.com/0xPolygon/polygon-edge/command/bridge/exit"
"github.com/0xPolygon/polygon-edge/command/bridge/mint"
withdrawERC1155 "github.com/0xPolygon/polygon-edge/command/bridge/withdraw/erc1155"
withdrawERC20 "github.com/0xPolygon/polygon-edge/command/bridge/withdraw/erc20"
withdrawERC721 "github.com/0xPolygon/polygon-edge/command/bridge/withdraw/erc721"
Expand Down Expand Up @@ -40,5 +41,7 @@ func registerSubcommands(baseCmd *cobra.Command) {
withdrawERC1155.GetCommand(),
// bridge exit
exit.GetCommand(),
// bridge mint erc-20
mint.GetCommand(),
)
}
150 changes: 150 additions & 0 deletions command/bridge/mint/mint_erc20.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package mint

import (
"fmt"

"github.com/0xPolygon/polygon-edge/command"
"github.com/0xPolygon/polygon-edge/command/helper"
"github.com/0xPolygon/polygon-edge/command/polybftsecrets"
rootHelper "github.com/0xPolygon/polygon-edge/command/rootchain/helper"
"github.com/0xPolygon/polygon-edge/txrelayer"
"github.com/0xPolygon/polygon-edge/types"
"github.com/spf13/cobra"
"golang.org/x/sync/errgroup"
)

var (
params mintParams
)

// GetCommand returns the rootchain fund command
func GetCommand() *cobra.Command {
mintCmd := &cobra.Command{
Use: "mint-erc20",
Short: "Mints ERC20 tokens to specified addresses",
PreRunE: preRunCommand,
Run: runCommand,
}

helper.RegisterJSONRPCFlag(mintCmd)

setFlags(mintCmd)

return mintCmd
}

func preRunCommand(cmd *cobra.Command, _ []string) error {
params.jsonRPCAddress = helper.GetJSONRPCAddress(cmd)

return params.validateFlags()
}

func setFlags(cmd *cobra.Command) {
cmd.Flags().StringSliceVar(
&params.addresses,
rootHelper.AddressesFlag,
nil,
"addresses to which tokens should be minted",
)

cmd.Flags().StringSliceVar(
&params.amounts,
rootHelper.AmountsFlag,
nil,
"token amounts which should be minted to given addresses",
)

cmd.Flags().StringVar(
&params.tokenAddr,
rootHelper.Erc20TokenFlag,
"",
"address of the erc20 token to be minted",
)

cmd.Flags().StringVar(
&params.deployerPrivateKey,
polybftsecrets.PrivateKeyFlag,
"",
"private key of the token deployer (minter)",
)
}

func runCommand(cmd *cobra.Command, _ []string) {
outputter := command.InitializeOutputter(cmd)
defer outputter.WriteOutput()

txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(params.jsonRPCAddress))
if err != nil {
outputter.SetError(fmt.Errorf("failed to initialize tx relayer: %w", err))

return
}

deployerKey, err := rootHelper.DecodePrivateKey(params.deployerPrivateKey)
if err != nil {
outputter.SetError(fmt.Errorf("failed to initialize deployer private key: %w", err))

return
}

g, ctx := errgroup.WithContext(cmd.Context())

results := make([]command.CommandResult, len(params.addresses))
tokenAddr := types.StringToAddress(params.tokenAddr)

for i := 0; i < len(params.addresses); i++ {
i := i

g.Go(func() error {
select {
case <-ctx.Done():
return ctx.Err()

default:
// mint tokens to address
addr := types.StringToAddress(params.addresses[i])
amount := params.amountValues[i]

mintTxn, err := rootHelper.CreateMintTxn(addr, tokenAddr, amount, true)
if err != nil {
return fmt.Errorf("failed to create mint native tokens transaction for validator '%s'. err: %w",
addr, err)
}

receipt, err := txRelayer.SendTransaction(mintTxn, deployerKey)
if err != nil {
return fmt.Errorf("failed to send mint native tokens transaction to validator '%s'. err: %w", addr, err)
}

if receipt.Status == uint64(types.ReceiptFailed) {
return fmt.Errorf("failed to mint native tokens to validator '%s'", addr)
}

results[i] = &mintResult{
Address: addr,
Amount: amount,
TxHash: types.Hash(receipt.TransactionHash),
}

return nil
}
})
}

if err := g.Wait(); err != nil {
outputter.SetError(err)
_, _ = outputter.Write([]byte("[MINT-ERC20] Successfully minted tokens to following accounts\n"))

for _, result := range results {
if result != nil {
// In case an error happened, some of the indices may not be populated.
// Filter those out.
outputter.SetCommandResult(result)
}
}

return
}

outputter.SetCommandResult(command.Results(results))
}
78 changes: 78 additions & 0 deletions command/bridge/mint/params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package mint

import (
"bytes"
"fmt"
"math/big"

"github.com/0xPolygon/polygon-edge/command/helper"
rootHelper "github.com/0xPolygon/polygon-edge/command/rootchain/helper"
"github.com/0xPolygon/polygon-edge/types"
)

type mintParams struct {
addresses []string
amounts []string
tokenAddr string
deployerPrivateKey string
jsonRPCAddress string

amountValues []*big.Int
}

func (m *mintParams) validateFlags() error {
if len(m.addresses) == 0 {
return rootHelper.ErrNoAddressesProvided
}

if len(m.amounts) != len(m.addresses) {
return rootHelper.ErrInconsistentLength
}

for _, addr := range m.addresses {
if err := types.IsValidAddress(addr); err != nil {
return err
}
}

m.amountValues = make([]*big.Int, len(m.amounts))
for i, amountRaw := range m.amounts {
amountValue, err := helper.ParseAmount(amountRaw)
if err != nil {
return err
}

m.amountValues[i] = amountValue
}

if m.tokenAddr == "" {
return rootHelper.ErrMandatoryERC20Token
}

if err := types.IsValidAddress(m.tokenAddr); err != nil {
return fmt.Errorf("invalid erc20 token address is provided: %w", err)
}

return nil
}

type mintResult struct {
Address types.Address `json:"address"`
Amount *big.Int `json:"amount"`
TxHash types.Hash `json:"tx_hash"`
}

func (m *mintResult) GetOutput() string {
var buffer bytes.Buffer

vals := make([]string, 0, 3)
vals = append(vals, fmt.Sprintf("Address|%s", m.Address))
vals = append(vals, fmt.Sprintf("Amount|%s", m.Amount))
vals = append(vals, fmt.Sprintf("Transaction (hash)|%s", m.TxHash))

buffer.WriteString("\n[MINT-ERC20]\n")
buffer.WriteString(helper.FormatKV(vals))
buffer.WriteString("\n")

return buffer.String()
}
Loading

0 comments on commit 9ace673

Please sign in to comment.