Skip to content

Commit 393e955

Browse files
committed
call constructor for contracts loaded from identifier location, test
1 parent 2874423 commit 393e955

File tree

2 files changed

+125
-9
lines changed

2 files changed

+125
-9
lines changed

runtime/environment.go

+27-9
Original file line numberDiff line numberDiff line change
@@ -1092,30 +1092,48 @@ func (e *interpreterEnvironment) newCompositeValueFunctionsHandler() interpreter
10921092
func (e *interpreterEnvironment) loadContract(
10931093
inter *interpreter.Interpreter,
10941094
compositeType *sema.CompositeType,
1095-
_ func(common.Address) *interpreter.HostFunctionValue,
1096-
_ ast.Range,
1095+
constructorGenerator func(common.Address) *interpreter.HostFunctionValue,
1096+
invocationRange ast.Range,
10971097
) *interpreter.CompositeValue {
10981098

1099-
var storedValue interpreter.Value
1099+
var contractValue interpreter.Value
1100+
1101+
location := compositeType.Location
1102+
switch location := location.(type) {
1103+
case common.IdentifierLocation:
1104+
// Identifier locations are used for built-in contracts,
1105+
// and are not stored in storage
1106+
1107+
constructorGenerator := constructorGenerator(common.ZeroAddress)
1108+
var err error
1109+
contractValue, err = inter.InvokeFunctionValue(
1110+
constructorGenerator,
1111+
nil,
1112+
nil,
1113+
nil,
1114+
compositeType,
1115+
invocationRange,
1116+
)
1117+
if err != nil {
1118+
panic(err)
1119+
}
11001120

1101-
switch location := compositeType.Location.(type) {
1102-
// TODO: support e.g. CryptoContractLocation
11031121
case common.AddressLocation:
11041122
storageMap := e.storage.GetStorageMap(
11051123
location.Address,
11061124
StorageDomainContract,
11071125
false,
11081126
)
11091127
if storageMap != nil {
1110-
storedValue = storageMap.ReadValue(inter, interpreter.StringStorageMapKey(location.Name))
1128+
contractValue = storageMap.ReadValue(inter, interpreter.StringStorageMapKey(location.Name))
11111129
}
11121130
}
11131131

1114-
if storedValue == nil {
1115-
panic(errors.NewDefaultUserError("failed to load contract: %s", compositeType.Location))
1132+
if contractValue == nil {
1133+
panic(errors.NewDefaultUserError("failed to load contract: %s", location))
11161134
}
11171135

1118-
return storedValue.(*interpreter.CompositeValue)
1136+
return contractValue.(*interpreter.CompositeValue)
11191137
}
11201138

11211139
func (e *interpreterEnvironment) newOnFunctionInvocationHandler() func(_ *interpreter.Interpreter) {

runtime/runtime_test.go

+98
Original file line numberDiff line numberDiff line change
@@ -11561,3 +11561,101 @@ func TestResultRedeclared(t *testing.T) {
1156111561
})
1156211562

1156311563
}
11564+
func TestRuntimeContractValueLocation(t *testing.T) {
11565+
11566+
t.Parallel()
11567+
11568+
signerAddress := common.MustBytesToAddress([]byte{0x42})
11569+
11570+
const fooContractName = "Foo"
11571+
fooIdentifierLocation := common.IdentifierLocation(fooContractName)
11572+
11573+
fooContract := []byte(`
11574+
access(all)
11575+
contract Foo {
11576+
access(all) var answer: Int
11577+
11578+
init() {
11579+
self.answer = 42
11580+
}
11581+
}
11582+
`)
11583+
11584+
accountCodes := map[Location][]byte{}
11585+
var events []cadence.Event
11586+
11587+
runtimeInterface := &TestRuntimeInterface{
11588+
Storage: NewTestLedger(nil, nil),
11589+
OnGetSigningAccounts: func() ([]Address, error) {
11590+
return []Address{signerAddress}, nil
11591+
},
11592+
OnResolveLocation: func(identifiers []Identifier, location Location) ([]ResolvedLocation, error) {
11593+
assert.Empty(t, identifiers)
11594+
assert.Equal(t, fooIdentifierLocation, location)
11595+
11596+
return []ResolvedLocation{
11597+
{
11598+
Location: location,
11599+
Identifiers: identifiers,
11600+
},
11601+
}, nil
11602+
},
11603+
OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
11604+
return accountCodes[location], nil
11605+
},
11606+
OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
11607+
accountCodes[location] = code
11608+
return nil
11609+
},
11610+
OnEmitEvent: func(event cadence.Event) error {
11611+
events = append(events, event)
11612+
return nil
11613+
},
11614+
OnGetCode: func(location Location) ([]byte, error) {
11615+
assert.Equal(t, fooIdentifierLocation, location)
11616+
return fooContract, nil
11617+
},
11618+
}
11619+
11620+
runtime := NewTestInterpreterRuntime()
11621+
11622+
nextTransactionLocation := NewTransactionLocationGenerator()
11623+
nextScriptLocation := NewScriptLocationGenerator()
11624+
11625+
// Deploy
11626+
11627+
deploy := DeploymentTransaction(fooContractName, fooContract)
11628+
11629+
err := runtime.ExecuteTransaction(
11630+
Script{
11631+
Source: deploy,
11632+
},
11633+
Context{
11634+
Interface: runtimeInterface,
11635+
Location: nextTransactionLocation(),
11636+
},
11637+
)
11638+
require.NoError(t, err)
11639+
11640+
// Test
11641+
11642+
result, err := runtime.ExecuteScript(
11643+
Script{
11644+
Source: []byte(`
11645+
import Foo
11646+
11647+
access(all)
11648+
fun main(): Int {
11649+
return Foo.answer
11650+
}
11651+
`),
11652+
},
11653+
Context{
11654+
Interface: runtimeInterface,
11655+
Location: nextScriptLocation(),
11656+
},
11657+
)
11658+
require.NoError(t, err)
11659+
11660+
assert.Equal(t, cadence.NewInt(42), result)
11661+
}

0 commit comments

Comments
 (0)