Canister smart contracts
Smart contracts on the Internet Computer come in the form of canisters: computational units that bundle together code and state. Each canister defines functions that can be called by other canisters and parties external to the IC, such as browsers or mobile apps. There are two types of endpoints in canisters: updates and queries. Updates modify the state of the canister, while queries read from the state without making changes. The code of a canister is a WebAssembly (Wasm) module. The state includes the usual Wasm memory heap, a special type of memory called stable memory and metainformation about the canister.
What are canisters
On the Internet Computer, smart contracts come in the form of canisters. These are computational units that bundle together code and state. Canisters expose endpoints that can be called both by other canisters and by external parties, such as browsers or mobile apps. Updates are calls that can modify the state of the canisters, while queries are calls that cannot modify the state. A good mental model for these is that updates are used to write to the state of a canister, and queries are used to read from that state.
How canisters work
Canisters behave much like actors from the actor-based concurrency model. Their code is single-threaded and executed in complete isolation from other canisters. Canisters communicate with one another via asynchronous messaging. When processing a message, a canister can make changes to its state, send messages to other canisters, or even create other canisters. Unlike in the traditional actor model, communication is bidirectional. Canister messages are either requests or replies. For each request sent, the Internet Computer records a callback to be invoked when the callee sends back a response. If the Internet Computer determines that there is no way for the callee to respond, then it will produce a response instead, thereby ensuring that every request receives a reply.
An important aspect of the canister-based model is how canisters handle errors during message processing. When a canister processes a request, it might send out other requests and wait for some of these replies before completing the original request. If an error occurs (the canister “traps”), the canister’s state reverts to what it was right after its last outgoing message.
Resource charging
As they execute, canisters use resources in the form of memory, computation, and network bandwidth. On the Internet Computer, all of these are paid for using a unit called cycles. Each canister maintains a local cycle account from which cycles are deducted as execution proceeds.
- Memory Usage: Charging for memory usage is straightforward. The protocol keeps track of the memory used by the canister and regularly charges the canister’s balance. This charging happens at regular intervals but not every round.
- Computation: Charging for computation occurs at the time the computation is performed. The canisters are instrumented with code that allows the Internet Computer to count the number of instructions executed while processing a message. There is an upper bound on the number of instructions that can be executed during a round. If this limit is exceeded, execution is paused and continued in a subsequent round, but cycles for the computation performed during any round are charged at the end of that round.
- Bandwidth: Charging for bandwidth occurs when a canister sends a message to another canister. The protocol calculates the number of cycles required for the outgoing call, which includes a fixed cost and a variable cost based on the payload size. Additionally, the protocol deducts the cost of sending a maximum-size reply from the callee, as the caller pays for the reply. If the actual reply size is smaller, the difference in cycles is refunded to the canister when the reply arrives.
Canisters have a freezing threshold to prevent sudden deletion when they run out of cycles. When a canister’s balance falls below this threshold, it stops processing new requests but continues handling replies. If a canister runs out of cycles completely, it is uninstalled, deleting its code and state but retaining other associated information.
Canister management
Canisters are managed by controllers, which can be users or other canisters. Controllers are responsible for deploying, maintaining, and managing canisters. They can perform operations such as starting, stopping, and updating the canister, as well as adjusting canister parameters like the freezing threshold. The control structure can be centralized (e.g., when the controllers include a centralized entity), decentralized (e.g., when the controller is a DAO), or non-existent, resulting in an immutable smart contract.
Controllers can update the code that runs on canisters by submitting a new Wasm module to replace the older one. By default, updating the Wasm module of a canister wipes out the Wasm memory, but the content of the stable memory remains unchanged. The Internet Computer offers an upgrade mechanism where three actions are executed atomically: serializing the Wasm memory of the canister and writing it to stable memory, installing the new Wasm code, and then deserializing the content of the stable memory. This allows for the Wasm heap memory to be kept even if the Wasm module changes. Of course, a canister may ensure at all times that the data that needs to be persisted across upgrades is stored in the stable memory, in which case the upgrade process is significantly simpler.
Learn more about creating, installing, upgrading, and managing canister smart contracts on the Internet Computer in this detailed video.