Add ERC165Checker.getSupportedInterfaces (#2469)
Co-authored-by: conspyrosy <1027439+Spyros-Stylianou@users.noreply.github.com> Co-authored-by: kamiebisu <kamiebisu@protonmail.com> Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com> Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
This commit is contained in:
@ -13,6 +13,7 @@
|
||||
* `UpgradeableProxy`: bubble revert reasons from initialization calls. ([#2454](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2454))
|
||||
* `SafeMath`: fix a memory allocation issue by adding new `SafeMath.tryOp(uint,uint)→(bool,uint)` functions. `SafeMath.op(uint,uint,string)→uint` are now deprecated. ([#2462](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2462))
|
||||
* `EnumerableMap`: fix a memory allocation issue by adding new `EnumerableMap.tryGet(uint)→(bool,address)` functions. `EnumerableMap.get(uint)→string` is now deprecated. ([#2462](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2462))
|
||||
* `ERC165Checker`: added batch `getSupportedInterfaces`. ([#2469](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2469))
|
||||
|
||||
## 3.3.0 (2020-11-26)
|
||||
|
||||
|
||||
@ -40,6 +40,29 @@ library ERC165Checker {
|
||||
_supportsERC165Interface(account, interfaceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns a boolean array where each value corresponds to the
|
||||
* interfaces passed in and whether they're supported or not. This allows
|
||||
* you to batch check interfaces for a contract where your expectation
|
||||
* is that some interfaces may not be supported.
|
||||
*
|
||||
* See {IERC165-supportsInterface}.
|
||||
*/
|
||||
function getSupportedInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool[] memory) {
|
||||
// an array of booleans corresponding to interfaceIds and whether they're supported or not
|
||||
bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);
|
||||
|
||||
// query support of ERC165 itself
|
||||
if (supportsERC165(account)) {
|
||||
// query support of each interface in interfaceIds
|
||||
for (uint256 i = 0; i < interfaceIds.length; i++) {
|
||||
interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return interfaceIdsSupported;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns true if `account` supports all the interfaces defined in
|
||||
* `interfaceIds`. Support for {IERC165} itself is queried automatically.
|
||||
|
||||
@ -18,4 +18,8 @@ contract ERC165CheckerMock {
|
||||
function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) public view returns (bool) {
|
||||
return account.supportsAllInterfaces(interfaceIds);
|
||||
}
|
||||
|
||||
function getSupportedInterfaces(address account, bytes4[] memory interfaceIds) public view returns (bool[] memory) {
|
||||
return account.getSupportedInterfaces(interfaceIds);
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,6 +37,12 @@ contract('ERC165Checker', function (accounts) {
|
||||
const supported = await this.mock.supportsAllInterfaces(this.target.address, [DUMMY_ID]);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
|
||||
it('does not support mock interface via getSupportedInterfaces', async function () {
|
||||
const supported = await this.mock.getSupportedInterfaces(this.target.address, [DUMMY_ID]);
|
||||
expect(supported.length).to.equal(1);
|
||||
expect(supported[0]).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('ERC165 supported', function () {
|
||||
@ -58,6 +64,12 @@ contract('ERC165Checker', function (accounts) {
|
||||
const supported = await this.mock.supportsAllInterfaces(this.target.address, [DUMMY_ID]);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
|
||||
it('does not support mock interface via getSupportedInterfaces', async function () {
|
||||
const supported = await this.mock.getSupportedInterfaces(this.target.address, [DUMMY_ID]);
|
||||
expect(supported.length).to.equal(1);
|
||||
expect(supported[0]).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('ERC165 and single interface supported', function () {
|
||||
@ -79,6 +91,12 @@ contract('ERC165Checker', function (accounts) {
|
||||
const supported = await this.mock.supportsAllInterfaces(this.target.address, [DUMMY_ID]);
|
||||
expect(supported).to.equal(true);
|
||||
});
|
||||
|
||||
it('supports mock interface via getSupportedInterfaces', async function () {
|
||||
const supported = await this.mock.getSupportedInterfaces(this.target.address, [DUMMY_ID]);
|
||||
expect(supported.length).to.equal(1);
|
||||
expect(supported[0]).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
context('ERC165 and many interfaces supported', function () {
|
||||
@ -117,6 +135,34 @@ contract('ERC165Checker', function (accounts) {
|
||||
const supported = await this.mock.supportsAllInterfaces(this.target.address, interfaceIdsToTest);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
|
||||
it('supports all interfaceIds via getSupportedInterfaces', async function () {
|
||||
const supported = await this.mock.getSupportedInterfaces(this.target.address, this.supportedInterfaces);
|
||||
expect(supported.length).to.equal(3);
|
||||
expect(supported[0]).to.equal(true);
|
||||
expect(supported[1]).to.equal(true);
|
||||
expect(supported[2]).to.equal(true);
|
||||
});
|
||||
|
||||
it('supports none of the interfaces queried via getSupportedInterfaces', async function () {
|
||||
const interfaceIdsToTest = [DUMMY_UNSUPPORTED_ID, DUMMY_UNSUPPORTED_ID_2];
|
||||
|
||||
const supported = await this.mock.getSupportedInterfaces(this.target.address, interfaceIdsToTest);
|
||||
expect(supported.length).to.equal(2);
|
||||
expect(supported[0]).to.equal(false);
|
||||
expect(supported[1]).to.equal(false);
|
||||
});
|
||||
|
||||
it('supports not all of the interfaces queried via getSupportedInterfaces', async function () {
|
||||
const interfaceIdsToTest = [...this.supportedInterfaces, DUMMY_UNSUPPORTED_ID];
|
||||
|
||||
const supported = await this.mock.getSupportedInterfaces(this.target.address, interfaceIdsToTest);
|
||||
expect(supported.length).to.equal(4);
|
||||
expect(supported[0]).to.equal(true);
|
||||
expect(supported[1]).to.equal(true);
|
||||
expect(supported[2]).to.equal(true);
|
||||
expect(supported[3]).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('account address does not support ERC165', function () {
|
||||
@ -134,5 +180,11 @@ contract('ERC165Checker', function (accounts) {
|
||||
const supported = await this.mock.supportsAllInterfaces(DUMMY_ACCOUNT, [DUMMY_ID]);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
|
||||
it('does not support mock interface via getSupportedInterfaces', async function () {
|
||||
const supported = await this.mock.getSupportedInterfaces(DUMMY_ACCOUNT, [DUMMY_ID]);
|
||||
expect(supported.length).to.equal(1);
|
||||
expect(supported[0]).to.equal(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user