Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
zilinissleepin opened this issue Feb 2, 2024 · 1 comment

Comments

@zilinissleepin
Copy link

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!

@kevinheavey
Copy link
Owner

This is too much to help with, but if you find a bug please post a minimal reproducible example

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants