From 479f94dc53251cdec6c5094eb70438f86ca40b5b Mon Sep 17 00:00:00 2001 From: brewmaster012 <88689859+brewmaster012@users.noreply.github.com> Date: Thu, 15 Aug 2024 01:42:26 -0500 Subject: [PATCH 1/4] program: add pause deposit state and guard in deposit & deposit_spl_token --- README.md | 27 ++++++++++++++++ programs/protocol-contracts-solana/src/lib.rs | 31 +++++++++++++++++++ tests/protocol-contracts-solana.ts | 19 ++++++++++++ 3 files changed, 77 insertions(+) diff --git a/README.md b/README.md index cc46223..57603e7 100644 --- a/README.md +++ b/README.md @@ -125,3 +125,30 @@ Ethereum style). `authority` is the one who can update the TSS address stored in PDA account. The `initialize` instruction sets nonce to 0. + +# Troubleshooting + +## MacOS error when runngin `anchor test` or `solana-test-validator` + +If you see errors like +``` +Unable to get latest blockhash. Test validator does not look started. Check ".anchor/test-ledger/test-ledger-log.txt" for errors. Consider increasing [test.startup_wait] in Anchor.toml. +``` + +or +```bash +% solana-test-validator --reset +Ledger location: test-ledger +Log: test-ledger/validator.log +Error: failed to start validator: Failed to create ledger at test-ledger: io error: Error checking to unpack genesis archive: Archive error: extra entry found: "._genesis.bin" Regular +``` + +This is because the BSD tar program is not compatible with the GNU tar program. +To fix it: + +```bash +brew install gnu-tar +# Put this in ~/.zshrc +export PATH="/opt/homebrew/opt/gnu-tar/libexec/gnubin:$PATH" +``` +see https://solana.stackexchange.com/questions/4499/blockstore-error-when-starting-solana-test-validator-on-macos-13-0-1 \ No newline at end of file diff --git a/programs/protocol-contracts-solana/src/lib.rs b/programs/protocol-contracts-solana/src/lib.rs index 58f05a9..ad19814 100644 --- a/programs/protocol-contracts-solana/src/lib.rs +++ b/programs/protocol-contracts-solana/src/lib.rs @@ -24,6 +24,8 @@ pub enum Errors { MemoLengthExceeded, #[msg("MemoLengthTooShort")] MemoLengthTooShort, + #[msg("DepositPaused")] + DepositPaused, } declare_id!("94U5AHQMKkV5txNJ17QPXWoh474PheGou6cNP2FEuL1d"); @@ -42,10 +44,22 @@ pub mod gateway { initialized_pda.tss_address = tss_address; initialized_pda.authority = ctx.accounts.signer.key(); initialized_pda.chain_id = chain_id; + initialized_pda.deposit_paused = false; Ok(()) } + pub fn set_deposit_paused(ctx: Context, deposit_paused: bool) -> Result<()> { + let pda = &mut ctx.accounts.pda; + require!( + ctx.accounts.signer.key() == pda.authority, + Errors::SignerIsNotAuthority + ); + pda.deposit_paused = deposit_paused; + msg!("set_deposit_paused: {:?}", deposit_paused); + Ok(()) + } + pub fn update_tss(ctx: Context, tss_address: [u8; 20]) -> Result<()> { let pda = &mut ctx.accounts.pda; require!( @@ -59,6 +73,10 @@ pub mod gateway { pub fn deposit(ctx: Context, amount: u64, memo: Vec) -> Result<()> { require!(memo.len() >= 20, Errors::MemoLengthTooShort); require!(memo.len() <= 512, Errors::MemoLengthExceeded); + + let pda = &mut ctx.accounts.pda; + require!(!pda.deposit_paused, Errors::DepositPaused); + let cpi_context = CpiContext::new( ctx.accounts.system_program.to_account_info(), system_program::Transfer { @@ -86,6 +104,9 @@ pub mod gateway { let token = &ctx.accounts.token_program; let from = &ctx.accounts.from; + let pda = &mut ctx.accounts.pda; + require!(!pda.deposit_paused, Errors::DepositPaused); + let pda_ata = spl_associated_token_account::get_associated_token_address( &ctx.accounts.pda.key(), &from.mint, @@ -293,12 +314,22 @@ pub struct UpdateTss<'info> { pub signer: Signer<'info>, } +#[derive(Accounts)] +pub struct UpdatePaused<'info> { + #[account(mut)] + pub pda: Account<'info, Pda>, + #[account(mut)] + pub signer: Signer<'info>, +} + + #[account] pub struct Pda { nonce: u64, // ensure that each signature can only be used once tss_address: [u8; 20], // 20 bytes address format of ethereum authority: Pubkey, chain_id: u64, + deposit_paused: bool, } #[cfg(test)] diff --git a/tests/protocol-contracts-solana.ts b/tests/protocol-contracts-solana.ts index 9e3dfde..5e07237 100644 --- a/tests/protocol-contracts-solana.ts +++ b/tests/protocol-contracts-solana.ts @@ -300,6 +300,25 @@ describe("some tests", () => { } }); + it("pause deposit and deposit should fail", async () => { + const newTss = new Uint8Array(20); + randomFillSync(newTss); + // console.log("generated new TSS address", newTss); + await gatewayProgram.methods.setDepositPaused(true).accounts({ + pda: pdaAccount, + }).rpc(); + + // now try deposit, should fail + try { + await gatewayProgram.methods.deposit(new anchor.BN(1_000_000), address).accounts({pda: pdaAccount}).rpc(); + } catch (err) { + console.log("Error message: ", err.message); + expect(err).to.be.instanceof(anchor.AnchorError); + expect(err.message).to.include("DepositPaused"); + } + + }); + }); From 751b0d3510f54e03ba526882a44481aef4e84507 Mon Sep 17 00:00:00 2001 From: brewmaster012 <88689859+brewmaster012@users.noreply.github.com> Date: Thu, 15 Aug 2024 01:53:31 -0500 Subject: [PATCH 2/4] program: add update_authority instruction and test --- programs/protocol-contracts-solana/src/lib.rs | 18 +++++++++++++++++ tests/protocol-contracts-solana.ts | 20 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/programs/protocol-contracts-solana/src/lib.rs b/programs/protocol-contracts-solana/src/lib.rs index ad19814..d11eef7 100644 --- a/programs/protocol-contracts-solana/src/lib.rs +++ b/programs/protocol-contracts-solana/src/lib.rs @@ -70,6 +70,16 @@ pub mod gateway { Ok(()) } + pub fn update_authority(ctx: Context, new_authority_address: Pubkey) -> Result<()> { + let pda = &mut ctx.accounts.pda; + require!( + ctx.accounts.signer.key() == pda.authority, + Errors::SignerIsNotAuthority + ); + pda.authority = new_authority_address; + Ok(()) + } + pub fn deposit(ctx: Context, amount: u64, memo: Vec) -> Result<()> { require!(memo.len() >= 20, Errors::MemoLengthTooShort); require!(memo.len() <= 512, Errors::MemoLengthExceeded); @@ -314,6 +324,14 @@ pub struct UpdateTss<'info> { pub signer: Signer<'info>, } +#[derive(Accounts)] +pub struct UpdateAuthority<'info> { + #[account(mut)] + pub pda: Account<'info, Pda>, + #[account(mut)] + pub signer: Signer<'info>, +} + #[derive(Accounts)] pub struct UpdatePaused<'info> { #[account(mut)] diff --git a/tests/protocol-contracts-solana.ts b/tests/protocol-contracts-solana.ts index 5e07237..498b8de 100644 --- a/tests/protocol-contracts-solana.ts +++ b/tests/protocol-contracts-solana.ts @@ -319,6 +319,26 @@ describe("some tests", () => { }); + it("update authority", async () => { + const newAuthority = anchor.web3.Keypair.generate(); + await gatewayProgram.methods.updateAuthority(newAuthority.publicKey).accounts({ + pda: pdaAccount, + }).rpc(); + // const pdaAccountData = await gatewayProgram.account.pda.fetch(pdaAccount); + // expect(pdaAccountData.authority).to.be.eq(newAuthority.publicKey); + + // now the old authority cannot update TSS address and will fail + try { + await gatewayProgram.methods.updateTss(Array.from(new Uint8Array(20))).accounts({ + pda: pdaAccount, + }).rpc(); + } catch (err) { + console.log("Error message: ", err.message); + expect(err).to.be.instanceof(anchor.AnchorError); + expect(err.message).to.include("SignerIsNotAuthority"); + } + }); + }); From 8587976a90333dce5e7b13dc4c23417f7b39e433 Mon Sep 17 00:00:00 2001 From: brewmaster012 <88689859+brewmaster012@users.noreply.github.com> Date: Thu, 15 Aug 2024 01:56:27 -0500 Subject: [PATCH 3/4] cargo fmt code --- programs/protocol-contracts-solana/src/lib.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/programs/protocol-contracts-solana/src/lib.rs b/programs/protocol-contracts-solana/src/lib.rs index d11eef7..6b52dd2 100644 --- a/programs/protocol-contracts-solana/src/lib.rs +++ b/programs/protocol-contracts-solana/src/lib.rs @@ -70,7 +70,10 @@ pub mod gateway { Ok(()) } - pub fn update_authority(ctx: Context, new_authority_address: Pubkey) -> Result<()> { + pub fn update_authority( + ctx: Context, + new_authority_address: Pubkey, + ) -> Result<()> { let pda = &mut ctx.accounts.pda; require!( ctx.accounts.signer.key() == pda.authority, @@ -340,7 +343,6 @@ pub struct UpdatePaused<'info> { pub signer: Signer<'info>, } - #[account] pub struct Pda { nonce: u64, // ensure that each signature can only be used once From 52a13a41d0f4d58b273f11ff8fb6fb645001f7cb Mon Sep 17 00:00:00 2001 From: brewmaster012 <88689859+brewmaster012@users.noreply.github.com> Date: Thu, 15 Aug 2024 11:36:04 -0500 Subject: [PATCH 4/4] Update README.md Co-authored-by: Lucas Bertrand --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 57603e7..5f5b9dc 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ The `initialize` instruction sets nonce to 0. # Troubleshooting -## MacOS error when runngin `anchor test` or `solana-test-validator` +## MacOS error when running `anchor test` or `solana-test-validator` If you see errors like ```