diff --git a/pkg/services/rpcsrv/client_test.go b/pkg/services/rpcsrv/client_test.go index 031dab5ee..d74b83afb 100644 --- a/pkg/services/rpcsrv/client_test.go +++ b/pkg/services/rpcsrv/client_test.go @@ -18,6 +18,7 @@ import ( "github.com/google/uuid" "github.com/gorilla/websocket" + "github.com/nspcc-dev/neo-go/internal/basicchain" "github.com/nspcc-dev/neo-go/internal/testchain" "github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/core" @@ -2499,3 +2500,34 @@ func TestWSClient_SubscriptionsCompat(t *testing.T) { checkRelevant(t, false) }) } + +func TestActor_CallWithNilParam(t *testing.T) { + chain, rpcSrv, httpSrv := initServerWithInMemoryChain(t) + defer chain.Close() + defer rpcSrv.Shutdown() + + c, err := rpcclient.New(context.Background(), httpSrv.URL, rpcclient.Options{}) + require.NoError(t, err) + acc, err := wallet.NewAccount() + require.NoError(t, err) + act, err := actor.New(c, []actor.SignerAccount{ + { + Signer: transaction.Signer{ + Account: acc.ScriptHash(), + }, + Account: acc, + }, + }) + require.NoError(t, err) + + rubles, err := chain.GetContractScriptHash(basicchain.RublesContractID) + require.NoError(t, err) + + // We don't have a suitable contract, thus use Rubles with simple put method, + // it should fail at the moment of conversion Null value to ByteString (not earlier, + // and that's the point of the test!). + res, err := act.Call(rubles, "putValue", "123", (*util.Uint160)(nil)) + require.NoError(t, err) + + require.True(t, strings.Contains(res.FaultException, "invalid conversion: Null/ByteString"), res.FaultException) +} diff --git a/pkg/services/rpcsrv/params/txBuilder.go b/pkg/services/rpcsrv/params/txBuilder.go index 9872c7cc6..9d2c9ea2d 100644 --- a/pkg/services/rpcsrv/params/txBuilder.go +++ b/pkg/services/rpcsrv/params/txBuilder.go @@ -84,7 +84,7 @@ func ExpandArrayIntoScript(script *io.BinWriter, slice []Param) error { return err } case smartcontract.AnyType: - if fp.Value.IsNull() { + if fp.Value.IsNull() || len(fp.Value.RawMessage) == 0 { emit.Opcodes(script, opcode.PUSHNULL) } default: