Skip to content

Commit 9d82ffe

Browse files
committed
Fix _mint / _update semantics
1 parent dd5038f commit 9d82ffe

File tree

2 files changed

+24
-28
lines changed

2 files changed

+24
-28
lines changed

contracts/src/ERC20NullOwnerCappedUpgradeable.sol

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ abstract contract ERC20NullOwnerCappedUpgradeable is Initializable, ContextUpgra
2222

2323
// Unique storage slot for this combined ERC20 + Cap storage
2424
// keccak256(abi.encode(uint256(keccak256("ethscriptions.storage.ERC20NullOwnerCapped")) - 1)) & ~bytes32(uint256(0xff))
25-
bytes32 private constant STORAGE_LOCATION = 0x8f4f7bb0f9a741a04db8c5a3930ef1872dc1b0c6f996f78adc3f57e5f8b78400;
25+
bytes32 private constant STORAGE_LOCATION = 0x4d6f413771b260e6694ffc0cfc1fc0bdb079c880580315446b9e26b778417b00;
2626

2727
function _getS() private pure returns (TokenStorage storage $) {
2828
assembly {
@@ -116,42 +116,38 @@ abstract contract ERC20NullOwnerCappedUpgradeable is Initializable, ContextUpgra
116116
_update(from, to, value);
117117
}
118118

119-
// Modified from OZ: do NOT burn on to == address(0); always credit recipient (including zero address).
119+
// Update balances without affecting total supply (supports from/to == address(0))
120120
function _update(address from, address to, uint256 value) internal virtual {
121121
TokenStorage storage $ = _getS();
122-
if (from == address(0)) {
123-
// Mint path
124-
$.totalSupply += value;
125-
} else {
126-
uint256 fromBalance = $.balances[from];
127-
if (fromBalance < value) {
128-
revert ERC20InsufficientBalance(from, fromBalance, value);
129-
}
130-
unchecked {
131-
$.balances[from] = fromBalance - value;
132-
}
122+
// Debit from
123+
uint256 fromBalance = $.balances[from];
124+
if (fromBalance < value) {
125+
revert ERC20InsufficientBalance(from, fromBalance, value);
133126
}
134-
135-
// No burning: credit even address(0)
127+
unchecked {
128+
$.balances[from] = fromBalance - value;
129+
}
130+
// Credit to
136131
unchecked {
137132
$.balances[to] += value;
138133
}
139-
140134
emit Transfer(from, to, value);
141-
142-
// Cap enforcement when minting
143-
if (from == address(0)) {
144-
uint256 maxSupply = $.cap;
145-
uint256 supply = $.totalSupply;
146-
if (supply > maxSupply) {
147-
revert ERC20ExceededCap(supply, maxSupply);
148-
}
149-
}
150135
}
151136

152-
// Mint (null-owner aware)
137+
// Mint (null-owner aware): increases totalSupply and credits recipient (can be address(0))
153138
function _mint(address account, uint256 value) internal {
154-
_update(address(0), account, value);
139+
TokenStorage storage $ = _getS();
140+
141+
uint256 newSupply = $.totalSupply + value;
142+
if (newSupply > $.cap) {
143+
revert ERC20ExceededCap(newSupply, $.cap);
144+
}
145+
146+
$.totalSupply = newSupply;
147+
148+
unchecked { $.balances[account] += value; }
149+
150+
emit Transfer(address(0), account, value);
155151
}
156152

157153
// Approvals

contracts/src/EthscriptionsERC20.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ contract EthscriptionsERC20 is ERC20NullOwnerCappedUpgradeable {
2828

2929
// TokenManager-only mint that allows to == address(0)
3030
function mint(address to, uint256 amount) external onlyTokenManager {
31-
_update(address(0), to, amount);
31+
_mint(to, amount);
3232
}
3333

3434
// TokenManager-only transfer that allows to/from == address(0)

0 commit comments

Comments
 (0)