Skip to content

Commit

Permalink
Rename isContract to hasCode
Browse files Browse the repository at this point in the history
  • Loading branch information
devtooligan committed May 17, 2022
1 parent 5772512 commit cd4c4e5
Show file tree
Hide file tree
Showing 14 changed files with 29 additions and 34 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* `CrossChainEnabledPolygonChild`: replace the `require` statement with the custom error `NotCrossChainCall`. ([#3380](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3380))
* `ERC20FlashMint`: Add customizable flash fee receiver. ([#3327](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3327))
* `Strings`: add a new overloaded function `toHexString` that converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. ([#3403](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3403))
* `isContract` has been renamed to `hasCode`

## 4.6.0 (2022-04-26)

Expand Down
4 changes: 2 additions & 2 deletions contracts/mocks/AddressImpl.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ contract AddressImpl {

event CallReturnValue(string data);

function isContract(address account) external view returns (bool) {
return Address.isContract(account);
function hasCode(address account) external view returns (bool) {
return Address.hasCode(account);
}

function sendValue(address payable receiver, uint256 amount) external {
Expand Down
2 changes: 1 addition & 1 deletion contracts/mocks/UUPS/UUPSLegacy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ contract UUPSUpgradeableLegacyMock is UUPSUpgradeableMock {
// ERC1967Upgrade._setImplementation is private so we reproduce it here.
// An extra underscore prevents a name clash error.
function __setImplementation(address newImplementation) private {
require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
require(Address.hasCode(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}

Expand Down
9 changes: 3 additions & 6 deletions contracts/proxy/ERC1967/ERC1967Upgrade.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ abstract contract ERC1967Upgrade {
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
require(Address.hasCode(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}

Expand Down Expand Up @@ -157,11 +157,8 @@ abstract contract ERC1967Upgrade {
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
require(
Address.isContract(IBeacon(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
require(Address.hasCode(newBeacon), "ERC1967: new beacon has no code");
require(Address.hasCode(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation has no code");
StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/proxy/beacon/UpgradeableBeacon.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ contract UpgradeableBeacon is IBeacon, Ownable {
* - `newImplementation` must be a contract.
*/
function _setImplementation(address newImplementation) private {
require(Address.isContract(newImplementation), "UpgradeableBeacon: implementation is not a contract");
require(Address.hasCode(newImplementation), "UpgradeableBeacon: implementation is not a contract");
_implementation = newImplementation;
}
}
5 changes: 1 addition & 4 deletions contracts/proxy/utils/Initializable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,7 @@ abstract contract Initializable {
// inheritance patterns, but we only do this in the context of a constructor, and for the lowest level
// of initializers, because in other contexts the contract may have been reentered.
if (_initializing) {
require(
version == 1 && !Address.isContract(address(this)),
"Initializable: contract is already initialized"
);
require(version == 1 && !Address.hasCode(address(this)), "Initializable: contract is already initialized");
return false;
} else {
require(_initialized < version, "Initializable: contract is already initialized");
Expand Down
4 changes: 2 additions & 2 deletions contracts/token/ERC1155/ERC1155.sol
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
uint256 amount,
bytes memory data
) private {
if (to.isContract()) {
if (to.hasCode()) {
try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {
if (response != IERC1155Receiver.onERC1155Received.selector) {
revert("ERC1155: ERC1155Receiver rejected tokens");
Expand All @@ -493,7 +493,7 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
uint256[] memory amounts,
bytes memory data
) private {
if (to.isContract()) {
if (to.hasCode()) {
try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (
bytes4 response
) {
Expand Down
2 changes: 1 addition & 1 deletion contracts/token/ERC721/ERC721.sol
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
uint256 tokenId,
bytes memory data
) private returns (bool) {
if (to.isContract()) {
if (to.hasCode()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
Expand Down
2 changes: 1 addition & 1 deletion contracts/token/ERC777/ERC777.sol
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ contract ERC777 is Context, IERC777, IERC20 {
if (implementer != address(0)) {
IERC777Recipient(implementer).tokensReceived(operator, from, to, amount, userData, operatorData);
} else if (requireReceptionAck) {
require(!to.isContract(), "ERC777: token recipient contract has no implementer for ERC777TokensRecipient");
require(!to.hasCode(), "ERC777: token recipient contract has no implementer for ERC777TokensRecipient");
}
}

Expand Down
12 changes: 6 additions & 6 deletions contracts/utils/Address.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ library Address {
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* Among others, `hasCode` will return false for the following
* types of addresses:
*
* - an externally-owned account
Expand All @@ -26,14 +26,14 @@ library Address {
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
* You shouldn't rely on `hasCode` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
function hasCode(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
Expand Down Expand Up @@ -132,7 +132,7 @@ library Address {
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
require(hasCode(target), "Address: call to non-contract");

(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
Expand All @@ -159,7 +159,7 @@ library Address {
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
require(hasCode(target), "Address: static call to non-contract");

(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
Expand All @@ -186,7 +186,7 @@ library Address {
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
require(hasCode(target), "Address: delegate call to non-contract");

(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
Expand Down
2 changes: 1 addition & 1 deletion contracts/utils/StorageSlot.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pragma solidity ^0.8.0;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* require(Address.hasCode(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
Expand Down
8 changes: 4 additions & 4 deletions docs/modules/ROOT/pages/utilities.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,13 @@ If you need support for more powerful collections than Solidity's native arrays
[[misc]]
== Misc

Want to check if an address is a contract? Use xref:api:utils.adoc#Address[`Address`] and xref:api:utils.adoc#Address-isContract-address-[`Address.isContract()`].
Want to check if an address has code deployed to it? Use xref:api:utils.adoc#Address[`Address`] and xref:api:utils.adoc#Address-hasCode-address-[`Address.hasCode()`].

Want to keep track of some numbers that increment by 1 every time you want another one? Check out xref:api:utils.adoc#Counters[`Counters`]. This is useful for lots of things, like creating incremental identifiers, as shown on the xref:erc721.adoc[ERC721 guide].

=== Base64

xref:api:utils.adoc#Base64[`Base64`] util allows you to transform `bytes32` data into its Base64 `string` representation.
xref:api:utils.adoc#Base64[`Base64`] util allows you to transform `bytes32` data into its Base64 `string` representation.

This is specially useful to build URL-safe tokenURIs for both xref:api:token/ERC721.adoc#IERC721Metadata-tokenURI-uint256-[`ERC721`] or xref:api:token/ERC1155.adoc#IERC1155MetadataURI-uri-uint256-[`ERC1155`]. This library provides a clever way to serve URL-safe https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/Data_URIs/[Data URI] compliant strings to serve on-chain data structures.

Expand All @@ -120,7 +120,7 @@ contract My721Token is ERC721 {
using Strings for uint256;
constructor() ERC721("My721Token", "MTK") {}
...
function tokenURI(uint256 tokenId)
Expand All @@ -138,7 +138,7 @@ contract My721Token is ERC721 {
return string(
abi.encodePacked(
"data:application/json;base64,",
"data:application/json;base64,",
Base64.encode(dataURI)
)
);
Expand Down
4 changes: 2 additions & 2 deletions test/proxy/beacon/BeaconProxy.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ contract('BeaconProxy', function (accounts) {
it('non-contract beacon', async function () {
await expectRevert(
BeaconProxy.new(anotherAccount, '0x'),
'ERC1967: new beacon is not a contract',
'ERC1967: new beacon has no code',
);
});

Expand All @@ -32,7 +32,7 @@ contract('BeaconProxy', function (accounts) {
const beacon = await BadBeaconNotContract.new();
await expectRevert(
BeaconProxy.new(beacon.address, '0x'),
'ERC1967: beacon implementation is not a contract',
'ERC1967: beacon implementation has no code',
);
});
});
Expand Down
6 changes: 3 additions & 3 deletions test/utils/Address.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ contract('Address', function (accounts) {
this.mock = await AddressImpl.new();
});

describe('isContract', function () {
describe('hasCode', function () {
it('returns false for account address', async function () {
expect(await this.mock.isContract(other)).to.equal(false);
expect(await this.mock.hasCode(other)).to.equal(false);
});

it('returns true for contract address', async function () {
const contract = await AddressImpl.new();
expect(await this.mock.isContract(contract.address)).to.equal(true);
expect(await this.mock.hasCode(contract.address)).to.equal(true);
});
});

Expand Down

0 comments on commit cd4c4e5

Please sign in to comment.