diff --git a/docs/guides/backends/data-persistence.mdx b/docs/guides/backends/data-persistence.mdx index dcb4e84f..23cfac0c 100644 --- a/docs/guides/backends/data-persistence.mdx +++ b/docs/guides/backends/data-persistence.mdx @@ -580,7 +580,7 @@ If the count drops to 0 after upgrade, the data is not in stable memory. Review | Heap | 4 GiB | No (Rust) / Yes (Motoko `persistent actor`) | Frequently accessed data, caches, ephemeral computation | | Stable | 500 GiB | Yes | All important data, large datasets, anything that must survive upgrades | -The practical rule: **use stable structures directly for any data that matters**. Avoid relying on `pre_upgrade` / `post_upgrade` hooks to serialize heap data to stable memory. Serializing large heap state during an upgrade can hit the instruction limit and trap, leaving the canister on the old code. Data in stable structures is already in stable memory from the first write — no serialization step required on upgrade. +The practical rule: **use stable structures directly for any data that matters**. Avoid relying on `pre_upgrade` / `post_upgrade` hooks to serialize heap data to stable memory. Serializing large heap state during an upgrade can hit the instruction limit and trap, leaving the canister on the old code. Data in stable structures is already in stable memory from the first write, with no serialization step required on upgrade. For Motoko, `persistent actor` makes all `let` and `var` declarations persistent automatically. There is no need to choose manually between heap and stable memory. diff --git a/docs/guides/digital-assets/chain-key-tokens.mdx b/docs/guides/digital-assets/chain-key-tokens.mdx index 7f8f7d3e..d20b4c39 100644 --- a/docs/guides/digital-assets/chain-key-tokens.mdx +++ b/docs/guides/digital-assets/chain-key-tokens.mdx @@ -380,7 +380,7 @@ The ckETH minter handles both ETH and ERC-20 deposits using a shared Ethereum he 1. Call `depositEth` on the ckETH helper contract on Ethereum (mainnet: `0x18901044688D3756C35Ed2b36D93e6a5B8e00E68`), passing: - The amount of ETH. - Your ICP principal encoded as `bytes32`. - - A 32-byte subaccount (`0x` for the default account, or a derived subaccount for per-user deposits — see [Per-user deposit addresses](#per-user-deposit-addresses)). + - A 32-byte subaccount (`0x` for the default account, or a derived subaccount for per-user deposits; see [Per-user deposit addresses](#per-user-deposit-addresses)). 2. The minter detects the `ReceivedEthOrErc20` event and mints ckETH to `(principal, subaccount)` after roughly 20 minutes. > The ckETH deposit flow requires an Ethereum wallet or library. For sending Ethereum transactions from an ICP canister, see [Ethereum integration](../chain-fusion/ethereum.md). diff --git a/scripts/validate.js b/scripts/validate.js index 5f2def34..0ba9a39a 100644 --- a/scripts/validate.js +++ b/scripts/validate.js @@ -34,8 +34,13 @@ function checkFrontmatter(file, content) { } } +// `checkForbiddenPatterns` skips fenced code, so these patterns only ever see +// prose. `mo:base` is the exception: what must never appear is an *import* +// (`mo:base/Buffer`), which lives inside a fence, while naming the legacy +// library in prose is legitimate (base-to-core migration tables do it). It +// therefore matches the import path and is checked inside fences too. const FORBIDDEN = [ - { re: /mo:base/, msg: '"mo:base" is banned — use "mo:core" instead' }, + { re: /mo:base\//, msg: '"mo:base/" import is banned — use "mo:core" instead', includeFences: true }, { re: /https?:\/\/(?:www\.)?internetcomputer\.org\/docs/, msg: 'internetcomputer.org/docs is retired — link internally or inline' }, { re: /docs\.internetcomputer\.org/, msg: 'docs.internetcomputer.org is this site — use relative paths for internal links' }, ]; @@ -68,8 +73,8 @@ function checkForbiddenPatterns(file, content) { for (let i = 0; i < lines.length; i++) { const line = lines[i]; if (/^```/.test(line.trimStart())) { inFence = !inFence; continue; } - if (inFence) continue; - for (const { re, msg } of FORBIDDEN) { + for (const { re, msg, includeFences } of FORBIDDEN) { + if (inFence && !includeFences) continue; if (re.test(line)) errors.push(`line ${i + 1}: ${msg}`); } }