Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename isContract to hasCode #3418

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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