diff --git a/migrations/entitlements/migration_test.go b/migrations/entitlements/migration_test.go index 21846b1a4e..91b775999b 100644 --- a/migrations/entitlements/migration_test.go +++ b/migrations/entitlements/migration_test.go @@ -1217,7 +1217,7 @@ func TestConvertToEntitledValue(t *testing.T) { wrap: func(staticType interpreter.StaticType) interpreter.Value { return interpreter.NewCapabilityValue( nil, - 0, + 1, interpreter.AddressValue{}, staticType, ) @@ -1241,7 +1241,7 @@ func TestConvertToEntitledValue(t *testing.T) { interpreter.AddressValue{}, interpreter.NewCapabilityValue( nil, - 0, + 1, interpreter.AddressValue{}, staticType, ), @@ -1453,7 +1453,7 @@ func TestMigrateSimpleContract(t *testing.T) { unentitledRCap := interpreter.NewCapabilityValue( inter, - 0, + 1, interpreter.NewAddressValue(inter, account), unentitledRRefStaticType, ) @@ -1475,7 +1475,7 @@ func TestMigrateSimpleContract(t *testing.T) { entitledRRefStaticType := entitledRRef.StaticType(inter) entitledRCap := interpreter.NewCapabilityValue( inter, - 0, + 1, interpreter.NewAddressValue(inter, account), entitledRRefStaticType, ) @@ -1492,7 +1492,7 @@ func TestMigrateSimpleContract(t *testing.T) { storedValue: unentitledRCap.Clone(inter), expectedValue: interpreter.NewCapabilityValue( inter, - 0, + 1, interpreter.NewAddressValue(inter, account), entitledRRefStaticType, ), diff --git a/runtime/capabilities_test.go b/runtime/capabilities_test.go index ac73a29e55..1a54e8a6b4 100644 --- a/runtime/capabilities_test.go +++ b/runtime/capabilities_test.go @@ -133,7 +133,7 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) { access(all) fun testR() { let path = /public/r - let cap = self.account.capabilities.get<&R>(path)! + let cap = self.account.capabilities.get<&R>(path) assert(self.account.capabilities.exists(path)) @@ -162,7 +162,7 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) { access(all) fun testRAsR2() { let path = /public/rAsR2 - let cap = self.account.capabilities.get<&R2>(path)! + let cap = self.account.capabilities.get<&R2>(path) assert(self.account.capabilities.exists(path)) @@ -185,7 +185,7 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) { access(all) fun testRAsS() { let path = /public/rAsS - let cap = self.account.capabilities.get<&S>(path)! + let cap = self.account.capabilities.get<&S>(path) assert(self.account.capabilities.exists(path)) @@ -208,7 +208,7 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) { access(all) fun testNonExistentTarget() { let path = /public/nonExistentTarget - let cap = self.account.capabilities.get<&R>(path)! + let cap = self.account.capabilities.get<&R>(path) assert(self.account.capabilities.exists(path)) @@ -231,13 +231,28 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) { access(all) fun testNonExistent() { let path = /public/nonExistent - assert(self.account.capabilities.get<&AnyResource>(path) == nil) + + let cap = self.account.capabilities.get<&R>(path) + assert(cap.id == 0) + assert(cap as? Capability<&R> != nil) + assert(cap as? Capability<&AnyResource> != nil) + assert(cap.borrow() == nil) + assert(cap.address == 0x1) + assert(cap.check() == false) + + let cap2 = self.account.capabilities.get<&AnyResource>(path) + assert(cap2.id == 0) + assert(cap2 as? Capability<&AnyResource> != nil) + assert(cap2.borrow() == nil) + assert(cap2.address == 0x1) + assert(cap2.check() == false) + assert(!self.account.capabilities.exists(path)) } access(all) fun testSwap(): Int { - let ref = self.account.capabilities.get<&R>(/public/r)!.borrow()! + let ref = self.account.capabilities.get<&R>(/public/r).borrow()! let r <- self.account.storage.load<@R>(from: /storage/r) destroy r @@ -385,7 +400,7 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) { access(all) fun testS() { let path = /public/s - let cap = self.account.capabilities.get<&S>(path)! + let cap = self.account.capabilities.get<&S>(path) assert(self.account.capabilities.exists(path)) @@ -414,7 +429,7 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) { access(all) fun testSAsS2() { let path = /public/sAsS2 - let cap = self.account.capabilities.get<&S2>(path)! + let cap = self.account.capabilities.get<&S2>(path) assert(self.account.capabilities.exists(path)) @@ -437,7 +452,7 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) { access(all) fun testSAsR() { let path = /public/sAsR - let cap = self.account.capabilities.get<&R>(path)! + let cap = self.account.capabilities.get<&R>(path) assert(self.account.capabilities.exists(path)) @@ -460,7 +475,7 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) { access(all) fun testNonExistentTarget() { let path = /public/nonExistentTarget - let cap = self.account.capabilities.get<&S>(path)! + let cap = self.account.capabilities.get<&S>(path) assert(self.account.capabilities.exists(path)) @@ -483,13 +498,28 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) { access(all) fun testNonExistent() { let path = /public/nonExistent - assert(self.account.capabilities.get<&AnyStruct>(path) == nil) + + let cap = self.account.capabilities.get<&S>(path) + assert(cap.id == 0) + assert(cap as? Capability<&S> != nil) + assert(cap as? Capability<&AnyStruct> != nil) + assert(cap.borrow() == nil) + assert(cap.address == 0x1) + assert(cap.check() == false) + + let cap2 = self.account.capabilities.get<&AnyStruct>(path) + assert(cap2.id == 0) + assert(cap2 as? Capability<&AnyStruct> != nil) + assert(cap2.borrow() == nil) + assert(cap2.address == 0x1) + assert(cap2.check() == false) + assert(!self.account.capabilities.exists(path)) } access(all) fun testSwap(): Int { - let ref = self.account.capabilities.get<&S>(/public/s)!.borrow()! + let ref = self.account.capabilities.get<&S>(/public/s).borrow()! self.account.storage.load(from: /storage/s) diff --git a/runtime/capabilitycontrollers_test.go b/runtime/capabilitycontrollers_test.go index 1d27eea7ec..b8bd18f82b 100644 --- a/runtime/capabilitycontrollers_test.go +++ b/runtime/capabilitycontrollers_test.go @@ -232,12 +232,15 @@ func TestRuntimeCapabilityControllers(t *testing.T) { let path = /public/x // Act - let gotCap: Capability<&AnyStruct>? = + let gotCap: Capability<&AnyStruct> = %[1]s.capabilities.get<&AnyStruct>(path) // Assert assert(!%[1]s.capabilities.exists(path)) - assert(gotCap == nil) + assert(gotCap.id == 0) + assert(gotCap.borrow() == nil) + assert(gotCap.check() == false) + assert(gotCap.address == 0x1) } } `, @@ -274,7 +277,7 @@ func TestRuntimeCapabilityControllers(t *testing.T) { // Act let gotCap: Capability<&Test.R> = - %[1]s.capabilities.get<&Test.R>(publicPath)! + %[1]s.capabilities.get<&Test.R>(publicPath) // Assert assert(%[1]s.capabilities.exists(publicPath)) @@ -308,7 +311,7 @@ func TestRuntimeCapabilityControllers(t *testing.T) { // Act let gotCap: Capability<&Account> = - %[1]s.capabilities.get<&Account>(publicPath)! + %[1]s.capabilities.get<&Account>(publicPath) // Assert assert(%[1]s.capabilities.exists(publicPath)) @@ -353,7 +356,7 @@ func TestRuntimeCapabilityControllers(t *testing.T) { // Act let gotCap: Capability<&Test.R> = - %[1]s.capabilities.get<&Test.R>(publicPath)! + %[1]s.capabilities.get<&Test.R>(publicPath) let ref: &Test.R = gotCap.borrow()! // Assert @@ -390,7 +393,7 @@ func TestRuntimeCapabilityControllers(t *testing.T) { // Act let gotCap: Capability<&Account> = - %[1]s.capabilities.get<&Account>(publicPath)! + %[1]s.capabilities.get<&Account>(publicPath) let ref: &Account = gotCap.borrow()! // Assert @@ -436,13 +439,16 @@ func TestRuntimeCapabilityControllers(t *testing.T) { signer.capabilities.publish(issuedCap, at: publicPath) // Act - let gotCap: Capability? = + let gotCap: Capability = %[1]s.capabilities.get(publicPath) // Assert assert(%[1]s.capabilities.exists(publicPath)) assert(issuedCap.id == expectedCapID) - assert(gotCap == nil) + assert(gotCap.id == 0) + assert(gotCap.borrow() == nil) + assert(gotCap.check() == false) + assert(gotCap.address == 0x1) } } `, @@ -472,13 +478,16 @@ func TestRuntimeCapabilityControllers(t *testing.T) { signer.capabilities.publish(issuedCap, at: publicPath) // Act - let gotCap: Capability<&Test.R>? = + let gotCap: Capability<&Test.R> = %[1]s.capabilities.get<&Test.R>(publicPath) // Assert assert(%[1]s.capabilities.exists(publicPath)) assert(issuedCap.id == expectedCapID) - assert(gotCap == nil) + assert(gotCap.id == 0) + assert(gotCap.borrow() == nil) + assert(gotCap.check() == false) + assert(gotCap.address == 0x1) } } `, @@ -516,13 +525,16 @@ func TestRuntimeCapabilityControllers(t *testing.T) { signer.capabilities.publish(issuedCap, at: publicPath) // Act - let gotCap: Capability<&Test.S>? = + let gotCap: Capability<&Test.S> = %[1]s.capabilities.get<&Test.S>(publicPath) // Assert assert(%[1]s.capabilities.exists(publicPath)) assert(issuedCap.id == expectedCapID) - assert(gotCap == nil) + assert(gotCap.id == 0) + assert(gotCap.borrow() == nil) + assert(gotCap.check() == false) + assert(gotCap.address == 0x1) } } `, @@ -550,13 +562,16 @@ func TestRuntimeCapabilityControllers(t *testing.T) { signer.capabilities.publish(issuedCap, at: publicPath) // Act - let gotCap: Capability<&AnyResource>? = + let gotCap: Capability<&AnyResource> = %[1]s.capabilities.get<&AnyResource>(publicPath) // Assert assert(%[1]s.capabilities.exists(publicPath)) assert(issuedCap.id == expectedCapID) - assert(gotCap == nil) + assert(gotCap.id == 0) + assert(gotCap.borrow() == nil) + assert(gotCap.check() == false) + assert(gotCap.address == 0x1) } } `, @@ -594,14 +609,17 @@ func TestRuntimeCapabilityControllers(t *testing.T) { let unpublishedcap = signer.capabilities.unpublish(publicPath) // Act - let gotCap: Capability<&Test.R>? = + let gotCap: Capability<&Test.R> = %[1]s.capabilities.get<&Test.R>(publicPath) // Assert assert(!%[1]s.capabilities.exists(publicPath)) assert(issuedCap.id == expectedCapID) assert(unpublishedcap!.id == expectedCapID) - assert(gotCap == nil) + assert(gotCap.id == 0) + assert(gotCap.borrow() == nil) + assert(gotCap.check() == false) + assert(gotCap.address == 0x1) } } `, @@ -629,14 +647,17 @@ func TestRuntimeCapabilityControllers(t *testing.T) { let unpublishedcap = signer.capabilities.unpublish(publicPath) // Act - let gotCap: Capability<&Account>? = + let gotCap: Capability<&Account> = %[1]s.capabilities.get<&Account>(publicPath) // Assert assert(!%[1]s.capabilities.exists(publicPath)) assert(issuedCap.id == expectedCapID) assert(unpublishedcap!.id == expectedCapID) - assert(gotCap == nil) + assert(gotCap.id == 0) + assert(gotCap.borrow() == nil) + assert(gotCap.check() == false) + assert(gotCap.address == 0x1) } } `, diff --git a/runtime/entitlements_test.go b/runtime/entitlements_test.go index bafe338e25..ab33609987 100644 --- a/runtime/entitlements_test.go +++ b/runtime/entitlements_test.go @@ -539,7 +539,7 @@ func TestRuntimeAccountEntitlementCapabilityCasting(t *testing.T) { import Test from 0x1 transaction { prepare(signer: &Account) { - let capX = signer.capabilities.get(/public/foo)! + let capX = signer.capabilities.get(/public/foo) let upCap = capX as Capability<&Test.R> let downCap = upCap as! Capability } @@ -647,8 +647,8 @@ func TestRuntimeAccountEntitlementCapabilityDictionary(t *testing.T) { import Test from 0x1 transaction { prepare(signer: &Account) { - let capX = signer.capabilities.get(/public/foo)! - let capY = signer.capabilities.get(/public/bar)! + let capX = signer.capabilities.get(/public/foo) + let capY = signer.capabilities.get(/public/bar) let dict: {Type: Capability<&Test.R>} = {} dict[capX.getType()] = capX @@ -762,8 +762,8 @@ func TestRuntimeAccountEntitlementGenericCapabilityDictionary(t *testing.T) { import Test from 0x1 transaction { prepare(signer: &Account) { - let capX = signer.capabilities.get(/public/foo)! - let capY = signer.capabilities.get(/public/bar)! + let capX = signer.capabilities.get(/public/foo) + let capY = signer.capabilities.get(/public/bar) let dict: {Type: Capability} = {} dict[capX.getType()] = capX @@ -988,7 +988,7 @@ func TestRuntimeCapabilityEntitlements(t *testing.T) { let issuedCap = account.capabilities.storage.issue(/storage/foo) account.capabilities.publish(issuedCap, at: /public/foo) - let cap: Capability = account.capabilities.get(/public/foo)! + let cap: Capability = account.capabilities.get(/public/foo) let runtimeType = cap.getType() @@ -1017,7 +1017,7 @@ func TestRuntimeCapabilityEntitlements(t *testing.T) { let issuedCap = account.capabilities.storage.issue<&S>(/storage/foo) account.capabilities.publish(issuedCap, at: /public/foo) - let cap: Capability<&S> = account.capabilities.get<&S>(/public/foo)! + let cap: Capability<&S> = account.capabilities.get<&S>(/public/foo) let runtimeType = cap.getType() let upcastCap = cap as Capability<&AnyStruct> @@ -1050,7 +1050,7 @@ func TestRuntimeCapabilityEntitlements(t *testing.T) { let issuedCap = account.capabilities.storage.issue(/storage/foo) account.capabilities.publish(issuedCap, at: /public/foo) - let cap = account.capabilities.get(/public/foo)! + let cap = account.capabilities.get(/public/foo) assert(cap.check()) } `) @@ -1109,7 +1109,7 @@ func TestRuntimeCapabilityEntitlements(t *testing.T) { account.capabilities.publish(issuedCap, at: /public/foo) let cap = account.capabilities.get(/public/foo) - assert(cap == nil) + assert(!cap.check()) } `) }) diff --git a/runtime/interpreter/errors.go b/runtime/interpreter/errors.go index d1ada8879c..6ff6d71395 100644 --- a/runtime/interpreter/errors.go +++ b/runtime/interpreter/errors.go @@ -1107,3 +1107,15 @@ func (ResourceLossError) IsUserError() {} func (e ResourceLossError) Error() string { return "resource loss: attempting to assign to non-nil resource-typed value" } + +// InvalidCapabilityIDError + +type InvalidCapabilityIDError struct{} + +var _ errors.InternalError = InvalidCapabilityIDError{} + +func (InvalidCapabilityIDError) IsInternalError() {} + +func (e InvalidCapabilityIDError) Error() string { + return "capability created with invalid ID" +} diff --git a/runtime/interpreter/interpreter.go b/runtime/interpreter/interpreter.go index 0c50402948..667fd50e15 100644 --- a/runtime/interpreter/interpreter.go +++ b/runtime/interpreter/interpreter.go @@ -2184,6 +2184,9 @@ func (interpreter *Interpreter) convert(value Value, valueType, targetType sema. case *IDCapabilityValue: valueBorrowType := capability.BorrowType.(*ReferenceStaticType) borrowType := interpreter.convertStaticType(valueBorrowType, targetBorrowType) + if capability.isInvalid() { + return NewInvalidCapabilityValue(interpreter, capability.Address, borrowType) + } return NewCapabilityValue( interpreter, capability.ID, @@ -5466,6 +5469,10 @@ func (interpreter *Interpreter) capabilityBorrowFunction( inter := invocation.Interpreter locationRange := invocation.LocationRange + if capabilityID == invalidCapabilityID { + return Nil + } + var wantedBorrowType *sema.ReferenceType typeParameterPair := invocation.TypeParameterTypes.Oldest() if typeParameterPair != nil { @@ -5504,6 +5511,10 @@ func (interpreter *Interpreter) capabilityCheckFunction( sema.CapabilityTypeCheckFunctionType(capabilityBorrowType), func(invocation Invocation) Value { + if capabilityID == invalidCapabilityID { + return FalseValue + } + inter := invocation.Interpreter locationRange := invocation.LocationRange diff --git a/runtime/interpreter/value_capability.go b/runtime/interpreter/value_capability.go index 20d3b3ff37..0d0dec56b5 100644 --- a/runtime/interpreter/value_capability.go +++ b/runtime/interpreter/value_capability.go @@ -27,6 +27,8 @@ import ( "github.com/onflow/cadence/runtime/sema" ) +const invalidCapabilityID UInt64Value = 0 + // CapabilityValue // TODO: remove once migration to Cadence 1.0 / ID capabilities is complete @@ -49,6 +51,9 @@ func NewUnmeteredCapabilityValue( address AddressValue, borrowType StaticType, ) *IDCapabilityValue { + if id == invalidCapabilityID { + panic(InvalidCapabilityIDError{}) + } return &IDCapabilityValue{ ID: id, Address: address, @@ -67,6 +72,20 @@ func NewCapabilityValue( return NewUnmeteredCapabilityValue(id, address, borrowType) } +func NewInvalidCapabilityValue( + memoryGauge common.MemoryGauge, + address AddressValue, + borrowType StaticType, +) *IDCapabilityValue { + // Constant because its constituents are already metered. + common.UseMemory(memoryGauge, common.CapabilityValueMemoryUsage) + return &IDCapabilityValue{ + ID: invalidCapabilityID, + Address: address, + BorrowType: borrowType, + } +} + var _ Value = &IDCapabilityValue{} var _ atree.Storable = &IDCapabilityValue{} var _ EquatableValue = &IDCapabilityValue{} @@ -77,6 +96,10 @@ func (*IDCapabilityValue) isValue() {} func (*IDCapabilityValue) isCapabilityValue() {} +func (v *IDCapabilityValue) isInvalid() bool { + return v.ID == invalidCapabilityID +} + func (v *IDCapabilityValue) Accept(interpreter *Interpreter, visitor Visitor, _ LocationRange) { visitor.VisitCapabilityValue(interpreter, v) } diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go index c70ee478a7..07abbd0260 100644 --- a/runtime/runtime_test.go +++ b/runtime/runtime_test.go @@ -8739,7 +8739,7 @@ func TestRuntimeWrappedErrorHandling(t *testing.T) { tx2 := []byte(` transaction { prepare(signer: &Account) { - let cap = signer.capabilities.get<&AnyStruct>(/public/r)! + let cap = signer.capabilities.get<&AnyStruct>(/public/r) cap.check() } } diff --git a/runtime/sema/account.cdc b/runtime/sema/account.cdc index ec6e9f0193..ce8d65a696 100644 --- a/runtime/sema/account.cdc +++ b/runtime/sema/account.cdc @@ -324,14 +324,15 @@ struct Account { let account: Account.AccountCapabilities /// Returns the capability at the given public path. - /// Returns nil if the capability does not exist, - /// or if the given type is not a supertype of the capability's borrow type. + /// If the capability does not exist, + /// or if the given type is not a supertype of the capability's borrow type, + /// returns an "invalid" capability with ID 0 that will always fail to `check` or `borrow` access(all) - view fun get(_ path: PublicPath): Capability? + view fun get(_ path: PublicPath): Capability /// Borrows the capability at the given public path. /// Returns nil if the capability does not exist, or cannot be borrowed using the given type. - /// The function is equivalent to `get(path)?.borrow()`. + /// The function is equivalent to `get(path).borrow()`. access(all) view fun borrow(_ path: PublicPath): T? diff --git a/runtime/sema/account.gen.go b/runtime/sema/account.gen.go index 1e1fbbc8d3..f7935b2086 100644 --- a/runtime/sema/account.gen.go +++ b/runtime/sema/account.gen.go @@ -1233,21 +1233,20 @@ var Account_CapabilitiesTypeGetFunctionType = &FunctionType{ }, }, ReturnTypeAnnotation: NewTypeAnnotation( - &OptionalType{ - Type: MustInstantiate( - &CapabilityType{}, - &GenericType{ - TypeParameter: Account_CapabilitiesTypeGetFunctionTypeParameterT, - }, - ), - }, + MustInstantiate( + &CapabilityType{}, + &GenericType{ + TypeParameter: Account_CapabilitiesTypeGetFunctionTypeParameterT, + }, + ), ), } const Account_CapabilitiesTypeGetFunctionDocString = ` Returns the capability at the given public path. -Returns nil if the capability does not exist, -or if the given type is not a supertype of the capability's borrow type. +If the capability does not exist, +or if the given type is not a supertype of the capability's borrow type, +returns an "invalid" capability with ID 0 that will always fail to ` + "`check`" + ` or ` + "`borrow`" + ` ` const Account_CapabilitiesTypeBorrowFunctionName = "borrow" @@ -1284,7 +1283,7 @@ var Account_CapabilitiesTypeBorrowFunctionType = &FunctionType{ const Account_CapabilitiesTypeBorrowFunctionDocString = ` Borrows the capability at the given public path. Returns nil if the capability does not exist, or cannot be borrowed using the given type. -The function is equivalent to ` + "`get(path)?.borrow()`" + `. +The function is equivalent to ` + "`get(path).borrow()`" + `. ` const Account_CapabilitiesTypeExistsFunctionName = "exists" diff --git a/runtime/stdlib/account.go b/runtime/stdlib/account.go index 5e71bd8945..752d6cf44c 100644 --- a/runtime/stdlib/account.go +++ b/runtime/stdlib/account.go @@ -3598,7 +3598,15 @@ func newAccountCapabilitiesGetFunction( typeParameterPairValue := invocation.TypeParameterTypes.Oldest().Value // `Never` is never a supertype of any stored value if typeParameterPairValue.Equal(sema.NeverType) { - return interpreter.Nil + if borrow { + return interpreter.Nil + } else { + return interpreter.NewInvalidCapabilityValue( + inter, + addressValue, + interpreter.PrimitiveStaticTypeNever, + ) + } } wantedBorrowType, ok := typeParameterPairValue.(*sema.ReferenceType) @@ -3606,13 +3614,25 @@ func newAccountCapabilitiesGetFunction( panic(errors.NewUnreachableError()) } + var failValue interpreter.Value + if borrow { + failValue = interpreter.Nil + } else { + failValue = + interpreter.NewInvalidCapabilityValue( + inter, + addressValue, + interpreter.ConvertSemaToStaticType(inter, wantedBorrowType), + ) + } + // Read stored capability, if any storageMapKey := interpreter.StringStorageMapKey(identifier) readValue := inter.ReadStored(address, domain, storageMapKey) if readValue == nil { - return interpreter.Nil + return failValue } var readCapabilityValue *interpreter.IDCapabilityValue @@ -3677,13 +3697,17 @@ func newAccountCapabilitiesGetFunction( } if resultValue == nil { - return interpreter.Nil + return failValue } - return interpreter.NewSomeValueNonCopying( - inter, - resultValue, - ) + if borrow { + resultValue = interpreter.NewSomeValueNonCopying( + inter, + resultValue, + ) + } + + return resultValue }, ) } diff --git a/runtime/storage_test.go b/runtime/storage_test.go index 15786b7cba..98cf8597b7 100644 --- a/runtime/storage_test.go +++ b/runtime/storage_test.go @@ -1176,7 +1176,7 @@ func TestRuntimeStorageSaveCapability(t *testing.T) { signer.capabilities.publish(cap, at: /public/test) signer.storage.save(cap, to: %[2]s) - let cap2 = signer.capabilities.get<%[1]s>(/public/test)! + let cap2 = signer.capabilities.get<%[1]s>(/public/test) signer.storage.save(cap2, to: %[3]s) } } @@ -3801,12 +3801,14 @@ func TestRuntimeStorageIteration(t *testing.T) { account.storage.forEachPublic(fun (path: PublicPath, type: Type): Bool { total = total + 1 - if var cap = account.capabilities.get<&[{Foo.Collection}]>(path) { - cap.check() - var refArray = cap.borrow()! - capTaken = true - } + var cap = account.capabilities.get<&[{Foo.Collection}]>(path) + if cap.id != 0 { + cap.check() + var refArray = cap.borrow()! + capTaken = true + } + return true }) @@ -3998,10 +4000,11 @@ func TestRuntimeStorageIteration(t *testing.T) { account.storage.forEachPublic(fun (path: PublicPath, type: Type): Bool { total = total + 1 - if var cap = account.capabilities.get<&{Foo.Collection}>(path) { - cap.check() - capTaken = true - } + var cap = account.capabilities.get<&{Foo.Collection}>(path) + if cap.id != 0 { + cap.check() + capTaken = true + } return true }) @@ -4207,7 +4210,7 @@ func TestRuntimeStorageIteration(t *testing.T) { prepare(account: &Account) { var total = 0 account.storage.forEachPublic(fun (path: PublicPath, type: Type): Bool { - var cap = account.capabilities.get<&String>(path)! + var cap = account.capabilities.get<&String>(path) cap.check() total = total + 1 return true diff --git a/runtime/tests/checker/account_test.go b/runtime/tests/checker/account_test.go index a6e6c81a99..bb2c43dfb0 100644 --- a/runtime/tests/checker/account_test.go +++ b/runtime/tests/checker/account_test.go @@ -1679,7 +1679,7 @@ func TestCheckAccountCapabilities(t *testing.T) { _, err := ParseAndCheck(t, ` fun test(capabilities: &Account.Capabilities) { - let cap: Capability<&Int> = capabilities.get<&Int>(/public/foo)! + let cap: Capability<&Int> = capabilities.get<&Int>(/public/foo) let ref: &Int = capabilities.borrow<&Int>(/public/foo)! } @@ -1694,7 +1694,7 @@ func TestCheckAccountCapabilities(t *testing.T) { _, err := ParseAndCheck(t, ` fun test(capabilities: auth(Capabilities) &Account.Capabilities) { - let cap: Capability<&Int> = capabilities.get<&Int>(/public/foo)! + let cap: Capability<&Int> = capabilities.get<&Int>(/public/foo) let ref: &Int = capabilities.borrow<&Int>(/public/foo)! @@ -1713,7 +1713,7 @@ func TestCheckAccountCapabilities(t *testing.T) { _, err := ParseAndCheck(t, ` fun test(capabilities: &Account.Capabilities) { - let cap: Capability<&Int> = capabilities.get<&Int>(/public/foo)! + let cap: Capability<&Int> = capabilities.get<&Int>(/public/foo) capabilities.publish(cap, at: /public/bar) @@ -1733,7 +1733,7 @@ func TestCheckAccountCapabilities(t *testing.T) { _, err := ParseAndCheck(t, ` fun test(capabilities: &Account.Capabilities) { - capabilities.get(/public/foo)! + capabilities.get(/public/foo) } `) errs := RequireCheckerErrors(t, err, 1) @@ -1752,7 +1752,7 @@ func TestCheckAccountCapabilities(t *testing.T) { _, err := ParseAndCheck(t, ` fun test(capabilities: &Account.Capabilities) { - capabilities.get(/public/foo)! + capabilities.get(/public/foo) } `) errs := RequireCheckerErrors(t, err, 1)