Skip to content

Commit

Permalink
Feat: Initialize Components Part, "Components How-To" (#145)
Browse files Browse the repository at this point in the history
* feat: Components How-To with simple `Switch` Component

* chore: remove `ch0*` prefix for improved modularity
  • Loading branch information
julio4 authored Dec 7, 2023
1 parent 629c6c0 commit 286b664
Show file tree
Hide file tree
Showing 208 changed files with 276 additions and 84 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ starknet.workspace = true
# openzeppelin.workspace = true

# If you want to use another Starknet By Example's listing, you can add it as a dependency like this:
# erc20 = { path = "../../ch00-getting-started/erc20" }
# erc20 = { path = "../../getting-started/erc20" }

[scripts]
test.workspace = true
Expand Down
4 changes: 4 additions & 0 deletions Scarb.lock
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ version = "0.1.0"
name = "calling_other_contracts"
version = "0.1.0"

[[package]]
name = "components"
version = "0.1.0"

[[package]]
name = "constant_product_amm"
version = "0.1.0"
Expand Down
6 changes: 3 additions & 3 deletions Scarb.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[workspace]
members = [
"listings/ch00-getting-started/*",
"listings/ch01-applications/*",
"listings/ch02-advanced-concepts/*",
"listings/getting-started/*",
"listings/applications/*",
"listings/advanced-concepts/*",
"listings/templates/*"
]

Expand Down
File renamed without changes.
11 changes: 11 additions & 0 deletions listings/applications/components/Scarb.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "components"
version.workspace = true

[dependencies]
starknet.workspace = true

[scripts]
test.workspace = true

[[target.starknet-contract]]
1 change: 1 addition & 0 deletions listings/applications/components/src/contracts.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod switch;
85 changes: 85 additions & 0 deletions listings/applications/components/src/contracts/switch.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// ANCHOR: contract
#[starknet::contract]
mod SwitchContract {
use components::switch::switch_component;
// This is needed to be able to use internal functions of the switch component.
use components::switch::switch_component::InternalSwitchImpl;

component!(path: switch_component, storage: switch, event: SwitchEvent);

#[abi(embed_v0)]
impl SwitchImpl = switch_component::Switch<ContractState>;
impl SwitchInternalImpl = switch_component::InternalSwitchImpl<ContractState>;

#[storage]
struct Storage {
#[substorage(v0)]
switch: switch_component::Storage,
}

#[constructor]
fn constructor(ref self: ContractState) {
self.switch._off();
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
SwitchEvent: switch_component::Event
}
}
// ANCHOR_END: contract

#[cfg(test)]
mod tests {
use components::switch::switch_component::InternalSwitchTrait;
use components::switch::ISwitchComponent;
use core::starknet::storage::StorageMemberAccessTrait;
use super::SwitchContract;

fn STATE() -> SwitchContract::ContractState {
SwitchContract::contract_state_for_testing()
}

#[test]
#[available_gas(2000000)]
fn test_init() {
let state = STATE();
assert(state.value() == false, 'The switch should be off');
}

#[test]
#[available_gas(2000000)]
fn test_switch() {
let mut state = STATE();

state.switch();
assert(state.value() == true, 'The switch should be on');

state.switch();
assert(state.value() == false, 'The switch should be off');
}

#[test]
#[available_gas(2000000)]
fn test_value() {
let mut state = STATE();
assert(state.value() == state.switch.value.read(), 'Wrong value');

state.switch.switch();
assert(state.value() == state.switch.value.read(), 'Wrong value');
}

#[test]
#[available_gas(2000000)]
fn test_internal_off() {
let mut state = STATE();

state.switch._off();
assert(state.value() == false, 'The switch should be off');

state.switch();
state.switch._off();
assert(state.value() == false, 'The switch should be off');
}
}
2 changes: 2 additions & 0 deletions listings/applications/components/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod contracts;
mod switch;
45 changes: 45 additions & 0 deletions listings/applications/components/src/switch.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#[starknet::interface]
trait ISwitchComponent<TContractState> {
fn value(self: @TContractState) -> bool;
fn switch(ref self: TContractState);
}

#[starknet::component]
mod switch_component {
#[storage]
struct Storage {
value: bool,
}

#[derive(Drop, starknet::Event)]
struct SwitchEvent {}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
SwitchEvent: SwitchEvent,
}

#[embeddable_as(Switch)]
impl SwitchImpl<
TContractState, +HasComponent<TContractState>
> of super::ISwitchComponent<ComponentState<TContractState>> {
fn value(self: @ComponentState<TContractState>) -> bool {
self.value.read()
}

fn switch(ref self: ComponentState<TContractState>) {
self.value.write(!self.value.read());
self.emit(Event::SwitchEvent(SwitchEvent {}));
}
}

#[generate_trait]
impl InternalSwitchImpl<
TContractState, +HasComponent<TContractState>
> of InternalSwitchTrait<TContractState> {
fn _off(ref self: ComponentState<TContractState>) {
self.value.write(false);
}
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions listings/getting-started/visibility/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target
4 changes: 2 additions & 2 deletions scripts/cairo_programs_verifier.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ error_file=$(mktemp)
# function to list modified listings
list_modified_listings() {
git diff --diff-filter=AM --name-only upstream/main -- listings | \
grep -E 'listings/ch.*/*' | \
grep -E 'listings/*/*' | \
cut -d '/' -f 2-3 | sort -u
}

list_all_listings() {
ls -d listings/ch*/* | grep -E 'listings/ch.*/*' | cut -d '/' -f 2-3
ls -d listings/*/* | grep -E 'listings/*/*' | cut -d '/' -f 2-3
}

# function to process listing
Expand Down
5 changes: 4 additions & 1 deletion src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,11 @@ Summary
- [Struct](./ch00/cairo_cheatsheet/struct.md)
- [Type casting](./ch00/cairo_cheatsheet/type_casting.md)

# Components
- [Components How-To](./components/how_to.md)

<!-- ch01 -->
# Applications examples
# Applications
- [Upgradeable Contract](./ch01/upgradeable_contract.md)
- [Defi Vault](./ch01/simple_vault.md)
- [ERC20 Token](./ch01/erc20.md)
Expand Down
4 changes: 2 additions & 2 deletions src/ch00/basics/constructor.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ Constructors are a special type of function that runs only once when deploying a
Here's a simple example that demonstrates how to initialize the state of a contract on deployment by defining logic inside a constructor.

```rust
{{#include ../../../listings/ch00-getting-started/constructor/src/constructor.cairo}}
{{#include ../../../listings/getting-started/constructor/src/constructor.cairo}}
```
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x017fd6558e67451dA583d123D77F4e2651E91502D08F8F8432355293b11e1f8F) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/constructor/src/constructor.cairo).
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x017fd6558e67451dA583d123D77F4e2651E91502D08F8F8432355293b11e1f8F) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/getting-started/constructor/src/constructor.cairo).
4 changes: 2 additions & 2 deletions src/ch00/basics/counter.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ Here's how it works:
- When a user calls 'decrement', the contract decrements the counter by 1.

