github.com/iotexproject/iotex-core@v1.14.1-rc1/ioctl/cmd/contract/contractdeploysol.go (about)

     1  // Copyright (c) 2022 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 contract
     7  
     8  import (
     9  	"encoding/json"
    10  	"fmt"
    11  	"os"
    12  	"strings"
    13  
    14  	"github.com/spf13/cobra"
    15  
    16  	"github.com/iotexproject/iotex-core/ioctl/cmd/action"
    17  	"github.com/iotexproject/iotex-core/ioctl/config"
    18  	"github.com/iotexproject/iotex-core/ioctl/flag"
    19  	"github.com/iotexproject/iotex-core/ioctl/output"
    20  	"github.com/iotexproject/iotex-core/ioctl/util"
    21  )
    22  
    23  // Multi-language support
    24  var (
    25  	_deploySolCmdUses = map[config.Language]string{
    26  		config.English: "sol [FILE_NAME:]CONTRACT_NAME [CODE_FILES...] [--with-arguments INIT_INPUT] [--init-amount IOTX数量]",
    27  		config.Chinese: "sol [文件名:]合约名 [代码文件...] [--with-arguments 初始化输入] [--init-amount IOTX数量]",
    28  	}
    29  	_deploySolCmdShorts = map[config.Language]string{
    30  		config.English: "deploy smart contract with sol files on IoTeX blockchain",
    31  		config.Chinese: "使用sol文件在IoTex区块链上部署智能合约",
    32  	}
    33  )
    34  
    35  // _contractDeploySolCmd represents the contract deploy sol command
    36  var _contractDeploySolCmd = &cobra.Command{
    37  	Use:   config.TranslateInLang(_deploySolCmdUses, config.UILanguage),
    38  	Short: config.TranslateInLang(_deploySolCmdShorts, config.UILanguage),
    39  	Args:  cobra.MinimumNArgs(1),
    40  	RunE: func(cmd *cobra.Command, args []string) error {
    41  		cmd.SilenceUsage = true
    42  		err := contractDeploySol(args)
    43  		return output.PrintError(err)
    44  	},
    45  }
    46  
    47  func init() {
    48  	_initialAmountFlag.RegisterCommand(_contractDeploySolCmd)
    49  }
    50  
    51  func contractDeploySol(args []string) error {
    52  	contractName := args[0]
    53  
    54  	files := args[1:]
    55  	if len(files) == 0 {
    56  		dirInfo, err := os.ReadDir("./")
    57  		if err != nil {
    58  			return output.NewError(output.ReadFileError, "failed to get current directory", err)
    59  		}
    60  
    61  		for _, fileInfo := range dirInfo {
    62  			if !fileInfo.IsDir() && strings.HasSuffix(fileInfo.Name(), ".sol") {
    63  				files = append(files, fileInfo.Name())
    64  			}
    65  		}
    66  
    67  		if len(files) == 0 {
    68  			return output.NewError(output.InputError, "failed to get source file(s)", nil)
    69  		}
    70  	}
    71  
    72  	contracts, err := Compile(files...)
    73  	if err != nil {
    74  		return output.NewError(0, "failed to compile", err)
    75  	}
    76  
    77  	for name := range contracts {
    78  		if strings.HasSuffix(name, contractName) {
    79  			if contractName != args[0] {
    80  				return output.NewError(output.CompilerError,
    81  					fmt.Sprintf("there are more than one %s contract", args[0]), nil)
    82  			}
    83  			contractName = name
    84  		}
    85  	}
    86  
    87  	contract, ok := contracts[contractName]
    88  	if !ok {
    89  		return output.NewError(output.CompilerError, fmt.Sprintf("failed to find out contract %s", contractName), nil)
    90  	}
    91  
    92  	bytecode, err := decodeBytecode(contract.Code)
    93  	if err != nil {
    94  		return output.NewError(output.ConvertError, "failed to decode bytecode", err)
    95  	}
    96  
    97  	if flag.WithArgumentsFlag.Value().(string) != "" {
    98  		abiByte, err := json.Marshal(contract.Info.AbiDefinition)
    99  		if err != nil {
   100  			return output.NewError(output.SerializationError, "failed to marshal abi", err)
   101  		}
   102  
   103  		abi, err := parseAbi(abiByte)
   104  		if err != nil {
   105  			return err
   106  		}
   107  
   108  		// Constructor's method name is "" (empty string)
   109  		packedArg, err := packArguments(abi, "", flag.WithArgumentsFlag.Value().(string))
   110  		if err != nil {
   111  			return output.NewError(output.ConvertError, "failed to pack given arguments", err)
   112  		}
   113  
   114  		bytecode = append(bytecode, packedArg...)
   115  	}
   116  
   117  	amount, err := util.StringToRau(_initialAmountFlag.Value().(string), util.IotxDecimalNum)
   118  	if err != nil {
   119  		return output.NewError(output.FlagError, "invalid amount", err)
   120  	}
   121  
   122  	return action.Execute("", amount, bytecode)
   123  }