github.com/iotexproject/iotex-core@v1.14.1-rc1/ioctl/newcmd/contract/contract.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/hex" 10 "os" 11 "path/filepath" 12 13 "github.com/ethereum/go-ethereum/accounts/abi" 14 "github.com/ethereum/go-ethereum/common/compiler" 15 "github.com/pkg/errors" 16 "github.com/spf13/cobra" 17 18 "github.com/iotexproject/iotex-core/ioctl" 19 "github.com/iotexproject/iotex-core/ioctl/config" 20 "github.com/iotexproject/iotex-core/ioctl/util" 21 ) 22 23 const _solCompiler = "solc" 24 25 // Multi-language support 26 var ( 27 _contractCmdShorts = map[config.Language]string{ 28 config.English: "Deal with smart contract of IoTeX blockchain", 29 config.Chinese: "处理IoTeX区块链的智能合约", 30 } 31 _flagInitialAmountUsage = map[config.Language]string{ 32 config.English: "transfer an initial amount to the new deployed contract", 33 config.Chinese: "为部署的新合约转入一笔初始资金", 34 } 35 ) 36 37 // NewContractCmd represents the contract command 38 func NewContractCmd(client ioctl.Client) *cobra.Command { 39 short, _ := client.SelectTranslation(_contractCmdShorts) 40 cmd := &cobra.Command{ 41 Use: "contract", 42 Short: short, 43 } 44 45 // TODO add sub commands 46 // cmd.AddCommand(NewContractPrepareCmd) 47 // cmd.AddCommand(NewContractCompileCmd) 48 // cmd.AddCommand(NewContractDeployCmd) 49 // cmd.AddCommand(NewContractInvokeCmd) 50 // cmd.AddCommand(NewContractTestCmd) 51 // cmd.AddCommand(NewContractShareCmd) 52 cmd.AddCommand(NewContractCompileCmd(client)) 53 client.SetEndpointWithFlag(cmd.PersistentFlags().StringVar) 54 client.SetInsecureWithFlag(cmd.PersistentFlags().BoolVar) 55 56 return cmd 57 } 58 59 // Compile compiles smart contract from source code 60 func Compile(sourceFiles ...string) (map[string]*compiler.Contract, error) { 61 solc, err := util.SolidityVersion(_solCompiler) 62 if err != nil { 63 return nil, errors.Wrap(err, "solidity compiler not ready") 64 } 65 if !checkCompilerVersion(solc) { 66 return nil, errors.Errorf("unsupported solc version %d.%d.%d", solc.Major, solc.Minor, solc.Patch) 67 } 68 69 contracts, err := util.CompileSolidity(_solCompiler, sourceFiles...) 70 if err != nil { 71 return nil, errors.Wrap(err, "failed to compile") 72 } 73 return contracts, nil 74 } 75 76 func checkCompilerVersion(solc *util.Solidity) bool { 77 if solc.Major == 0 && solc.Minor == 8 { 78 return true 79 } 80 return false 81 } 82 83 func decodeBytecode(bytecode string) ([]byte, error) { 84 return hex.DecodeString(util.TrimHexPrefix(bytecode)) 85 } 86 87 func readAbiFile(abiFile string) (*abi.ABI, error) { 88 abiBytes, err := os.ReadFile(filepath.Clean(abiFile)) 89 if err != nil { 90 return nil, errors.Wrap(err, "failed to read abi file") 91 } 92 93 return parseAbi(abiBytes) 94 } 95 96 func packArguments(targetAbi *abi.ABI, targetMethod string, rowInput string) ([]byte, error) { 97 var method abi.Method 98 var ok bool 99 100 if rowInput == "" { 101 rowInput = "{}" 102 } 103 104 rowArguments, err := parseInput(rowInput) 105 if err != nil { 106 return nil, err 107 } 108 109 if targetMethod == "" { 110 method = targetAbi.Constructor 111 } else { 112 method, ok = targetAbi.Methods[targetMethod] 113 if !ok { 114 return nil, errors.New("invalid method name") 115 } 116 } 117 118 arguments := make([]interface{}, 0, len(method.Inputs)) 119 for _, param := range method.Inputs { 120 if param.Name == "" { 121 param.Name = "_" 122 } 123 124 rowArg, ok := rowArguments[param.Name] 125 if !ok { 126 return nil, errors.Errorf("failed to parse argument \"%s\"", param.Name) 127 } 128 129 arg, err := parseInputArgument(¶m.Type, rowArg) 130 if err != nil { 131 return nil, errors.Wrapf(err, "failed to parse argument \"%s\"", param.Name) 132 } 133 arguments = append(arguments, arg) 134 } 135 return targetAbi.Pack(targetMethod, arguments...) 136 }