diff --git a/cmd/neofs-adm/internal/modules/morph/deploy.go b/cmd/neofs-adm/internal/modules/morph/deploy.go index f9c976cc..81b6099e 100644 --- a/cmd/neofs-adm/internal/modules/morph/deploy.go +++ b/cmd/neofs-adm/internal/modules/morph/deploy.go @@ -1,13 +1,16 @@ package morph import ( + "encoding/json" "fmt" "os" "strings" + "github.com/nspcc-dev/neo-go/cli/cmdargs" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/io" + "github.com/nspcc-dev/neo-go/pkg/services/rpcsrv/params" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" @@ -24,7 +27,9 @@ var deployCmd = &cobra.Command{ Use: "deploy", Short: "Deploy additional smart-contracts", Long: `Deploy additional smart-contract which are not related to core. -All contracts are deployed by the committee, so access to the alphabet wallets is required.`, +All contracts are deployed by the committee, so access to the alphabet wallets is required. +Optionally, arguments can be provided to be passed to a contract's _deploy function. +The syntax is the same as for 'neo-go contract testinvokefunction' command.`, PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) @@ -45,7 +50,7 @@ func init() { ff.Bool(updateFlag, false, "Update an existing contract") } -func deployContractCmd(cmd *cobra.Command, _ []string) error { +func deployContractCmd(cmd *cobra.Command, args []string) error { v := viper.GetViper() c, err := newInitializeContext(cmd, v) if err != nil { @@ -92,10 +97,15 @@ func deployContractCmd(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't sign manifest group: %v", err) } - params := getContractDeployParameters(cs, nil) - w := io.NewBufBinWriter() - emit.AppCall(w.BinWriter, callHash, method, callflag.All, params...) + if err := emitDeploymentArguments(w.BinWriter, args); err != nil { + return err + } + emit.Bytes(w.BinWriter, cs.RawManifest) + emit.Bytes(w.BinWriter, cs.RawNEF) + emit.Int(w.BinWriter, 3) + emit.Opcodes(w.BinWriter, opcode.PACK) + emit.AppCallNoArgs(w.BinWriter, callHash, method, callflag.All) emit.Opcodes(w.BinWriter, opcode.DROP) // contract state on stack if !isUpdate { s, err := c.nnsRegisterDomainScript(nnsCs.Hash, cs.Hash, domain) @@ -118,6 +128,35 @@ func deployContractCmd(cmd *cobra.Command, _ []string) error { return c.awaitTx() } +func emitDeploymentArguments(w *io.BinWriter, args []string) error { + _, ps, err := cmdargs.ParseParams(args, true) + if err != nil { + return err + } + + if len(ps) == 0 { + emit.Opcodes(w, opcode.NEWARRAY0) + return nil + } + + if len(ps) != 1 { + return fmt.Errorf("at most one argument is expected for deploy, got %d", len(ps)) + } + + // We could emit this directly, but round-trip through JSON is more robust. + // This a CLI, so optimizing the conversion is not worth the effort. + data, err := json.Marshal(ps) + if err != nil { + return err + } + + var pp params.Params + if err := json.Unmarshal(data, &pp); err != nil { + return err + } + return params.ExpandArrayIntoScript(w, pp) +} + func probeContractName(ctrPath string) (string, error) { ds, err := os.ReadDir(ctrPath) if err != nil {