You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EIP3009调用失败:签名无效问题排查求助

排查EIP3009 transferWithAuthorization签名无效问题

调用EIP3009的transferWithAuthorization(委托转账)功能时,交易报错:Fail with error 'FiatTokenV2: invalid signature'。交易哈希为0x405cb5c8a6f0295d1194bf6ce794f906537cefb5b65ab2005d674812e7f66c35,合约地址为0x1c7d4b196cb0c7b01d743fbc6116a902379c7238。怀疑链下签名存在问题,附上Python代码请求排查:

chain_id = 11155111  # Sepolia chain id
full_message = {
    "types": {
        "EIP712Domain": [
            {"name": "name", "type": "string"},
            {"name": "version", "type": "string"},
            {"name": "chainId", "type": "uint256"},
            {"name": "verifyingContract", "type": "address"},
        ],
        "TransferWithAuthorization": [
            {"name": "from", "type": "address"},
            {"name": "to", "type": "address"},
            {"name": "value", "type": "uint256"},
            {"name": "validAfter", "type": "uint256"},
            {"name": "validBefore", "type": "uint256"},
            {"name": "nonce", "type": "bytes32"},
        ],
    },
    "primaryType": "TransferWithAuthorization",
    "domain": {
        "name": "USDC",
        "version": "2",
        "chainId": chain_id,
        "verifyingContract": contract_address,
    },
    "message": {
        "from": token_owner_address,
        "to": recipient_address,
        "value": value,
        "validAfter": validAfter,
        "validBefore": validBefore,
        "nonce": "0x" + secrets.token_hex(32),
    },
}

# Get signable bytes according to EIP-712
signed_message = Account.sign_typed_data(token_owner_private_key, full_message=full_message)

v = signed_message.v
r_hex = hex(signed_message.r)
s_hex = hex(signed_message.s)


contract = w3.eth.contract(address=w3.to_checksum_address(contract_address), abi=abi)

tx = contract.functions.transferWithAuthorization(
    token_owner_address,
    recipient_address,
    value,
    validAfter,
    validBefore,
    nonce,
    v,
    r_hex,
    s_hex
).build_transaction({
    "from": fee_payer_address,
    "nonce": w3.eth.get_transaction_count(fee_payer_address),
    "gas": 200000,
    "gasPrice": w3.to_wei("10", "gwei"),
    "chainId": chain_id
})

signed_tx = w3.eth.account.sign_transaction(tx, private_key=fee_payer_private_key)
tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)

可能的问题点及修正建议

  • Nonce一致性问题:代码中签名时生成的nonce是临时值,但调用合约时传入的nonce变量未明确和签名值绑定。需确保签名与合约调用使用完全相同的nonce,建议生成后存入变量并同步到message和调用参数中:

    nonce = "0x" + secrets.token_hex(32)
    full_message["message"]["nonce"] = nonce
    
  • R/S参数格式错误:Account.sign_typed_data返回的r和s是整数,代码中用hex()转成十六进制字符串后传入合约,但合约要求bytes32类型。直接传入整数即可,web3.py会自动处理格式转换:

    r = signed_message.r
    s = signed_message.s
    # 调用合约时直接传r、s整数
    tx = contract.functions.transferWithAuthorization(..., r, s).build_transaction(...)
    
  • Domain参数校验:确认合约实际的name和version是否为"USDC"和"2",可通过调用合约的name()、version()方法获取准确值,不一致会导致EIP-712签名验证失败。

  • 地址格式问题:确保token_owner_address、contract_address等均为校验和格式(checksum address),签名与合约调用的地址格式需完全一致。

  • 私钥与地址匹配:验证token_owner_private_key对应的地址确实是token_owner_address,私钥地址不匹配会直接导致签名无效。

内容的提问来源于stack exchange,提问作者Itai Bar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 09:11:00