0

如果用户没有发送足够多的 Eth,我希望 UI 知道并回复一条消息。

此函数验证 msg.value,但在这种情况下,我想触发和事件(UI 可以响应)。

function doSomething() external payable {
  require(
      msg.value == price,
      'Please send the correct amount of ETH'
  );
  //Do something
}

这是正确的方法吗?

有没有办法将 require() 与发送事件结合起来?

function doSomething() external payable {
 if (msg.value < amount){
   emit NotEnoughEth('Please make sure to send correct amount');
   revert();
 }

  //Do something
}
4

1 回答 1

0
emit NotEnoughEth('Please make sure to send correct amount');

你不能这样做。为了能够发出一个types.Log你需要你evm.Call()执行而不做还原的事情。您所指的 EVM 中有 2 条指令:(makeLoghttps://github.com/ethereum/go-ethereum/blob/2aaff0ad76991be8851ae30454d2e2e967704102/core/vm/instructions.go#L828 这是创建和事件日志的指令. 并且opReverthttps://github.com/ethereum/go-ethereum/blob/2aaff0ad76991be8851ae30454d2e2e967704102/core/vm/instructions.go#L806),所以如果你进行还原,你Call()将返回一个错误,以及所有的结果以太坊状态数据库上的交易将被还原,并且不会保存任何内容。由于存储被取消,您的日志无法保存在区块链上。

这是将检查错误并恢复到以前保存的状态(又名快照)的代码:

    if err != nil {
        evm.StateDB.RevertToSnapshot(snapshot)
        if err != ErrExecutionReverted {
            gas = 0
        }
        // TODO: consider clearing up unused snapshots:
        //} else {
        //  evm.StateDB.DiscardSnapshot(snapshot)
    }
    return ret, gas, err
}

https://github.com/ethereum/go-ethereum/blob/2aaff0ad76991be8851ae30454d2e2e967704102/core/vm/evm.go#L280

即使 opRevert() 指令没有显式返回错误,跳转表也配置为始终返回错误opRevert

instructionSet[REVERT] = &operation{
    execute:    opRevert,
    dynamicGas: gasRevert,
    minStack:   minStack(2, 0),
    maxStack:   maxStack(2, 0),
    memorySize: memoryRevert,
    reverts:    true,
    returns:    true,
}

https://github.com/ethereum/go-ethereum/blob/2aaff0ad76991be8851ae30454d2e2e967704102/core/vm/jump_table.go#L155

口译员将errExecutionReverted自行发布:

    case operation.reverts:
        return res, ErrExecutionReverted

https://github.com/ethereum/go-ethereum/blob/2aaff0ad76991be8851ae30454d2e2e967704102/core/vm/interpreter.go#L297

于 2021-01-13T12:50:46.917 回答