Agenda
Anchorでアカウント作成(init)を2つ同時実施したときのエラー
現象
anchor testすると以下のエラー。
ターミナル
hello
1) Creates a vault
0 passing (156ms)
1 failing
1) hello
Creates a vault:
Error: Signature verification failed
at Transaction.serialize (node_modules/@solana/web3.js/src/transaction.ts:736:13)
at AnchorProvider.sendAndConfirm (node_modules/@project-serum/anchor/src/provider.ts:145:22)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at MethodsBuilder.rpc [as _rpcFn] (node_modules/@project-serum/anchor/src/program/namespace/rpc.ts:29:16)
lib.rs
use anchor_lang::prelude::*;
declare_id!("6KzWJqAvnZhDZDkd69N6oVy7ySVsXDMM2B7UfQynEpf4");
#[program]
pub mod hello {
use super::*;
pub fn create(ctx: Context<Create>, authority: Pubkey) -> Result<()> {
let vault = &mut ctx.accounts.vault;
vault.authority = authority;
vault.count = 0;
Ok(())
}
}
#[derive(Accounts)]
pub struct Create<'info> {
#[account(init, payer = user, space = 8 + 40)]
pub vault: Account<'info, Vault>,
#[account(mut)]
pub user: Signer<'info>,
pub system_program: Program<'info, System>,
#[account(init, payer = user, space = 8 + 40)]
pub vault2: Account<'info, Vault2>,
}
#[account]
pub struct Vault {
pub authority: Pubkey,
pub count: u64,
}
#[account]
pub struct Vault2 {
pub authority: Pubkey,
pub count: u64,
}
tests/hello.ts
import * as anchor from "@project-serum/anchor";
import { Program } from "@project-serum/anchor";
import { Hello } from "../target/types/hello";
import { assert } from 'chai';
describe("hello", () => {
// Configure the client to use the local cluster.
anchor.setProvider(anchor.AnchorProvider.env());
const program = anchor.workspace.Hello as Program<Hello>;
const provider = anchor.AnchorProvider.local();
const vault = anchor.web3.Keypair.generate();
const vault2 = anchor.web3.Keypair.generate();
console.log(vault.publicKey.toString());
console.log(vault2.publicKey.toString());
it("Creates a vault", async () => {
await program.methods
.create(
provider.wallet.publicKey
)
.accounts({
vault: vault.publicKey,
user: provider.wallet.publicKey,
systemProgram: anchor.web3.SystemProgram.programId,
vault2: vault2.publicKey,
})
.signers([vault])
.rpc()
let vaultAccount = await program.account.vault.fetch(vault.publicKey);
assert.ok(vaultAccount.authority.equals(provider.wallet.publicKey));
assert.ok(vaultAccount.count.toNumber() === 0);
});
});
原因
2つ目のアカウントを作成するためのSignerが足りていないため。
対応
Signersに2つ目のアカウントを作成するためのKeypairを渡す。
tests/hello.ts
const vault = anchor.web3.Keypair.generate();
const vault2 = anchor.web3.Keypair.generate();
〜〜〜省略〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
.accounts({
vault: vault.publicKey,
user: provider.wallet.publicKey,
systemProgram: anchor.web3.SystemProgram.programId,
vault2: vault2.publicKey,
})
.signers([vault, vault2]) // ← ここに2つ目(vault2)を追加
@solana/spl-tokenのmintToしたときのエラー
@solana/spl-token v0.2.0で、mintToしたときに発生したエラー。
現象
anchor testを実行すると以下のエラーが発生。
(エラー発生箇所は、Anchorとは関係なく、Solanaのjs「spl-token」で発生)
ターミナル:
escrow
1) Initialise escrow state
0 passing (2s)
1 failing
1) escrow
Initialise escrow state:
Error: Signature verification failed
at Transaction.serialize (node_modules/@solana/web3.js/src/transaction.ts:736:13)
at Connection.sendTransaction (node_modules/@solana/web3.js/src/connection.ts:4426:41)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at sendAndConfirmTransaction (node_modules/@solana/web3.js/src/util/send-and-confirm-transaction.ts:31:21)
escrow.ts(抜粋):
const payer = Keypair.generate();
const mintAuthority = Keypair.generate();
const mintA = await createMint(
connection, // connection
payer, // payer
mintAuthority.publicKey, // mintAuthority
null, // freezeAuthority
9 // decimals
);
const mintATx = await mintTo(
connection, // connection
payer, // payer
mintA, // mint
initializerTokenAccountA.address, // destination
mintAuthority.publicKey, // authority
initializerAmount, // amount
[] // signer(s)
);
原因
authorityがpayerと異なる場合は、Keypairの指定が必要っぽい?
もし、 payer = authority だと、publicKeyの指定でも大丈夫だった。
solana-program-library/mintTo.ts のパラメータ
「authority: Signer | PublicKey,」とあるが、テストコードでは
solana-program-library/mint.test.ts のテストコード
「let mintAuthority: Keypair;」となっていて、KeyPairを渡していた。
対応
authorityにKeypairを渡すようにして解決。
escrow.ts(抜粋):
const payer = Keypair.generate();
const mintAuthority = Keypair.generate();
const mintA = await createMint(
connection, // connection
payer, // payer
mintAuthority.publicKey, // mintAuthority
null, // freezeAuthority
9 // decimals
);
const mintATx = await mintTo(
connection, // connection
payer, // payer
mintA, // mint
initializerTokenAccountA.address, // destination
mintAuthority, // authority ← Keypairを渡すようにした
initializerAmount, // amount
[] // signer(s)
);