F
Flow4mo ago
Giovanni S

Giovanni S | Flow (2024-02-02)

What's the 1.0 syntax for casting a resource as an auth reference so I can downcast? e.g.
access(all) resource interface A {}
access(all) resource interface B : A {}
access(all) resource R : B {
access(all) fun bar: String { return "bar" }
}

let a: @{A} <- self.createR()
let aRef = &a as auth &{A}
let b = aRef as! &{B}
b.bar()
access(all) resource interface A {}
access(all) resource interface B : A {}
access(all) resource R : B {
access(all) fun bar: String { return "bar" }
}

let a: @{A} <- self.createR()
let aRef = &a as auth &{A}
let b = aRef as! &{B}
b.bar()
9 Replies
Needle
Needle4mo ago
I've created a thread for your message. Please continue any relevant discussion in this thread. You can rename this thread using /title <new title> If this is a technical question that others may benefit from, considering also asking it on Stackoverflow: https://stackoverflow.com/questions/ask?tags=onflow-cadence
turbolent
turbolent4mo ago
references now always be downcast to a subtype (with equal or fewer entitlements). the auth modifier is for entitlements now in your example, what are A and B and what is there relationship? A is a resource, B is a resource interface, and A implements B?
Giovanni S
Giovanni S4mo ago
Sorry, updated the example
turbolent
turbolent4mo ago
just remove the auth keyword no entitlements involved, no auth keyword needed we can maybe provide a better error here, could you please open an issue for that?
Giovanni S
Giovanni S4mo ago
I cleared it up - I had to create an intermediary reference. Example for reference:
access(all) contract C {
access(all) resource interface A {}
access(all) resource interface B : A {
access(all) fun bar(): String {
return "bar"
}
}
access(all) resource R : B {}

access(all) fun createR(): @R {
return <-create R()
}
access(all) fun barFromA(a: @{C.A}): String {
var bar = ""
if a.getType().isSubtype(of: Type<@{B}>()) {
let aRef: &{A} = &a
let b = aRef as! &{B}
bar = b.bar()
}
destroy a
return bar
}
}
access(all) contract C {
access(all) resource interface A {}
access(all) resource interface B : A {
access(all) fun bar(): String {
return "bar"
}
}
access(all) resource R : B {}

access(all) fun createR(): @R {
return <-create R()
}
access(all) fun barFromA(a: @{C.A}): String {
var bar = ""
if a.getType().isSubtype(of: Type<@{B}>()) {
let aRef: &{A} = &a
let b = aRef as! &{B}
bar = b.bar()
}
destroy a
return bar
}
}
turbolent
turbolent4mo ago
you mean there's still a problem/question? I think a.getType().isSubtype(of: Type<@{A}>()) is always true. Did you mean to check if you can cast to B?
Giovanni S
Giovanni S4mo ago
No problem, just posting the pattern I arrived at in case others have a similar question now/in the future Ah right :facepalm: brain's been a little foggy
turbolent
turbolent4mo ago
no worries! no need for run-time type-based type checking and then force-casting, when the type value is constant (of: Type<@{B}>()). you can just use static types here and optional-binding (if let) makes it concise:
access(all) fun barFromA(a: @{A}): String {
var bar = ""
let aRef: &{A} = &a
if let b = aRef as? &{B} {
bar = b.bar()
}
destroy a
return bar
}
access(all) fun barFromA(a: @{A}): String {
var bar = ""
let aRef: &{A} = &a
if let b = aRef as? &{B} {
bar = b.bar()
}
destroy a
return bar
}
Giovanni S
Giovanni S4mo ago
Nice, much cleaner!