Solang token.sol调用mint_to报unknown signer错误如何解决
Solang 调用Solana token.sol合约mint_to报unknown signer错误修复方案
错误根因
抛出unknown signer: <publicKey>错误的本质是Solana交易编译阶段,发现交易要求的签名方没有提供对应的签名密钥,代码存在两个核心问题:
- 调用
mint_to方法时传入的signers数组只包含mintAuthority,遗漏了支付交易手续费的payer密钥对,同时mintAuthority是单独生成的密钥对,没有和合约初始化的mint权限做绑定,合约校验签名时无法识别该签名方。 - 手动调用
@solana/spl-token的createMint方法独立创建代币Mint,和Solang官方token.sol合约内置的Mint初始化逻辑冲突,后续调用set_mint传入的Mint地址对应的权限配置和合约预期不匹配。
修复步骤
- 移除外部手动调用
createMint的逻辑,直接使用合约内置的create_mint方法完成代币初始化,保证权限配置和合约存储状态一致。 - 调用合约方法时,将所有需要参与签名的密钥对(包括支付手续费的payer、mint权限方)完整传入
signers配置数组,不要遗漏签名方。 - 账户传入顺序、可写账户配置严格对齐合约的接口要求,公钥参数统一使用
publicKeyToHex转换为合约可识别的hex格式。
修正后的可运行代码
const web3 = require('@solana/web3.js'); const { PublicKey, clusterApiUrl, Connection, LAMPORTS_PER_SOL, Keypair } = require('@solana/web3.js'); const { Contract, publicKeyToHex } = require('@solana/solidity'); const { readFileSync } = require('fs'); const { TOKEN_PROGRAM_ID, getAssociatedTokenAddress, createAssociatedTokenAccountInstruction } = require('@solana/spl-token'); const SPL_TOKEN_ABI = JSON.parse(readFileSync('./Token.abi', 'utf8')); const PROGRAM_SO = readFileSync('./bundle.so'); (async function () { console.log('Connecting to Solana devnet ...'); const connection = new Connection(clusterApiUrl('devnet'), 'confirmed'); const payer = Keypair.generate(); const mintAuthority = payer; const program = Keypair.generate(); const storage = Keypair.generate(); console.log('Payer address: ' + payer.publicKey.toBase58()); console.log('Airdropping SOL to payer wallet ...'); const signature = await connection.requestAirdrop(payer.publicKey, 1.5 * LAMPORTS_PER_SOL); await connection.confirmTransaction(signature, 'confirmed'); console.log('Initializing contract instance ...'); const contract = new Contract(connection, program.publicKey, storage.publicKey, SPL_TOKEN_ABI, payer); console.log('Program address: ' + program.publicKey.toBase58()); console.log('Storage address: ' + storage.publicKey.toBase58()); await contract.load(program, PROGRAM_SO); await contract.deploy('Token', [], program, storage, 3096 *8); console.log('Contract deployed successfully'); console.log('Creating token mint via contract ...'); const decimals = 3; await contract.functions.create_mint( publicKeyToHex(mintAuthority.publicKey), publicKeyToHex(mintAuthority.publicKey), decimals, { accounts: [TOKEN_PROGRAM_ID], signers: [payer] } ); const mint = new PublicKey((await contract.functions.get_mint())[0]); console.log('Mint address: ' + mint.toBase58()); console.log('Creating associated token account ...'); const tokenAccount = await getAssociatedTokenAddress( mint, payer.publicKey ); const createAtaIx = createAssociatedTokenAccountInstruction( payer.publicKey, tokenAccount, payer.publicKey, mint ); const ataTx = new web3.Transaction().add(createAtaIx); await web3.sendAndConfirmTransaction(connection, ataTx, [payer]); console.log('Token account address: ' + tokenAccount.toBase58()); console.log('Minting tokens ...'); const mintAmount = 100000; await contract.functions.mint_to( publicKeyToHex(tokenAccount), publicKeyToHex(mintAuthority.publicKey), mintAmount, { accounts: [TOKEN_PROGRAM_ID], writableAccounts: [mint, tokenAccount], signers: [payer, mintAuthority] } ); console.log('Mint completed successfully!'); })();
关键注意事项
- 不要混用SPL Token原生SDK和Solang合约的代币操作逻辑:官方
token.sol已经封装了SPL代币的全流程操作,外部手动创建Mint、修改Mint权限会导致合约状态和链上状态不一致。 - 所有参与交易签名的密钥对必须完整传入
signers数组,包括支付手续费的账户,少传任何一个签名方都会触发unknown signer报错。 - 传入合约的地址参数必须转换为hex格式,不要直接传入base58编码的字符串,避免合约解析参数失败。
内容的提问来源于stack exchange,提问作者Aleks Nagorniak
相关产品推荐
相关产品推荐

