From b977e0746724b88728e3fa5227048668c54cc683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20P=C5=82askonka?= Date: Fri, 13 Nov 2026 12:37:26 +0100 Subject: [PATCH] Docs for Odra 2.11: #[odra(..)] on non-entry-point functions, shared error codes Co-Authored-By: Claude Fable 5.2 --- docusaurus/docs/advanced/03-attributes.md | 3 ++ docusaurus/docs/basics/08-errors.md | 6 ++- docusaurus/docs/migrations/to-2.11.0.md | 53 ++++++++++++++++++++++- 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/docusaurus/docs/advanced/03-attributes.md b/docusaurus/docs/advanced/03-attributes.md index 4171357e1..03bcaa8ff 100644 --- a/docusaurus/docs/advanced/03-attributes.md +++ b/docusaurus/docs/advanced/03-attributes.md @@ -144,6 +144,9 @@ the error, so `try_all_balances()` returns `Err` instead of panicking. ## Mixing attributes +The attributes belong on entry points, the `pub` functions of a module. Since Odra 2.11.0 an +attribute on any other function is a compile error; before, it was accepted and did nothing. + A function can accept more than one attribute, with one exception: a constructor cannot be payable. :::caution diff --git a/docusaurus/docs/basics/08-errors.md b/docusaurus/docs/basics/08-errors.md index 8c5076dc0..d9eb4f369 100644 --- a/docusaurus/docs/basics/08-errors.md +++ b/docusaurus/docs/basics/08-errors.md @@ -79,7 +79,11 @@ Defining an error in Odra, you must keep in mind a few rules: 3. Avoid implicit discriminants. :::note -In your project you can define as many error enums as you wish, but you must ensure that the discriminants are unique across the project! +In your project you can define as many error enums as you wish, but the discriminants must be unique +within a contract: a failed call reports only the number, and the errors of all the modules a +contract is composed of share one range of codes. Since Odra 2.11.0, `cargo odra schema` and +`cargo odra build` stop when two errors of a contract use the same code, and name both. Using the +same enum in several modules is fine. ::: ## Testing errors diff --git a/docusaurus/docs/migrations/to-2.11.0.md b/docusaurus/docs/migrations/to-2.11.0.md index 931be3b61..bc5a0d170 100644 --- a/docusaurus/docs/migrations/to-2.11.0.md +++ b/docusaurus/docs/migrations/to-2.11.0.md @@ -5,7 +5,7 @@ description: Migration guide to v2.11.0 # Migration guide to v2.11.0 from 2.10 -Odra v2.11.0 needs no changes in contract code. Bump the version: +Most projects need no changes in contract code for Odra v2.11.0. Bump the version: ```toml odra = "2.11.0" @@ -17,13 +17,62 @@ and install the matching build tool. `cargo-odra` 0.2.1 goes with Odra 2.11: cargo install cargo-odra --locked ``` -Two things are worth a look: +Two mistakes that used to pass in silence stop the build now: + +- [`#[odra(..)]` on a function that is not an entry point](#attributes-on-private-functions) is a + compile error. +- [Two errors with the same code in one contract](#shared-error-codes) fail `cargo odra schema` and + `cargo odra build`. + +Two more things are worth a look: - [`cargo odra test -- `](#test-arguments) passes the arguments to the test binary. A command that passed arguments to `cargo test` itself needs a small change. - [`odra::link_contract_crates!()`](#link-contract-crates) is one optional line that replaces the hand-written `use` of a dependency whose contracts you build. +## `#[odra(..)]` on a function that is not an entry point {#attributes-on-private-functions} + +`#[odra(payable)]`, `#[odra(non_reentrant)]` and `#[odra(offchain)]` are applied by the entry point +Odra generates for a `pub` function. On any other function of a module they compiled and did +nothing, so a helper marked `non_reentrant` was not guarded: + +```rust +#[odra::module] +impl Vault { + pub fn withdraw(&mut self) { + self.pay_out(); + } + + #[odra(non_reentrant)] // had no effect + fn pay_out(&mut self) { /* ... */ } +} +``` + +This is a compile error now: + +``` +error: `#[odra(non_reentrant)]` has no effect on `pay_out`, which is not an entry point: only entry points are guarded against reentrancy; make the function `pub` or remove the attribute +``` + +Move the attribute to the entry point that calls the helper (`withdraw` above), or remove it. + +## Error codes shared within a contract {#shared-error-codes} + +A failed call reports only a number (`User error: 1`), and the errors of all the modules of a +contract share one range of codes. If two modules of a contract use the same code for different +errors, nothing can tell which one reverted. Generating the schema of such a contract fails now: + +``` +Contract `OwnedToken`: error code 1 is shared by `InsufficientBalance` and `NotAnOwner`; a failed call reports only the code, so these errors cannot be told apart. ... +``` + +Give one of the errors another discriminant. Changing a discriminant changes the code an already +deployed contract reports after its next upgrade, so update whatever matches on the number. + +The same error enum used by several modules is not a collision. The check runs for the contracts +listed in `Odra.toml`, when their schema is generated; OdraVM tests do not run it. + ## Arguments of `cargo odra test` {#test-arguments} With `cargo-odra` 0.2.1 the arguments after `--` go to the test binary, as they do after