```rust
{{#include ../../../listings/ch00-getting-started/counter/src/contracts.cairo}}
{{#include ../../../listings/getting-started/counter/src/contracts.cairo}}
```
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x01664a69Fe701a1df7Bb0ae4A353792d0cf4E27146ee860075cbf6108b1D5718) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/counter/src/contracts.cairo).
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x01664a69Fe701a1df7Bb0ae4A353792d0cf4E27146ee860075cbf6108b1D5718) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/getting-started/counter/src/contracts.cairo).
4 changes: 2 additions & 2 deletions src/ch00/basics/custom-types-in-entrypoints.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Using custom types in entrypoints requires our type to implement the `Serde` tra
Thankfully, we can just derive the `Serde` trait for our custom type.

```rust
{{#include ../../../listings/ch00-getting-started/custom_type_serde/src/contract.cairo}}
{{#include ../../../listings/getting-started/custom_type_serde/src/contract.cairo}}
```

Play with this contract in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/custom_type_serde/src/contract.cairo).
Play with this contract in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/getting-started/custom_type_serde/src/contract.cairo).
12 changes: 6 additions & 6 deletions src/ch00/basics/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,24 @@ To throw an error, use the `assert` or `panic` functions:
Here's a simple example that demonstrates the use of these functions:

```rust
{{#include ../../../listings/ch00-getting-started/errors/src/simple_errors.cairo}}
{{#include ../../../listings/getting-started/errors/src/simple_errors.cairo}}
```
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x0022664463FF0b711CC9B549a9E87d65A0882bB1D29338C4108696B8F2216a40) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/errors/src/simple_errors.cairo).
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x0022664463FF0b711CC9B549a9E87d65A0882bB1D29338C4108696B8F2216a40) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/getting-started/errors/src/simple_errors.cairo).

