Skip to content

invalid transaction: Transaction failed to sanitize accounts offsets correctly #133

@zilinissleepin

Description

@zilinissleepin

I got an error : InvalidParamsMessage { message: "invalid transaction: Transaction failed to sanitize accounts offsets correctly" } when simulate and send transaction to mainnet and local net.
I have used the "anchorpy client-gen" command to generate a Python client, and I checked many times to make the accounts and args right.

Here is my code:

async def execute_whirlpool_swap():
    MIN_SQRT_PRICE = 4295048016
    MAX_SQRT_PRICE = 79226673515401279992447579055
    WHIRLPOOL_PROGRAM_ID = Pubkey.from_string("whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc")
    
    # swap SOL for USDC
    args = {
        "amount": int(1e9 * 0.01),
        "other_amount_threshold": int(1e6 * 0.01),
        "sqrt_price_limit": MIN_SQRT_PRICE,
        "amount_specified_is_input": True,
        "a_to_b": True
    }
    print("args", args)
    
    pool = await whirlpool.Whirlpool.fetch(provider.connection, SOL_USDC_8_WHIRLPOOL_PUBKEY)
    
    # -24350
    print("pool.tick_current_index", pool.tick_current_index)
    
    tick_arrays = tick_utils.TickUtil.get_tick_array_pdas(tick=pool.tick_current_index,
                                    tick_spacing=pool.tick_spacing,
                                    num_of_tick_arrays=3,
                                    program_id=WHIRLPOOL_PROGRAM_ID,
                                    whirlpool_address=SOL_USDC_8_WHIRLPOOL_PUBKEY, 
                                    a_to_b=True)
    
    seeds = [bytes("oracle", 'utf8'), bytes(SOL_USDC_8_WHIRLPOOL_PUBKEY)]
    oracle = Pubkey.find_program_address(seeds, WHIRLPOOL_PROGRAM_ID)
    
    accounts = instructions.ExecuteWhirlpoolSwapAccounts(
        whirlpool_program = WHIRLPOOL_PROGRAM_ID,
        access_control = pda[0],
        whirlpool = SOL_USDC_8_WHIRLPOOL_PUBKEY,
        token_owner_account_a = get_associated_token_address(owner=dev.pubkey(), mint=WRAPPED_SOL_MINT),
        token_vault_a = Pubkey.from_string("9RfZwn2Prux6QesG1Noo4HzMEBv3rPndJ2bN2Wwd6a7p"),
        token_owner_account_b = get_associated_token_address(owner=dev.pubkey(), mint=USDC),
        token_vault_b = Pubkey.from_string("BVNo8ftg2LkkssnWT4ZWdtoFaevnfD6ExYeramwM27pe"),
        oracle = oracle[0],
        # oracle = Pubkey.from_string("6vK8gSiRHSnZzAa5JsvBF2ej1LrxpRX21Y185CzP4PeA"),
        # oracle = Pubkey.from_string("BVNo8ftg2LkkssnWT4ZWdtoFaevnfD6ExYeramwM27pe"), ####
        tick_array0 = tick_arrays[0].public_key,
        tick_array1 = tick_arrays[1].public_key,
        tick_array2 = tick_arrays[2].public_key,
        executor = dev.pubkey(),
    )
    
    ix = instructions.execute_whirlpool_swap(args, accounts)
    
    recent_blockhash = await provider.connection.get_latest_blockhash(commitment="finalized")
    
    tx = Transaction(recent_blockhash=recent_blockhash.value.blockhash).add(ix)
    
    tx.sign(dev)
    
    print("dev", dev.pubkey())
    
    # NOTE: for simulate
    print(await provider.simulate(tx))

"execute_whirlpool_swap" is to send a orca swap transaction.
"instructions.execute_whirlpool_swap" is my program function.
Type "ExecuteWhirlpoolSwapAccounts" is auto generated. Here is detail:

class ExecuteWhirlpoolSwapArgs(typing.TypedDict):
    amount: int
    other_amount_threshold: int
    sqrt_price_limit: int
    amount_specified_is_input: bool
    a_to_b: bool


layout = borsh.CStruct(
    "amount" / borsh.U64,
    "other_amount_threshold" / borsh.U64,
    "sqrt_price_limit" / borsh.U128,
    "amount_specified_is_input" / borsh.Bool,
    "a_to_b" / borsh.Bool,
)


class ExecuteWhirlpoolSwapAccounts(typing.TypedDict):
    whirlpool_program: Pubkey
    access_control: Pubkey
    whirlpool: Pubkey
    token_owner_account_a: Pubkey
    token_vault_a: Pubkey
    token_owner_account_b: Pubkey
    token_vault_b: Pubkey
    tick_array0: Pubkey
    tick_array1: Pubkey
    tick_array2: Pubkey
    oracle: Pubkey
    executor: Pubkey


def execute_whirlpool_swap(
    args: ExecuteWhirlpoolSwapArgs,
    accounts: ExecuteWhirlpoolSwapAccounts,
    program_id: Pubkey = PROGRAM_ID,
    remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
) -> Instruction:
    keys: list[AccountMeta] = [
        AccountMeta(
            pubkey=accounts["whirlpool_program"], is_signer=False, is_writable=False
        ),
        AccountMeta(pubkey=TOKEN_PROGRAM_ID, is_signer=False, is_writable=False),
        AccountMeta(
            pubkey=accounts["access_control"], is_signer=False, is_writable=False
        ),
        AccountMeta(pubkey=accounts["whirlpool"], is_signer=False, is_writable=True),
        AccountMeta(
            pubkey=accounts["token_owner_account_a"], is_signer=False, is_writable=True
        ),
        AccountMeta(
            pubkey=accounts["token_vault_a"], is_signer=False, is_writable=True
        ),
        AccountMeta(
            pubkey=accounts["token_owner_account_b"], is_signer=False, is_writable=True
        ),
        AccountMeta(
            pubkey=accounts["token_vault_b"], is_signer=False, is_writable=True
        ),
        AccountMeta(pubkey=accounts["tick_array0"], is_signer=False, is_writable=True),
        AccountMeta(pubkey=accounts["tick_array1"], is_signer=False, is_writable=True),
        AccountMeta(pubkey=accounts["tick_array2"], is_signer=False, is_writable=True),
        AccountMeta(pubkey=accounts["oracle"], is_signer=False, is_writable=False),
        AccountMeta(pubkey=accounts["executor"], is_signer=True, is_writable=False),
    ]
    print("token program id", TOKEN_PROGRAM_ID)
    if remaining_accounts is not None:
        keys += remaining_accounts
    identifier = b"\x8cW\xc8\xe1 d\xae\xe1"
    encoded_args = layout.build(
        {
            "amount": args["amount"],
            "other_amount_threshold": args["other_amount_threshold"],
            "sqrt_price_limit": args["sqrt_price_limit"],
            "amount_specified_is_input": args["amount_specified_is_input"],
            "a_to_b": args["a_to_b"],
        }
    )
    data = identifier + encoded_args
    return Instruction(program_id, data, keys)

Please help me find out why I got this error. I would appreciate very much. Thanks a lot!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions