@@ -24,11 +24,13 @@ import (
2424 "strings"
2525 "testing"
2626
27+ "github.com/onflow/atree"
2728 "github.com/stretchr/testify/assert"
2829 "github.com/stretchr/testify/require"
2930 "golang.org/x/crypto/sha3"
3031
3132 "github.com/onflow/cadence"
33+ "github.com/onflow/cadence/bbq/vm"
3234 "github.com/onflow/cadence/common"
3335 "github.com/onflow/cadence/interpreter"
3436 . "github.com/onflow/cadence/runtime"
@@ -365,3 +367,136 @@ func TestRuntimeTransactionWithContractDeployment(t *testing.T) {
365367 })
366368 })
367369}
370+
371+ func TestRuntimeContractDeploymentInitializerArgument (t * testing.T ) {
372+
373+ t .Parallel ()
374+
375+ runtime := NewTestRuntime ()
376+
377+ addressValue := cadence .BytesToAddress ([]byte {0xCA , 0xDE })
378+
379+ contract := []byte (`
380+ access(all) contract Test {
381+ init(arg: {Int: Int}) {
382+ check(arg)
383+ }
384+ }
385+ ` )
386+
387+ deploy := fmt .Sprintf (
388+ `
389+ transaction {
390+ prepare(signer: auth(Contracts) &Account) {
391+ let arg: {Int: Int} = {}
392+ signer.contracts.add(name: "Test", code: "%s".decodeHex(), arg: arg)
393+ }
394+ }
395+ ` ,
396+ hex .EncodeToString (contract ),
397+ )
398+
399+ var accountCode []byte
400+
401+ runtimeInterface := & TestRuntimeInterface {
402+ OnGetCode : func (_ Location ) (bytes []byte , err error ) {
403+ return accountCode , nil
404+ },
405+ Storage : NewTestLedger (nil , nil ),
406+ OnGetSigningAccounts : func () ([]Address , error ) {
407+ return []Address {Address (addressValue )}, nil
408+ },
409+ OnGetAccountContractCode : func (_ common.AddressLocation ) (code []byte , err error ) {
410+ return accountCode , nil
411+ },
412+ OnUpdateAccountContractCode : func (_ common.AddressLocation , code []byte ) error {
413+ accountCode = code
414+ return nil
415+ },
416+ OnEmitEvent : func (event cadence.Event ) error {
417+ return nil
418+ },
419+ }
420+
421+ check := func (value interpreter.Value ) {
422+ dictionaryValue , ok := value .(* interpreter.DictionaryValue )
423+ require .True (t , ok )
424+
425+ assert .Equal (t ,
426+ atree.ValueID {
427+ 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
428+ 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x6 ,
429+ },
430+ dictionaryValue .ValueID (),
431+ )
432+ }
433+
434+ transactionEnvironment := newTransactionEnvironment ()
435+
436+ functionType := sema .NewSimpleFunctionType (
437+ sema .FunctionPurityView ,
438+ []sema.Parameter {
439+ {
440+ Label : sema .ArgumentLabelNotRequired ,
441+ Identifier : "arg" ,
442+ TypeAnnotation : sema .NewTypeAnnotation (
443+ sema .NewDictionaryType (nil , sema .IntType , sema .IntType ),
444+ ),
445+ },
446+ },
447+ sema .VoidTypeAnnotation ,
448+ )
449+
450+ var function interpreter.FunctionValue
451+
452+ const functionName = "check"
453+ if * compile {
454+ function = vm .NewNativeFunctionValue (
455+ functionName ,
456+ functionType ,
457+ func (
458+ _ interpreter.NativeFunctionContext ,
459+ _ interpreter.TypeArgumentsIterator ,
460+ _ interpreter.Value ,
461+ args []interpreter.Value ,
462+ ) interpreter.Value {
463+ check (args [0 ])
464+ return interpreter .Void
465+ },
466+ )
467+ } else {
468+ function = interpreter .NewStaticHostFunctionValue (
469+ nil ,
470+ functionType ,
471+ func (invocation interpreter.Invocation ) interpreter.Value {
472+ check (invocation .Arguments [0 ])
473+ return interpreter .Void
474+ },
475+ )
476+ }
477+
478+ transactionEnvironment .DeclareValue (
479+ stdlib.StandardLibraryValue {
480+ Name : functionName ,
481+ Type : functionType ,
482+ Kind : common .DeclarationKindFunction ,
483+ Value : function ,
484+ },
485+ nil ,
486+ )
487+
488+ nextTransactionLocation := NewTransactionLocationGenerator ()
489+
490+ err := runtime .ExecuteTransaction (
491+ Script {
492+ Source : []byte (deploy ),
493+ },
494+ Context {
495+ Interface : runtimeInterface ,
496+ Environment : transactionEnvironment ,
497+ Location : nextTransactionLocation (),
498+ UseVM : * compile ,
499+ },
500+ )
501+ require .NoError (t , err )
502+ }
0 commit comments