modifier 就是一个function before hook,
1. _ 下划线表示被hook的方法内容。
2. _ 可以出现多次
3. modifier的执行顺序和出现顺序是一致的(上面的stackexchange中的的例子, 把各种内容都放到 message中,是特别厉害的)
4. modifier 也可以出现多次
下面是一个例子:
pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; contract VeryGoodNftWithMaxSupply is ERC721URIStorage { uint256 private _currentId = 0; address public rootAddress = address(0); uint256 public _maxSupply = 10; event Minted(address to, uint256 nftId, address minter); modifier shouldLessThanMaxSupply(){ require( _currentId <= _maxSupply, "Reached max supply, no available nft left" ); // 下划线表示被hook方法的内容。 会在编译、执行的时候做个替换 _; } constructor() ERC721("VeryGoodNftWithMaxSupply", "VGNWM") { rootAddress = msg.sender; } function mint(address to) external shouldLessThanMaxSupply{ uint256 nftId = _currentId + 1; _mint(to, nftId); _currentId = nftId; address from = msg.sender; emit Minted(to, nftId, from); } }
一个function带有多个modifier:
// 执行顺序就是 checkOne, checkTwo, checkThree, 然后才是方法体 function test() checkOne checkTwo checkThree returns (uint256) { messages.push("test - 1"); testVariable = 345; messages.push("test - 2"); return testVariable; }
可以把函数的参数传给modifier,
例如:
// 这个modifier 有参数。
modifier shouldInWhiteList(address to){ string memory message = string.concat("This address( ", Strings.toString(to), " ) is not in white list"); require( whiteList.include(to), message); _; }
// 这里包含多个modifier , 注意把函数的参数to 传递给了modifier function mint(address to) external shouldLessThanMaxSupply shouldInWhiteList(to) { uint256 nftId = _currentId + 1; _mint(to, nftId); _currentId = nftId; address from = msg.sender; emit Minted(to, nftId, from); }
modifier 需要在function的returns前面,
例如:
// 这是个external 方法 function doSomeOperation(a,b) external modifier1 modifier2(b) returns(uint) { return 10; }