我偶然发现了burn()在OpenZeppelin ERC20 contracts中的一个问题。我有以下测试:
import { time, loadFixture } from "@nomicfoundation/hardhat-network-helpers";
import { anyValue } from "@nomicfoundation/hardhat-chai-matchers/withArgs";
import { expect } from "chai";
import { ethers } from "hardhat";
import {rpcBlock} from "hardhat/internal/core/jsonrpc/types/output/block";
import {address} from "hardhat/internal/core/config/config-validation";
describe("MSGSNDR", function () {
// We define a fixture to reuse the same setup in every test.
// We use loadFixture to run this setup once, snapshot that state,
// and reset Hardhat Network to that snapshot in every test.
async function deployContractFixture() {
// Contracts are deployed using the first signer/account by default
const [owner, otherAccount, yetAnotherAccount] = await ethers.getSigners();
const MSGSNDR = await ethers.getContractFactory("MSGSNDR");
const msgsndr = await MSGSNDR.deploy("MSGSNDR", "MSGS");
return { msgsndr, owner, otherAccount, yetAnotherAccount };
}
describe("Burnable", function () {
it("burn(): burn 2_400 wei", async function () {
const { msgsndr, owner, otherAccount } = await loadFixture(deployContractFixture);
await msgsndr.mint(otherAccount.address, 10_000);
await expect(msgsndr.connect(otherAccount).burn(2_400))
.to.emit(msgsndr, 'Transfer')
.withArgs(otherAccount.address, ethers.constants.AddressZero, 2_400);
expect(await msgsndr.balanceOf(otherAccount.address)).to.equal(7_600);
});
});
});我正在测试_burn()的行为,发现以下两个版本的合同行为方式不同:
_burn()逐字复制的OpenZeppelin GitHub回购。// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import 'hardhat/console.sol';
contract MSGSNDR is ERC20, ERC20Burnable, Ownable {
mapping(address => uint256) private _balances;
uint256 private _totalSupply;
constructor(string memory name_, string memory symbol_) ERC20(name_, symbol_) {
_totalSupply = 10_000;
}
function mint(address to, uint256 _amount) public {
_mint(to, _amount);
}
/**
* copied from: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/d59306bd06a241083841c2e4a39db08e1f3722cc/contracts/token/ERC20/ERC20.sol
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal override virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
// Overflow not possible: amount <= accountBalance <= totalSupply.
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import 'hardhat/console.sol';
contract MSGSNDR is ERC20, ERC20Burnable, Ownable {
mapping(address => uint256) private _balances;
uint256 private _totalSupply;
constructor(string memory name_, string memory symbol_) ERC20(name_, symbol_) {
_totalSupply = 10_000;
}
function mint(address to, uint256 _amount) public {
_mint(to, _amount);
}
}是什么导致了这种行为的改变?
发布于 2023-02-10 08:48:01
https://ethereum.stackexchange.com/questions/144641
复制相似问题