github.com/iotexproject/iotex-core@v1.14.1-rc1/tools/multisend/multisend.go (about)

     1  // Copyright (c) 2019 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package main
     7  
     8  import (
     9  	"encoding/hex"
    10  	"encoding/json"
    11  	"fmt"
    12  	"math/big"
    13  	"os"
    14  	"strings"
    15  
    16  	"github.com/ethereum/go-ethereum/accounts/abi"
    17  	"github.com/ethereum/go-ethereum/common"
    18  	"github.com/spf13/cobra"
    19  
    20  	"github.com/iotexproject/iotex-core/pkg/util/addrutil"
    21  )
    22  
    23  func main() {
    24  	if err := rootCmd.Execute(); err != nil {
    25  		fmt.Println(err)
    26  		os.Exit(1)
    27  	}
    28  }
    29  
    30  // rootCmd represents the base command when called without any subcommands
    31  var rootCmd = &cobra.Command{
    32  	Use:   "multisend 'JSON_DATA'",
    33  	Short: "multisend bytecode generator",
    34  	Args:  cobra.ExactArgs(1),
    35  	RunE: func(cmd *cobra.Command, args []string) error {
    36  		output, err := multiSend(args)
    37  		if err == nil {
    38  			fmt.Println(output)
    39  		}
    40  		return err
    41  	},
    42  }
    43  
    44  var abiJSON = `[{"constant":false,"inputs":[{"name":"recipients","type":"address[]"},
    45  {"name":"amounts","type":"uint256[]"},{"name":"payload","type":"string"}],
    46  "name":"multiSend","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},
    47  {"anonymous":false,"inputs":[{"indexed":false,"name":"recipient","type":"address"},
    48  {"indexed":false,"name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},
    49  {"anonymous":false,"inputs":[{"indexed":false,"name":"refund","type":"uint256"}],
    50  "name":"Refund","type":"event"},{"anonymous":false,
    51  "inputs":[{"indexed":false,"name":"payload","type":"string"}],"name":"Payload","type":"event"}]`
    52  var abiFunc = "multiSend"
    53  
    54  type targets struct {
    55  	Targets []target `json:"targets"`
    56  	Payload string   `json:"payload"`
    57  }
    58  type target struct {
    59  	Recipient string `json:"recipient"`
    60  	Amount    string `json:"amount"`
    61  }
    62  
    63  func multiSend(args []string) (string, error) {
    64  	var targetSet targets
    65  	if err := json.Unmarshal([]byte(args[0]), &targetSet); err != nil {
    66  		return "", err
    67  	}
    68  	recipients := make([]common.Address, 0)
    69  	amounts := make([]*big.Int, 0)
    70  	for _, target := range targetSet.Targets {
    71  		recipient, err := addrutil.IoAddrToEvmAddr(target.Recipient)
    72  		if err != nil {
    73  			return "", err
    74  		}
    75  		recipients = append(recipients, recipient)
    76  		amount, ok := new(big.Int).SetString(target.Amount, 10)
    77  		if !ok {
    78  			return "", fmt.Errorf("failed to convert string to big int")
    79  		}
    80  		amounts = append(amounts, amount)
    81  	}
    82  	reader := strings.NewReader(abiJSON)
    83  	multisendABI, err := abi.JSON(reader)
    84  	if err != nil {
    85  		return "", err
    86  	}
    87  	bytecode, err := multisendABI.Pack(abiFunc, recipients, amounts, targetSet.Payload)
    88  	if err != nil {
    89  		return "", err
    90  	}
    91  	return hex.EncodeToString(bytecode), nil
    92  }