diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index fad42bcb8e..924c01885e 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -262,6 +262,8 @@ jobs: path: tests/events - cmd: cd tests/cashiers-check && anchor test path: tests/cashiers-check + - cmd: cd tests/declare-id && anchor test + path: tests/declare-id - cmd: cd tests/typescript && anchor test path: tests/typescript - cmd: cd tests/zero-copy && anchor test && cd programs/zero-copy && cargo test-bpf diff --git a/CHANGELOG.md b/CHANGELOG.md index 023b1a7524..fd99ac2032 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ incremented for features. ## [Unreleased] +### Features + +* lang: add check that declared id == program id ([#1451](https://github.com/project-serum/anchor/pull/1451)) + ### Fixes * ts: Allow nullable types for `Option` mapped types ([#1428](https://github.com/project-serum/anchor/pull/1428)). diff --git a/lang/src/error.rs b/lang/src/error.rs index 5e9a276cf0..73f444c974 100644 --- a/lang/src/error.rs +++ b/lang/src/error.rs @@ -154,6 +154,11 @@ pub enum ErrorCode { #[msg("The given state account does not have the correct address")] 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 /// 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")] diff --git a/lang/syn/src/codegen/program/entry.rs b/lang/syn/src/codegen/program/entry.rs index 8f9bcb7bd9..af3dd360c5 100644 --- a/lang/syn/src/codegen/program/entry.rs +++ b/lang/syn/src/codegen/program/entry.rs @@ -56,6 +56,9 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream { { msg!("anchor-debug is active"); } + if *program_id != ID { + return Err(anchor_lang::error::ErrorCode::DeclaredProgramIdMismatch.into()); + } if data.len() < 8 { return #fallback_maybe } diff --git a/tests/declare-id/Anchor.toml b/tests/declare-id/Anchor.toml new file mode 100644 index 0000000000..0555c68f16 --- /dev/null +++ b/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/" diff --git a/tests/declare-id/Cargo.toml b/tests/declare-id/Cargo.toml new file mode 100644 index 0000000000..a60de986d3 --- /dev/null +++ b/tests/declare-id/Cargo.toml @@ -0,0 +1,4 @@ +[workspace] +members = [ + "programs/*" +] diff --git a/tests/declare-id/package.json b/tests/declare-id/package.json new file mode 100644 index 0000000000..0be35fc5a2 --- /dev/null +++ b/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" + } +} diff --git a/tests/declare-id/programs/declare-id/Cargo.toml b/tests/declare-id/programs/declare-id/Cargo.toml new file mode 100644 index 0000000000..0bbbab6119 --- /dev/null +++ b/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" } diff --git a/tests/declare-id/programs/declare-id/Xargo.toml b/tests/declare-id/programs/declare-id/Xargo.toml new file mode 100644 index 0000000000..475fb71ed1 --- /dev/null +++ b/tests/declare-id/programs/declare-id/Xargo.toml @@ -0,0 +1,2 @@ +[target.bpfel-unknown-unknown.dependencies.std] +features = [] diff --git a/tests/declare-id/programs/declare-id/src/lib.rs b/tests/declare-id/programs/declare-id/src/lib.rs new file mode 100644 index 0000000000..5e98ce2e5c --- /dev/null +++ b/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) -> ProgramResult { + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Initialize { +} diff --git a/tests/declare-id/tests/declare-id.js b/tests/declare-id/tests/declare-id.js new file mode 100644 index 0000000000..ca1c290a6a --- /dev/null +++ b/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); + } + }); +}); diff --git a/tests/interface/programs/counter-auth/src/lib.rs b/tests/interface/programs/counter-auth/src/lib.rs index a89af60ec1..2281bd3a3e 100644 --- a/tests/interface/programs/counter-auth/src/lib.rs +++ b/tests/interface/programs/counter-auth/src/lib.rs @@ -19,11 +19,11 @@ pub mod counter_auth { fn is_authorized(_ctx: Context, current: u64, new: u64) -> ProgramResult { if current % 2 == 0 { if new % 2 == 0 { - return Err(ProgramError::Custom(50)); // Arbitrary error code. + return Err(ProgramError::Custom(15000)); // Arbitrary error code. } } else { if new % 2 == 1 { - return Err(ProgramError::Custom(60)); // Arbitrary error code. + return Err(ProgramError::Custom(16000)); // Arbitrary error code. } } Ok(()) diff --git a/tests/interface/tests/interface.js b/tests/interface/tests/interface.js index 574cac9e51..c8997810be 100644 --- a/tests/interface/tests/interface.js +++ b/tests/interface/tests/interface.js @@ -25,7 +25,7 @@ describe("interface", () => { }); }, (err) => { - if (err.toString().split("custom program error: 0x32").length !== 2) { + if (err.toString().split("custom program error: 0x3a98").length !== 2) { return false; } 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), { accounts: { authProgram: counterAuth.programId, diff --git a/tests/package.json b/tests/package.json index 40198cd2ed..7159a5d679 100644 --- a/tests/package.json +++ b/tests/package.json @@ -28,7 +28,8 @@ "sysvars", "tictactoe", "typescript", - "zero-copy" + "zero-copy", + "declare-id" ], "dependencies": { "@project-serum/anchor": "^0.21.0", diff --git a/tests/yarn.lock b/tests/yarn.lock index 69ce24aeb5..14e85c6443 100644 --- a/tests/yarn.lock +++ b/tests/yarn.lock @@ -50,18 +50,19 @@ snake-case "^3.0.4" 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: - "@project-serum/borsh" "^0.2.2" + "@project-serum/borsh" "^0.2.4" "@solana/web3.js" "^1.17.0" base64-js "^1.5.1" bn.js "^5.1.2" bs58 "^4.0.1" buffer-layout "^1.2.2" camelcase "^5.3.1" + cross-fetch "^3.1.5" crypto-hash "^1.3.0" eventemitter3 "^4.0.7" find "^0.3.0" @@ -78,6 +79,14 @@ bn.js "^5.1.2" 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": version "0.0.1-beta.3" 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: 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: version "1.3.0" 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" 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: version "4.3.0" 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" 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: version "0.1.0" 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" 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: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" diff --git a/ts/src/error.ts b/ts/src/error.ts index 52dffd7798..e9bdbc5f27 100644 --- a/ts/src/error.ts +++ b/ts/src/error.ts @@ -102,6 +102,9 @@ const LangErrorCode = { // State. StateInvalidAddress: 4000, + // Miscellaneous + DeclaredProgramIdMismatch: 4100, + // Used for APIs that shouldn't be used anymore. Deprecated: 5000, }; @@ -219,7 +222,13 @@ const LangErrorMessage = new Map([ "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, "The API being used is deprecated and should no longer be used",