diff --git a/runtime/interpreter/value.go b/runtime/interpreter/value.go index 6f36d14146..84e39ca244 100644 --- a/runtime/interpreter/value.go +++ b/runtime/interpreter/value.go @@ -20601,6 +20601,13 @@ func (v *StorageReferenceValue) dereference(interpreter *Interpreter, locationRa return nil, nil } + if reference, isReference := referenced.(ReferenceValue); isReference { + panic(NestedReferenceError{ + Value: reference, + LocationRange: locationRange, + }) + } + if v.BorrowedType != nil { staticType := referenced.StaticType(interpreter) diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go index 5972980f49..8f6eeeacd7 100644 --- a/runtime/runtime_test.go +++ b/runtime/runtime_test.go @@ -10842,3 +10842,71 @@ func TestRuntimeAccountEntitlementEscalation(t *testing.T) { }) require.ErrorAs(t, err, &interpreter.InvalidMemberReferenceError{}) } + +func TestRuntimeAccountStorageBorrowEphemeralReferenceValue(t *testing.T) { + + t.Parallel() + + addressValue := Address{ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, + } + + runtime := NewTestInterpreterRuntime() + + contract := []byte(` + access(all) contract C { + + init() { + let pubAccount = getAccount(0x01) + self.account.storage.save(pubAccount as AnyStruct, to: /storage/account) + let authAccount = self.account.storage.borrow(from: /storage/account)! + } + } + `) + + deploy := DeploymentTransaction("C", contract) + + accountCodes := map[Location][]byte{} + var events []cadence.Event + + runtimeInterface := &TestRuntimeInterface{ + OnGetCode: func(location Location) (bytes []byte, err error) { + return accountCodes[location], nil + }, + Storage: NewTestLedger(nil, nil), + OnGetSigningAccounts: func() ([]Address, error) { + return []Address{addressValue}, nil + }, + OnResolveLocation: NewSingleIdentifierLocationResolver(t), + OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + return accountCodes[location], nil + }, + OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { + accountCodes[location] = code + return nil + }, + OnCreateAccount: func(payer Address) (address Address, err error) { + return addressValue, nil + }, + OnEmitEvent: func(event cadence.Event) error { + events = append(events, event) + return nil + }, + } + + nextTransactionLocation := NewTransactionLocationGenerator() + + err := runtime.ExecuteTransaction( + Script{ + Source: deploy, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + RequireError(t, err) + + var nestedReferenceErr interpreter.NestedReferenceError + require.ErrorAs(t, err, &nestedReferenceErr) +}