Michael.W基于Foundry精讀Openzeppelin第41期——ERC20Capped.sol
- 0. 版本
- 0.1 ERC20Capped.sol
- 1. 目標合約
- 2. 代碼精讀
- 2.1 constructor() && cap()
- 2.2 _mint(address account, uint256 amount)
0. 版本
[openzeppelin]:v4.8.3,[forge-std]:v1.5.6
0.1 ERC20Capped.sol
Github: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.3/contracts/token/ERC20/extensions/ERC20Capped.sol
ERC20Capped庫是ERC20的拓展。該庫設置了ERC20發行量的上限。
1. 目標合約
繼承ERC20Capped合約:
Github: https://github.com/RevelationOfTuring/foundry-openzeppelin-contracts/blob/master/src/token/ERC20/extensions/MockERC20Capped.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;import "openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Capped.sol";contract MockERC20Capped is ERC20Capped {constructor(string memory name, string memory symbol, uint cap)ERC20(name, symbol)ERC20Capped(cap){}function mint(address account, uint amount) external {_mint(account, amount);}
}
全部foundry測試合約:
Github: https://github.com/RevelationOfTuring/foundry-openzeppelin-contracts/blob/master/test/token/ERC20/extensions/ERC20Capped.t.sol
2. 代碼精讀
2.1 constructor() && cap()
constructor()
:初始化函數對發行量上限進行了設置;cap()
:返回ERC20發行量上限
// token發行量上限(immutable類型,合約初始化后無法再更改)uint256 private immutable _cap;constructor(uint256 cap_) {// 要求設置的發行量上限大于0require(cap_ > 0, "ERC20Capped: cap is 0");// 設置上限_cap = cap_;}function cap() public view virtual returns (uint256) {// 返回常量_cap的值return _cap;}
foundry代碼驗證:
contract ERC20CappedTest is Test {MockERC20Capped private _testing = new MockERC20Capped("test name", "test symbol", 100);function test_Constructor() external {assertEq(_testing.cap(), 100);// revert with 0 cap in constructorvm.expectRevert("ERC20Capped: cap is 0");new MockERC20Capped("test name", "test symbol", 0);}
}
2.2 _mint(address account, uint256 amount)
為account地址鑄造數量為amount的token。
function _mint(address account, uint256 amount) internal virtual override {// 檢查本次mint后的總發行量不得大于發行量上限require(ERC20.totalSupply() + amount <= cap(), "ERC20Capped: cap exceeded");// 調用ERC20.mint()進行鑄造super._mint(account, amount);}
foundry代碼驗證:
contract ERC20CappedTest is Test {MockERC20Capped private _testing = new MockERC20Capped("test name", "test symbol", 100);address private user = address(1);function test_Mint() external {_testing.mint(user, 100);assertEq(_testing.totalSupply(), 100);vm.expectRevert("ERC20Capped: cap exceeded");_testing.mint(user, 1);}
}
ps:
本人熱愛圖靈,熱愛中本聰,熱愛V神。
以下是我個人的公眾號,如果有技術問題可以關注我的公眾號來跟我交流。
同時我也會在這個公眾號上每周更新我的原創文章,喜歡的小伙伴或者老伙計可以支持一下!
如果需要轉發,麻煩注明作者。十分感謝!
公眾號名稱:后現代潑痞浪漫主義奠基人