## Custom errors

You can make error handling easier by defining your error codes in a specific module.

```rust
{{#include ../../../listings/ch00-getting-started/errors/src/custom_errors.cairo}}
{{#include ../../../listings/getting-started/errors/src/custom_errors.cairo}}
```
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x0501CD5da5B453a18515B5A20b8029bd7583DFE7a399ad9f79c284F7829e4A57) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/errors/src/custom_errors.cairo).
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x0501CD5da5B453a18515B5A20b8029bd7583DFE7a399ad9f79c284F7829e4A57) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/getting-started/errors/src/custom_errors.cairo).

## Vault example

Here's another example that demonstrates the use of errors in a more complex contract:

```rust
{{#include ../../../listings/ch00-getting-started/errors/src/vault_errors.cairo}}
{{#include ../../../listings/getting-started/errors/src/vault_errors.cairo}}
```
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x020C2da26F42A28Ef54ED428eF1810FE433784b055f9bF315C5d992b1579C268) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/errors/src/vault_errors.cairo).
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x020C2da26F42A28Ef54ED428eF1810FE433784b055f9bF315C5d992b1579C268) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/getting-started/errors/src/vault_errors.cairo).
4 changes: 2 additions & 2 deletions src/ch00/basics/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ An event is defined as struct that derives the `#[starknet::Event]` trait. The f
Here's a simple example of a contract using events that emit an event each time a counter is incremented by the "increment" function:

```rust
{{#include ../../../listings/ch00-getting-started/events/src/counter.cairo}}
{{#include ../../../listings/getting-started/events/src/counter.cairo}}
```
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x022e3B59518EA04aBb5da671ea04ecC3a154400f226d2Df38eFE146741b9E2F6) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/events/src/counter.cairo).
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x022e3B59518EA04aBb5da671ea04ecC3a154400f226d2Df38eFE146741b9E2F6) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/getting-started/events/src/counter.cairo).
4 changes: 2 additions & 2 deletions src/ch00/basics/mappings.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ Some additional notes:
- In mappings, the address of the value at key `k_1,...,k_n` is `h(...h(h(sn_keccak(variable_name),k_1),k_2),...,k_n)` where `` is the Pedersen hash and the final value is taken `mod2251−256`. You can learn more about the contract storage layout in the [Starknet Documentation](https://docs.starknet.io/documentation/architecture_and_concepts/Contracts/contract-storage/#storage_variables)

```rust
{{#include ../../../listings/ch00-getting-started/mappings/src/mappings.cairo}}
{{#include ../../../listings/getting-started/mappings/src/mappings.cairo}}
```
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x06214AB4c23Cc545bf2221D465eB83aFb7412779AD498BD48a724B3F645E3505) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/mappings/src/mappings.cairo).
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x06214AB4c23Cc545bf2221D465eB83aFb7412779AD498BD48a724B3F645E3505) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/getting-started/mappings/src/mappings.cairo).
4 changes: 2 additions & 2 deletions src/ch00/basics/storage.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
Here's the most minimal contract you can write in Cairo:

```rust
{{#include ../../../listings/ch00-getting-started/storage/src/minimal_contract.cairo}}
{{#include ../../../listings/getting-started/storage/src/minimal_contract.cairo}}
```

Storage is a struct annoted with `#[storage]`. Every contract must have one and only one storage.
It's a key-value store, where each key will be mapped to a storage address of the contract's storage space.

