使用ethereumjs-tx签名以太坊主网交易时遇EIP155兼容性错误
问题根源及解决方案
错误原因
- 手动设置无效的
v值:你在交易对象里硬写了v: "0x1",但以太坊主网(chainId=1)遵循EIP155规范——未签名交易不需要设置v、r、s字段,这些值是签名后自动生成的,且主网合法的v值应为37或38(计算公式:2*chainId + 35/2*chainId + 36)。 - 未指定chainId参数:创建
Transaction实例时没传入chainId选项,导致ethereumjs-tx无法按照EIP155规则验证交易,触发兼容性错误。
修正步骤及代码
1. 清理交易对象,移除无效字段
删掉交易中的v、r、s,同时把硬编码的gasLimit换成之前定义的变量,保持代码一致性:
const tx_ = { to: host, nonce: web3.utils.toHex(nonce1), gasLimit: web3.utils.toHex(gasLimit), // 使用提前定义的gasLimit变量 gasPrice: web3.utils.toHex(txFee), value: web3.utils.toHex(1000000000000n), data: "0x", };
2. 修改hashTx函数,传入chainId配置
创建Transaction时明确指定chainId,让库按照EIP155规则处理交易:
const hashTx = (hash: TxData, chainId: bigint): Transaction => { // 传入chainId,匹配主网的chainId=1 const tx = new Transaction(hash, { chainId: Number(chainId) }); return tx; }; // 创建交易实例时传入获取到的chainId const tx: Transaction = hashTx(tx_, chainId);
3. 完成交易签名(两种可选方式)
方式一:用ethereumjs-tx签名
如果需要用该库完成签名,调用sign方法即可:
import { Buffer } from 'buffer'; // 私钥需转为Buffer格式 const privateKey = Buffer.from('你的发送者私钥', 'hex'); tx.sign(privateKey); // 获取序列化后的交易和交易哈希 const serializedTx = tx.serialize().toString('hex'); const txHash = tx.hash().toString('hex');
方式二:用web3.js直接签名
更简便的方式是用web3.js内置方法,自动处理EIP155规则:
const signedTx = await web3.eth.signTransaction(tx_, '你的发送者私钥'); // 获取序列化交易和哈希 const serializedTx = signedTx.rawTransaction; const txHash = signedTx.transactionHash;
额外注意事项
- 永远不要手动设置
v、r、s,这些是签名算法生成的字段,手动赋值会破坏EIP155的验证逻辑。 - 确保
chainId与当前连接的网络一致(主网1、Goerli测试网5等)。
内容的提问来源于stack exchange,提问作者Adebayo Anuoluwa
相关产品推荐
相关产品推荐

