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

I found a Design Issue when using solana and anchor... #397

Open
zilinissleepin opened this issue Feb 28, 2024 · 0 comments
Open

I found a Design Issue when using solana and anchor... #397

zilinissleepin opened this issue Feb 28, 2024 · 0 comments

Comments

@zilinissleepin
Copy link

intro

I am working for using my own deployed program to swap in DEXs such as orca using anchorpy and solana-py.

But I have found that when I create a instruction with my program, there will be an Error: InvalidParamsMessage { message: "invalid transaction: Transaction failed to sanitize accounts offsets correctly" }

this is my client code:

async def update_owner(new_owner: Pubkey, owner: Keypair):
    acc = await AccessControl.fetch(provider.connection, pda[0])
    print(f"The owner will change from {acc.only_owner} to {new_owner}")
    
    ix = instructions.update_owner({
        "new_owner": new_owner,
    }, {
        "access_control": pda[0],
        "only_owner": owner.pubkey()
    })
    
    recent_blockhash = await provider.connection.get_latest_blockhash(commitment="finalized")
    
    tx = Transaction(recent_blockhash=recent_blockhash.value.blockhash).add(ix)
    
    tx.sign(owner)
    
    print(await provider.simulate(tx))

pda is a PDA address that stores some Access Control Infos.

only_owner is a read-only account that must be signed.

instructions.update_owner is a piece of auto-generated code by anchorpy.

class UpdateOwnerAccounts(typing.TypedDict):
    access_control: Pubkey
    only_owner: Pubkey

def update_owner(
    args: UpdateOwnerArgs,
    accounts: UpdateOwnerAccounts,
    program_id: Pubkey = PROGRAM_ID,
    remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
) -> Instruction:
    keys: list[AccountMeta] = [
        AccountMeta(
            pubkey=accounts["access_control"], is_signer=False, is_writable=True
        ),
        AccountMeta(pubkey=accounts["only_owner"], is_signer=True, is_writable=False),
    ]
    if remaining_accounts is not None:
        keys += remaining_accounts
    identifier = b"\xa4\xbc|\xfe\x84\x1a\xc6\xb2"
    encoded_args = layout.build(
        {
            "new_owner": args["new_owner"],
        }
    )
    data = identifier + encoded_args
    return Instruction(program_id, data, keys)

Therefore, I will include 3 accounts: access_control pda, only_owner account and a transaction payer. But I set the payer the same as the only_owner account. So there will be 2 accounts.

I found that when I run this client code, I will get an error InvalidParamsMessage { message: "invalid transaction: Transaction failed to sanitize accounts offsets correctly" }.

I dive deep and find that the MessageHeader builds incorrectly in solders pacakage. the MessageHeader is header: MessageHeader { num_required_signatures: 1, num_readonly_signed_accounts: 1, num_readonly_unsigned_accounts: 1 }

num_readonly_signed_accounts is 0 not 1, because the only_owner account will be the transaction payer and become writable. However, it seems that the solder and solana SDK does not effectively address this issue.

I have found that the root reason is at tx = Transaction(recent_blockhash=recent_blockhash.value.blockhash).add(ix), Transaction init must clarify the fee_payer, otherwise, the fee_payer will be set to None and cause the Sanitize Error.

But I have clarified the payer already when init the provider.

This is maybe a SDK Design Issue?

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

1 participant