Browse Source

Merge branch 'master' into armani/versioning

Armani Ferrante 3 years ago
parent
commit
2dd6caa2e5
74 changed files with 761 additions and 47 deletions
  1. 6 0
      .github/workflows/tests.yaml
  2. 6 0
      CHANGELOG.md
  3. 15 7
      README.md
  4. 6 0
      avm/src/lib.rs
  5. 19 1
      cli/src/config.rs
  6. 6 1
      cli/src/lib.rs
  7. 10 12
      cli/src/template.rs
  8. 6 0
      lang/src/error.rs
  9. 1 1
      lang/syn/Cargo.toml
  10. 3 0
      lang/syn/src/codegen/program/entry.rs
  11. 4 0
      lang/syn/src/idl/file.rs
  12. 4 0
      lang/syn/src/idl/mod.rs
  13. 51 1
      lang/syn/src/parser/context.rs
  14. 1 1
      tests/auction-house
  15. 3 0
      tests/cashiers-check/Anchor.toml
  16. 3 0
      tests/cfo/Anchor.toml
  17. 1 1
      tests/cfo/deps/stake
  18. 1 1
      tests/cfo/deps/swap
  19. 3 0
      tests/chat/Anchor.toml
  20. 3 0
      tests/custom-coder/Anchor.toml
  21. 9 0
      tests/declare-id/Anchor.toml
  22. 4 0
      tests/declare-id/Cargo.toml
  23. 19 0
      tests/declare-id/package.json
  24. 16 0
      tests/declare-id/programs/declare-id/Cargo.toml
  25. 2 0
      tests/declare-id/programs/declare-id/Xargo.toml
  26. 18 0
      tests/declare-id/programs/declare-id/src/lib.rs
  27. 17 0
      tests/declare-id/tests/declare-id.js
  28. 3 0
      tests/errors/Anchor.toml
  29. 3 0
      tests/escrow/Anchor.toml
  30. 12 0
      tests/floats/Anchor.toml
  31. 4 0
      tests/floats/Cargo.toml
  32. 12 0
      tests/floats/migrations/deploy.ts
  33. 19 0
      tests/floats/package.json
  34. 19 0
      tests/floats/programs/floats/Cargo.toml
  35. 2 0
      tests/floats/programs/floats/Xargo.toml
  36. 51 0
      tests/floats/programs/floats/src/lib.rs
  37. 67 0
      tests/floats/tests/floats.ts
  38. 10 0
      tests/floats/tsconfig.json
  39. 3 0
      tests/ido-pool/Anchor.toml
  40. 3 0
      tests/interface/Anchor.toml
  41. 2 2
      tests/interface/programs/counter-auth/src/lib.rs
  42. 2 2
      tests/interface/tests/interface.js
  43. 3 0
      tests/lockup/Anchor.toml
  44. 49 0
      tests/misc/programs/misc/src/context.rs
  45. 1 0
      tests/misc/programs/misc2/src/lib.rs
  46. 3 0
      tests/multisig/Anchor.toml
  47. 3 1
      tests/package.json
  48. 1 0
      tests/pda-derivation/Anchor.toml
  49. 3 0
      tests/pyth/Anchor.toml
  50. 6 0
      tests/safety-checks/.gitignore
  51. 13 0
      tests/safety-checks/Anchor.toml
  52. 4 0
      tests/safety-checks/Cargo.toml
  53. 12 0
      tests/safety-checks/migrations/deploy.ts
  54. 19 0
      tests/safety-checks/programs/account-info/Cargo.toml
  55. 2 0
      tests/safety-checks/programs/account-info/Xargo.toml
  56. 16 0
      tests/safety-checks/programs/account-info/src/lib.rs
  57. 19 0
      tests/safety-checks/programs/unchecked-account/Cargo.toml
  58. 2 0
      tests/safety-checks/programs/unchecked-account/Xargo.toml
  59. 16 0
      tests/safety-checks/programs/unchecked-account/src/lib.rs
  60. 27 0
      tests/safety-checks/test.sh
  61. 16 0
      tests/safety-checks/tests/safety-checks.ts
  62. 10 0
      tests/safety-checks/tsconfig.json
  63. 3 0
      tests/spl/token-proxy/Anchor.toml
  64. 3 0
      tests/swap/Anchor.toml
  65. 46 5
      tests/yarn.lock
  66. 3 0
      tests/zero-copy/Anchor.toml
  67. 1 1
      ts/package.json
  68. 6 0
      ts/src/coder/borsh/idl.ts
  69. 4 0
      ts/src/coder/common.ts
  70. 10 1
      ts/src/error.ts
  71. 2 0
      ts/src/idl.ts
  72. 1 1
      ts/src/program/namespace/types.ts
  73. 4 4
      ts/src/spl/token.ts
  74. 4 4
      ts/yarn.lock

+ 6 - 0
.github/workflows/tests.yaml

@@ -262,6 +262,8 @@ jobs:
             path: tests/events
             path: tests/events
           - cmd: cd tests/cashiers-check && anchor test
           - cmd: cd tests/cashiers-check && anchor test
             path: tests/cashiers-check
             path: tests/cashiers-check
+          - cmd: cd tests/declare-id && anchor test
+            path: tests/declare-id
           - cmd: cd tests/typescript && anchor test
           - cmd: cd tests/typescript && anchor test
             path: tests/typescript
             path: tests/typescript
           - cmd: cd tests/zero-copy && anchor test && cd programs/zero-copy && cargo test-bpf
           - cmd: cd tests/zero-copy && anchor test && cd programs/zero-copy && cargo test-bpf
@@ -274,6 +276,10 @@ jobs:
             path: tests/cfo
             path: tests/cfo
           - cmd: cd tests/auction-house && yarn && anchor test
           - cmd: cd tests/auction-house && yarn && anchor test
             path: tests/auction-house
             path: tests/auction-house
+          - cmd: cd tests/floats && yarn && anchor test
+            path: tests/floats
+          - cmd: cd tests/safety-checks && ./test.sh
+            path: tests/safety-checks
     steps:
     steps:
       - uses: actions/checkout@v2
       - uses: actions/checkout@v2
       - uses: ./.github/actions/setup/
       - uses: ./.github/actions/setup/

+ 6 - 0
CHANGELOG.md

@@ -11,6 +11,11 @@ incremented for features.
 
 
 ## [Unreleased]
 ## [Unreleased]
 
 
