Skip to content

Commit 2b4183d

Browse files
JoshDFNJosh
andauthored
Fix 4 verified skill content bugs from issue #1 (#2)
- Add [package] + [lib] crate-type=["cdylib"] to 6 Rust Cargo.toml examples - Fix II Rust backend: StableCell for OWNER instead of thread_local! heap - Fix SNS token math: governance 5.2M → 5M to match 10M total - Standardize ic-stable-structures to 0.7 across all skills Co-authored-by: Josh <josh@Joshs-MacBook-Pro.local>
1 parent 802cd98 commit 2b4183d

10 files changed

Lines changed: 129 additions & 21 deletions

File tree

public/llms-full.txt

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2559,6 +2559,14 @@ persistent actor {
25592559

25602560
```toml
25612561
# Cargo.toml
2562+
[package]
2563+
name = "https_outcalls_backend"
2564+
version = "0.1.0"
2565+
edition = "2021"
2566+
2567+
[lib]
2568+
crate-type = ["cdylib"]
2569+
25622570
[dependencies]
25632571
ic-cdk = "0.18"
25642572
candid = "0.10"
@@ -3055,6 +3063,14 @@ persistent actor {
30553063
#### Cargo.toml Dependencies
30563064

30573065
```toml
3066+
[package]
3067+
name = "icrc_ledger_backend"
3068+
version = "0.1.0"
3069+
edition = "2021"
3070+
3071+
[lib]
3072+
crate-type = ["cdylib"]
3073+
30583074
[dependencies]
30593075
ic-cdk = "0.18"
30603076
candid = "0.10"
@@ -3387,6 +3403,8 @@ Internet Identity (II) is the Internet Computer's native authentication system.
33873403

33883404
7. **Not calling `agent.fetchRootKey()` in local development.** Without this, certificate verification fails on localhost. Never call it in production -- it's a security risk on mainnet.
33893405

3406+
8. **Storing auth state in `thread_local!` without stable storage (Rust)** -- `thread_local! { RefCell<T> }` is heap memory, wiped on every canister upgrade. Use `StableCell` from `ic-stable-structures` for any state that must persist across upgrades, especially ownership/auth data.
3407+
33903408
## Implementation
33913409

33923410
### icp.json Configuration
@@ -3566,19 +3584,31 @@ persistent actor {
35663584

35673585
```toml
35683586
# Cargo.toml
3587+
[package]
3588+
name = "ii_backend"
3589+
version = "0.1.0"
3590+
edition = "2021"
3591+
3592+
[lib]
3593+
crate-type = ["cdylib"]
3594+
35693595
[dependencies]
35703596
ic-cdk = "0.18"
35713597
candid = "0.10"
35723598
serde = { version = "1", features = ["derive"] }
3599+
ic-stable-structures = "0.7"
35733600
```
35743601

35753602
```rust
35763603
use candid::Principal;
35773604
use ic_cdk::{caller, query, update};
3605+
use ic_stable_structures::{DefaultMemoryImpl, StableCell};
35783606
use std::cell::RefCell;
35793607

35803608
thread_local! {
3581-
static OWNER: RefCell<Option<Principal>> = RefCell::new(None);
3609+
static OWNER: RefCell<StableCell<Option<Principal>, DefaultMemoryImpl>> = RefCell::new(
3610+
StableCell::init(DefaultMemoryImpl::default(), None).unwrap()
3611+
);
35823612
}
35833613

35843614
/// Reject anonymous principal. Call this at the top of every protected endpoint.
@@ -3597,10 +3627,10 @@ fn init_owner() -> String {
35973627
let caller = require_auth();
35983628

35993629
OWNER.with(|owner| {
3600-
let mut owner = owner.borrow_mut();
3601-
match *owner {
3630+
let mut cell = owner.borrow_mut();
3631+
match cell.get() {
36023632
None => {
3603-
*owner = Some(caller);
3633+
cell.set(Some(caller)).unwrap();
36043634
format!("Owner set to {}", caller)
36053635
}
36063636
Some(_) => "Owner already initialized".to_string(),
@@ -3613,8 +3643,8 @@ fn admin_action() -> String {
36133643
let caller = require_auth();
36143644

36153645
OWNER.with(|owner| {
3616-
let owner = owner.borrow();
3617-
match *owner {
3646+
let cell = owner.borrow();
3647+
match cell.get() {
36183648
Some(o) if o == caller => "Admin action performed".to_string(),
36193649
Some(_) => ic_cdk::trap("Only the owner can call this function."),
36203650
None => ic_cdk::trap("Owner not set. Call init_owner first."),
@@ -4089,7 +4119,7 @@ crate-type = ["cdylib"]
40894119
ic-cdk = "0.18"
40904120
candid = "0.10"
40914121
serde = { version = "1", features = ["derive"] }
4092-
ic-stable-structures = "0.6"
4122+
ic-stable-structures = "0.7"
40934123
```
40944124

40954125
#### src/user_service/src/lib.rs
@@ -4198,7 +4228,7 @@ crate-type = ["cdylib"]
41984228
ic-cdk = "0.18"
41994229
candid = "0.10"
42004230
serde = { version = "1", features = ["derive"] }
4201-
ic-stable-structures = "0.6"
4231+
ic-stable-structures = "0.7"
42024232
```
42034233

42044234
#### src/content_service/src/lib.rs
@@ -4830,7 +4860,7 @@ Distribution:
48304860
vesting_period: 31_557_600 # seconds (12 months)
48314861

48324862
InitialBalances:
4833-
governance: 520_000_000_000_000 # e8s (5_200_000 tokens) — Treasury (controlled by DAO)
4863+
governance: 500_000_000_000_000 # e8s (5_000_000 tokens) — Treasury (controlled by DAO)
48344864
swap: 250_000_000_000_000 # e8s (2_500_000 tokens) — Sold during decentralization swap
48354865

48364866
total: 1_000_000_000_000_000 # e8s (10_000_000 tokens) — Must equal sum of all allocations
@@ -5213,6 +5243,14 @@ Rust canisters use `ic-stable-structures` for persistent storage. The `MemoryMan
52135243
#### Cargo.toml
52145244

52155245
```toml
5246+
[package]
5247+
name = "stable_memory_backend"
5248+
version = "0.1.0"
5249+
edition = "2021"
5250+
5251+
[lib]
5252+
crate-type = ["cdylib"]
5253+
52165254
[dependencies]
52175255
ic-cdk = "0.18"
52185256
ic-stable-structures = "0.7"
@@ -5570,6 +5608,14 @@ vetkd_derive_key : (record {
55705608
**Cargo.toml:**
55715609

55725610
```toml
5611+
[package]
5612+
name = "vetkd_backend"
5613+
version = "0.1.0"
5614+
edition = "2021"
5615+
5616+
[lib]
5617+
crate-type = ["cdylib"]
5618+
55735619
[dependencies]
55745620
candid = "0.10"
55755621
ic-cdk = "0.18"
@@ -6052,6 +6098,14 @@ persistent actor {
60526098
#### Cargo.toml Dependencies
60536099

60546100
```toml
6101+
[package]
6102+
name = "wallet_backend"
6103+
version = "0.1.0"
6104+
edition = "2021"
6105+
6106+
[lib]
6107+
crate-type = ["cdylib"]
6108+
60556109
[dependencies]
60566110
ic-cdk = "0.18"
60576111
candid = "0.10"

public/sitemap.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
33
<url>
44
<loc>https://dfinity.github.io/icskills/</loc>
5-
<lastmod>2026-02-25</lastmod>
5+
<lastmod>2026-02-26</lastmod>
66
<changefreq>weekly</changefreq>
77
<priority>1.0</priority>
88
</url>
@@ -80,13 +80,13 @@
8080
</url>
8181
<url>
8282
<loc>https://dfinity.github.io/icskills/llms.txt</loc>
83-
<lastmod>2026-02-25</lastmod>
83+
<lastmod>2026-02-26</lastmod>
8484
<changefreq>weekly</changefreq>
8585
<priority>0.8</priority>
8686
</url>
8787
<url>
8888
<loc>https://dfinity.github.io/icskills/llms-full.txt</loc>
89-
<lastmod>2026-02-25</lastmod>
89+
<lastmod>2026-02-26</lastmod>
9090
<changefreq>weekly</changefreq>
9191
<priority>0.8</priority>
9292
</url>

skills/https-outcalls/SKILL.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,14 @@ persistent actor {
187187

188188
```toml
189189
# Cargo.toml
190+
[package]
191+
name = "https_outcalls_backend"
192+
version = "0.1.0"
193+
edition = "2021"
194+
195+
[lib]
196+
crate-type = ["cdylib"]
197+
190198
[dependencies]
191199
ic-cdk = "0.18"
192200
candid = "0.10"

skills/icrc-ledger/SKILL.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,14 @@ persistent actor {
234234
#### Cargo.toml Dependencies
235235

236236
```toml
237+
[package]
238+
name = "icrc_ledger_backend"
239+
version = "0.1.0"
240+
edition = "2021"
241+
242+
[lib]
243+
crate-type = ["cdylib"]
244+
237245
[dependencies]
238246
ic-cdk = "0.18"
239247
candid = "0.10"

skills/internet-identity/SKILL.md

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ Internet Identity (II) is the Internet Computer's native authentication system.
4848

4949
7. **Not calling `agent.fetchRootKey()` in local development.** Without this, certificate verification fails on localhost. Never call it in production -- it's a security risk on mainnet.
5050

51+
8. **Storing auth state in `thread_local!` without stable storage (Rust)** -- `thread_local! { RefCell<T> }` is heap memory, wiped on every canister upgrade. Use `StableCell` from `ic-stable-structures` for any state that must persist across upgrades, especially ownership/auth data.
52+
5153
## Implementation
5254

5355
### icp.json Configuration
@@ -227,19 +229,31 @@ persistent actor {
227229
228230
```toml
229231
# Cargo.toml
232+
[package]
233+
name = "ii_backend"
234+
version = "0.1.0"
235+
edition = "2021"
236+
237+
[lib]
238+
crate-type = ["cdylib"]
239+
230240
[dependencies]
231241
ic-cdk = "0.18"
232242
candid = "0.10"
233243
serde = { version = "1", features = ["derive"] }
244+
ic-stable-structures = "0.7"
234245
```
235246
236247
```rust
237248
use candid::Principal;
238249
use ic_cdk::{caller, query, update};
250+
use ic_stable_structures::{DefaultMemoryImpl, StableCell};
239251
use std::cell::RefCell;
240252

241253
thread_local! {
242-
static OWNER: RefCell<Option<Principal>> = RefCell::new(None);
254+
static OWNER: RefCell<StableCell<Option<Principal>, DefaultMemoryImpl>> = RefCell::new(
255+
StableCell::init(DefaultMemoryImpl::default(), None).unwrap()
256+
);
243257
}
244258

245259
/// Reject anonymous principal. Call this at the top of every protected endpoint.
@@ -258,10 +272,10 @@ fn init_owner() -> String {
258272
let caller = require_auth();
259273

260274
OWNER.with(|owner| {
261-
let mut owner = owner.borrow_mut();
262-
match *owner {
275+
let mut cell = owner.borrow_mut();
276+
match cell.get() {
263277
None => {
264-
*owner = Some(caller);
278+
cell.set(Some(caller)).unwrap();
265279
format!("Owner set to {}", caller)
266280
}
267281
Some(_) => "Owner already initialized".to_string(),
@@ -274,8 +288,8 @@ fn admin_action() -> String {
274288
let caller = require_auth();
275289

276290
OWNER.with(|owner| {
277-
let owner = owner.borrow();
278-
match *owner {
291+
let cell = owner.borrow();
292+
match cell.get() {
279293
Some(o) if o == caller => "Admin action performed".to_string(),
280294
Some(_) => ic_cdk::trap("Only the owner can call this function."),
281295
None => ic_cdk::trap("Owner not set. Call init_owner first."),

skills/multi-canister/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ crate-type = ["cdylib"]
382382
ic-cdk = "0.18"
383383
candid = "0.10"
384384
serde = { version = "1", features = ["derive"] }
385-
ic-stable-structures = "0.6"
385+
ic-stable-structures = "0.7"
386386
```
387387

388388
#### src/user_service/src/lib.rs
@@ -491,7 +491,7 @@ crate-type = ["cdylib"]
491491
ic-cdk = "0.18"
492492
candid = "0.10"
493493
serde = { version = "1", features = ["derive"] }
494-
ic-stable-structures = "0.6"
494+
ic-stable-structures = "0.7"
495495
```
496496

497497
#### src/content_service/src/lib.rs

skills/sns-launch/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ Distribution:
143143
vesting_period: 31_557_600 # seconds (12 months)
144144

145145
InitialBalances:
146-
governance: 520_000_000_000_000 # e8s (5_200_000 tokens) — Treasury (controlled by DAO)
146+
governance: 500_000_000_000_000 # e8s (5_000_000 tokens) — Treasury (controlled by DAO)
147147
swap: 250_000_000_000_000 # e8s (2_500_000 tokens) — Sold during decentralization swap
148148

149149
total: 1_000_000_000_000_000 # e8s (10_000_000 tokens) — Must equal sum of all allocations

skills/stable-memory/SKILL.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,14 @@ Rust canisters use `ic-stable-structures` for persistent storage. The `MemoryMan
121121
#### Cargo.toml
122122

123123
```toml
124+
[package]
125+
name = "stable_memory_backend"
126+
version = "0.1.0"
127+
edition = "2021"
128+
129+
[lib]
130+
crate-type = ["cdylib"]
131+
124132
[dependencies]
125133
ic-cdk = "0.18"
126134
ic-stable-structures = "0.7"

skills/vetkd/SKILL.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,14 @@ vetkd_derive_key : (record {
114114
**Cargo.toml:**
115115

116116
```toml
117+
[package]
118+
name = "vetkd_backend"
119+
version = "0.1.0"
120+
edition = "2021"
121+
122+
[lib]
123+
crate-type = ["cdylib"]
124+
117125
[dependencies]
118126
candid = "0.10"
119127
ic-cdk = "0.18"

skills/wallet/SKILL.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,14 @@ persistent actor {
153153
#### Cargo.toml Dependencies
154154

155155
```toml
156+
[package]
157+
name = "wallet_backend"
158+
version = "0.1.0"
159+
edition = "2021"
160+
161+
[lib]
162+
crate-type = ["cdylib"]
163+
156164
[dependencies]
157165
ic-cdk = "0.18"
158166
candid = "0.10"

0 commit comments

Comments
 (0)