Solidity中的事件和日志学习笔记

什么是日志,什么是事件

EVM是以太坊和许多其他区块链的核心。EVM有一个日志功能,用于将数据“写”到智能合约之外的数据结构中。其中一个重要的数据是Solidity事件。事件允许我们“打印”在区块链上的信息,这种方式比在智能合约中保存到公共存储变量更容易搜索,且更省gas费。

日志是区块链上的一种特殊数据结构。它们不能被智能合约访问,但能提供关于交易和区块中发生的信息。正是因为它们不能被智能合约访问,才使得它们的使用成本更低。

滚动到交易的“日志”部分,我们可以看到以下内容:

一个事件可以分解为:

Address: 地址,发出事件的合约或账户的地址。

Topics:主题,事件的索引参数。

Data: 数据,事件的非索引参数的ABI编码或“哈希”。由于我们知道合约的ABI(因为我们在Etherscan上验证了合约),我们可以在“Dec”或“Decoded”模式下查看它,或者在其原始的“hex”、“Hexidecimal”或 “Encoded”模式下查看。如果我们没有验证过合约,我们就无法看到解码的版本。

使用代码打印出来的事件大概是这样 :

{

blockNumber: 9,
blockHash: '0x5eaa8438d80d30e521b6c48db8c22d5b40255cd472d71cfd387c314486a7e679', transactionIndex: 0,
removed: false,
address: '0x5FbDB2315678afecb367f032d93F642f64180aa3',
data: '0x00000000000000000000000000000000000000000000000000000000000003e8', topics: [

'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', '0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266', '0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8'

],
transactionHash: '0x1eda2652cde3d9b3d8dbb1e0441a2139ebd25ba25a97fab3158406a695e33ba9', logIndex: 0

}

事件的局限

事件构建在Ethereum中,底层的日志接口之上。虽然您通常不会直接处理日志消息,但是了解它们的限制非常重要。

日志结构最多有4个“主题”和一个“数据”字段。第一个主题用于存储事件签名的哈希值,这样就只剩下三个主题用于索引参数。主题需要32字节长,因此,如果使用数组作为索引参数(包括类型string和bytes),那么首先将哈希值转换为32字节。非索引参数存储在数据字段中,没有大小限制。

日志,包括记录在日志中的事件,不能从Ethereum虚拟机(EVM)中访问。这意味着合约不能读取自己的或其他合约的日志及事件。

使用事件的一个例子:

pragma solidity ^0.8.7;

contract SimpleStorage {
    uint256 favoriteNumber;
    event storedNumber(
        uint256 indexed oldNumber,
        uint256 indexed newNumber,
        uint256 addedNumber,
        address sender
    );

    function store(uint256 _favoriteNumber) public {
        emit storedNumber(
            favoriteNumber,
            _favoriteNumber,
            _favoriteNumber + favoriteNumber,
            msg.sender
        );
        favoriteNumber = _favoriteNumber;
    }

    function retrieve() public view returns (uint256) {
        return favoriteNumber;
    }
}

event :定义事件

emit:触发事件

执行 如下部署脚本:

// We require the Hardhat Runtime Environment explicitly here. This is optional
// but useful for running the script in a standalone fashion through `node <script>`.
//
// When running the script with `npx hardhat run <script>` you"ll find the Hardhat
// Runtime Environment"s members available in the global scope.
const hre = require("hardhat")

async function main() {
  await hre.run("compile")

  // We get the contract to deploy
  const SimpleStorage = await hre.ethers.getContractFactory("SimpleStorage")
  const simpleStorage = await SimpleStorage.deploy()
  await simpleStorage.deployed()
  const transactionResponse = await simpleStorage.store(1)
  const transactionReceipt = await transactionResponse.wait()
  console.log(transactionReceipt.events[0])
  console.log(transactionReceipt.events[0].args.oldNumber.toString())
  console.log(transactionReceipt.events[0].args.newNumber.toString())
  console.log(transactionReceipt.events[0].args.addedNumber.toString())
  console.log(transactionReceipt.events[0].args.sender)
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
  console.error(error)
  process.exitCode = 1
})

进行部署并执行 执行结果如下 

xxx@xxxdeMacBook-Pro w2 % npx hardhat run  script/deploy_and_store.js --network dev
Nothing to compile
{
  transactionIndex: 0,
  blockNumber: 4,
  transactionHash: '0x253dda14073f9d49c1778e4e864a522dcbbb73218953131a6bc57ecdb283611c',
  address: '0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0',
  topics: [
    '0xe304654f140653267f4d09df4968c896d7d6fd0b8e23c45f1db26a86cf930001',
    '0x0000000000000000000000000000000000000000000000000000000000000000',
    '0x0000000000000000000000000000000000000000000000000000000000000001'
  ],
  data: '0x0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266',
  logIndex: 0,
  blockHash: '0x2597345618446a9727cf83fc2c886654b4b5224d7a67159aa2d849f408070be3',
  args: [
    BigNumber { value: "0" },
    BigNumber { value: "1" },
    BigNumber { value: "1" },
    '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
    oldNumber: BigNumber { value: "0" },
    newNumber: BigNumber { value: "1" },
    addedNumber: BigNumber { value: "1" },
    sender: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'
  ],
  decode: [Function (anonymous)],
  event: 'storedNumber',
  eventSignature: 'storedNumber(uint256,uint256,uint256,address)',
  removeListener: [Function (anonymous)],
  getBlock: [Function (anonymous)],
  getTransaction: [Function (anonymous)],
  getTransactionReceipt: [Function (anonymous)]
}
0
1
1
0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266

猜你喜欢

转载自blog.csdn.net/bareape/article/details/123993923