diff --git a/chainlink.go b/chainlink.go index 5347507..31cd17b 100644 --- a/chainlink.go +++ b/chainlink.go @@ -25,6 +25,9 @@ func chainLinkParser(tx *Tx, instruction Instruction, inners InnerInstructions, } decode := instruction.Data + if len(decode) < 4 { + return increaseOffset(offset), nil + } discriminator := binary.LittleEndian.Uint32(decode[0:4]) switch discriminator { @@ -55,6 +58,9 @@ func chainLinkSubmitParser(instruction Instruction, inners InnerInstructions, of if storeInstruction.Accounts[0] >= len(tx.rawTx.accountList) || tx.rawTx.accountList[storeInstruction.Accounts[0]] != chainlinkSOLUSDFeedAccount { return increaseOffset(offset), InstructionIgnoredError } + if len(storeInstruction.Data) < 8 { + return increaseOffset(offset), InstructionIgnoredError + } if !bytes.Equal(storeInstruction.Data[0:8], chainlinkSubmitDiscriminator[:]) { return increaseOffset(offset), InstructionIgnoredError } diff --git a/metaorapool.go b/metaorapool.go index f68972d..3632c79 100644 --- a/metaorapool.go +++ b/metaorapool.go @@ -741,6 +741,9 @@ func metaoraPoolRemoveLiquidity(tx *Tx, instruction Instruction, innerInstructio } func metaoraPoolSwap(tx *Tx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { + if len(instruction.Accounts) < 13 { + return nil, increaseOffset(offset), fmt.Errorf("not enough accounts for swap instruction") + } swapOffset := offset var args metaoraPoolSwapArgs if err := agbinary.NewBorshDecoder(instruction.Data[8:]).Decode(&args); err != nil { diff --git a/meteoradamm.go b/meteoradamm.go index 2e217fc..4185c28 100644 --- a/meteoradamm.go +++ b/meteoradamm.go @@ -83,7 +83,13 @@ type MetaoraDammInitializePoolEvent struct { } func meteoraDammV2InitializePoolParser(tx *Tx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { - if len(instruction.Accounts) < 12 { + requiredAccounts := 12 + if bytes.Equal(instruction.Data[:8], meteoraDammV2InitializePoolWithDynamicConfig[:]) { + requiredAccounts = 13 + } else if bytes.Equal(instruction.Data[:8], meteoraDammV2InitializeCustomizablePoolDiscriminator[:]) { + requiredAccounts = 11 + } + if len(instruction.Accounts) < requiredAccounts { return nil, increaseOffset(offset), fmt.Errorf("invalid instruction accounts length") } var entryContract = tx.rawTx.accountList[tx.rawTx.Transaction.Message.Instructions[offset[0]].ProgramIDIndex] @@ -439,7 +445,7 @@ func meteoraDammV2AddLiquidityParser(tx *Tx, instruction Instruction, innerInstr } func meteoraDammV2RemoveLiquidityParser(tx *Tx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { - if len(instruction.Accounts) < 8 { + if len(instruction.Accounts) < 9 { return nil, increaseOffset(offset), fmt.Errorf("invalid instruction accounts length") } tokenAMint := tx.rawTx.accountList[instruction.Accounts[7]] diff --git a/pump.go b/pump.go index 702097c..a702473 100644 --- a/pump.go +++ b/pump.go @@ -173,9 +173,17 @@ func CreateParser(tx *Tx, instr Instruction, innerInstructions InnerInstructions } userIndex := 0 if bytes.HasPrefix(instr.Data, pumpCreateV2Discriminator[:]) { + if len(instr.Accounts) < 6 { + return nil, increaseOffset(offset), InstructionIgnoredError + } userIndex = instr.Accounts[5] } else if bytes.HasPrefix(instr.Data, pumpCreateDiscriminator[:]) { + if len(instr.Accounts) < 8 { + return nil, increaseOffset(offset), InstructionIgnoredError + } userIndex = instr.Accounts[7] + } else { + return nil, increaseOffset(offset), InstructionIgnoredError } userBase := getAccountBalanceAfterTx(result, userIndex) userQuote, _ := GetSolAfterTx(result, userIndex) diff --git a/pumpamm.go b/pumpamm.go index f098d62..f3dfdaf 100644 --- a/pumpamm.go +++ b/pumpamm.go @@ -182,6 +182,9 @@ func pumpAmmParser(tx *Tx, instruction Instruction, innerInstructions InnerInstr } func ammCreatePoolParser(tx *Tx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { + if len(instruction.Accounts) < 15 { + return nil, increaseOffset(offset), InstructionIgnoredError + } result := tx.rawTx var entryContract = result.accountList[result.Transaction.Message.Instructions[offset[0]].ProgramIDIndex] var err error @@ -275,6 +278,9 @@ func pumpAmmSwapAmountInfoFromArgs(args PumpSwapArgs) (swapMode SwapMode, fixedA } func failedTxAmmBuyParser(tx *Tx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { + if len(instruction.Accounts) < 13 { + return nil, increaseOffset(offset), InstructionIgnoredError + } if tx.Err == nil || tx.Err.UnKnown != "" { return nil, increaseOffset(offset), fmt.Errorf("tx pump amm sell failed but error is nil, offset, %d, %d", offset[0], offset[1]) } @@ -401,6 +407,9 @@ func failedTxAmmBuyParser(tx *Tx, instruction Instruction, innerInstructions Inn } func failedTxAmmSellParser(tx *Tx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { + if len(instruction.Accounts) < 13 { + return nil, increaseOffset(offset), InstructionIgnoredError + } if tx.Err == nil || tx.Err.UnKnown != "" { return nil, increaseOffset(offset), fmt.Errorf("tx pump amm sell failed but error is nil, offset, %d, %d", offset[0], offset[1]) } @@ -525,6 +534,9 @@ func ammBuyParser(tx *Tx, instruction Instruction, innerInstructions InnerInstru var entryContract = result.accountList[result.Transaction.Message.Instructions[offset[0]].ProgramIDIndex] var err error var prefixLen = offset[1] + if len(instruction.Accounts) < 13 { + return nil, increaseOffset(offset), InstructionIgnoredError + } inners, err := getInnerInstructions(innerInstructions, prefixLen) if err != nil { return nil, increaseOffset(offset), fmt.Errorf("pumpamm create get inner instructions error: %v, offset: %d, %d", err, offset[0], prefixLen) @@ -662,6 +674,9 @@ func ammSellParser(tx *Tx, instruction Instruction, innerInstructions InnerInstr result := tx.rawTx var entryContract = result.accountList[result.Transaction.Message.Instructions[offset[0]].ProgramIDIndex] var err error + if len(instruction.Accounts) < 13 { + return nil, increaseOffset(offset), InstructionIgnoredError + } var prefixLen = offset[1] inners, err := getInnerInstructions(innerInstructions, prefixLen) if err != nil { @@ -789,6 +804,9 @@ func depositParse(tx *Tx, instruction Instruction, innerInstructions InnerInstru result := tx.rawTx var entryContract = result.accountList[result.Transaction.Message.Instructions[offset[0]].ProgramIDIndex] var err error + if len(instruction.Accounts) < 11 { + return nil, increaseOffset(offset), InstructionIgnoredError + } var prefixLen = offset[1] inners, err := getInnerInstructions(innerInstructions, prefixLen) if err != nil { @@ -887,6 +905,9 @@ func withdrawParse(tx *Tx, instruction Instruction, innerInstructions InnerInstr result := tx.rawTx var entryContract = result.accountList[result.Transaction.Message.Instructions[offset[0]].ProgramIDIndex] var err error + if len(instruction.Accounts) < 11 { + return nil, increaseOffset(offset), InstructionIgnoredError + } var prefixLen = offset[1] inners, err := getInnerInstructions(innerInstructions, prefixLen) if err != nil { diff --git a/raydiumclmm.go b/raydiumclmm.go index b9c2ceb..4496456 100644 --- a/raydiumclmm.go +++ b/raydiumclmm.go @@ -108,38 +108,14 @@ func raydiumClmmAddLiquidityParser(tx *Tx, instruction Instruction, innerInstruc switch discriminator { case raydiumClmmIncreaseLiquidityDiscriminator: accountMin = 12 - market = tx.rawTx.accountList[instruction.Accounts[2]] - vault0 = instruction.Accounts[9] - vault1 = instruction.Accounts[10] case raydiumClmmIncreaseLiquidityV2Discriminator: accountMin = 15 - market = tx.rawTx.accountList[instruction.Accounts[2]] - vault0 = instruction.Accounts[9] - vault1 = instruction.Accounts[10] - //token0 = tx.rawTx.accountList[instruction.Accounts[13]] - //token1 = tx.rawTx.accountList[instruction.Accounts[14]] case raydiumClmmOpenPositionDiscriminator: accountMin = 19 - market = tx.rawTx.accountList[instruction.Accounts[5]] - vault0 = instruction.Accounts[12] - vault1 = instruction.Accounts[13] - lpToken = tx.rawTx.accountList[instruction.Accounts[2]] case raydiumClmmOpenPositionV2Discriminator: accountMin = 22 - market = tx.rawTx.accountList[instruction.Accounts[5]] - vault0 = instruction.Accounts[12] - vault1 = instruction.Accounts[13] - lpToken = tx.rawTx.accountList[instruction.Accounts[2]] - //token0 = tx.rawTx.accountList[instruction.Accounts[20]] - //token1 = tx.rawTx.accountList[instruction.Accounts[21]] case raydiumClmmOpenPositionWithToken22NftDiscriminator: accountMin = 20 - market = tx.rawTx.accountList[instruction.Accounts[4]] - vault0 = instruction.Accounts[11] - vault1 = instruction.Accounts[12] - lpToken = tx.rawTx.accountList[instruction.Accounts[2]] - //token0 = tx.rawTx.accountList[instruction.Accounts[18]] - //token1 = tx.rawTx.accountList[instruction.Accounts[19]] default: return nil, increaseOffset(offset), fmt.Errorf("invalid discriminator") } @@ -148,6 +124,23 @@ func raydiumClmmAddLiquidityParser(tx *Tx, instruction Instruction, innerInstruc return nil, increaseOffset(offset), fmt.Errorf("not enough accounts for raydiumClmm add liquidity instruction, offset, %d, %d", offset[0], offset[1]) } + switch discriminator { + case raydiumClmmIncreaseLiquidityDiscriminator, raydiumClmmIncreaseLiquidityV2Discriminator: + market = tx.rawTx.accountList[instruction.Accounts[2]] + vault0 = instruction.Accounts[9] + vault1 = instruction.Accounts[10] + case raydiumClmmOpenPositionDiscriminator, raydiumClmmOpenPositionV2Discriminator: + market = tx.rawTx.accountList[instruction.Accounts[5]] + vault0 = instruction.Accounts[12] + vault1 = instruction.Accounts[13] + lpToken = tx.rawTx.accountList[instruction.Accounts[2]] + case raydiumClmmOpenPositionWithToken22NftDiscriminator: + market = tx.rawTx.accountList[instruction.Accounts[4]] + vault0 = instruction.Accounts[11] + vault1 = instruction.Accounts[12] + lpToken = tx.rawTx.accountList[instruction.Accounts[2]] + } + baseTokenBalance, err := getTokenBalanceAfterTx(tx.rawTx, vault0) if err != nil { return nil, increaseOffset(offset), fmt.Errorf("failed to get token0 vault balance after tx: %v", err) @@ -197,6 +190,8 @@ func raydiumClmmDecreaseLiquidityParser(tx *Tx, instruction Instruction, innerIn accountMin = 14 } else if discriminator == raydiumClmmDecreaseLiquidityV2Discriminator { accountMin = 16 + } else { + return nil, increaseOffset(offset), fmt.Errorf("invalid discriminator") } if len(instruction.Accounts) < accountMin { return nil, increaseOffset(offset), fmt.Errorf("not enough accounts for decrease liquidity instruction") @@ -299,23 +294,21 @@ func raydiumClmmSwapParser(tx *Tx, instruction Instruction, innerInstructions In } if discriminator == raydiumClmmSwapDiscriminator { accountMin = 9 - pool = tx.rawTx.accountList[instruction.Accounts[2]] - userTokenInAccount = instruction.Accounts[3] - userTokenOutAccount = instruction.Accounts[4] - tokenInVault = instruction.Accounts[5] - tokenOutVault = instruction.Accounts[6] } else if discriminator == raydiumClmmSwapV2Discriminator { accountMin = 13 - pool = tx.rawTx.accountList[instruction.Accounts[2]] - userTokenInAccount = instruction.Accounts[3] - userTokenOutAccount = instruction.Accounts[4] - tokenInVault = instruction.Accounts[5] - tokenOutVault = instruction.Accounts[6] + } else { + return nil, increaseOffset(offset), fmt.Errorf("invalid discriminator") } if len(instruction.Accounts) < accountMin { return nil, increaseOffset(offset), fmt.Errorf("not enough accounts for swap instruction") } + pool = tx.rawTx.accountList[instruction.Accounts[2]] + userTokenInAccount = instruction.Accounts[3] + userTokenOutAccount = instruction.Accounts[4] + tokenInVault = instruction.Accounts[5] + tokenOutVault = instruction.Accounts[6] + baseTokenBalance, err := getTokenBalanceAfterTx(tx.rawTx, tokenInVault) if err != nil { return nil, increaseOffset(offset), fmt.Errorf("failed to get tokenIn vault balance after tx: %w", err) diff --git a/raydiumlaunchlab.go b/raydiumlaunchlab.go index f0b1eab..42c04e3 100644 --- a/raydiumlaunchlab.go +++ b/raydiumlaunchlab.go @@ -373,6 +373,9 @@ type raydiumLaunchLabSwapArgs struct { } func raydiumLaunchLabSwapParser(tx *Tx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { + if len(instruction.Accounts) < 13 { + return nil, increaseOffset(offset), InstructionIgnoredError + } platformConfig := tx.rawTx.accountList[instruction.Accounts[3]] var programName string if platformConfig.Equals(bonkPlatformConfig) { diff --git a/system.go b/system.go index f3ddfc6..75faa30 100644 --- a/system.go +++ b/system.go @@ -15,6 +15,9 @@ func systemParser(tx *Tx, instruction Instruction, _ InnerInstructions, offset [ } decode := instruction.Data + if len(decode) < 4 { + return increaseOffset(offset), nil + } discriminator := binary.LittleEndian.Uint32(decode[0:4]) switch discriminator { @@ -29,6 +32,9 @@ func TransferParser(result *RawTx, instruction Instruction, offset [2]uint, tx * if len(decodeData) < 8 { return increaseOffset(offset), nil } + if len(instruction.Accounts) < 2 || len(result.Transaction.Message.Instructions[offset[0]].Accounts) < 1 { + return increaseOffset(offset), InstructionIgnoredError + } var lamports uint64 = binary.LittleEndian.Uint64(decodeData) from := result.accountList[result.Transaction.Message.Instructions[offset[0]].Accounts[0]]