+### Features
+
+* lang: add check that declared id == program id ([#1451](https://github.com/project-serum/anchor/pull/1451))
+* ts: Added float types support ([#1425](https://github.com/project-serum/anchor/pull/1425)).
+
 ### Fixes
 ### Fixes
 
 
 * ts: Allow nullable types for `Option<T>` mapped types ([#1428](https://github.com/project-serum/anchor/pull/1428)).
 * ts: Allow nullable types for `Option<T>` mapped types ([#1428](https://github.com/project-serum/anchor/pull/1428)).
@@ -21,6 +26,7 @@ incremented for features.
 * lang, client, ts: 8 byte account discriminator has been replaced with a versioned account header. This is a state breaking change. If you have existing Anchor programs, previously deployed, one can continue to use the old 8 byte account discriminator by using the `deprecated-layout` feature flag ([#1415](https://github.com/project-serum/anchor/pull/1415)).
 * lang, client, ts: 8 byte account discriminator has been replaced with a versioned account header. This is a state breaking change. If you have existing Anchor programs, previously deployed, one can continue to use the old 8 byte account discriminator by using the `deprecated-layout` feature flag ([#1415](https://github.com/project-serum/anchor/pull/1415)).
 * lang: The `AccountLoader` and `Loader`'s `load_init` method has been removed. Instead, use `load_mut` ([#1415](https://github.com/project-serum/anchor/pull/1415)).
 * lang: The `AccountLoader` and `Loader`'s `load_init` method has been removed. Instead, use `load_mut` ([#1415](https://github.com/project-serum/anchor/pull/1415)).
 * lang: All error-related code is now in the error module ([#1426](https://github.com/project-serum/anchor/pull/1426)).
 * lang: All error-related code is now in the error module ([#1426](https://github.com/project-serum/anchor/pull/1426)).
+* lang: Require doc comments when using AccountInfo or UncheckedAccount types ([#1452](https://github.com/project-serum/anchor/pull/1452)).
 * ts: `BorshAccountsCoder.accountDiscriminator` method has been replaced with `BorshAccountHeader.discriminator` ([#1415](https://github.com/project-serum/anchor/pull/1415)).
 * ts: `BorshAccountsCoder.accountDiscriminator` method has been replaced with `BorshAccountHeader.discriminator` ([#1415](https://github.com/project-serum/anchor/pull/1415)).
 
 
 ## [0.21.0] - 2022-02-07
 ## [0.21.0] - 2022-02-07

+ 15 - 7
README.md

@@ -10,7 +10,7 @@
   <p>
   <p>
     <a href="https://github.com/project-serum/anchor/actions"><img alt="Build Status" src="https://github.com/project-serum/anchor/actions/workflows/tests.yaml/badge.svg" /></a>
     <a href="https://github.com/project-serum/anchor/actions"><img alt="Build Status" src="https://github.com/project-serum/anchor/actions/workflows/tests.yaml/badge.svg" /></a>
     <a href="https://project-serum.github.io/anchor/"><img alt="Tutorials" src="https://img.shields.io/badge/docs-tutorials-blueviolet" /></a>
     <a href="https://project-serum.github.io/anchor/"><img alt="Tutorials" src="https://img.shields.io/badge/docs-tutorials-blueviolet" /></a>
-    <a href="https://discord.com/channels/889577356681945098"><img alt="Discord Chat" src="https://img.shields.io/discord/889577356681945098?color=blueviolet" /></a>
+    <a href="https://discord.gg/PDeRXyVURd"><img alt="Discord Chat" src="https://img.shields.io/discord/889577356681945098?color=blueviolet" /></a>
     <a href="https://opensource.org/licenses/Apache-2.0"><img alt="License" src="https://img.shields.io/github/license/project-serum/anchor?color=blueviolet" /></a>
     <a href="https://opensource.org/licenses/Apache-2.0"><img alt="License" src="https://img.shields.io/github/license/project-serum/anchor?color=blueviolet" /></a>
   </p>
   </p>
 </div>
 </div>
@@ -97,6 +97,14 @@ pub struct Counter {
 For more, see the [examples](https://github.com/project-serum/anchor/tree/master/examples)
 For more, see the [examples](https://github.com/project-serum/anchor/tree/master/examples)
 and [tests](https://github.com/project-serum/anchor/tree/master/tests) directories.
 and [tests](https://github.com/project-serum/anchor/tree/master/tests) directories.
 
 
+## License
+
+Anchor is licensed under [Apache 2.0](./LICENSE).
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in Anchor by you, as defined in the Apache-2.0 license, shall be
+licensed as above, without any additional terms or conditions.
+
 ## Contribution
 ## Contribution
 
 
 Thank you for your interest in contributing to Anchor! All contributions are welcome no
 Thank you for your interest in contributing to Anchor! All contributions are welcome no
@@ -113,10 +121,10 @@ For simple documentation changes, feel free to just open a pull request.
 If you're considering larger changes or self motivated features, please file an issue
 If you're considering larger changes or self motivated features, please file an issue
 and engage with the maintainers in [Discord](https://discord.gg/sxy4zxBckh).
 and engage with the maintainers in [Discord](https://discord.gg/sxy4zxBckh).
 
 
-## License
-
-Anchor is licensed under [Apache 2.0](./LICENSE).
+### Thanks ❤️
 
 
-Unless you explicitly state otherwise, any contribution intentionally submitted
-for inclusion in Anchor by you, as defined in the Apache-2.0 license, shall be
-licensed as above, without any additional terms or conditions.
+<div align="center">
+  <a href="https://github.com/project-serum/anchor/graphs/contributors">
+    <img src="https://contrib.rocks/image?repo=project-serum/anchor" width="100%" />
+  </a>
+</div>

+ 6 - 0
avm/src/lib.rs

@@ -261,6 +261,9 @@ mod tests {
         let mut current_version_file =
         let mut current_version_file =
             fs::File::create(current_version_file_path().as_path()).unwrap();
             fs::File::create(current_version_file_path().as_path()).unwrap();
         current_version_file.write_all("0.18.2".as_bytes()).unwrap();
         current_version_file.write_all("0.18.2".as_bytes()).unwrap();
+        // Sync the file to disk before the read in current_version() to
+        // mitigate the read not seeing the written version bytes.
+        current_version_file.sync_all().unwrap();
         assert!(current_version().unwrap() == Version::parse("0.18.2").unwrap());
         assert!(current_version().unwrap() == Version::parse("0.18.2").unwrap());
     }
     }
 
 
@@ -278,6 +281,9 @@ mod tests {
         let mut current_version_file =
         let mut current_version_file =
             fs::File::create(current_version_file_path().as_path()).unwrap();
             fs::File::create(current_version_file_path().as_path()).unwrap();
         current_version_file.write_all("0.18.2".as_bytes()).unwrap();
         current_version_file.write_all("0.18.2".as_bytes()).unwrap();
+        // Sync the file to disk before the read in current_version() to
+        // mitigate the read not seeing the written version bytes.
+        current_version_file.sync_all().unwrap();
         // Create a fake binary for anchor-0.18.2 in the bin directory
         // Create a fake binary for anchor-0.18.2 in the bin directory
         fs::File::create(version_binary_path(&version)).unwrap();
         fs::File::create(version_binary_path(&version)).unwrap();
         uninstall_version(&version).unwrap();
         uninstall_version(&version).unwrap();

+ 19 - 1
cli/src/config.rs

@@ -166,6 +166,7 @@ impl WithPath<Config> {
                 path.join("src/lib.rs"),
                 path.join("src/lib.rs"),
                 version,
                 version,
                 self.features.seeds,
                 self.features.seeds,
+                false,
             )?;
             )?;
             r.push(Program {
             r.push(Program {
                 lib_name,
                 lib_name,
@@ -256,9 +257,26 @@ pub struct Config {
     pub test: Option<Test>,
     pub test: Option<Test>,
 }
 }
 
 
-#[derive(Default, Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize)]
 pub struct FeaturesConfig {
 pub struct FeaturesConfig {
+    #[serde(default)]
     pub seeds: bool,
     pub seeds: bool,
+    #[serde(default = "default_safety_checks")]
+    pub safety_checks: bool,
+}
+
+impl Default for FeaturesConfig {
+    fn default() -> Self {
+        Self {
+            seeds: false,
+            // Anchor safety checks on by default
+            safety_checks: true,
+        }
+    }
+}
+
+fn default_safety_checks() -> bool {
+    true
 }
 }
 
 
 #[derive(Clone, Debug, Serialize, Deserialize)]
 #[derive(Clone, Debug, Serialize, Deserialize)]

+ 6 - 1
cli/src/lib.rs

@@ -1388,7 +1388,12 @@ fn extract_idl(cfg: &WithPath<Config>, file: &str) -> Result<Option<Idl>> {
     let manifest_from_path = std::env::current_dir()?.join(PathBuf::from(&*file).parent().unwrap());
     let manifest_from_path = std::env::current_dir()?.join(PathBuf::from(&*file).parent().unwrap());
     let cargo = Manifest::discover_from_path(manifest_from_path)?
     let cargo = Manifest::discover_from_path(manifest_from_path)?
         .ok_or_else(|| anyhow!("Cargo.toml not found"))?;
         .ok_or_else(|| anyhow!("Cargo.toml not found"))?;
-    anchor_syn::idl::file::parse(&*file, cargo.version(), cfg.features.seeds)
+    anchor_syn::idl::file::parse(
+        &*file,
+        cargo.version(),
+        cfg.features.seeds,
+        cfg.features.safety_checks,
+    )
 }
 }
 
 
 fn idl(cfg_override: &ConfigOverride, subcmd: IdlCommand) -> Result<()> {
 fn idl(cfg_override: &ConfigOverride, subcmd: IdlCommand) -> Result<()> {

+ 10 - 12
cli/src/template.rs

@@ -141,7 +141,7 @@ module.exports = async function (provider) {
   anchor.setProvider(provider);
   anchor.setProvider(provider);
 
 
   // Add your deploy script here.
   // Add your deploy script here.
-}
+};
 "#
 "#
 }
 }
 
 
@@ -157,7 +157,7 @@ module.exports = async function (provider) {
   anchor.setProvider(provider);
   anchor.setProvider(provider);
 
 
   // Add your deploy script here.
   // Add your deploy script here.
-}
+};
 "#
 "#
 }
 }
 
 
@@ -191,14 +191,13 @@ pub struct Initialize {{}}
 
 
 pub fn mocha(name: &str) -> String {
 pub fn mocha(name: &str) -> String {
     format!(
     format!(
-        r#"const anchor = require('@project-serum/anchor');
-
-describe('{}', () => {{
+        r#"const anchor = require("@project-serum/anchor");
 
 
+describe("{}", () => {{
   // Configure the client to use the local cluster.
   // Configure the client to use the local cluster.
   anchor.setProvider(anchor.Provider.env());
   anchor.setProvider(anchor.Provider.env());
 
 
-  it('Is initialized!', async () => {{
+  it("Is initialized!", async () => {{
     // Add your test here.
     // Add your test here.
     const program = anchor.workspace.{};
     const program = anchor.workspace.{};
     const tx = await program.rpc.initialize();
     const tx = await program.rpc.initialize();
@@ -248,18 +247,17 @@ pub fn ts_package_json() -> String {
 
 
 pub fn ts_mocha(name: &str) -> String {
 pub fn ts_mocha(name: &str) -> String {
     format!(
     format!(
-        r#"import * as anchor from '@project-serum/anchor';
-import {{ Program }} from '@project-serum/anchor';
-import {{ {} }} from '../target/types/{}';
-
-describe('{}', () => {{
+        r#"import * as anchor from "@project-serum/anchor";
+import {{ Program }} from "@project-serum/anchor";
+import {{ {} }} from "../target/types/{}";
 
 
+describe("{}", () => {{
   // Configure the client to use the local cluster.
   // Configure the client to use the local cluster.
   anchor.setProvider(anchor.Provider.env());
   anchor.setProvider(anchor.Provider.env());
 
 
   const program = anchor.workspace.{} as Program<{}>;
   const program = anchor.workspace.{} as Program<{}>;
 
 
-  it('Is initialized!', async () => {{
+  it("Is initialized!", async () => {{
     // Add your test here.
     // Add your test here.
     const tx = await program.rpc.initialize({{}});
     const tx = await program.rpc.initialize({{}});
     console.log("Your transaction signature", tx);
     console.log("Your transaction signature", tx);

+ 6 - 0
lang/src/error.rs

@@ -10,6 +10,7 @@ pub const ERROR_CODE_OFFSET: u32 = 6000;
 /// - &gt;= 2000 constraint error codes
 /// - &gt;= 2000 constraint error codes
 /// - &gt;= 3000 account error codes
 /// - &gt;= 3000 account error codes
 /// - = 4000 state error code
 /// - = 4000 state error code
+/// - &gt;= 4100 misc error codes
 /// - = 5000 deprecated error code
 /// - = 5000 deprecated error code
 ///
 ///
 /// The starting point for user-defined errors is defined
 /// The starting point for user-defined errors is defined
@@ -154,6 +155,11 @@ pub enum ErrorCode {
     #[msg("The given state account does not have the correct address")]
     #[msg("The given state account does not have the correct address")]
     StateInvalidAddress = 4000,
     StateInvalidAddress = 4000,
 
 
+    // Miscellaneous
+    /// 4100 - The declared program id does not match actual program id
+    #[msg("The declared program id does not match the actual program id")]
+    DeclaredProgramIdMismatch = 4100,
+
     // Deprecated
     // Deprecated
     /// 5000 - The API being used is deprecated and should no longer be used
     /// 5000 - The API being used is deprecated and should no longer be used
     #[msg("The API being used is deprecated and should no longer be used")]
     #[msg("The API being used is deprecated and should no longer be used")]

+ 1 - 1
lang/syn/Cargo.toml

@@ -17,7 +17,7 @@ seeds = []
 
 
 [dependencies]
 [dependencies]
 arrayref = "0.3.6"
 arrayref = "0.3.6"
-proc-macro2 = "1.0"
+proc-macro2 = { version = "1.0", features=["span-locations"]}
 proc-macro2-diagnostics = "0.9"
 proc-macro2-diagnostics = "0.9"
 quote = "1.0"
 quote = "1.0"
 syn = { version = "1.0.60", features = ["full", "extra-traits", "parsing"] }
 syn = { version = "1.0.60", features = ["full", "extra-traits", "parsing"] }

+ 3 - 0
lang/syn/src/codegen/program/entry.rs

@@ -56,6 +56,9 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
             {
             {
                 msg!("anchor-debug is active");
                 msg!("anchor-debug is active");
             }
             }
+            if *program_id != ID {
+                return Err(anchor_lang::error::ErrorCode::DeclaredProgramIdMismatch.into());
+            }
             if data.len() < 8 {
             if data.len() < 8 {
                 return #fallback_maybe
                 return #fallback_maybe
             }
             }

+ 4 - 0
lang/syn/src/idl/file.rs

@@ -18,8 +18,12 @@ pub fn parse(
     filename: impl AsRef<Path>,
     filename: impl AsRef<Path>,
     version: String,
     version: String,
     seeds_feature: bool,
     seeds_feature: bool,
+    safety_checks: bool,
 ) -> Result<Option<Idl>> {
 ) -> Result<Option<Idl>> {
     let ctx = CrateContext::parse(filename)?;
     let ctx = CrateContext::parse(filename)?;
+    if safety_checks {
+        ctx.safety_checks()?;
+    }
 
 
     let program_mod = match parse_program_mod(&ctx) {
     let program_mod = match parse_program_mod(&ctx) {
         None => return Ok(None),
         None => return Ok(None),

+ 4 - 0
lang/syn/src/idl/mod.rs

@@ -178,8 +178,10 @@ pub enum IdlType {
     I16,
     I16,
     U32,
     U32,
     I32,
     I32,
+    F32,
     U64,
     U64,
     I64,
     I64,
+    F64,
     U128,
     U128,
     I128,
     I128,
     Bytes,
     Bytes,
@@ -217,8 +219,10 @@ impl std::str::FromStr for IdlType {
             "i16" => IdlType::I16,
             "i16" => IdlType::I16,
             "u32" => IdlType::U32,
             "u32" => IdlType::U32,
             "i32" => IdlType::I32,
             "i32" => IdlType::I32,
+            "f32" => IdlType::F32,
             "u64" => IdlType::U64,
             "u64" => IdlType::U64,
             "i64" => IdlType::I64,
             "i64" => IdlType::I64,
+            "f64" => IdlType::F64,
             "u128" => IdlType::U128,
             "u128" => IdlType::U128,
             "i128" => IdlType::I128,
             "i128" => IdlType::I128,
             "Vec<u8>" => IdlType::Bytes,
             "Vec<u8>" => IdlType::Bytes,

+ 51 - 1
lang/syn/src/parser/context.rs

@@ -1,6 +1,6 @@
+use anyhow::anyhow;
 use std::collections::BTreeMap;
 use std::collections::BTreeMap;
 use std::path::{Path, PathBuf};
 use std::path::{Path, PathBuf};
-
 use syn::parse::{Error as ParseError, Result as ParseResult};
 use syn::parse::{Error as ParseError, Result as ParseResult};
 
 
 /// Crate parse context
 /// Crate parse context
@@ -40,6 +40,41 @@ impl CrateContext {
             modules: ParsedModule::parse_recursive(root.as_ref())?,
             modules: ParsedModule::parse_recursive(root.as_ref())?,
         })
         })
     }
     }
+
+    // Perform Anchor safety checks on the parsed create
+    pub fn safety_checks(&self) -> Result<(), anyhow::Error> {
+        // Check all structs for unsafe field types, i.e. AccountInfo and UncheckedAccount.
+        for (_, ctx) in self.modules.iter() {
+            for unsafe_field in ctx.unsafe_struct_fields() {
+                // Check if unsafe field type has been documented with a /// SAFETY: doc string.
+                let is_documented = unsafe_field.attrs.iter().any(|attr| {
+                    attr.tokens.clone().into_iter().any(|token| match token {
+                        // Check for doc comments containing CHECK
+                        proc_macro2::TokenTree::Literal(s) => s.to_string().contains("CHECK"),
+                        _ => false,
+                    })
+                });
+                if !is_documented {
+                    let ident = unsafe_field.ident.as_ref().unwrap();
+                    let span = ident.span();
+                    // Error if undocumented.
+                    return Err(anyhow!(
+                        r#"
+        {}:{}:{}
+        Struct field "{}" is unsafe, but is not documented.
+        Please add a `/// CHECK:` 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.
+                    "#,
+                        ctx.file.canonicalize().unwrap().display(),
+                        span.start().line,
+                        span.start().column,
+                        ident.to_string()
+                    ));
+                };
+            }
+        }
+        Ok(())
+    }
 }
 }
 
 
 /// Module parse context
 /// Module parse context
@@ -181,6 +216,21 @@ impl ParsedModule {
         })
         })
     }
     }
 
 
+    fn unsafe_struct_fields(&self) -> impl Iterator<Item = &syn::Field> {
+        self.structs()
+            .flat_map(|s| &s.fields)
+            .filter(|f| match &f.ty {
+                syn::Type::Path(syn::TypePath {
+                    path: syn::Path { segments, .. },
+                    ..
+                }) => {
+                    segments.len() == 1 && segments[0].ident == "UncheckedAccount"
+                        || segments[0].ident == "AccountInfo"
+                }
+                _ => false,
+            })
+    }
+
     fn enums(&self) -> impl Iterator<Item = &syn::ItemEnum> {
     fn enums(&self) -> impl Iterator<Item = &syn::ItemEnum> {
         self.items.iter().filter_map(|i| match i {
         self.items.iter().filter_map(|i| match i {
             syn::Item::Enum(item) => Some(item),
             syn::Item::Enum(item) => Some(item),

+ 1 - 1
tests/auction-house

@@ -1 +1 @@
-Subproject commit 2bfe49bdac2333d0e413a1e452c0ab7b502266fa
+Subproject commit 2b1b1e04986106715ab53794bcb63d3641673f64

+ 3 - 0
tests/cashiers-check/Anchor.toml

@@ -7,3 +7,6 @@ cashiers_check = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
 
 
 [scripts]
 [scripts]
 test = "yarn run mocha -t 1000000 tests/"
 test = "yarn run mocha -t 1000000 tests/"
+
+[features]
+safety_checks = false

+ 3 - 0
tests/cfo/Anchor.toml

@@ -41,3 +41,6 @@ program = "./deps/stake/target/deploy/registry.so"
 [[test.genesis]]
 [[test.genesis]]
 address = "6ebQNeTPZ1j7k3TtkCCtEPRvG7GQsucQrZ7sSEDQi9Ks"
 address = "6ebQNeTPZ1j7k3TtkCCtEPRvG7GQsucQrZ7sSEDQi9Ks"
 program = "./deps/stake/target/deploy/lockup.so"
 program = "./deps/stake/target/deploy/lockup.so"
+
+[features]
+safety_checks = false

+ 1 - 1
tests/cfo/deps/stake

@@ -1 +1 @@
-Subproject commit f04b2aaf8817dac4c8d89e75eaaa0c099dfbf166
+Subproject commit 990eaa7944c6682838fdaa6c14cc07ed680007f0

+ 1 - 1
tests/cfo/deps/swap

@@ -1 +1 @@
-Subproject commit b3021f1444280a372721133bb2e5acca2d271283
+Subproject commit 96e3b1e2a53a95ef56e6ec2da68348ffd6a5c091

+ 3 - 0
tests/chat/Anchor.toml

@@ -7,3 +7,6 @@ chat = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
 
 
 [scripts]
 [scripts]
 test = "yarn run mocha -t 1000000 tests/"
 test = "yarn run mocha -t 1000000 tests/"
+
+[features]
+safety_checks = false

+ 3 - 0
tests/custom-coder/Anchor.toml

@@ -11,3 +11,6 @@ wallet = "~/.config/solana/id.json"
 
 
 [scripts]
 [scripts]
 test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
 test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
+
+[features]
+safety_checks = false

+ 9 - 0
tests/declare-id/Anchor.toml

@@ -0,0 +1,9 @@
+[provider]
+cluster = "localnet"
+wallet = "~/.config/solana/id.json"
+
+[programs.localnet]
+declare_id = "FJcF5c8HncdfAgjPjTH49GAEypkJCG2ZADh2xhduNi5B"
+
+[scripts]
+test = "yarn run mocha -t 1000000 tests/"

+ 4 - 0
tests/declare-id/Cargo.toml

@@ -0,0 +1,4 @@
+[workspace]
+members = [
+    "programs/*"
+]

+ 19 - 0
tests/declare-id/package.json

@@ -0,0 +1,19 @@
+{
+  "name": "declare-id",
+  "version": "0.21.0",
+  "license": "(MIT OR Apache-2.0)",
+  "homepage": "https://github.com/project-serum/anchor#readme",
+  "bugs": {
+    "url": "https://github.com/project-serum/anchor/issues"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/project-serum/anchor.git"
+  },
+  "engines": {
+    "node": ">=11"
+  },
+  "scripts": {
+    "test": "anchor test"
+  }
+}

+ 16 - 0
tests/declare-id/programs/declare-id/Cargo.toml

@@ -0,0 +1,16 @@
+[package]
+name = "declare-id"
+version = "0.1.0"
+description = "Created with Anchor"
+edition = "2018"
+
+[lib]
+crate-type = ["cdylib", "lib"]
+name = "declare_id"
+
+[features]
+no-entrypoint = []
+cpi = ["no-entrypoint"]
+
+[dependencies]
+anchor-lang = { path = "../../../../lang" }

+ 2 - 0
tests/declare-id/programs/declare-id/Xargo.toml

@@ -0,0 +1,2 @@
+[target.bpfel-unknown-unknown.dependencies.std]
+features = []

+ 18 - 0
tests/declare-id/programs/declare-id/src/lib.rs

@@ -0,0 +1,18 @@
+use anchor_lang::prelude::*;
+
+// Intentionally different program id than the one defined in Anchor.toml.
+declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
+
+
+#[program]
+mod declare_id {
+    use super::*;
+
+    pub fn initialize(_ctx: Context<Initialize>) -> ProgramResult {
+        Ok(())
+    }
+}
+
+#[derive(Accounts)]
+pub struct Initialize {
+}

+ 17 - 0
tests/declare-id/tests/declare-id.js

@@ -0,0 +1,17 @@
+const anchor = require("@project-serum/anchor");
+const splToken = require("@solana/spl-token");
+const assert = require("assert");
+
+describe("declare_id", () => {
+  anchor.setProvider(anchor.Provider.local());
+  const program = anchor.workspace.DeclareId;
+
+  it("throws error!", async () => {
+    try {
+      await program.rpc.initialize();
+      assert.ok(false);
+    } catch (err) {
+      assert.equal(err.code, 4100);
+    }
+  });
+});

+ 3 - 0
tests/errors/Anchor.toml

@@ -7,3 +7,6 @@ errors = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
 
 
 [scripts]
 [scripts]
 test = "yarn run mocha -t 1000000 tests/"
 test = "yarn run mocha -t 1000000 tests/"
+
+[features]
+safety_checks = false

+ 3 - 0
tests/escrow/Anchor.toml

@@ -7,3 +7,6 @@ escrow = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
 
 
 [scripts]
 [scripts]
 test = "yarn run ts-mocha -t 1000000 tests/*.ts"
 test = "yarn run ts-mocha -t 1000000 tests/*.ts"
+
+[features]
+safety_checks = false

+ 12 - 0
tests/floats/Anchor.toml

@@ -0,0 +1,12 @@
+[programs.localnet]
+floats = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
+
+[registry]
+url = "https://anchor.projectserum.com"
+
+[provider]
+cluster = "localnet"
+wallet = "~/.config/solana/id.json"
+
+[scripts]
+test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"

+ 4 - 0
tests/floats/Cargo.toml

@@ -0,0 +1,4 @@
+[workspace]
+members = [
+    "programs/*"
+]

+ 12 - 0
tests/floats/migrations/deploy.ts

@@ -0,0 +1,12 @@
+// Migrations are an early feature. Currently, they're nothing more than this
+// single deploy script that's invoked from the CLI, injecting a provider
+// configured from the workspace's Anchor.toml.
+
+const anchor = require("@project-serum/anchor");
+
+module.exports = async function (provider) {
+  // Configure client to use the provider.
+  anchor.setProvider(provider);
+
+  // Add your deploy script here.
+};

+ 19 - 0
tests/floats/package.json

@@ -0,0 +1,19 @@
+{
+    "name": "floats",
+    "version": "0.21.0",
+    "license": "(MIT OR Apache-2.0)",
+    "homepage": "https://github.com/project-serum/anchor#readme",
+    "bugs": {
+      "url": "https://github.com/project-serum/anchor/issues"
+    },
+    "repository": {
+      "type": "git",
+      "url": "https://github.com/project-serum/anchor.git"
+    },
+    "engines": {
+      "node": ">=11"
+    },
+    "scripts": {
+      "test": "anchor test"
+    }
+  }

+ 19 - 0
tests/floats/programs/floats/Cargo.toml

@@ -0,0 +1,19 @@
+[package]
+name = "floats"
+version = "0.1.0"
+description = "Created with Anchor"
+edition = "2018"
+
+[lib]
+crate-type = ["cdylib", "lib"]
+name = "floats"
+
+[features]
+no-entrypoint = []
+no-idl = []
+no-log-ix-name = []
+cpi = ["no-entrypoint"]
+default = []
+
+[dependencies]
+anchor-lang = { path = "../../../../lang" }

+ 2 - 0
tests/floats/programs/floats/Xargo.toml

@@ -0,0 +1,2 @@
+[target.bpfel-unknown-unknown.dependencies.std]
+features = []

+ 51 - 0
tests/floats/programs/floats/src/lib.rs

@@ -0,0 +1,51 @@
+use anchor_lang::prelude::*;
+
+declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
+
+#[program]
+pub mod floats {
+    use super::*;
+
+    pub fn create(ctx: Context<Create>, data_f32: f32, data_f64: f64) -> ProgramResult {
+        let account = &mut ctx.accounts.account;
+        let authority = &mut ctx.accounts.authority;
+
+        account.data_f32 = data_f32;
+        account.data_f64 = data_f64;
+        account.authority = authority.key();
+
+        Ok(())
+    }
+
+    pub fn update(ctx: Context<Update>, data_f32: f32, data_f64: f64) -> ProgramResult {
+        let account = &mut ctx.accounts.account;
+
+        account.data_f32 = data_f32;
+        account.data_f64 = data_f64;
+
+        Ok(())
+    }
+}
+
+#[derive(Accounts)]
+pub struct Create<'info> {
+    #[account(init, payer = authority, space = 8 + 8 + 4 + 32)]
+    pub account: Account<'info, FloatDataAccount>,
+    #[account(mut)]
+    pub authority: Signer<'info>,
+    pub system_program: Program<'info, System>,
+}
+
+#[derive(Accounts)]
+pub struct Update<'info> {
+    #[account(mut, has_one = authority)]
+    pub account: Account<'info, FloatDataAccount>,
+    pub authority: Signer<'info>,
+}
+
+#[account]
+pub struct FloatDataAccount {
+    pub data_f64: f64,
+    pub data_f32: f32,
+    pub authority: Pubkey,
+}

+ 67 - 0
tests/floats/tests/floats.ts

@@ -0,0 +1,67 @@
+import * as anchor from "@project-serum/anchor";
+import { Program, getProvider } from "@project-serum/anchor";
+import { Keypair, SystemProgram } from "@solana/web3.js";
+import { Floats } from "../target/types/floats";
+import assert from "assert";
+
+describe("floats", () => {
+  // Configure the client to use the local cluster.
+  anchor.setProvider(anchor.Provider.env());
+
+  const program = anchor.workspace.Floats as Program<Floats>;
+
+  it("Creates an account with float data", async () => {
+    const accountKeypair = Keypair.generate();
+
+    await program.methods
+      .create(1.0, 2.0)
+      .accounts({
+        account: accountKeypair.publicKey,
+        authority: getProvider().wallet.publicKey,
+        systemProgram: SystemProgram.programId,
+      })
+      .signers([accountKeypair])
+      .rpc();
+
+    const account = await program.account.floatDataAccount.fetch(
+      accountKeypair.publicKey
+    );
+
+    assert.strictEqual(account.dataF32, 1.0);
+    assert.strictEqual(account.dataF64, 2.0);
+  });
+
+  it("Updates an account with float data", async () => {
+    const accountKeypair = Keypair.generate();
+    const authorityPublicKey = getProvider().wallet.publicKey;
+
+    await program.methods
+      .create(1.0, 2.0)
+      .accounts({
+        account: accountKeypair.publicKey,
+        authority: authorityPublicKey,
+        systemProgram: SystemProgram.programId,
+      })
+      .signers([accountKeypair])
+      .rpc();
+
+    let account = await program.account.floatDataAccount.fetch(
+      accountKeypair.publicKey
+    );
+
+    await program.methods
+      .update(3.0, 4.0)
+      .accounts({
+        account: accountKeypair.publicKey,
+        authority: authorityPublicKey,
+      })
+      .rpc();
+
+    account = await program.account.floatDataAccount.fetch(
+      accountKeypair.publicKey
+    );
+
+    assert.strictEqual(account.dataF32, 3.0);
+    assert.strictEqual(account.dataF64, 4.0);
+  });
+});

+ 10 - 0
tests/floats/tsconfig.json

@@ -0,0 +1,10 @@
+{
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}

+ 3 - 0
tests/ido-pool/Anchor.toml

@@ -7,3 +7,6 @@ ido_pool = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
 
 
 [scripts]
 [scripts]
 test = "yarn run mocha -t 1000000 tests/"
 test = "yarn run mocha -t 1000000 tests/"
+
+[features]
+safety_checks = false

+ 3 - 0
tests/interface/Anchor.toml

@@ -8,3 +8,6 @@ counter_auth = "Aws2XRVHjNqCUbMmaU245ojT2DBJFYX58KVo2YySEeeP"
 
 
 [scripts]
 [scripts]
 test = "yarn run mocha -t 1000000 tests/"
 test = "yarn run mocha -t 1000000 tests/"
+
+[features]
+safety_checks = false

+ 2 - 2
tests/interface/programs/counter-auth/src/lib.rs

@@ -19,11 +19,11 @@ pub mod counter_auth {
         fn is_authorized(_ctx: Context<Empty>, current: u64, new: u64) -> ProgramResult {
         fn is_authorized(_ctx: Context<Empty>, current: u64, new: u64) -> ProgramResult {
             if current % 2 == 0 {
             if current % 2 == 0 {
                 if new % 2 == 0 {
                 if new % 2 == 0 {
-                    return Err(ProgramError::Custom(50)); // Arbitrary error code.
+                    return Err(ProgramError::Custom(15000)); // Arbitrary error code.
                 }
                 }
             } else {
             } else {
                 if new % 2 == 1 {
                 if new % 2 == 1 {
-                    return Err(ProgramError::Custom(60)); // Arbitrary error code.
+                    return Err(ProgramError::Custom(16000)); // Arbitrary error code.
                 }
                 }
             }
             }
             Ok(())
             Ok(())

+ 2 - 2
tests/interface/tests/interface.js

@@ -25,7 +25,7 @@ describe("interface", () => {
         });
         });
       },
       },
       (err) => {
       (err) => {
-        if (err.toString().split("custom program error: 0x32").length !== 2) {
+        if (err.toString().split("custom program error: 0x3a98").length !== 2) {
           return false;
           return false;
         }
         }
         return true;
         return true;
@@ -33,7 +33,7 @@ describe("interface", () => {
     );
     );
   });
   });
 
 
-  it("Shold succeed to go from even to odd", async () => {
+  it("Should succeed to go from even to odd", async () => {
     await counter.state.rpc.setCount(new anchor.BN(3), {
     await counter.state.rpc.setCount(new anchor.BN(3), {
       accounts: {
       accounts: {
         authProgram: counterAuth.programId,
         authProgram: counterAuth.programId,

+ 3 - 0
tests/lockup/Anchor.toml

@@ -8,3 +8,6 @@ registry = "HmbTLCmaGvZhKnn1Zfa1JVnp7vkMV4DYVxPLWBVoN65L"
 
 
 [scripts]
 [scripts]
 test = "yarn run mocha -t 1000000 tests/"
 test = "yarn run mocha -t 1000000 tests/"
+
+[features]
+safety_checks = false

+ 49 - 0
tests/misc/programs/misc/src/context.rs

@@ -28,6 +28,7 @@ pub struct TestTokenSeedsInit<'info> {
     )]
     )]
     pub my_pda: Account<'info, TokenAccount>,
     pub my_pda: Account<'info, TokenAccount>,
     #[account(mut)]
     #[account(mut)]
+    /// CHECK:
     pub authority: AccountInfo<'info>,
     pub authority: AccountInfo<'info>,
     pub system_program: Program<'info, System>,
     pub system_program: Program<'info, System>,
     pub rent: Sysvar<'info, Rent>,
     pub rent: Sysvar<'info, Rent>,
@@ -60,6 +61,7 @@ pub struct TestValidateAssociatedToken<'info> {
     )]
     )]
     pub token: Account<'info, TokenAccount>,
     pub token: Account<'info, TokenAccount>,
     pub mint: Account<'info, Mint>,
     pub mint: Account<'info, Mint>,
+    /// CHECK:
     pub wallet: AccountInfo<'info>,
     pub wallet: AccountInfo<'info>,
 }
 }
 
 
@@ -70,7 +72,9 @@ pub struct TestInstructionConstraint<'info> {
         seeds = [b"my-seed", my_account.key.as_ref()],
         seeds = [b"my-seed", my_account.key.as_ref()],
         bump = nonce,
         bump = nonce,
     )]
     )]
+    /// CHECK:
     pub my_pda: AccountInfo<'info>,
     pub my_pda: AccountInfo<'info>,
+    /// CHECK:
     pub my_account: AccountInfo<'info>,
     pub my_account: AccountInfo<'info>,
 }
 }
 
 
@@ -86,6 +90,7 @@ pub struct TestPdaInit<'info> {
     pub my_pda: Account<'info, DataU16>,
     pub my_pda: Account<'info, DataU16>,
     #[account(mut)]
     #[account(mut)]
     pub my_payer: Signer<'info>,
     pub my_payer: Signer<'info>,
+    /// CHECK:
     pub foo: AccountInfo<'info>,
     pub foo: AccountInfo<'info>,
     pub system_program: Program<'info, System>,
     pub system_program: Program<'info, System>,
 }
 }
@@ -112,6 +117,7 @@ pub struct TestPdaMutZeroCopy<'info> {
         bump = my_pda.load()?.bump,
         bump = my_pda.load()?.bump,
     )]
     )]
     pub my_pda: Loader<'info, DataZeroCopy>,
     pub my_pda: Loader<'info, DataZeroCopy>,
+    /// CHECK:
     pub my_payer: AccountInfo<'info>,
     pub my_payer: AccountInfo<'info>,
 }
 }
 
 
@@ -135,29 +141,35 @@ pub struct InitializeSkipRentExempt<'info> {
 
 
 #[derive(Accounts)]
 #[derive(Accounts)]
 pub struct InitializeNoRentExempt<'info> {
 pub struct InitializeNoRentExempt<'info> {
+    /// CHECK:
     pub data: AccountInfo<'info>,
     pub data: AccountInfo<'info>,
 }
 }
 
 
 #[derive(Accounts)]
 #[derive(Accounts)]
 pub struct TestOwner<'info> {
 pub struct TestOwner<'info> {
     #[account(owner = *misc.key)]
     #[account(owner = *misc.key)]
+    /// CHECK:
     pub data: AccountInfo<'info>,
     pub data: AccountInfo<'info>,
+    /// CHECK:
     pub misc: AccountInfo<'info>,
     pub misc: AccountInfo<'info>,
 }
 }
 
 
 #[derive(Accounts)]
 #[derive(Accounts)]
 pub struct TestExecutable<'info> {
 pub struct TestExecutable<'info> {
     #[account(executable)]
     #[account(executable)]
+    /// CHECK:
     pub program: AccountInfo<'info>,
     pub program: AccountInfo<'info>,
 }
 }
 
 
 #[derive(Accounts)]
 #[derive(Accounts)]
 pub struct TestStateCpi<'info> {
 pub struct TestStateCpi<'info> {
     #[account(signer)]
     #[account(signer)]
+    /// CHECK:
     pub authority: AccountInfo<'info>,
     pub authority: AccountInfo<'info>,
     #[account(mut, state = misc2_program)]
     #[account(mut, state = misc2_program)]
     pub cpi_state: CpiState<'info, Misc2State>,
     pub cpi_state: CpiState<'info, Misc2State>,
     #[account(executable)]
     #[account(executable)]
+    /// CHECK:
     pub misc2_program: AccountInfo<'info>,
     pub misc2_program: AccountInfo<'info>,
 }
 }
 
 
@@ -165,6 +177,7 @@ pub struct TestStateCpi<'info> {
 pub struct TestClose<'info> {
 pub struct TestClose<'info> {
     #[account(mut, close = sol_dest)]
     #[account(mut, close = sol_dest)]
     pub data: Account<'info, Data>,
     pub data: Account<'info, Data>,
+    /// CHECK:
     sol_dest: AccountInfo<'info>,
     sol_dest: AccountInfo<'info>,
 }
 }
 
 
@@ -259,6 +272,7 @@ pub struct TestInitWithEmptySeeds<'info> {
 #[derive(Accounts)]
 #[derive(Accounts)]
 pub struct TestEmptySeedsConstraint<'info> {
 pub struct TestEmptySeedsConstraint<'info> {
     #[account(seeds = [], bump)]
     #[account(seeds = [], bump)]
+    /// CHECK:
     pub pda: AccountInfo<'info>,
     pub pda: AccountInfo<'info>,
 }
 }
 
 
@@ -283,10 +297,12 @@ pub struct TestInitIfNeeded<'info> {
 #[derive(Accounts)]
 #[derive(Accounts)]
 pub struct TestInitIfNeededChecksOwner<'info> {
 pub struct TestInitIfNeededChecksOwner<'info> {
     #[account(init_if_needed, payer = payer, space = 100, owner = *owner.key, seeds = [b"hello"], bump)]
     #[account(init_if_needed, payer = payer, space = 100, owner = *owner.key, seeds = [b"hello"], bump)]
+    /// CHECK:
     pub data: UncheckedAccount<'info>,
     pub data: UncheckedAccount<'info>,
     #[account(mut)]
     #[account(mut)]
     pub payer: Signer<'info>,
     pub payer: Signer<'info>,
     pub system_program: Program<'info, System>,
     pub system_program: Program<'info, System>,
+    /// CHECK:
     pub owner: AccountInfo<'info>,
     pub owner: AccountInfo<'info>,
 }
 }
 
 
@@ -294,6 +310,7 @@ pub struct TestInitIfNeededChecksOwner<'info> {
 #[instruction(seed_data: String)]
 #[instruction(seed_data: String)]
 pub struct TestInitIfNeededChecksSeeds<'info> {
 pub struct TestInitIfNeededChecksSeeds<'info> {
     #[account(init_if_needed, payer = payer, space = 100, seeds = [seed_data.as_bytes()], bump)]
     #[account(init_if_needed, payer = payer, space = 100, seeds = [seed_data.as_bytes()], bump)]
+    /// CHECK:
     pub data: UncheckedAccount<'info>,
     pub data: UncheckedAccount<'info>,
     #[account(mut)]
     #[account(mut)]
     pub payer: Signer<'info>,
     pub payer: Signer<'info>,
@@ -310,7 +327,9 @@ pub struct TestInitMintIfNeeded<'info> {
     pub rent: Sysvar<'info, Rent>,
     pub rent: Sysvar<'info, Rent>,
     pub system_program: Program<'info, System>,
     pub system_program: Program<'info, System>,
     pub token_program: Program<'info, Token>,
     pub token_program: Program<'info, Token>,
+    /// CHECK:
     pub mint_authority: AccountInfo<'info>,
     pub mint_authority: AccountInfo<'info>,
+    /// CHECK:
     pub freeze_authority: AccountInfo<'info>,
     pub freeze_authority: AccountInfo<'info>,
 }
 }
 
 
@@ -324,6 +343,7 @@ pub struct TestInitTokenIfNeeded<'info> {
     pub rent: Sysvar<'info, Rent>,
     pub rent: Sysvar<'info, Rent>,
     pub system_program: Program<'info, System>,
     pub system_program: Program<'info, System>,
     pub token_program: Program<'info, Token>,
     pub token_program: Program<'info, Token>,
+    /// CHECK:
     pub authority: AccountInfo<'info>,
     pub authority: AccountInfo<'info>,
 }
 }
 
 
@@ -343,6 +363,7 @@ pub struct TestInitAssociatedTokenIfNeeded<'info> {
     pub system_program: Program<'info, System>,
     pub system_program: Program<'info, System>,
     pub token_program: Program<'info, Token>,
     pub token_program: Program<'info, Token>,
     pub associated_token_program: Program<'info, AssociatedToken>,
     pub associated_token_program: Program<'info, AssociatedToken>,
+    /// CHECK:
     pub authority: AccountInfo<'info>,
     pub authority: AccountInfo<'info>,
 }
 }
 
 
@@ -360,18 +381,21 @@ pub struct TestConstArraySize<'info> {
 
 
 #[derive(Accounts)]
 #[derive(Accounts)]
 pub struct NoRentExempt<'info> {
 pub struct NoRentExempt<'info> {
+    /// CHECK:
     pub data: AccountInfo<'info>,
     pub data: AccountInfo<'info>,
 }
 }
 
 
 #[derive(Accounts)]
 #[derive(Accounts)]
 pub struct EnforceRentExempt<'info> {
 pub struct EnforceRentExempt<'info> {
     #[account(rent_exempt = enforce)]
     #[account(rent_exempt = enforce)]
+    /// CHECK:
     pub data: AccountInfo<'info>,
     pub data: AccountInfo<'info>,
 }
 }
 
 
 #[derive(Accounts)]
 #[derive(Accounts)]
 pub struct InitDecreaseLamports<'info> {
 pub struct InitDecreaseLamports<'info> {
     #[account(init, payer = user, space = 1000)]
     #[account(init, payer = user, space = 1000)]
+    /// CHECK:
     pub data: AccountInfo<'info>,
     pub data: AccountInfo<'info>,
     #[account(mut)]
     #[account(mut)]
     pub user: Signer<'info>,
     pub user: Signer<'info>,
@@ -381,6 +405,7 @@ pub struct InitDecreaseLamports<'info> {
 #[derive(Accounts)]
 #[derive(Accounts)]
 pub struct InitIfNeededChecksRentExemption<'info> {
 pub struct InitIfNeededChecksRentExemption<'info> {
     #[account(init_if_needed, payer = user, space = 1000)]
     #[account(init_if_needed, payer = user, space = 1000)]
+    /// CHECK:
     pub data: AccountInfo<'info>,
     pub data: AccountInfo<'info>,
     #[account(mut)]
     #[account(mut)]
     pub user: Signer<'info>,
     pub user: Signer<'info>,
@@ -393,9 +418,11 @@ pub struct TestProgramIdConstraint<'info> {
     // not a real associated token account
     // not a real associated token account
     // just deriving like this for testing purposes
     // just deriving like this for testing purposes
     #[account(seeds = [b"seed"], bump = bump, seeds::program = anchor_spl::associated_token::ID)]
     #[account(seeds = [b"seed"], bump = bump, seeds::program = anchor_spl::associated_token::ID)]
+    /// CHECK:
     first: AccountInfo<'info>,
     first: AccountInfo<'info>,
 
 
     #[account(seeds = [b"seed"], bump = second_bump, seeds::program = crate::ID)]
     #[account(seeds = [b"seed"], bump = second_bump, seeds::program = crate::ID)]
+    /// CHECK:
     second: AccountInfo<'info>,
     second: AccountInfo<'info>,
 }
 }
 
 
@@ -404,8 +431,30 @@ pub struct TestProgramIdConstraintUsingFindPda<'info> {
     // not a real associated token account
     // not a real associated token account
     // just deriving like this for testing purposes
     // just deriving like this for testing purposes
     #[account(seeds = [b"seed"], bump, seeds::program = anchor_spl::associated_token::ID)]
     #[account(seeds = [b"seed"], bump, seeds::program = anchor_spl::associated_token::ID)]
+    /// CHECK:
     first: AccountInfo<'info>,
     first: AccountInfo<'info>,
 
 
     #[account(seeds = [b"seed"], bump, seeds::program = crate::ID)]
     #[account(seeds = [b"seed"], bump, seeds::program = crate::ID)]
+    /// CHECK:
     second: AccountInfo<'info>,
     second: AccountInfo<'info>,
 }
 }
+
+#[derive(Accounts)]
+pub struct TestUnsafeFieldSafetyErrors<'info> {
+    #[doc = "test"]
+    /// CHECK:
+    pub data: UncheckedAccount<'info>,
+    #[account(mut)]
+    /// CHECK:
+    pub data_two: UncheckedAccount<'info>,
+    #[account(
+        seeds = [b"my-seed", signer.key.as_ref()],
+        bump
+    )]
+    /// CHECK:
+    pub data_three: UncheckedAccount<'info>,
+    /// CHECK:
+    pub data_four: UncheckedAccount<'info>,
+    pub signer: Signer<'info>,
+    pub system_program: Program<'info, System>,
+}

+ 1 - 0
tests/misc/programs/misc2/src/lib.rs

@@ -33,5 +33,6 @@ pub mod misc2 {
 #[derive(Accounts)]
 #[derive(Accounts)]
 pub struct Auth<'info> {
 pub struct Auth<'info> {
     #[account(signer)]
     #[account(signer)]
+    /// CHECK:
     pub authority: AccountInfo<'info>,
     pub authority: AccountInfo<'info>,
 }
 }

+ 3 - 0
tests/multisig/Anchor.toml

@@ -7,3 +7,6 @@ multisig = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
 
 
 [scripts]
 [scripts]
 test = "yarn run mocha -t 1000000 tests/"
 test = "yarn run mocha -t 1000000 tests/"
+
+[features]
+safety_checks = false

+ 3 - 1
tests/package.json

@@ -14,6 +14,7 @@
     "errors",
     "errors",
     "escrow",
     "escrow",
     "events",
     "events",
+    "floats",
     "ido-pool",
     "ido-pool",
     "interface",
     "interface",
     "lockup",
     "lockup",
@@ -28,7 +29,8 @@
     "sysvars",
     "sysvars",
     "tictactoe",
     "tictactoe",
     "typescript",
     "typescript",
-    "zero-copy"
+    "zero-copy",
+    "declare-id"
   ],
   ],
   "dependencies": {
   "dependencies": {
     "@project-serum/anchor": "^0.21.0",
     "@project-serum/anchor": "^0.21.0",

+ 1 - 0
tests/pda-derivation/Anchor.toml

@@ -1,5 +1,6 @@
 [features]
 [features]
 seeds = true
 seeds = true
+safety_checks = false
 
 
 [provider]
 [provider]
 cluster = "localnet"
 cluster = "localnet"

+ 3 - 0
tests/pyth/Anchor.toml

@@ -7,3 +7,6 @@ pyth = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
 
 
 [scripts]
 [scripts]
 test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
 test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
+
+[features]
+safety_checks = false

+ 6 - 0
tests/safety-checks/.gitignore

@@ -0,0 +1,6 @@
+
+.anchor
+.DS_Store
+target
+**/*.rs.bk
+node_modules

+ 13 - 0
tests/safety-checks/Anchor.toml

@@ -0,0 +1,13 @@
+[programs.localnet]
+unchecked_account = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
+account_info = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
+
+[registry]
+url = "https://anchor.projectserum.com"
+
+[provider]
+cluster = "localnet"
+wallet = "/home/armaniferrante/.config/solana/id.json"
+
+[scripts]
+test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"

+ 4 - 0
tests/safety-checks/Cargo.toml

@@ -0,0 +1,4 @@
+[workspace]
+members = [
+    "programs/*"
+]

+ 12 - 0
tests/safety-checks/migrations/deploy.ts

@@ -0,0 +1,12 @@
+// Migrations are an early feature. Currently, they're nothing more than this
+// single deploy script that's invoked from the CLI, injecting a provider
+// configured from the workspace's Anchor.toml.
+
+const anchor = require("@project-serum/anchor");
+
+module.exports = async function (provider) {
+  // Configure client to use the provider.
+  anchor.setProvider(provider);
+
+  // Add your deploy script here.
+};

+ 19 - 0
tests/safety-checks/programs/account-info/Cargo.toml

@@ -0,0 +1,19 @@
+[package]
+name = "account-info"
+version = "0.1.0"
+description = "Created with Anchor"
+edition = "2018"
+
+[lib]
+crate-type = ["cdylib", "lib"]
+name = "account_info"
+
+[features]
+no-entrypoint = []
+no-idl = []
+no-log-ix-name = []
+cpi = ["no-entrypoint"]
+default = []
+
+[dependencies]
+anchor-lang = "0.21.0"

+ 2 - 0
tests/safety-checks/programs/account-info/Xargo.toml

@@ -0,0 +1,2 @@
+[target.bpfel-unknown-unknown.dependencies.std]
+features = []

+ 16 - 0
tests/safety-checks/programs/account-info/src/lib.rs

@@ -0,0 +1,16 @@
+use anchor_lang::prelude::*;
+
+declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
+
+#[program]
+pub mod account_info {
+    use super::*;
+    pub fn initialize(ctx: Context<Initialize>) -> ProgramResult {
+        Ok(())
+    }
+}
+
+#[derive(Accounts)]
+pub struct Initialize<'info> {
+    unchecked: AccountInfo<'info>,
+}

+ 19 - 0
tests/safety-checks/programs/unchecked-account/Cargo.toml

@@ -0,0 +1,19 @@
+[package]
+name = "unchecked-account"
+version = "0.1.0"
+description = "Created with Anchor"
+edition = "2018"
+
+[lib]
+crate-type = ["cdylib", "lib"]
+name = "safety_checks"
+
+[features]
+no-entrypoint = []
+no-idl = []
+no-log-ix-name = []
+cpi = ["no-entrypoint"]
+default = []
+
+[dependencies]
+anchor-lang = { path = "../../../../lang" }

+ 2 - 0
tests/safety-checks/programs/unchecked-account/Xargo.toml

@@ -0,0 +1,2 @@
+[target.bpfel-unknown-unknown.dependencies.std]
+features = []

+ 16 - 0
tests/safety-checks/programs/unchecked-account/src/lib.rs

@@ -0,0 +1,16 @@
+use anchor_lang::prelude::*;
+
+declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
+
+#[program]
+pub mod unchecked_account {
+    use super::*;
+    pub fn initialize(ctx: Context<Initialize>) -> ProgramResult {
+        Ok(())
+    }
+}
+
+#[derive(Accounts)]
+pub struct Initialize<'info> {
+    unchecked: UncheckedAccount<'info>,
+}

+ 27 - 0
tests/safety-checks/test.sh

@@ -0,0 +1,27 @@
+#!/bin/bash
+
+echo "Building programs"
+
+#
+# Build the UncheckedAccount variant.
+#
+pushd programs/unchecked-account/
+anchor build
+if [ $? -eq 0 ]; then
+   echo "Error: expected failure"
+   exit 1
+fi
+popd
+
+#
+# Build the AccountInfo variant.
+#
+pushd programs/account-info/
+anchor build
+if [ $? -eq 0 ]; then
+   echo "Error: expected failure"
+   exit 1
+fi
+popd
+
+echo "Success. All builds failed."

+ 16 - 0
tests/safety-checks/tests/safety-checks.ts

@@ -0,0 +1,16 @@
+import * as anchor from "@project-serum/anchor";
+import { Program } from "@project-serum/anchor";
+import { SafetyChecks } from "../target/types/safety_checks";
+
+describe("safety-checks", () => {
+  // Configure the client to use the local cluster.
+  anchor.setProvider(anchor.Provider.env());
+
+  const program = anchor.workspace.SafetyChecks as Program<SafetyChecks>;
+
+  it("Is initialized!", async () => {
+    // Add your test here.
+    const tx = await program.rpc.initialize({});
+    console.log("Your transaction signature", tx);
+  });
+});

+ 10 - 0
tests/safety-checks/tsconfig.json

@@ -0,0 +1,10 @@
+{
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}

+ 3 - 0
tests/spl/token-proxy/Anchor.toml

@@ -7,3 +7,6 @@ token_proxy = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
 
 
 [scripts]
 [scripts]
 test = "yarn run mocha -t 1000000 tests/"
 test = "yarn run mocha -t 1000000 tests/"
+
+[features]
+safety_checks = false

+ 3 - 0
tests/swap/Anchor.toml

@@ -11,3 +11,6 @@ program = "./deps/serum-dex/dex/target/deploy/serum_dex.so"
 
 
 [scripts]
 [scripts]
 test = "yarn run mocha -t 1000000 tests/"
 test = "yarn run mocha -t 1000000 tests/"
+
+[features]
+safety_checks = false

+ 46 - 5
tests/yarn.lock

@@ -50,18 +50,19 @@
     snake-case "^3.0.4"
     snake-case "^3.0.4"
     toml "^3.0.0"
     toml "^3.0.0"
 
 
-"@project-serum/anchor@^0.20.0":
-  version "0.20.0"
-  resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.20.0.tgz#547f5c0ff7e66809fa7118b2e3abd8087b5ec519"
-  integrity sha512-p1KOiqGBIbNsopMrSVoPwgxR1iPffsdjMNCOysahTPL9whX2CLX9HQCdopHjYaGl7+SdHRuXml6Wahk/wUmC8g==
+"@project-serum/anchor@^0.21.0":
+  version "0.21.0"
+  resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.21.0.tgz#ad5fb33744991ec1900cdb2fd22707c908b12b5f"
+  integrity sha512-flRuW/F+iC8mitNokx82LOXyND7Dyk6n5UUPJpQv/+NfySFrNFlzuQZaBZJ4CG5g9s8HS/uaaIz1nVkDR8V/QA==
   dependencies:
   dependencies:
-    "@project-serum/borsh" "^0.2.2"
+    "@project-serum/borsh" "^0.2.4"
     "@solana/web3.js" "^1.17.0"
     "@solana/web3.js" "^1.17.0"
     base64-js "^1.5.1"
     base64-js "^1.5.1"
     bn.js "^5.1.2"
     bn.js "^5.1.2"
     bs58 "^4.0.1"
     bs58 "^4.0.1"
     buffer-layout "^1.2.2"
     buffer-layout "^1.2.2"
     camelcase "^5.3.1"
     camelcase "^5.3.1"
+    cross-fetch "^3.1.5"
     crypto-hash "^1.3.0"
     crypto-hash "^1.3.0"
     eventemitter3 "^4.0.7"
     eventemitter3 "^4.0.7"
     find "^0.3.0"
     find "^0.3.0"
@@ -78,6 +79,14 @@
     bn.js "^5.1.2"
     bn.js "^5.1.2"
     buffer-layout "^1.2.0"
     buffer-layout "^1.2.0"
 
 
+"@project-serum/borsh@^0.2.4":
+  version "0.2.5"
+  resolved "https://registry.yarnpkg.com/@project-serum/borsh/-/borsh-0.2.5.tgz#6059287aa624ecebbfc0edd35e4c28ff987d8663"
+  integrity sha512-UmeUkUoKdQ7rhx6Leve1SssMR/Ghv8qrEiyywyxSWg7ooV7StdpPBhciiy5eB3T0qU1BXvdRNC8TdrkxK7WC5Q==
+  dependencies:
+    bn.js "^5.1.2"
+    buffer-layout "^1.2.0"
+
 "@project-serum/common@^0.0.1-beta.3":
 "@project-serum/common@^0.0.1-beta.3":
   version "0.0.1-beta.3"
   version "0.0.1-beta.3"
   resolved "https://registry.yarnpkg.com/@project-serum/common/-/common-0.0.1-beta.3.tgz#53586eaff9d9fd7e8938b1e12080c935b8b6ad07"
   resolved "https://registry.yarnpkg.com/@project-serum/common/-/common-0.0.1-beta.3.tgz#53586eaff9d9fd7e8938b1e12080c935b8b6ad07"
@@ -455,6 +464,13 @@ cross-fetch@^3.1.4:
   dependencies:
   dependencies:
     node-fetch "2.6.1"
     node-fetch "2.6.1"
 
 
+cross-fetch@^3.1.5:
+  version "3.1.5"
+  resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f"
+  integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==
+  dependencies:
+    node-fetch "2.6.7"
+
 crypto-hash@^1.3.0:
 crypto-hash@^1.3.0:
   version "1.3.0"
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/crypto-hash/-/crypto-hash-1.3.0.tgz#b402cb08f4529e9f4f09346c3e275942f845e247"
   resolved "https://registry.yarnpkg.com/crypto-hash/-/crypto-hash-1.3.0.tgz#b402cb08f4529e9f4f09346c3e275942f845e247"
@@ -906,6 +922,13 @@ node-fetch@2.6.1:
   resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
   resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
   integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
   integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
 
 
+node-fetch@2.6.7:
+  version "2.6.7"
+  resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
+  integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
+  dependencies:
+    whatwg-url "^5.0.0"
+
 node-gyp-build@^4.2.0, node-gyp-build@^4.3.0:
 node-gyp-build@^4.2.0, node-gyp-build@^4.3.0:
   version "4.3.0"
   version "4.3.0"
   resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3"
   resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3"
@@ -1127,6 +1150,11 @@ toml@^3.0.0:
   resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee"
   resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee"
   integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==
   integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==
 
 
+tr46@~0.0.3:
+  version "0.0.3"
+  resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
+  integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
+
 traverse-chain@~0.1.0:
 traverse-chain@~0.1.0:
   version "0.1.0"
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/traverse-chain/-/traverse-chain-0.1.0.tgz#61dbc2d53b69ff6091a12a168fd7d433107e40f1"
   resolved "https://registry.yarnpkg.com/traverse-chain/-/traverse-chain-0.1.0.tgz#61dbc2d53b69ff6091a12a168fd7d433107e40f1"
@@ -1202,6 +1230,19 @@ uuid@^8.3.0:
   resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
   resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
   integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
   integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
 
 
+webidl-conversions@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
+  integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=
+
+whatwg-url@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
+  integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0=
+  dependencies:
+    tr46 "~0.0.3"
+    webidl-conversions "^3.0.0"
+
 which@2.0.2:
 which@2.0.2:
   version "2.0.2"
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
   resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"

+ 3 - 0
tests/zero-copy/Anchor.toml

@@ -11,3 +11,6 @@ test = "yarn run mocha -t 1000000 tests/"
 [programs.localnet]
 [programs.localnet]
 zero_cpi = "ErjUjtqKE5AGWUsjseSJCVLtddM6rhaMbDqmhzraF9h6"
 zero_cpi = "ErjUjtqKE5AGWUsjseSJCVLtddM6rhaMbDqmhzraF9h6"
 zero_copy = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
 zero_copy = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
+
+[features]
+safety_checks = false

+ 1 - 1
ts/package.json

@@ -33,7 +33,7 @@
     "test": "jest tests --detectOpenHandles"
     "test": "jest tests --detectOpenHandles"
   },
   },
   "dependencies": {
   "dependencies": {
-    "@project-serum/borsh": "^0.2.4",
+    "@project-serum/borsh": "^0.2.5",
     "@solana/web3.js": "^1.17.0",
     "@solana/web3.js": "^1.17.0",
     "base64-js": "^1.5.1",
     "base64-js": "^1.5.1",
     "bn.js": "^5.1.2",
     "bn.js": "^5.1.2",

+ 6 - 0
ts/src/coder/borsh/idl.ts

@@ -33,12 +33,18 @@ export class IdlCoder {
       case "i32": {
       case "i32": {
         return borsh.i32(fieldName);
         return borsh.i32(fieldName);
       }
       }
+      case "f32": {
+        return borsh.f32(fieldName);
+      }
       case "u64": {
       case "u64": {
         return borsh.u64(fieldName);
         return borsh.u64(fieldName);
       }
       }
       case "i64": {
       case "i64": {
         return borsh.i64(fieldName);
         return borsh.i64(fieldName);
       }
       }
+      case "f64": {
+        return borsh.f64(fieldName);
+      }
       case "u128": {
       case "u128": {
         return borsh.u128(fieldName);
         return borsh.u128(fieldName);
       }
       }

+ 4 - 0
ts/src/coder/common.ts

@@ -46,10 +46,14 @@ function typeSize(idl: Idl, ty: IdlType): number {
       return 4;
       return 4;
     case "i32":
     case "i32":
       return 4;
       return 4;
+    case "f32":
+      return 4;
     case "u64":
     case "u64":
       return 8;
       return 8;
     case "i64":
     case "i64":
       return 8;
       return 8;
+    case "f64":
+      return 8;
     case "u128":
     case "u128":
       return 16;
       return 16;
     case "i128":
     case "i128":

+ 10 - 1
ts/src/error.ts

@@ -102,6 +102,9 @@ const LangErrorCode = {
   // State.
   // State.
   StateInvalidAddress: 4000,
   StateInvalidAddress: 4000,
 
 
+  // Miscellaneous
+  DeclaredProgramIdMismatch: 4100,
+
   // Used for APIs that shouldn't be used anymore.
   // Used for APIs that shouldn't be used anymore.
   Deprecated: 5000,
   Deprecated: 5000,
 };
 };
@@ -219,7 +222,13 @@ const LangErrorMessage = new Map([
     "The given state account does not have the correct address",
     "The given state account does not have the correct address",
   ],
   ],
 
 
-  // Misc.
+  // Miscellaneous
+  [
+    LangErrorCode.DeclaredProgramIdMismatch,
+    "The declared program id does not match the actual program id",
+  ],
+
+  // Deprecated
   [
   [
     LangErrorCode.Deprecated,
     LangErrorCode.Deprecated,
     "The API being used is deprecated and should no longer be used",
     "The API being used is deprecated and should no longer be used",

+ 2 - 0
ts/src/idl.ts

@@ -102,8 +102,10 @@ export type IdlType =
   | "i16"
   | "i16"
   | "u32"
   | "u32"
   | "i32"
   | "i32"
+  | "f32"
   | "u64"
   | "u64"
   | "i64"
   | "i64"
+  | "f64"
   | "u128"
   | "u128"
   | "i128"
   | "i128"
   | "bytes"
   | "bytes"

+ 1 - 1
ts/src/program/namespace/types.ts

@@ -94,7 +94,7 @@ type TypeMap = {
   bool: boolean;
   bool: boolean;
   string: string;
   string: string;
 } & {
 } & {
-  [K in "u8" | "i8" | "u16" | "i16" | "u32" | "i32"]: number;
+  [K in "u8" | "i8" | "u16" | "i16" | "u32" | "i32" | "f32" | "f64"]: number;
 } &
 } &
   {
   {
     [K in "u64" | "i64" | "u128" | "i128"]: BN;
     [K in "u64" | "i64" | "u128" | "i128"]: BN;

+ 4 - 4
ts/src/spl/token.ts

@@ -544,7 +544,7 @@ export type SplToken = {
   ];
   ];
   accounts: [
   accounts: [
     {
     {
-      name: "Mint";
+      name: "mint";
       type: {
       type: {
         kind: "struct";
         kind: "struct";
         fields: [
         fields: [
@@ -576,7 +576,7 @@ export type SplToken = {
       };
       };
     },
     },
     {
     {
-      name: "Token";
+      name: "token";
       type: {
       type: {
         kind: "struct";
         kind: "struct";
         fields: [
         fields: [
@@ -1150,7 +1150,7 @@ export const IDL: SplToken = {
   ],
   ],
   accounts: [
   accounts: [
     {
     {
-      name: "Mint",
+      name: "mint",
       type: {
       type: {
         kind: "struct",
         kind: "struct",
         fields: [
         fields: [
@@ -1182,7 +1182,7 @@ export const IDL: SplToken = {
       },
       },
     },
     },
     {
     {
-      name: "Token",
+      name: "token",
       type: {
       type: {
         kind: "struct",
         kind: "struct",
         fields: [
         fields: [

+ 4 - 4
ts/yarn.lock

@@ -855,10 +855,10 @@
     "@nodelib/fs.scandir" "2.1.4"
     "@nodelib/fs.scandir" "2.1.4"
     fastq "^1.6.0"
     fastq "^1.6.0"
 
 
-"@project-serum/borsh@^0.2.4":
-  version "0.2.4"
-  resolved "https://registry.yarnpkg.com/@project-serum/borsh/-/borsh-0.2.4.tgz#8884c3a759984a39d54bf5b7390bd1ee0b579f16"
-  integrity sha512-tQPc1ktAp1Jtn9D72DmObAfhAic9ivfYBOS5b+T4H7MvkQ84uML88LY1LfvGep30mCy+ua5rf+X9ocPfg6u9MA==
+"@project-serum/borsh@^0.2.5":
+  version "0.2.5"
+  resolved "https://registry.yarnpkg.com/@project-serum/borsh/-/borsh-0.2.5.tgz#6059287aa624ecebbfc0edd35e4c28ff987d8663"
+  integrity sha512-UmeUkUoKdQ7rhx6Leve1SssMR/Ghv8qrEiyywyxSWg7ooV7StdpPBhciiy5eB3T0qU1BXvdRNC8TdrkxK7WC5Q==
   dependencies:
   dependencies:
     bn.js "^5.1.2"
     bn.js "^5.1.2"
     buffer-layout "^1.2.0"
     buffer-layout "^1.2.0"