Skip to content

Instantly share code, notes, and snippets.

@chasefleming
Last active December 14, 2023 14:49
Show Gist options
  • Save chasefleming/0d5e21606cf8c9a3d5584a0625544c29 to your computer and use it in GitHub Desktop.
Save chasefleming/0d5e21606cf8c9a3d5584a0625544c29 to your computer and use it in GitHub Desktop.
Cadence Cheatsheet
// Cadence is a resource-oriented programming language for smart contracts on the Flow blockchain.
///////////////
// 1. Basics //
///////////////
// This is a single-line comment
/*
This is a multi-line comment
*/
// Declare a constant
let x: Int = 42
// Declare a variable
var y: Int = 5
y = 10 // Re-assign the variable
// Strings
let hello: String = "Hello, World!"
// Arrays
let numbers: [Int] = [1, 2, 3, 4, 5]
// Dictionaries
let fruits: {String: Int} = {"apple": 5, "banana": 8}
// Optionals: Cadence supports optionals, which can either hold a value or be nil.
var maybeInt: Int? = nil
maybeInt = 42
// To safely access the value inside an optional, you can use conditional unwrapping:
if let actualInt = maybeInt {
log(actualInt) // This will log the value 42
}
////////////////////////
// 2. Functions & Types//
////////////////////////
// Define a function
pub fun add(a: Int, b: Int): Int {
return a + b
}
// Structs
pub struct Point {
pub var x: Int
pub var y: Int
init(x: Int, y: Int) {
self.x = x
self.y = y
}
}
// Enums
pub enum Direction: UInt8 {
pub case north
pub case south
pub case east
pub case west
}
////////////////////////
// 3. Resources & Contracts //
////////////////////////
// Resources are a special type in Cadence, representing a unique value.
// They have to be carefully managed, as they can only exist in one place at a time.
// The purpose of resources is to represent a unique ownable asset, such as an NFT.
pub resource R {
pub var n: Int
init(n: Int) {
self.n = n
}
}
// Contracts are the top-level declarations in Cadence.
// They can declare multiple types, resources, and functions, as well as storing value.
// They are like digital programs that can be deployed and executed by anyone on the Flow blockchain.
pub contract C {
pub var count: Int
init() {
self.count = 0
}
pub fun increment() {
self.count = self.count + 1
}
}
////////////////////////
// 4. Scripts //
////////////////////////
// Scripts are submited to the network to read the state of the blockchain.
// They can be executed by anyone, but they cannot mutate the global state.
pub fun main(a: Int, b: Int): Int {
// This is where the main logic of the script goes
}
////////////////////////
// 5. Transactions //
////////////////////////
// Transactions are submitted to the network to mutate state.
// Signer is an account that authorizes this transaction and allows it to modify its account assets.
import Foo from 0xABC123
transaction(a: Int, b: Int) {
prepare(signer: AuthAccount) {
// This is where resources can be withdrawn from accounts
}
execute {
// This is where the main logic of the transaction goes
Foo.bar(a, b) // This calls a function on another contract
}
}
////////////////////////
// 6. Events //
////////////////////////
// Events allow smart contracts to log information about changes in their state.
pub event NewValueSet(value: Int)
////////////////////////
// 7. Capabilities //
////////////////////////
// A contract or a resource can have an interface that declares a certain set of functions.
pub resource interface Readable {
pub fun read(): Int
}
// A contract or resource that wants to be "Readable" must conform to this interface.
pub resource ReadableResource: Readable {
pub var data: Int
init(initData: Int) {
self.data = initData
}
pub fun read(): Int {
return self.data
}
}
// In Cadence, accounts have storage that is organized through paths.
// There are three types of paths: storage, private, and public.
// - /storage/ : Used to store and manage values, particularly resources.
// - /private/ : Used to store private capabilities.
// - /public/ : Used to store public capabilities.
// In a real-world scenario, you'd typically have an account that stores an instance of `ReadableResource` in storage.
// Then, it can publish a capability that allows others to borrow a reference to that instance with the restrictions
// imposed by the `Readable` interface. This way, other accounts can only invoke the methods allowed by the interface, not all methods on the resource.
// Store a resource in an account's storage
account.save(<- create ReadableResource(initData: 10), to: /storage/MyResource)
// Link a public capability so others can borrow a reference (note: in this example `Test` is the name of the contract)
account.link<&Test.ReadableResource{Test.Readable}>(/public/Readable, target: /storage/MyResource)
// An external account can then borrow a reference using the capability:
// (note: "getAccount" is a Cadence function that returns an account by address)
let publicAccount = getAccount(address)
let readerRef: &{Test.Readable}? = publicAccount.getCapability(/public/Readable).borrow<&{Test.Readable}>()
if let ref = readerRef {
let value = ref.read()
}
@10thfloor
Copy link

10thfloor commented Aug 29, 2023

Can I store a borrowed capability in my account?
Can I allow other accounts to use a capability my account has borrowed?
What is the pattern for revoking a capability?

@raven-kus
Copy link

Please add it to learnxinyminutes.com =)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment