From 73ad095541a8c4944b0761a722547c4b32118229 Mon Sep 17 00:00:00 2001 From: Tom Linton Date: Mon, 21 Feb 2022 15:00:03 +1300 Subject: [PATCH] Add section on safety checks (#6) --- src/chapter_3/the_accounts_struct.md | 47 +++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/src/chapter_3/the_accounts_struct.md b/src/chapter_3/the_accounts_struct.md index 6b83ab7..e0a9d08 100644 --- a/src/chapter_3/the_accounts_struct.md +++ b/src/chapter_3/the_accounts_struct.md @@ -1,11 +1,12 @@ # The Accounts Struct -The Accounts struct is where you define which accounts your instruction expects and which constraints these accounts should adhere to. You do this via two constructs: Types and constraints. + +The Accounts struct is where you define which accounts your instruction expects and which constraints these accounts should adhere to. You do this via two constructs: Types and constraints. ## Types > [Account Types Reference](https://docs.rs/anchor-lang/latest/anchor_lang/accounts/index.html) -Each type has a specific use case in mind. Detailed explanations for the types can be found in the [reference](https://docs.rs/anchor-lang/latest/anchor_lang/accounts/index.html). We will briefly explain the most important type here, the `Account` type. +Each type has a specific use case in mind. Detailed explanations for the types can be found in the [reference](https://docs.rs/anchor-lang/latest/anchor_lang/accounts/index.html). We will briefly explain the most important type here, the `Account` type. ### The Account Type @@ -46,8 +47,7 @@ Most importantly, the `#[account]` attribute sets the owner of that data to the #### Using `Account<'a, T>` with non-anchor program accounts - -There may be cases where you want your program to interact with a non-Anchor program. You can still get all the benefits of `Account` but you have to write a custom wrapper type instead of using `#[account]`. For instance, Anchor provides wrapper types for the token program accounts so they can be used with `Account`. +There may be cases where you want your program to interact with a non-Anchor program. You can still get all the benefits of `Account` but you have to write a custom wrapper type instead of using `#[account]`. For instance, Anchor provides wrapper types for the token program accounts so they can be used with `Account`. ```rust,ignore use anchor_lang::prelude::*; @@ -97,12 +97,14 @@ Check out the [reference for the Account type](https://docs.rs/anchor-lang/lates Account types can do a lot of work for you but they're not dynamic enough to handle all the security checks a secure program requires. Add constraints to an account with the following format: + ```rust,ignore #[account()] pub account: AccountType ``` Some constraints support custom Errors (we will explore errors [later](./errors.md)): + ```rust,ignore #[account(..., @ MyError::MyErrorVariant, ...)] pub account: AccountType @@ -124,4 +126,39 @@ pub struct SetData<'info> { } ``` -You can find information about all constraints in the reference. We will cover some of the most important ones in the milestone project at the end of the Essentials section. \ No newline at end of file +You can find information about all constraints in the reference. We will cover some of the most important ones in the milestone project at the end of the Essentials section. + +## Safety checks + +Two of the Anchor account types, [AccountInfo](https://docs.rs/anchor-lang/latest/anchor_lang/accounts/account_info/index.html) and [UncheckedAccount](https://docs.rs/anchor-lang/latest/anchor_lang/accounts/unchecked_account/index.html) do not implement any checks on the account being passed. Anchor implements safety checks that encourage additional documentation describing why additional checks are not necesssary. + +Attempting to build a program containing the following excerpt with `anchor build`: + +```rust,ignore +#[derive(Accounts)] +pub struct Initialize<'info> { + pub potentially_dangerous: UncheckedAccount<'info> +} +``` + +will result in an error similar to the following: + +``` +Error: + /anchor/tests/unchecked/programs/unchecked/src/lib.rs:15:8 + Struct field "potentially_dangerous" is unsafe, but is not documented. + Please add a `/// SAFETY:` doc comment explaining why no checks through types are necessary. + See https://book.anchor-lang.com/chapter_3/the_accounts_struct.html#safety-checks for more information. +``` + +To fix this, write a doc comment describing the potential security implications, e.g.: + +```rust,ignore +#[derive(Accounts)] +pub struct Initialize<'info> { + /// SAFETY: This is not dangerous because we don't read or write from this account + pub potentially_dangerous: UncheckedAccount<'info> +} +``` + +Note the doc comment needs to be a [line or block doc comment](https://doc.rust-lang.org/reference/comments.html#doc-comments) (/// or /\*\*) to be interepreted as doc attribute by Rust. Double slash comments (//) are not interpreted as such.