调用write的智能合约方法时,有些方法可以来起来metamask,有些方法却不可以,甚至有些方法一开始可以,后面不可以了。这些问题的原因如下:首先确定一点,就是调用智能合约方法都是纯前端的代码,完全没有和服务器后段交互。是前端js直接和钱包的rpc接口进行通信的。当调用一个需要写入的合约方
调用write的智能合约方法时,有些方法可以来起来metamask,有些方法却不可以,甚至有些方法一开始可以,后面不可以了。这些问题的原因如下:
首先确定一点,就是调用智能合约方法都是纯前端的代码,完全没有和服务器后段交互。是前端js直接和钱包的rpc接口进行通信的。
当调用一个需要写入的合约方法时,流程是这样的:
用户点击调用 -> gas估算 -> MetaMask签名 -> 发送交易 -> 等待确认
在 addCommitteeMember
的情况下:
用户点击调用 -> gas估算(失败) -> 直接报错,不会到MetaMask签名步骤
具体原因:
Committee total cannot exceed maximum size
的检查时直接 revertUNPREDICTABLE_GAS_LIMIT
错误而在 setChallengePeriod
的情况下:
用户点击调用 -> gas估算(成功) -> MetaMask弹出签名请求 -> 用户确认/拒绝
User rejected the request
这样的错误这就是为什么两个方法会有不同的表现:
setChallengePeriod
会触发钱包签名addCommitteeMember
在 gas 估算阶段就失败了,根本到不了签名步骤要解决这个问题,我们需要在调用前先检查合约状态,避免在 gas 估算阶段就失败。这就是为什么我们之前添加了检查委员会成员数量的代码。
在 gas 估算阶段,节点会使用调用者的地址(from
地址)来模拟执行交易。这个地址就是我们在代码中通过 provider.getSigner()
获取的签名者地址。
让我们看看相关代码:
const createContract = () => {
const provider = new ethers.providers.Web3Provider(window.ethereum)
const signer = provider.getSigner()
return new ethers.Contract(verifyData.address, verifyData.abi, signer)
}
当合约执行 onlyOwner
修饰符时:
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
msg.sender
会被设置为 gas 估算时使用的 from
地址所以关键点是:
from
地址必须是有权限的地址provider.getSigner()
获取的当前连接的 MetaMask 账户这就是为什么:
所以,权限检查在 gas 估算阶段是有效的,因为:
msg.sender
的这就是为什么我们需要确保:
drand服务发起随机数,PDP SP收到随机数当作随机挑战,对挑战到的数据生成proof,提交到链上,这个时候不管proof正确与否,链上合约都不用验证,等到PDP SP调用合约取钱的时候,才进行proof的验证,如果已经提交了数据是错误的,或者没有提交,则会扣钱,或者不能取现。否则获得收入。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!