2020-03-18 15:21:12 +00:00
package manifest
import (
"encoding/json"
2023-11-22 11:07:15 +00:00
"fmt"
2021-02-03 18:09:50 +00:00
"math/big"
2024-08-24 10:03:16 +00:00
"slices"
2020-03-18 15:21:12 +00:00
"testing"
2021-06-30 07:50:26 +00:00
"github.com/nspcc-dev/neo-go/internal/random"
2020-03-18 15:21:12 +00:00
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
2021-02-03 18:09:50 +00:00
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
2020-03-18 15:21:12 +00:00
"github.com/nspcc-dev/neo-go/pkg/util"
2021-02-03 18:09:50 +00:00
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
2020-03-18 15:21:12 +00:00
"github.com/stretchr/testify/require"
)
// Test vectors are taken from the main NEO repo
// https://github.com/neo-project/neo/blob/master/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs#L10
func TestManifest_MarshalJSON ( t * testing . T ) {
t . Run ( "default" , func ( t * testing . T ) {
2021-04-30 14:19:52 +00:00
s := ` { "groups":[],"features": { },"supportedstandards":[],"name":"Test","abi": { "methods":[],"events":[]},"permissions":[ { "contract":"*","methods":"*"}],"trusts":[],"extra":null} `
2020-03-18 15:21:12 +00:00
m := testUnmarshalMarshalManifest ( t , s )
2020-11-18 09:43:51 +00:00
require . Equal ( t , DefaultManifest ( "Test" ) , m )
2020-03-18 15:21:12 +00:00
} )
t . Run ( "permissions" , func ( t * testing . T ) {
2021-04-30 14:19:52 +00:00
s := ` { "groups":[],"features": { },"supportedstandards":[],"name":"Test","abi": { "methods":[],"events":[]},"permissions":[ { "contract":"0x0000000000000000000000000000000000000000","methods":["method1","method2"]}],"trusts":[],"extra":null} `
2020-03-18 15:21:12 +00:00
testUnmarshalMarshalManifest ( t , s )
} )
t . Run ( "safe methods" , func ( t * testing . T ) {
2021-04-30 14:19:52 +00:00
s := ` { "groups":[],"features": { },"supportedstandards":[],"name":"Test","abi": { "methods":[ { "name":"safeMet","offset":123,"parameters":[],"returntype":"Integer","safe":true}],"events":[]},"permissions":[ { "contract":"*","methods":"*"}],"trusts":[],"extra":null} `
2020-03-18 15:21:12 +00:00
testUnmarshalMarshalManifest ( t , s )
} )
t . Run ( "trust" , func ( t * testing . T ) {
2021-04-30 14:19:52 +00:00
s := ` { "groups":[],"features": { },"supportedstandards":[],"name":"Test","abi": { "methods":[],"events":[]},"permissions":[ { "contract":"*","methods":"*"}],"trusts":["0x0000000000000000000000000000000000000001"],"extra":null} `
2020-03-18 15:21:12 +00:00
testUnmarshalMarshalManifest ( t , s )
} )
t . Run ( "groups" , func ( t * testing . T ) {
2021-04-30 14:19:52 +00:00
s := ` { "groups":[ { "pubkey":"03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c","signature":"QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ=="}],"features": { },"supportedstandards":[],"name":"Test","abi": { "methods":[],"events":[]},"permissions":[ { "contract":"*","methods":"*"}],"trusts":[],"extra":null} `
2020-03-18 15:21:12 +00:00
testUnmarshalMarshalManifest ( t , s )
} )
t . Run ( "extra" , func ( t * testing . T ) {
2021-04-30 14:19:52 +00:00
s := ` { "groups":[],"features": { },"supportedstandards":[],"name":"Test","abi": { "methods":[],"events":[]},"permissions":[ { "contract":"*","methods":"*"}],"trusts":[],"extra": { "key":"value"}} `
2020-03-18 15:21:12 +00:00
testUnmarshalMarshalManifest ( t , s )
} )
}
func testUnmarshalMarshalManifest ( t * testing . T , s string ) * Manifest {
js := [ ] byte ( s )
2020-11-18 09:43:51 +00:00
c := NewManifest ( "Test" )
2020-03-18 15:21:12 +00:00
require . NoError ( t , json . Unmarshal ( js , c ) )
data , err := json . Marshal ( c )
require . NoError ( t , err )
require . JSONEq ( t , s , string ( data ) )
return c
}
func TestManifest_CanCall ( t * testing . T ) {
2020-12-08 10:27:41 +00:00
man1 := DefaultManifest ( "Test1" )
man2 := DefaultManifest ( "Test2" )
require . True ( t , man1 . CanCall ( util . Uint160 { } , man2 , "method1" ) )
2020-03-18 15:21:12 +00:00
}
func TestPermission_IsAllowed ( t * testing . T ) {
2020-11-18 09:43:51 +00:00
manifest := DefaultManifest ( "Test" )
2020-03-18 15:21:12 +00:00
t . Run ( "wildcard" , func ( t * testing . T ) {
2021-06-30 07:50:26 +00:00
h := random . Uint160 ( )
2020-03-18 15:21:12 +00:00
perm := NewPermission ( PermissionWildcard )
2021-06-30 07:50:26 +00:00
require . True ( t , perm . IsAllowed ( h , manifest , "AAA" ) )
perm . Methods . Restrict ( )
require . False ( t , perm . IsAllowed ( h , manifest , "AAA" ) )
perm . Methods . Add ( "AAA" )
require . True ( t , perm . IsAllowed ( h , manifest , "AAA" ) )
2020-03-18 15:21:12 +00:00
} )
t . Run ( "hash" , func ( t * testing . T ) {
perm := NewPermission ( PermissionHash , util . Uint160 { } )
2020-11-18 09:43:51 +00:00
require . True ( t , perm . IsAllowed ( util . Uint160 { } , manifest , "AAA" ) )
2020-03-18 15:21:12 +00:00
t . Run ( "restrict methods" , func ( t * testing . T ) {
perm . Methods . Restrict ( )
2020-11-18 09:43:51 +00:00
require . False ( t , perm . IsAllowed ( util . Uint160 { } , manifest , "AAA" ) )
2020-03-18 15:21:12 +00:00
perm . Methods . Add ( "AAA" )
2020-11-18 09:43:51 +00:00
require . True ( t , perm . IsAllowed ( util . Uint160 { } , manifest , "AAA" ) )
2020-03-18 15:21:12 +00:00
} )
} )
t . Run ( "invalid hash" , func ( t * testing . T ) {
perm := NewPermission ( PermissionHash , util . Uint160 { 1 } )
2020-11-18 09:43:51 +00:00
require . False ( t , perm . IsAllowed ( util . Uint160 { } , manifest , "AAA" ) )
2020-03-18 15:21:12 +00:00
} )
priv , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
manifest . Groups = [ ] Group { { PublicKey : priv . PublicKey ( ) } }
t . Run ( "group" , func ( t * testing . T ) {
perm := NewPermission ( PermissionGroup , priv . PublicKey ( ) )
2020-11-18 09:43:51 +00:00
require . True ( t , perm . IsAllowed ( util . Uint160 { } , manifest , "AAA" ) )
2020-03-18 15:21:12 +00:00
priv2 , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
2021-06-30 07:55:14 +00:00
perm = NewPermission ( PermissionGroup , priv2 . PublicKey ( ) )
2020-11-18 09:43:51 +00:00
require . False ( t , perm . IsAllowed ( util . Uint160 { } , manifest , "AAA" ) )
2021-06-30 07:55:14 +00:00
manifest . Groups = append ( manifest . Groups , Group { PublicKey : priv2 . PublicKey ( ) } )
perm = NewPermission ( PermissionGroup , priv2 . PublicKey ( ) )
require . True ( t , perm . IsAllowed ( util . Uint160 { } , manifest , "AAA" ) )
2020-03-18 15:21:12 +00:00
} )
}
2020-07-15 11:39:20 +00:00
func TestIsValid ( t * testing . T ) {
contractHash := util . Uint160 { 1 , 2 , 3 }
2021-02-08 19:58:22 +00:00
m := & Manifest { }
t . Run ( "invalid, no name" , func ( t * testing . T ) {
2023-11-22 17:15:43 +00:00
require . Error ( t , m . IsValid ( contractHash , true ) )
2021-02-08 19:58:22 +00:00
} )
m = NewManifest ( "Test" )
2020-07-15 11:39:20 +00:00
2021-02-08 10:15:10 +00:00
t . Run ( "invalid, no ABI methods" , func ( t * testing . T ) {
2023-11-22 17:15:43 +00:00
require . Error ( t , m . IsValid ( contractHash , true ) )
2021-02-08 10:15:10 +00:00
} )
m . ABI . Methods = append ( m . ABI . Methods , Method {
Name : "dummy" ,
ReturnType : smartcontract . VoidType ,
Parameters : [ ] Parameter { } ,
} )
2021-02-08 14:38:03 +00:00
t . Run ( "valid, no groups/events" , func ( t * testing . T ) {
2023-11-22 17:15:43 +00:00
require . NoError ( t , m . IsValid ( contractHash , true ) )
2020-07-15 11:39:20 +00:00
} )
2024-07-26 08:43:10 +00:00
t . Run ( "invalid, no features" , func ( t * testing . T ) {
m . Features = nil
require . Error ( t , m . IsValid ( contractHash , true ) )
} )
m . Features = json . RawMessage ( emptyFeatures )
t . Run ( "invalid, bad features" , func ( t * testing . T ) {
m . Features = json . RawMessage ( ` { "v" : true} ` )
require . Error ( t , m . IsValid ( contractHash , true ) )
} )
m . Features = json . RawMessage ( emptyFeatures )
t . Run ( "valid, features with spaces" , func ( t * testing . T ) {
m . Features = json . RawMessage ( "{ \t\n\r }" )
require . NoError ( t , m . IsValid ( contractHash , true ) )
} )
m . Features = json . RawMessage ( emptyFeatures )
2021-02-08 14:38:03 +00:00
m . ABI . Events = append ( m . ABI . Events , Event {
Name : "itHappened" ,
Parameters : [ ] Parameter { } ,
} )
t . Run ( "valid, with events" , func ( t * testing . T ) {
2023-11-22 17:15:43 +00:00
require . NoError ( t , m . IsValid ( contractHash , true ) )
2021-02-08 14:38:03 +00:00
} )
m . ABI . Events = append ( m . ABI . Events , Event {
Name : "itHappened" ,
Parameters : [ ] Parameter {
NewParameter ( "qwerty" , smartcontract . IntegerType ) ,
NewParameter ( "qwerty" , smartcontract . IntegerType ) ,
} ,
} )
t . Run ( "invalid, bad event" , func ( t * testing . T ) {
2023-11-22 17:15:43 +00:00
require . Error ( t , m . IsValid ( contractHash , true ) )
2021-02-08 14:38:03 +00:00
} )
m . ABI . Events = m . ABI . Events [ : 1 ]
2021-02-08 18:07:05 +00:00
m . Permissions = append ( m . Permissions , * NewPermission ( PermissionHash , util . Uint160 { 1 , 2 , 3 } ) )
t . Run ( "valid, with permissions" , func ( t * testing . T ) {
2023-11-22 17:15:43 +00:00
require . NoError ( t , m . IsValid ( contractHash , true ) )
2021-02-08 18:07:05 +00:00
} )
m . Permissions = append ( m . Permissions , * NewPermission ( PermissionHash , util . Uint160 { 1 , 2 , 3 } ) )
t . Run ( "invalid, with permissions" , func ( t * testing . T ) {
2023-11-22 17:15:43 +00:00
require . Error ( t , m . IsValid ( contractHash , true ) )
2021-02-08 18:07:05 +00:00
} )
m . Permissions = m . Permissions [ : 1 ]
2021-02-08 19:58:22 +00:00
m . SupportedStandards = append ( m . SupportedStandards , "NEP-17" )
t . Run ( "valid, with standards" , func ( t * testing . T ) {
2023-11-22 17:15:43 +00:00
require . NoError ( t , m . IsValid ( contractHash , true ) )
2021-02-08 19:58:22 +00:00
} )
m . SupportedStandards = append ( m . SupportedStandards , "" )
t . Run ( "invalid, with nameless standard" , func ( t * testing . T ) {
2023-11-22 17:15:43 +00:00
require . Error ( t , m . IsValid ( contractHash , true ) )
2021-02-08 19:58:22 +00:00
} )
m . SupportedStandards = m . SupportedStandards [ : 1 ]
m . SupportedStandards = append ( m . SupportedStandards , "NEP-17" )
t . Run ( "invalid, with duplicate standards" , func ( t * testing . T ) {
2023-11-22 17:15:43 +00:00
require . Error ( t , m . IsValid ( contractHash , true ) )
2021-02-08 19:58:22 +00:00
} )
m . SupportedStandards = m . SupportedStandards [ : 1 ]
2024-07-26 09:32:49 +00:00
t . Run ( "invalid, no trusts" , func ( t * testing . T ) {
m . Trusts . Value = nil
m . Trusts . Wildcard = false
require . Error ( t , m . IsValid ( contractHash , true ) )
} )
m . Trusts . Restrict ( )
2021-05-04 11:48:50 +00:00
d := PermissionDesc { Type : PermissionHash , Value : util . Uint160 { 1 , 2 , 3 } }
m . Trusts . Add ( d )
2021-02-08 19:58:22 +00:00
t . Run ( "valid, with trust" , func ( t * testing . T ) {
2023-11-22 17:15:43 +00:00
require . NoError ( t , m . IsValid ( contractHash , true ) )
2021-02-08 19:58:22 +00:00
} )
2021-05-04 11:48:50 +00:00
m . Trusts . Add ( PermissionDesc { Type : PermissionHash , Value : util . Uint160 { 3 , 2 , 1 } } )
2021-02-08 19:58:22 +00:00
t . Run ( "valid, with trusts" , func ( t * testing . T ) {
2023-11-22 17:15:43 +00:00
require . NoError ( t , m . IsValid ( contractHash , true ) )
2021-02-08 19:58:22 +00:00
} )
2021-05-04 11:48:50 +00:00
m . Trusts . Add ( d )
2021-02-08 19:58:22 +00:00
t . Run ( "invalid, with trusts" , func ( t * testing . T ) {
2023-11-22 17:15:43 +00:00
require . Error ( t , m . IsValid ( contractHash , true ) )
2021-02-08 19:58:22 +00:00
} )
m . Trusts . Restrict ( )
2020-07-15 11:39:20 +00:00
t . Run ( "with groups" , func ( t * testing . T ) {
m . Groups = make ( [ ] Group , 3 )
pks := make ( [ ] * keys . PrivateKey , 3 )
for i := range pks {
pk , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
pks [ i ] = pk
m . Groups [ i ] = Group {
PublicKey : pk . PublicKey ( ) ,
Signature : pk . Sign ( contractHash . BytesBE ( ) ) ,
}
}
t . Run ( "valid" , func ( t * testing . T ) {
2023-11-22 17:15:43 +00:00
require . NoError ( t , m . IsValid ( contractHash , true ) )
2020-07-15 11:39:20 +00:00
} )
t . Run ( "invalid, wrong contract hash" , func ( t * testing . T ) {
2023-11-22 17:15:43 +00:00
require . Error ( t , m . IsValid ( util . Uint160 { 4 , 5 , 6 } , true ) )
2020-07-15 11:39:20 +00:00
} )
t . Run ( "invalid, wrong group signature" , func ( t * testing . T ) {
pk , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
m . Groups = append ( m . Groups , Group {
PublicKey : pk . PublicKey ( ) ,
// actually, there shouldn't be such situation, as Signature is always the signature
// of the contract hash.
Signature : pk . Sign ( [ ] byte { 1 , 2 , 3 } ) ,
} )
2023-11-22 17:15:43 +00:00
require . Error ( t , m . IsValid ( contractHash , true ) )
2020-07-15 11:39:20 +00:00
} )
} )
2023-11-22 11:07:15 +00:00
m . Groups = m . Groups [ : 0 ]
t . Run ( "invalid, unserializable" , func ( t * testing . T ) {
2024-08-30 18:41:02 +00:00
for i := range stackitem . MaxSerialized {
2023-11-22 11:07:15 +00:00
m . ABI . Events = append ( m . ABI . Events , Event {
Name : fmt . Sprintf ( "Event%d" , i ) ,
Parameters : [ ] Parameter { } ,
} )
}
2023-11-22 17:15:43 +00:00
err := m . IsValid ( contractHash , true )
2023-11-22 11:07:15 +00:00
require . ErrorIs ( t , err , stackitem . ErrTooBig )
} )
2020-07-15 11:39:20 +00:00
}
2021-02-03 18:09:50 +00:00
func TestManifestToStackItem ( t * testing . T ) {
check := func ( t * testing . T , expected * Manifest ) {
item , err := expected . ToStackItem ( )
require . NoError ( t , err )
actual := new ( Manifest )
require . NoError ( t , actual . FromStackItem ( item ) )
require . Equal ( t , expected , actual )
}
t . Run ( "default" , func ( t * testing . T ) {
expected := DefaultManifest ( "manifest" )
check ( t , expected )
} )
t . Run ( "full" , func ( t * testing . T ) {
pk , _ := keys . NewPrivateKey ( )
expected := & Manifest {
Name : "manifest" ,
ABI : ABI {
Methods : [ ] Method { {
Name : "method" ,
Offset : 15 ,
Parameters : [ ] Parameter { {
Name : "param" ,
Type : smartcontract . StringType ,
} } ,
ReturnType : smartcontract . BoolType ,
Safe : true ,
} } ,
Events : [ ] Event { {
Name : "event" ,
Parameters : [ ] Parameter { {
Name : "param" ,
Type : smartcontract . BoolType ,
} } ,
} } ,
} ,
2021-04-30 14:19:52 +00:00
Features : json . RawMessage ( "{}" ) ,
2021-02-03 18:09:50 +00:00
Groups : [ ] Group { {
PublicKey : pk . PublicKey ( ) ,
2021-02-08 12:11:31 +00:00
Signature : make ( [ ] byte , keys . SignatureLen ) ,
2021-02-03 18:09:50 +00:00
} } ,
Permissions : [ ] Permission { * NewPermission ( PermissionWildcard ) } ,
SupportedStandards : [ ] string { "NEP-17" } ,
2021-05-04 11:48:50 +00:00
Trusts : WildPermissionDescs {
Value : [ ] PermissionDesc {
{
Type : PermissionHash ,
Value : util . Uint160 { 1 , 2 , 3 } ,
} ,
{
Type : PermissionGroup ,
Value : pk . PublicKey ( ) ,
} ,
} ,
2021-02-03 18:09:50 +00:00
} ,
2021-06-28 16:09:19 +00:00
Extra : [ ] byte ( ` "even string allowed" ` ) ,
2021-02-03 18:09:50 +00:00
}
check ( t , expected )
} )
2023-11-08 13:08:24 +00:00
t . Run ( "compat" , func ( t * testing . T ) {
// Compatibility test with NeoC#, see https://github.com/neo-project/neo/pull/2948.
var mJSON = ` { "name":"CallOracleContract-6","groups":[],"features": { },"supportedstandards":[],"abi": { "methods":[ { "name":"request","parameters":[ { "name":"url","type":"String"}, { "name":"filter","type":"String"}, { "name":"gasForResponse","type":"Integer"}],"returntype":"Void","offset":0,"safe":false}, { "name":"callback","parameters":[ { "name":"url","type":"String"}, { "name":"userData","type":"Any"}, { "name":"responseCode","type":"Integer"}, { "name":"response","type":"ByteArray"}],"returntype":"Void","offset":86,"safe":false}, { "name":"getStoredUrl","parameters":[],"returntype":"String","offset":129,"safe":false}, { "name":"getStoredResponseCode","parameters":[],"returntype":"Integer","offset":142,"safe":false}, { "name":"getStoredResponse","parameters":[],"returntype":"ByteArray","offset":165,"safe":false}],"events":[]},"permissions":[ { "contract":"0xfe924b7cfe89ddd271abaf7210a80a7e11178758","methods":"*"}, { "contract":"*","methods":"*"}],"trusts":["0xfe924b7cfe89ddd271abaf7210a80a7e11178758","*"],"extra": { }} `
c := NewManifest ( "Test" )
require . NoError ( t , json . Unmarshal ( [ ] byte ( mJSON ) , c ) )
si , err := c . ToStackItem ( )
require . NoError ( t , err )
actual := new ( Manifest )
require . NoError ( t , actual . FromStackItem ( si ) )
require . NotEqual ( t , actual . Permissions [ 0 ] . Contract . Type , PermissionWildcard )
require . True ( t , actual . Permissions [ 0 ] . Methods . IsWildcard ( ) )
require . Equal ( t , actual . Permissions [ 1 ] . Contract . Type , PermissionWildcard )
require . True ( t , actual . Permissions [ 1 ] . Methods . IsWildcard ( ) )
require . NotEqual ( t , actual . Trusts . Value [ 0 ] . Type , PermissionWildcard )
require . Equal ( t , actual . Trusts . Value [ 1 ] . Type , PermissionWildcard )
} )
2021-02-03 18:09:50 +00:00
}
func TestManifest_FromStackItemErrors ( t * testing . T ) {
2021-05-05 15:11:49 +00:00
name := stackitem . NewByteArray ( [ ] byte { } )
groups := stackitem . NewArray ( [ ] stackitem . Item { } )
features := stackitem . NewMap ( )
sStandards := stackitem . NewArray ( [ ] stackitem . Item { } )
abi := stackitem . NewStruct ( [ ] stackitem . Item { stackitem . NewArray ( [ ] stackitem . Item { } ) , stackitem . NewArray ( [ ] stackitem . Item { } ) } )
permissions := stackitem . NewArray ( [ ] stackitem . Item { } )
trusts := stackitem . NewArray ( [ ] stackitem . Item { } )
extra := stackitem . NewByteArray ( [ ] byte { } )
// check OK
goodSI := [ ] stackitem . Item { name , groups , features , sStandards , abi , permissions , trusts , extra }
m := new ( Manifest )
require . NoError ( t , m . FromStackItem ( stackitem . NewStruct ( goodSI ) ) )
2021-02-03 18:09:50 +00:00
errCases := map [ string ] stackitem . Item {
"not a struct" : stackitem . NewArray ( [ ] stackitem . Item { } ) ,
"invalid length" : stackitem . NewStruct ( [ ] stackitem . Item { } ) ,
2024-08-24 10:03:16 +00:00
"invalid name type" : stackitem . NewStruct ( slices . Concat ( [ ] stackitem . Item { stackitem . NewInterop ( nil ) } , goodSI [ 1 : ] ) ) ,
"invalid Groups type" : stackitem . NewStruct ( slices . Concat ( goodSI [ : 1 ] , [ ] stackitem . Item { stackitem . Null { } } , goodSI [ 2 : ] ) ) ,
"invalid group" : stackitem . NewStruct ( slices . Concat ( goodSI [ : 1 ] , [ ] stackitem . Item { stackitem . NewArray ( [ ] stackitem . Item { stackitem . Null { } } ) } , goodSI [ 2 : ] ) ) ,
"invalid Features type" : stackitem . NewStruct ( slices . Concat ( goodSI [ : 2 ] , [ ] stackitem . Item { stackitem . Null { } } , goodSI [ 3 : ] ) ) ,
"invalid supported standards type" : stackitem . NewStruct ( slices . Concat ( goodSI [ : 3 ] , [ ] stackitem . Item { stackitem . Null { } } , goodSI [ 4 : ] ) ) ,
"invalid supported standard" : stackitem . NewStruct ( slices . Concat ( goodSI [ : 3 ] , [ ] stackitem . Item { stackitem . NewArray ( [ ] stackitem . Item { stackitem . Null { } } ) } , goodSI [ 4 : ] ) ) ,
"invalid ABI" : stackitem . NewStruct ( slices . Concat ( goodSI [ : 4 ] , [ ] stackitem . Item { stackitem . Null { } } , goodSI [ 5 : ] ) ) ,
"invalid Permissions type" : stackitem . NewStruct ( slices . Concat ( goodSI [ : 5 ] , [ ] stackitem . Item { stackitem . Null { } } , goodSI [ 6 : ] ) ) ,
"invalid permission" : stackitem . NewStruct ( slices . Concat ( goodSI [ : 5 ] , [ ] stackitem . Item { stackitem . NewArray ( [ ] stackitem . Item { stackitem . Null { } } ) } , goodSI [ 6 : ] ) ) ,
"invalid Trusts type" : stackitem . NewStruct ( slices . Concat ( goodSI [ : 6 ] , [ ] stackitem . Item { stackitem . NewInterop ( nil ) } , goodSI [ 7 : ] ) ) ,
"invalid trust" : stackitem . NewStruct ( slices . Concat ( goodSI [ : 6 ] , [ ] stackitem . Item { stackitem . NewArray ( [ ] stackitem . Item { stackitem . NewInterop ( nil ) } ) } , goodSI [ 7 : ] ) ) ,
"invalid Uint160 trust" : stackitem . NewStruct ( slices . Concat ( goodSI [ : 6 ] , [ ] stackitem . Item { stackitem . NewArray ( [ ] stackitem . Item { stackitem . NewByteArray ( [ ] byte { 1 , 2 , 3 } ) } ) } , goodSI [ 7 : ] ) ) ,
"invalid extra type" : stackitem . NewStruct ( slices . Concat ( goodSI [ : 7 ] , [ ] stackitem . Item { stackitem . Null { } } ) ) ,
2021-02-03 18:09:50 +00:00
}
for name , errCase := range errCases {
t . Run ( name , func ( t * testing . T ) {
p := new ( Manifest )
require . Error ( t , p . FromStackItem ( errCase ) )
} )
}
}
func TestABI_ToStackItemFromStackItem ( t * testing . T ) {
a := & ABI {
Methods : [ ] Method { {
Name : "mur" ,
Offset : 5 ,
Parameters : [ ] Parameter { { Name : "p1" , Type : smartcontract . BoolType } } ,
ReturnType : smartcontract . StringType ,
Safe : true ,
} } ,
Events : [ ] Event { {
Name : "mur" ,
Parameters : [ ] Parameter { { Name : "p1" , Type : smartcontract . BoolType } } ,
} } ,
}
expected := stackitem . NewStruct ( [ ] stackitem . Item {
stackitem . NewArray ( [ ] stackitem . Item {
stackitem . NewStruct ( [ ] stackitem . Item {
stackitem . NewByteArray ( [ ] byte ( "mur" ) ) ,
stackitem . NewArray ( [ ] stackitem . Item {
stackitem . NewStruct ( [ ] stackitem . Item {
stackitem . NewByteArray ( [ ] byte ( "p1" ) ) ,
stackitem . NewBigInteger ( big . NewInt ( int64 ( smartcontract . BoolType ) ) ) ,
} ) ,
} ) ,
stackitem . NewBigInteger ( big . NewInt ( int64 ( smartcontract . StringType ) ) ) ,
stackitem . NewBigInteger ( big . NewInt ( int64 ( 5 ) ) ) ,
stackitem . NewBool ( true ) ,
} ) ,
} ) ,
stackitem . NewArray ( [ ] stackitem . Item {
stackitem . NewStruct ( [ ] stackitem . Item {
stackitem . NewByteArray ( [ ] byte ( "mur" ) ) ,
stackitem . NewArray ( [ ] stackitem . Item {
stackitem . NewStruct ( [ ] stackitem . Item {
stackitem . NewByteArray ( [ ] byte ( "p1" ) ) ,
stackitem . NewBigInteger ( big . NewInt ( int64 ( smartcontract . BoolType ) ) ) ,
} ) ,
} ) ,
} ) ,
} ) ,
} )
CheckToFromStackItem ( t , a , expected )
}
func TestABI_FromStackItemErrors ( t * testing . T ) {
errCases := map [ string ] stackitem . Item {
"not a struct" : stackitem . NewArray ( [ ] stackitem . Item { } ) ,
"invalid length" : stackitem . NewStruct ( [ ] stackitem . Item { } ) ,
"invalid methods type" : stackitem . NewStruct ( [ ] stackitem . Item { stackitem . NewInterop ( nil ) , stackitem . Null { } } ) ,
"invalid method" : stackitem . NewStruct ( [ ] stackitem . Item { stackitem . NewArray ( [ ] stackitem . Item { stackitem . Null { } } ) , stackitem . Null { } } ) ,
"invalid events type" : stackitem . NewStruct ( [ ] stackitem . Item { stackitem . NewArray ( [ ] stackitem . Item { } ) , stackitem . Null { } } ) ,
"invalid event" : stackitem . NewStruct ( [ ] stackitem . Item { stackitem . NewArray ( [ ] stackitem . Item { } ) , stackitem . NewArray ( [ ] stackitem . Item { stackitem . Null { } } ) } ) ,
}
for name , errCase := range errCases {
t . Run ( name , func ( t * testing . T ) {
p := new ( ABI )
require . Error ( t , p . FromStackItem ( errCase ) )
} )
}
}
2021-06-28 16:09:19 +00:00
func TestExtraToStackItem ( t * testing . T ) {
testCases := [ ] struct {
raw , expected string
} {
{ "null" , "null" } ,
{ "1" , "1" } ,
{ "1.23456789101112131415" , "1.23456789101112131415" } ,
{ ` "string with space" ` , ` "string with space" ` } ,
{ ` { "a":1, "sss" : { "m" : 1, "a" : 2} , "x" : 2 ,"c" :3,"z":4, "s":"5"} ` ,
` { "a":1,"sss": { "m":1,"a":2},"x":2,"c":3,"z":4,"s":"5"} ` } ,
{ ` [ 1, "array", { "d": "z", "a":"x", "c" : "y", "b":3}] ` ,
` [1,"array", { "d":"z","a":"x","c":"y","b":3}] ` } ,
2024-01-11 19:20:32 +00:00
{
// C# double quotes marshalling compatibility test, ref. #3284.
` { "Author":"NEOZEN","Description":"NEO\u0027s First Inscriptions Meta Protocol","Deployment":" { \"p\":\"neoz-20\",\"op\":\"deploy\",\"tick\":\"neoz\",\"max\":\"21000000\",\"lim\":\"1000\"}"} ` ,
` { "Author":"NEOZEN","Description":"NEO\u0027s First Inscriptions Meta Protocol","Deployment":" { \u0022p\u0022:\u0022neoz-20\u0022,\u0022op\u0022:\u0022deploy\u0022,\u0022tick\u0022:\u0022neoz\u0022,\u0022max\u0022:\u002221000000\u0022,\u0022lim\u0022:\u00221000\u0022}"} ` ,
} ,
2021-06-28 16:09:19 +00:00
}
for _ , tc := range testCases {
res := extraToStackItem ( [ ] byte ( tc . raw ) )
actual , ok := res . Value ( ) . ( [ ] byte )
require . True ( t , ok )
require . Equal ( t , tc . expected , string ( actual ) )
}
}
2021-07-23 12:52:30 +00:00
func TestManifest_IsStandardSupported ( t * testing . T ) {
m := & Manifest {
SupportedStandards : [ ] string { NEP17StandardName , NEP17Payable , NEP11Payable } ,
}
for _ , st := range m . SupportedStandards {
require . True ( t , m . IsStandardSupported ( st ) )
}
require . False ( t , m . IsStandardSupported ( NEP11StandardName ) )
require . False ( t , m . IsStandardSupported ( "" ) )
require . False ( t , m . IsStandardSupported ( "unknown standard" ) )
}