调用write方法时无法拉起来metamask的原因。

调用write的智能合约方法时,有些方法可以来起来metamask,有些方法却不可以,甚至有些方法一开始可以,后面不可以了。这些问题的原因如下:首先确定一点,就是调用智能合约方法都是纯前端的代码,完全没有和服务器后段交互。是前端js直接和钱包的rpc接口进行通信的。当调用一个需要写入的合约方

调用write的智能合约方法时,有些方法可以来起来metamask,有些方法却不可以,甚至有些方法一开始可以,后面不可以了。这些问题的原因如下:

首先确定一点,就是调用智能合约方法都是纯前端的代码,完全没有和服务器后段交互。是前端js直接和钱包的rpc接口进行通信的。

  1. 当调用一个需要写入的合约方法时,流程是这样的:

    用户点击调用 -> gas估算 -> MetaMask签名 -> 发送交易 -> 等待确认
  2. addCommitteeMember 的情况下:

    用户点击调用 -> gas估算(失败) -> 直接报错,不会到MetaMask签名步骤
  3. 具体原因:

    • 在 gas 估算阶段,以太坊节点会模拟执行这个交易
    • 合约执行到 Committee total cannot exceed maximum size 的检查时直接 revert
    • 由于模拟执行失败,无法估算出 gas 费用
    • 系统抛出 UNPREDICTABLE_GAS_LIMIT 错误
    • 整个流程就此终止,不会触发 MetaMask 签名
  4. 而在 setChallengePeriod 的情况下:

    用户点击调用 -> gas估算(成功) -> MetaMask弹出签名请求 -> 用户确认/拒绝
    • gas 估算成功
    • 系统可以继续执行到 MetaMask 签名步骤
    • 所以会看到 User rejected the request 这样的错误

这就是为什么两个方法会有不同的表现:

  • setChallengePeriod 会触发钱包签名
  • addCommitteeMember 在 gas 估算阶段就失败了,根本到不了签名步骤

要解决这个问题,我们需要在调用前先检查合约状态,避免在 gas 估算阶段就失败。这就是为什么我们之前添加了检查委员会成员数量的代码。

  1. 在 gas 估算阶段,节点会使用调用者的地址(from 地址)来模拟执行交易。这个地址就是我们在代码中通过 provider.getSigner() 获取的签名者地址。

  2. 让我们看看相关代码:

    const createContract = () => {
    const provider = new ethers.providers.Web3Provider(window.ethereum)
    const signer = provider.getSigner()
    return new ethers.Contract(verifyData.address, verifyData.abi, signer)
    }
  3. 当合约执行 onlyOwner 修饰符时:

    modifier onlyOwner() {
    require(msg.sender == owner, "Not owner");
    _;
    }
    • msg.sender 会被设置为 gas 估算时使用的 from 地址
    • 如果这个地址确实是合约的 owner,那么权限检查就会通过
    • 如果这个地址不是 owner,那么权限检查会失败,导致 gas 估算失败
  4. 所以关键点是:

    • gas 估算时使用的 from 地址必须是有权限的地址
    • 这个地址是通过 provider.getSigner() 获取的当前连接的 MetaMask 账户
    • 如果当前连接的账户没有权限,gas 估算会失败,不会触发签名
  5. 这就是为什么:

    • 如果当前连接的 MetaMask 账户是合约 owner,gas 估算会成功,然后触发签名
    • 如果当前连接的账户不是 owner,gas 估算会失败,不会触发签名

所以,权限检查在 gas 估算阶段是有效的,因为:

  1. 节点使用实际的调用者地址进行模拟
  2. 合约的权限检查是基于 msg.sender
  3. 如果权限检查失败,gas 估算就会失败,整个交易就不会继续

这就是为什么我们需要确保:

  1. 用户连接了正确的 MetaMask 账户
  2. 这个账户有足够的权限执行合约方法
  3. 在调用前检查权限状态,避免在 gas 估算阶段就失败

filecoin PDP 笔记

drand服务发起随机数,PDP SP收到随机数当作随机挑战,对挑战到的数据生成proof,提交到链上,这个时候不管proof正确与否,链上合约都不用验证,等到PDP SP调用合约取钱的时候,才进行proof的验证,如果已经提交了数据是错误的,或者没有提交,则会扣钱,或者不能取现。否则获得收入。

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
杜满想Elvin
杜满想Elvin
老程序员,区块链架构师