From 0957fa799dd2eac682bfe2522dd7445cb67ee3d7 Mon Sep 17 00:00:00 2001 From: moosecat Date: Wed, 18 Dec 2024 12:57:07 -0800 Subject: [PATCH] refactor lazer for updated idl (#1393) --- Cargo.lock | 21 ++----- programs/drift/Cargo.toml | 2 +- .../src/instructions/pyth_lazer_oracle.rs | 57 +++++++++++++------ sdk/src/driftClient.ts | 20 ++++++- tests/pythLazer.ts | 6 +- 5 files changed, 67 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d498d6b5f..ef01d967b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -977,7 +977,7 @@ dependencies = [ "phoenix-v1", "pyth", "pyth-client", - "pyth-lazer-sdk", + "pyth-lazer-solana-contract", "pyth-solana-receiver-sdk", "pythnet-sdk", "serum_dex", @@ -1852,8 +1852,8 @@ checksum = "44de48029c54ec1ca570786b5baeb906b0fc2409c8e0145585e287ee7a526c72" [[package]] name = "pyth-lazer-protocol" -version = "0.1.0" -source = "git+https://github.com/drift-labs/pyth-crosschain?rev=776b6f772ba8ae49f26d16d04649073c3d6f77cf#776b6f772ba8ae49f26d16d04649073c3d6f77cf" +version = "0.1.2" +source = "git+https://github.com/drift-labs/pyth-crosschain?rev=1f8d9d4f5322fa96c51420e3252c3e9a995d5df0#1f8d9d4f5322fa96c51420e3252c3e9a995d5df0" dependencies = [ "anyhow", "byteorder", @@ -1864,27 +1864,18 @@ dependencies = [ ] [[package]] -name = "pyth-lazer-sdk" -version = "0.1.0" -source = "git+https://github.com/drift-labs/pyth-crosschain?rev=776b6f772ba8ae49f26d16d04649073c3d6f77cf#776b6f772ba8ae49f26d16d04649073c3d6f77cf" +name = "pyth-lazer-solana-contract" +version = "0.2.0" +source = "git+https://github.com/drift-labs/pyth-crosschain?rev=1f8d9d4f5322fa96c51420e3252c3e9a995d5df0#1f8d9d4f5322fa96c51420e3252c3e9a995d5df0" dependencies = [ "anchor-lang", "bytemuck", "byteorder", "pyth-lazer-protocol", - "pyth-lazer-solana-contract", "solana-program", "thiserror", ] -[[package]] -name = "pyth-lazer-solana-contract" -version = "0.1.0" -source = "git+https://github.com/drift-labs/pyth-crosschain?rev=776b6f772ba8ae49f26d16d04649073c3d6f77cf#776b6f772ba8ae49f26d16d04649073c3d6f77cf" -dependencies = [ - "anchor-lang", -] - [[package]] name = "pyth-solana-receiver-sdk" version = "0.3.0" diff --git a/programs/drift/Cargo.toml b/programs/drift/Cargo.toml index e15689367..0bda4532c 100644 --- a/programs/drift/Cargo.toml +++ b/programs/drift/Cargo.toml @@ -22,7 +22,7 @@ anchor-lang = "0.29.0" solana-program = "1.16" anchor-spl = "0.29.0" pyth-client = "0.2.2" -pyth-lazer-sdk = { git = "https://github.com/drift-labs/pyth-crosschain", rev = "776b6f772ba8ae49f26d16d04649073c3d6f77cf"} +pyth-lazer-solana-contract = { git = "https://github.com/drift-labs/pyth-crosschain", rev = "1f8d9d4f5322fa96c51420e3252c3e9a995d5df0"} pythnet-sdk = { git = "https://github.com/drift-labs/pyth-crosschain", rev = "3e8a24ecd0bcf22b787313e2020f4186bb22c729"} pyth-solana-receiver-sdk = { git = "https://github.com/drift-labs/pyth-crosschain", rev = "3e8a24ecd0bcf22b787313e2020f4186bb22c729"} bytemuck = { version = "1.4.0" } diff --git a/programs/drift/src/instructions/pyth_lazer_oracle.rs b/programs/drift/src/instructions/pyth_lazer_oracle.rs index 6535f5632..e2468dd3e 100644 --- a/programs/drift/src/instructions/pyth_lazer_oracle.rs +++ b/programs/drift/src/instructions/pyth_lazer_oracle.rs @@ -6,9 +6,13 @@ use crate::state::pyth_lazer_oracle::{ }; use crate::validate; use anchor_lang::prelude::*; -use pyth_lazer_sdk::protocol::payload::{PayloadData, PayloadPropertyValue}; -use pyth_lazer_sdk::protocol::router::Price; +use anchor_lang::InstructionData; +use pyth_lazer_solana_contract::instruction::VerifyMessage; +use pyth_lazer_solana_contract::protocol::message::SolanaMessage; +use pyth_lazer_solana_contract::protocol::payload::{PayloadData, PayloadPropertyValue}; +use pyth_lazer_solana_contract::protocol::router::Price; use solana_program::sysvar::instructions::load_current_index_checked; +use solana_program::{instruction::Instruction as ProgramInstruction, program::invoke}; pub fn handle_update_pyth_lazer_oracle<'c: 'info, 'info>( ctx: Context<'_, '_, 'c, 'info, UpdatePythLazerOracle>, @@ -22,19 +26,32 @@ pub fn handle_update_pyth_lazer_oracle<'c: 'info, 'info>( "instruction index must be greater than 0 to include the sig verify ix" )?; - let verified = pyth_lazer_sdk::verify_message( - &ctx.accounts.pyth_lazer_storage, - &ctx.accounts.ix_sysvar.to_account_info(), - &pyth_message, - ix_idx - 1, - 0, - 12, // 8 bytes for anchor ix discriminator, 4 bytes for borsh vec len encoding - ); - - if verified.is_err() { - msg!("{:?}", verified); - return Err(ErrorCode::UnverifiedPythLazerMessage.into()); - } + invoke( + &ProgramInstruction::new_with_bytes( + pyth_lazer_solana_contract::ID, + &VerifyMessage { + message_data: pyth_message.to_vec(), + ed25519_instruction_index: ix_idx - 1, + signature_index: 0, + message_offset: 12, + } + .data(), + vec![ + AccountMeta::new(*ctx.accounts.keeper.key, true), + AccountMeta::new_readonly(*ctx.accounts.pyth_lazer_storage.key, false), + AccountMeta::new(*ctx.accounts.pyth_lazer_treasury.key, false), + AccountMeta::new_readonly(*ctx.accounts.pyth_lazer_treasury.key, false), + AccountMeta::new_readonly(*ctx.accounts.ix_sysvar.key, false), + ], + ), + &[ + ctx.accounts.keeper.to_account_info(), + ctx.accounts.pyth_lazer_storage.clone(), + ctx.accounts.pyth_lazer_treasury.clone(), + ctx.accounts.system_program.to_account_info(), + ctx.accounts.ix_sysvar.to_account_info(), + ], + )?; // Load oracle accounts from remaining accounts let remaining_accounts = ctx.remaining_accounts; @@ -43,7 +60,10 @@ pub fn handle_update_pyth_lazer_oracle<'c: 'info, 'info>( ErrorCode::OracleTooManyPriceAccountUpdates )?; - let data = PayloadData::deserialize_slice_le(verified.unwrap().payload) + let deserialized_pyth_message = SolanaMessage::deserialize_slice(&pyth_message) + .map_err(|_| ProgramError::InvalidInstructionData)?; + + let data = PayloadData::deserialize_slice_le(&deserialized_pyth_message.payload) .map_err(|_| ProgramError::InvalidInstructionData)?; let next_timestamp = data.timestamp_us.0; @@ -127,10 +147,13 @@ pub struct UpdatePythLazerOracle<'info> { pub keeper: Signer<'info>, /// CHECK: Pyth lazer storage account not available to us #[account( - address = PYTH_LAZER_STORAGE_ID @ ErrorCode::InvalidPythLazerStorageOwner + address = PYTH_LAZER_STORAGE_ID @ ErrorCode::InvalidPythLazerStorageOwner, )] pub pyth_lazer_storage: AccountInfo<'info>, + /// CHECK: this account doesn't need additional constraints. + pub pyth_lazer_treasury: AccountInfo<'info>, /// CHECK: checked by ed25519 verify #[account(address = solana_program::sysvar::instructions::ID)] pub ix_sysvar: AccountInfo<'info>, + pub system_program: Program<'info, System>, } diff --git a/sdk/src/driftClient.ts b/sdk/src/driftClient.ts index 2bd1141e5..2efc0443f 100644 --- a/sdk/src/driftClient.ts +++ b/sdk/src/driftClient.ts @@ -233,6 +233,7 @@ export class DriftClient { txHandler: TxHandler; receiverProgram?: Program; + pythLazerTreausryPubkey?: PublicKey; wormholeProgram?: Program; sbOnDemandProgramdId: PublicKey; sbOnDemandProgram?: Program30; @@ -8529,6 +8530,13 @@ export class DriftClient { return txSig; } + public async loadPythLazerTreasuryPubkey(): Promise { + const accountInfo = await this.connection.getAccountInfo( + PYTH_LAZER_STORAGE_ACCOUNT_KEY + ); + return new PublicKey(accountInfo!.data.slice(40, 72)); + } + public async getUpdatePythPullOracleIxs( params: { merklePriceUpdate: { @@ -8568,7 +8576,7 @@ export class DriftClient { feedIds: number[], pythMessageHex: string ): Promise { - const postIxs = this.getPostPythLazerOracleUpdateIxs( + const postIxs = await this.getPostPythLazerOracleUpdateIxs( feedIds, pythMessageHex, undefined, @@ -8579,12 +8587,16 @@ export class DriftClient { return txSig; } - public getPostPythLazerOracleUpdateIxs( + public async getPostPythLazerOracleUpdateIxs( feedIds: number[], pythMessageHex: string, precedingIxs: TransactionInstruction[] = [], overrideIxCount?: number - ): TransactionInstruction[] { + ): Promise { + if (!this.pythLazerTreausryPubkey) { + this.pythLazerTreausryPubkey = await this.loadPythLazerTreasuryPubkey(); + } + const pythMessageBytes = Buffer.from(pythMessageHex, 'hex'); const verifyIx = createMinimalEd25519VerifyIx( @@ -8608,6 +8620,8 @@ export class DriftClient { keeper: this.wallet.publicKey, pythLazerStorage: PYTH_LAZER_STORAGE_ACCOUNT_KEY, ixSysvar: SYSVAR_INSTRUCTIONS_PUBKEY, + systemProgram: anchor.web3.SystemProgram.programId, + pythLazerTreasury: this.pythLazerTreausryPubkey, }, remainingAccounts: remainingAccountsMeta, } diff --git a/tests/pythLazer.ts b/tests/pythLazer.ts index 4decbe0d6..37fa85f8d 100644 --- a/tests/pythLazer.ts +++ b/tests/pythLazer.ts @@ -96,7 +96,7 @@ describe('pyth lazer oracles', () => { }); it('crank', async () => { - const ixs = driftClient.getPostPythLazerOracleUpdateIxs( + const ixs = await driftClient.getPostPythLazerOracleUpdateIxs( [1], PYTH_LAZER_HEX_STRING_BTC, [] @@ -118,7 +118,7 @@ describe('pyth lazer oracles', () => { }); it('crank multi', async () => { - const ixs = driftClient.getPostPythLazerOracleUpdateIxs( + const ixs = await driftClient.getPostPythLazerOracleUpdateIxs( [1, 2, 6], PYTH_LAZER_HEX_STRING_MULTI ); @@ -135,7 +135,7 @@ describe('pyth lazer oracles', () => { }); it('fails on wrong message passed', async () => { - const ixs = driftClient.getPostPythLazerOracleUpdateIxs( + const ixs = await driftClient.getPostPythLazerOracleUpdateIxs( [1], PYTH_LAZER_HEX_STRING_SOL );