You can define [storage variables](./variables.md#storage-variables) in your contract, and then use them to store and retrieve data.
```rust
{{#include ../../../listings/ch00-getting-started/storage/src/contract.cairo}}
{{#include ../../../listings/getting-started/storage/src/contract.cairo}}
```

> Actually these two contracts have the same underlying sierra program.
Expand Down
4 changes: 2 additions & 2 deletions src/ch00/basics/storing-custom-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
While native types can be stored in a contract's storage without any additional work, custom types require a bit more work. This is because at compile time, the compiler does not know how to store custom types in storage. To solve this, we need to implement the `Store` trait for our custom type. Hopefully, we can just derive this trait for our custom type - unless it contains arrays or dictionaries.

```rust
{{#include ../../../listings/ch00-getting-started/storing_custom_types/src/contract.cairo}}
{{#include ../../../listings/getting-started/storing_custom_types/src/contract.cairo}}
```

Play with this contract in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/storing_custom_types/src/contract.cairo).
Play with this contract in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/getting-started/storing_custom_types/src/contract.cairo).
12 changes: 6 additions & 6 deletions src/ch00/basics/variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ Local variables are stored in memory and are not stored on the blockchain. This
Here's a simple example of a contract with only local variables:

```rust
{{#include ../../../listings/ch00-getting-started/variables/src/local_variables.cairo}}
{{#include ../../../listings/getting-started/variables/src/local_variables.cairo}}
```
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x015B3a10F9689BeD741Ca3C210017BC097122CeF76f3cAA191A20ff8b9b56b96) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/variables/src/local_variables.cairo).
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x015B3a10F9689BeD741Ca3C210017BC097122CeF76f3cAA191A20ff8b9b56b96) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/getting-started/variables/src/local_variables.cairo).

## Storage Variables

Expand All @@ -36,9 +36,9 @@ On the other hand, you can read state variables, for free, without any transacti
Here's a simple example of a contract with one storage variable:

```rust
{{#include ../../../listings/ch00-getting-started/variables/src/storage_variables.cairo}}
{{#include ../../../listings/getting-started/variables/src/storage_variables.cairo}}
```
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x06eA827B32875483709b785A7F9e846a52776Cd8D42C3fE696218c2624b0DCCa) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/variables/src/storage_variables.cairo).
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x06eA827B32875483709b785A7F9e846a52776Cd8D42C3fE696218c2624b0DCCa) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/getting-started/variables/src/storage_variables.cairo).

## Global Variables

Expand All @@ -49,6 +49,6 @@ In Starknet, you can access global variables by using specific functions contain
For example, the `get_caller_address` function returns the address of the caller of the current transaction, and the `get_contract_address` function returns the address of the current contract.

```rust
{{#include ../../../listings/ch00-getting-started/variables/src/global_variables.cairo}}
{{#include ../../../listings/getting-started/variables/src/global_variables.cairo}}
```
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x05bD2F3943bd4e030f85678b55b2EC2C1be939e32388530FB20ED967B3Be433F) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/variables/src/global_variables.cairo).
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x05bD2F3943bd4e030f85678b55b2EC2C1be939e32388530FB20ED967B3Be433F) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/getting-started/variables/src/global_variables.cairo).
4 changes: 2 additions & 2 deletions src/ch00/basics/visibility-mutability.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ Internal functions can't be called externally, but the same principle applies re
Let's take a look at a simple example contract to see these in action:

```rust
{{#include ../../../listings/ch00-getting-started/visibility/src/visibility.cairo}}
{{#include ../../../listings/getting-started/visibility/src/visibility.cairo}}
```
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x0071dE3093AB58053b0292C225aa0eED40293e7694A0042685FF6D813d39889F) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/visibility/src/visibility.cairo).
Visit contract on [Voyager](https://goerli.voyager.online/contract/0x0071dE3093AB58053b0292C225aa0eED40293e7694A0042685FF6D813d39889F) or play with it in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/getting-started/visibility/src/visibility.cairo).
2 changes: 1 addition & 1 deletion src/ch00/cairo_cheatsheet/arrays.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ trait ArrayTrait<T> {
For example:

```rust
{{#include ../../../listings/ch00-getting-started/cairo_cheatsheet/src/array_example.cairo}}
{{#include ../../../listings/getting-started/cairo_cheatsheet/src/array_example.cairo}}
```
Loading

0 comments on commit 286b664

Please sign in to comment.