Summary of "Re{solve} Hackathon Workshop: Starknet Smart Contracts"
Summary of "Re{solve} Hackathon Workshop: Starknet Smart Contracts"
This workshop provides a practical introduction to building and testing smart contracts on Starknet using the Cairo programming language and the Starknet Foundry toolset. It is part of a hackathon series organized by the Starknet Foundation.
Key Technological Concepts and Tools Covered
- Cairo Language for Starknet
- Starknet Development Environment Setup
- Project Initialization and Configuration
- Smart Contract Structure in Cairo
- A contract is a module annotated with the
#[contract]attribute. - Storage is defined as a
structannotated with#[storage]. - A constructor function initializes storage variables and is annotated with
#[constructor]. - Traits define the public interface of the contract, annotated with
#[contract_interface]. - The trait is implemented for the contract with an implementation block annotated with
#[impl_contract](versioned asv0for future-proofing). - Reading and writing to storage uses traits like
StorageReadandStorageWrite.
- A contract is a module annotated with the
- Example: Counter Smart Contract
- Storage holds a single
u32counter variable. - Constructor initializes the counter with a passed initial value.
- Interface exposes a
get_counter()method to read the counter. - Implementation reads from storage and returns the counter value.
- Storage holds a single
- Testing with Starknet Foundry (
smforge)- Tests are defined as functions annotated with
#[test]. - Common test setup involves declaring the contract and deploying it to a local devnet.
- Deployment requires serialized constructor arguments passed as an array of felts.
- Tests verify constructor initialization, increment and decrement functions, and error handling.
- Tests are defined as functions annotated with
- Increment and Decrement Functions
increase_counterincrements the stored counter by 1.decrease_counterdecrements the counter but includes:- A check to prevent underflow (counter cannot go below zero).
- Ownership restriction: only the contract owner can call
decrease_counter.
- Ownership and Access Control
- Owner address stored in contract storage.
- Ownership is checked by comparing the caller address (retrieved via
get_caller_address()) with the stored owner. - If the caller is not the owner, the contract reverts with an error.
- Testing ownership uses Foundry’s cheat codes to mock the caller address, allowing tests to simulate calls from owner and non-owner accounts.
- Error Handling and Assertions
- Use of
assertstatements to enforce conditions and revert transactions with error messages. - Tests include scenarios that expect panics (reverts) with specific error messages to verify correct error handling.
- Use of
- Best Practices and Advanced Notes
- Emphasis on modular design: separating storage, interface, implementation.
- Use of traits and generics for flexibility and compile-time safety.
- Encouragement to reuse audited components (e.g., ownership modules from OpenZeppelin’s Cairo smart contracts) rather than implementing access control manually.
- Reference to OpenZeppelin components for secure, tested smart contract features.
Summary of Workshop Flow
- Installation and setup of Starknet development environment using Starkup and asdf.
- Creating a new Cairo smart contract project with smforge.
- Writing a simple counter contract with storage, constructor, and getter method.
- Compiling the contract to verify correctness.
- Writing and running unit tests for contract initialization and reading storage.
- Adding increment and decrement functions with proper storage mutation.
- Implementing ownership logic and access control on decrement function.
- Using Foundry cheat codes to mock caller addresses in tests to validate access control.
Category
Technology