Last release today
02 Sep 2026
Ships on a steady schedule
a new release about every 2 weeks
Nearly every release is documented
notes for 60 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
6 years old
7565 releases · first in 2020
One column per quarter.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
This update mainly focuses on improving safety and consistency in Cadence. As part of this effort, several changes have been introduced to prevent accidental foot-guns by users.
filter and map array-functionsA breaking change was introduced for filter and map to make them consistent with for-in loops and indexed array access.
If filter or map is used on an array reference whose element type is itself a container type (e.g. struct, resource, array, or dictionary), then the callback parameter must now also be a reference type.
For example, assume S is a struct type and arrayRef is a reference to an array of S structs as shown below.
access(all) struct S {}
var array: [S] = [S()]
var arrayRef: &[S] = &arrayThen, previously, using the filter function on this array-reference required a callback of type fun(S): Bool:
var filteredArray = arrayRef.filter(
// Note the parameter type used to be `S`
view fun(element: S): Bool {
return true
},
)From this release onwards, the filter method was changed to require a callback of type fun(&S): Bool:
var filteredArray = arrayRef.filter(
// Note the parameter type is now a reference type `&S`
view fun(element: &S): Bool {
return true
},
)Similarly, for map method, the callback that needs to be passed-in must have a reference type (&S) parameter.
var mappedArray = arrayRef.map(
// Note the parameter type is now a reference type `&S`
view fun(element: &S): Int {
return 1
},
)AnyStructPreviously, authorized references retained their entitlements when upcast to AnyStruct.
var authRef: auth(E) &T = ...
// Assign to `AnyStruct`
var any: AnyStruct = authRef
// Can get the auth-ref back by down-casting
var downCastedAuthRef = any as! auth(E) &THowever, this behaviour was inconsistent with normal reference upcasting, where entitlements are stripped to match the target type.
This inconsistency could lead developers to incorrectly assume that upcasting to AnyStruct also strips entitlements.
From this release onward, upcasting to AnyStruct behaves the same as other reference upcasts and strips entitlements during the cast.
var authRef: auth(E) &T = ...
// Assign to `AnyStruct`
var any: AnyStruct = authRef
// This would panic at runtime, since the entitlements were stripped during the up-cast in the previous step.
var downCastedAuthRef = any as! auth(E) &TPreviously, when an interface default function also defines conditions, and the concrete type overrides the default function as shown below, then the conditions also get overridden.
resource interface Receiver {
// Default function also defines a condition.
fun log(_ message: String) {
pre{ message != "" }
log(message.append("from Receiver"))
}
}
resource Vault: Receiver {}
// `log` function is overridden.
// This also overrides the condition (i.e: ignores conditions from `Receiver` interface).
fun log(_ message: String) {
log(message)
}
}This has been a foot-gun because the author of the interface might not be aware that the conditions are getting ignored/overridden too.
Therefore, to avoid that, the behaviour was changed such that the conditions are always run, regardless of whether the concrete type implements/override the default implementation or not.
resource Vault: Receiver {}
// `log` function is overridden.
// However, the conditions won't get overridden.
// The condition defined on the interface would still be applicable.
fun log(_ message: String) {
log(message)
}
}When a nested authorized reference is accessed via an unauthorized reference (e.g: an array reference of type &[auth(E) &T] and then accessing the element refs[0]), the inner authorized reference auth(E) &T was returned as is. However, this behaviour was not well defined in the member-access semantics proposal FLIP 89, and was not very intuitive, leaving potential of accidental foot-guns.
var arrayRef: &[auth(E) &T] = ...
// The resulting type used to be the entitled-type `auth(E) &T`
var element: auth(E) &T = arrayRef[0]Therefore, this was changed such that the result's authorization would now be the intersection of the outer (container) reference's authorization and the inner (element) reference's authorization.
var arrayRef: &[auth(E) &T] = ...
// The resulting type now is the un-entitled type `&T`
var element: &T = arrayRef[0]The intersection is computed as follows:
| Container Type | Old Result | New Result |
|---|---|---|
auth(E) &[&T] |
&T |
&T (no change — inner is already unauthorized) |
&[auth(E) &T] |
auth(E) &T |
&T (outer unauthorized strips inner) |
auth(E) &[auth(E) &T] |
auth(E) &T |
auth(E) &T (no change — intersection preserves matching auth) |
auth(E,F) &[auth(F,G) &T] |
auth(F,G) &T |
auth(F) &T (only F is in both) |
auth(E) &[auth(F) &T] |
auth(F) &T |
&T (E and F are disjoint, empty intersection) |
For dictionaries, the same rules apply, e.g., auth(E) &{String: auth(E) &T} gives (auth(E) &T)?. Unauthorized outer strips inner auth, same as arrays.
The outer authorization for intersection is the raw outer reference's authorization (not mapped, since access(mapping M) fields cannot have reference types).
| Container Type | Old Result | New Result |
|---|---|---|
&S with field let x: auth(E) &T |
auth(E) &T |
&T (outer unauthorized strips inner) |
auth(E) &S with field let x: auth(E) &T |
auth(E) &T |
auth(E) &T (matching auth preserved) |
auth(E,F) &S with field let x: auth(F,G) &T |
auth(F,G) &T |
auth(F) &T (partial intersection) |
auth(E) &S with field let x: auth(F) &T |
auth(F) &T |
&T (disjoint, empty intersection) |
release/v1.10.2 to master by @github-actions[bot] in #4467Full Changelog: v1.10.2...v1.10.3
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
StringBuilder type which allows constructing strings efficiently by @turbolent in #4453guard statement by @turbolent in #4432freezeTime and unfreezeTime to Test stdlib Blockchain interface by @holyfuchs in #4466release/v1.10.1 to master by @github-actions[bot] in #4462Full Changelog: v1.10.1...v1.10.2
Nothing published for this version
Nothing published for this version