Description
-
OpenZeppelin's balanceOf(address(0)) returns 0, and allowance(address(0), x) or allowance(x, address(0)) returns 0.
-
Token-0x reverts on these calls, which may break integrations that query zero address balances for various reasons.
function _balanceOf(address owner) internal view returns (uint256) {
assembly {
if iszero(owner) {
revert(0, 0)
}
}
}
function _allowance(address owner, address spender) internal view returns (uint256 remaining) {
assembly {
if or(iszero(owner), iszero(spender)) {
revert(0, 0)
}
}
}
Risk
Likelihood:
Impact:
Proof of Concept
function test_zero_address_revert() public {
vm.expectRevert();
token.balanceOf(address(0));
assertEq(token2.balanceOf(address(0)), 0);
}
Recommended Mitigation
function _balanceOf(address owner) internal view returns (uint256) {
assembly {
+
if iszero(owner) {
- revert(0, 0)
+ mstore(0x00, 0)
+ return(0x00, 0x20)
}
let baseSlot := _balances.slot
let ptr := mload(0x40)
mstore(ptr, owner)
mstore(add(ptr, 0x20), baseSlot)
let dataSlot := keccak256(ptr, 0x40)
let amount := sload(dataSlot)
mstore(ptr, amount)
mstore(add(ptr, 0x20), 0)
return(ptr, 0x20)
}
}
Similar change for _allowance:
function _allowance(address owner, address spender) internal view returns (uint256 remaining) {
assembly {
+
- if or(iszero(owner), iszero(spender)) {
- revert(0, 0)
- }
+ if iszero(owner) {
+ mstore(0x00, 0)
+ return(0x00, 0x20)
+ }
+
+ if iszero(spender) {
+ mstore(0x00, 0)
+ return(0x00, 0x20)
+ }
let ptr := mload(0x40)
let baseSlot := _allowances.slot
mstore(ptr, owner)
mstore(add(ptr, 0x20), baseSlot)
let initialHash := keccak256(ptr, 0x40)
mstore(ptr, spender)
mstore(add(ptr, 0x20), initialHash)
let allowanceSlot := keccak256(ptr, 0x40)
remaining := sload(allowanceSlot)
}
}