mirror of
https://github.com/th30d4y/OpenLearnX.git
synced 2026-05-27 03:36:32 +00:00
Fix .gitignore: stop tracking ignored files
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
const { shouldSupportInterfaces } = require('./SupportsInterface.behavior');
|
||||
|
||||
const ERC165 = artifacts.require('$ERC165');
|
||||
|
||||
contract('ERC165', function () {
|
||||
beforeEach(async function () {
|
||||
this.mock = await ERC165.new();
|
||||
});
|
||||
|
||||
shouldSupportInterfaces(['ERC165']);
|
||||
});
|
||||
@@ -0,0 +1,302 @@
|
||||
require('@openzeppelin/test-helpers');
|
||||
|
||||
const { expect } = require('chai');
|
||||
|
||||
const ERC165Checker = artifacts.require('$ERC165Checker');
|
||||
const ERC165Storage = artifacts.require('$ERC165Storage');
|
||||
const ERC165MissingData = artifacts.require('ERC165MissingData');
|
||||
const ERC165MaliciousData = artifacts.require('ERC165MaliciousData');
|
||||
const ERC165NotSupported = artifacts.require('ERC165NotSupported');
|
||||
const ERC165ReturnBombMock = artifacts.require('ERC165ReturnBombMock');
|
||||
|
||||
const DUMMY_ID = '0xdeadbeef';
|
||||
const DUMMY_ID_2 = '0xcafebabe';
|
||||
const DUMMY_ID_3 = '0xdecafbad';
|
||||
const DUMMY_UNSUPPORTED_ID = '0xbaddcafe';
|
||||
const DUMMY_UNSUPPORTED_ID_2 = '0xbaadcafe';
|
||||
const DUMMY_ACCOUNT = '0x1111111111111111111111111111111111111111';
|
||||
|
||||
contract('ERC165Checker', function () {
|
||||
beforeEach(async function () {
|
||||
this.mock = await ERC165Checker.new();
|
||||
});
|
||||
|
||||
context('ERC165 missing return data', function () {
|
||||
beforeEach(async function () {
|
||||
this.target = await ERC165MissingData.new();
|
||||
});
|
||||
|
||||
it('does not support ERC165', async function () {
|
||||
const supported = await this.mock.$supportsERC165(this.target.address);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
|
||||
it('does not support mock interface via supportsInterface', async function () {
|
||||
const supported = await this.mock.$supportsInterface(this.target.address, DUMMY_ID);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
|
||||
it('does not support mock interface via supportsAllInterfaces', async function () {
|
||||
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);
|
||||
});
|
||||
|
||||
it('does not support mock interface via supportsERC165InterfaceUnchecked', async function () {
|
||||
const supported = await this.mock.$supportsERC165InterfaceUnchecked(this.target.address, DUMMY_ID);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('ERC165 malicious return data', function () {
|
||||
beforeEach(async function () {
|
||||
this.target = await ERC165MaliciousData.new();
|
||||
});
|
||||
|
||||
it('does not support ERC165', async function () {
|
||||
const supported = await this.mock.$supportsERC165(this.target.address);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
|
||||
it('does not support mock interface via supportsInterface', async function () {
|
||||
const supported = await this.mock.$supportsInterface(this.target.address, DUMMY_ID);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
|
||||
it('does not support mock interface via supportsAllInterfaces', async function () {
|
||||
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);
|
||||
});
|
||||
|
||||
it('does not support mock interface via supportsERC165InterfaceUnchecked', async function () {
|
||||
const supported = await this.mock.$supportsERC165InterfaceUnchecked(this.target.address, DUMMY_ID);
|
||||
expect(supported).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
context('ERC165 not supported', function () {
|
||||
beforeEach(async function () {
|
||||
this.target = await ERC165NotSupported.new();
|
||||
});
|
||||
|
||||
it('does not support ERC165', async function () {
|
||||
const supported = await this.mock.$supportsERC165(this.target.address);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
|
||||
it('does not support mock interface via supportsInterface', async function () {
|
||||
const supported = await this.mock.$supportsInterface(this.target.address, DUMMY_ID);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
|
||||
it('does not support mock interface via supportsAllInterfaces', async function () {
|
||||
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);
|
||||
});
|
||||
|
||||
it('does not support mock interface via supportsERC165InterfaceUnchecked', async function () {
|
||||
const supported = await this.mock.$supportsERC165InterfaceUnchecked(this.target.address, DUMMY_ID);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('ERC165 supported', function () {
|
||||
beforeEach(async function () {
|
||||
this.target = await ERC165Storage.new();
|
||||
});
|
||||
|
||||
it('supports ERC165', async function () {
|
||||
const supported = await this.mock.$supportsERC165(this.target.address);
|
||||
expect(supported).to.equal(true);
|
||||
});
|
||||
|
||||
it('does not support mock interface via supportsInterface', async function () {
|
||||
const supported = await this.mock.$supportsInterface(this.target.address, DUMMY_ID);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
|
||||
it('does not support mock interface via supportsAllInterfaces', async function () {
|
||||
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);
|
||||
});
|
||||
|
||||
it('does not support mock interface via supportsERC165InterfaceUnchecked', async function () {
|
||||
const supported = await this.mock.$supportsERC165InterfaceUnchecked(this.target.address, DUMMY_ID);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('ERC165 and single interface supported', function () {
|
||||
beforeEach(async function () {
|
||||
this.target = await ERC165Storage.new();
|
||||
await this.target.$_registerInterface(DUMMY_ID);
|
||||
});
|
||||
|
||||
it('supports ERC165', async function () {
|
||||
const supported = await this.mock.$supportsERC165(this.target.address);
|
||||
expect(supported).to.equal(true);
|
||||
});
|
||||
|
||||
it('supports mock interface via supportsInterface', async function () {
|
||||
const supported = await this.mock.$supportsInterface(this.target.address, DUMMY_ID);
|
||||
expect(supported).to.equal(true);
|
||||
});
|
||||
|
||||
it('supports mock interface via supportsAllInterfaces', async function () {
|
||||
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);
|
||||
});
|
||||
|
||||
it('supports mock interface via supportsERC165InterfaceUnchecked', async function () {
|
||||
const supported = await this.mock.$supportsERC165InterfaceUnchecked(this.target.address, DUMMY_ID);
|
||||
expect(supported).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
context('ERC165 and many interfaces supported', function () {
|
||||
beforeEach(async function () {
|
||||
this.supportedInterfaces = [DUMMY_ID, DUMMY_ID_2, DUMMY_ID_3];
|
||||
this.target = await ERC165Storage.new();
|
||||
await Promise.all(this.supportedInterfaces.map(interfaceId => this.target.$_registerInterface(interfaceId)));
|
||||
});
|
||||
|
||||
it('supports ERC165', async function () {
|
||||
const supported = await this.mock.$supportsERC165(this.target.address);
|
||||
expect(supported).to.equal(true);
|
||||
});
|
||||
|
||||
it('supports each interfaceId via supportsInterface', async function () {
|
||||
for (const interfaceId of this.supportedInterfaces) {
|
||||
const supported = await this.mock.$supportsInterface(this.target.address, interfaceId);
|
||||
expect(supported).to.equal(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('supports all interfaceIds via supportsAllInterfaces', async function () {
|
||||
const supported = await this.mock.$supportsAllInterfaces(this.target.address, this.supportedInterfaces);
|
||||
expect(supported).to.equal(true);
|
||||
});
|
||||
|
||||
it('supports none of the interfaces queried via supportsAllInterfaces', async function () {
|
||||
const interfaceIdsToTest = [DUMMY_UNSUPPORTED_ID, DUMMY_UNSUPPORTED_ID_2];
|
||||
|
||||
const supported = await this.mock.$supportsAllInterfaces(this.target.address, interfaceIdsToTest);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
|
||||
it('supports not all of the interfaces queried via supportsAllInterfaces', async function () {
|
||||
const interfaceIdsToTest = [...this.supportedInterfaces, DUMMY_UNSUPPORTED_ID];
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
it('supports each interfaceId via supportsERC165InterfaceUnchecked', async function () {
|
||||
for (const interfaceId of this.supportedInterfaces) {
|
||||
const supported = await this.mock.$supportsERC165InterfaceUnchecked(this.target.address, interfaceId);
|
||||
expect(supported).to.equal(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
context('account address does not support ERC165', function () {
|
||||
it('does not support ERC165', async function () {
|
||||
const supported = await this.mock.$supportsERC165(DUMMY_ACCOUNT);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
|
||||
it('does not support mock interface via supportsInterface', async function () {
|
||||
const supported = await this.mock.$supportsInterface(DUMMY_ACCOUNT, DUMMY_ID);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
|
||||
it('does not support mock interface via supportsAllInterfaces', async function () {
|
||||
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);
|
||||
});
|
||||
|
||||
it('does not support mock interface via supportsERC165InterfaceUnchecked', async function () {
|
||||
const supported = await this.mock.$supportsERC165InterfaceUnchecked(DUMMY_ACCOUNT, DUMMY_ID);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('Return bomb resistance', async function () {
|
||||
this.target = await ERC165ReturnBombMock.new();
|
||||
|
||||
const tx1 = await this.mock.$supportsInterface.sendTransaction(this.target.address, DUMMY_ID);
|
||||
expect(tx1.receipt.gasUsed).to.be.lessThan(120000); // 3*30k + 21k + some margin
|
||||
|
||||
const tx2 = await this.mock.$getSupportedInterfaces.sendTransaction(this.target.address, [
|
||||
DUMMY_ID,
|
||||
DUMMY_ID_2,
|
||||
DUMMY_ID_3,
|
||||
DUMMY_UNSUPPORTED_ID,
|
||||
DUMMY_UNSUPPORTED_ID_2,
|
||||
]);
|
||||
expect(tx2.receipt.gasUsed).to.be.lessThan(250000); // (2+5)*30k + 21k + some margin
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
const { expectRevert } = require('@openzeppelin/test-helpers');
|
||||
|
||||
const { shouldSupportInterfaces } = require('./SupportsInterface.behavior');
|
||||
|
||||
const ERC165Storage = artifacts.require('$ERC165Storage');
|
||||
|
||||
contract('ERC165Storage', function () {
|
||||
beforeEach(async function () {
|
||||
this.mock = await ERC165Storage.new();
|
||||
});
|
||||
|
||||
it('register interface', async function () {
|
||||
expect(await this.mock.supportsInterface('0x00000001')).to.be.equal(false);
|
||||
await this.mock.$_registerInterface('0x00000001');
|
||||
expect(await this.mock.supportsInterface('0x00000001')).to.be.equal(true);
|
||||
});
|
||||
|
||||
it('does not allow 0xffffffff', async function () {
|
||||
await expectRevert(this.mock.$_registerInterface('0xffffffff'), 'ERC165: invalid interface id');
|
||||
});
|
||||
|
||||
shouldSupportInterfaces(['ERC165']);
|
||||
});
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
const { expectRevert, singletons } = require('@openzeppelin/test-helpers');
|
||||
const { bufferToHex, keccakFromString } = require('ethereumjs-util');
|
||||
|
||||
const { expect } = require('chai');
|
||||
|
||||
const ERC1820Implementer = artifacts.require('$ERC1820Implementer');
|
||||
|
||||
contract('ERC1820Implementer', function (accounts) {
|
||||
const [registryFunder, implementee, other] = accounts;
|
||||
|
||||
const ERC1820_ACCEPT_MAGIC = bufferToHex(keccakFromString('ERC1820_ACCEPT_MAGIC'));
|
||||
|
||||
beforeEach(async function () {
|
||||
this.implementer = await ERC1820Implementer.new();
|
||||
this.registry = await singletons.ERC1820Registry(registryFunder);
|
||||
|
||||
this.interfaceA = bufferToHex(keccakFromString('interfaceA'));
|
||||
this.interfaceB = bufferToHex(keccakFromString('interfaceB'));
|
||||
});
|
||||
|
||||
context('with no registered interfaces', function () {
|
||||
it('returns false when interface implementation is queried', async function () {
|
||||
expect(await this.implementer.canImplementInterfaceForAddress(this.interfaceA, implementee)).to.not.equal(
|
||||
ERC1820_ACCEPT_MAGIC,
|
||||
);
|
||||
});
|
||||
|
||||
it('reverts when attempting to set as implementer in the registry', async function () {
|
||||
await expectRevert(
|
||||
this.registry.setInterfaceImplementer(implementee, this.interfaceA, this.implementer.address, {
|
||||
from: implementee,
|
||||
}),
|
||||
'Does not implement the interface',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('with registered interfaces', function () {
|
||||
beforeEach(async function () {
|
||||
await this.implementer.$_registerInterfaceForAddress(this.interfaceA, implementee);
|
||||
});
|
||||
|
||||
it('returns true when interface implementation is queried', async function () {
|
||||
expect(await this.implementer.canImplementInterfaceForAddress(this.interfaceA, implementee)).to.equal(
|
||||
ERC1820_ACCEPT_MAGIC,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns false when interface implementation for non-supported interfaces is queried', async function () {
|
||||
expect(await this.implementer.canImplementInterfaceForAddress(this.interfaceB, implementee)).to.not.equal(
|
||||
ERC1820_ACCEPT_MAGIC,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns false when interface implementation for non-supported addresses is queried', async function () {
|
||||
expect(await this.implementer.canImplementInterfaceForAddress(this.interfaceA, other)).to.not.equal(
|
||||
ERC1820_ACCEPT_MAGIC,
|
||||
);
|
||||
});
|
||||
|
||||
it('can be set as an implementer for supported interfaces in the registry', async function () {
|
||||
await this.registry.setInterfaceImplementer(implementee, this.interfaceA, this.implementer.address, {
|
||||
from: implementee,
|
||||
});
|
||||
|
||||
expect(await this.registry.getInterfaceImplementer(implementee, this.interfaceA)).to.equal(
|
||||
this.implementer.address,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
const { makeInterfaceId } = require('@openzeppelin/test-helpers');
|
||||
|
||||
const { expect } = require('chai');
|
||||
|
||||
const INTERFACES = {
|
||||
ERC165: ['supportsInterface(bytes4)'],
|
||||
ERC721: [
|
||||
'balanceOf(address)',
|
||||
'ownerOf(uint256)',
|
||||
'approve(address,uint256)',
|
||||
'getApproved(uint256)',
|
||||
'setApprovalForAll(address,bool)',
|
||||
'isApprovedForAll(address,address)',
|
||||
'transferFrom(address,address,uint256)',
|
||||
'safeTransferFrom(address,address,uint256)',
|
||||
'safeTransferFrom(address,address,uint256,bytes)',
|
||||
],
|
||||
ERC721Enumerable: ['totalSupply()', 'tokenOfOwnerByIndex(address,uint256)', 'tokenByIndex(uint256)'],
|
||||
ERC721Metadata: ['name()', 'symbol()', 'tokenURI(uint256)'],
|
||||
ERC1155: [
|
||||
'balanceOf(address,uint256)',
|
||||
'balanceOfBatch(address[],uint256[])',
|
||||
'setApprovalForAll(address,bool)',
|
||||
'isApprovedForAll(address,address)',
|
||||
'safeTransferFrom(address,address,uint256,uint256,bytes)',
|
||||
'safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)',
|
||||
],
|
||||
ERC1155Receiver: [
|
||||
'onERC1155Received(address,address,uint256,uint256,bytes)',
|
||||
'onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)',
|
||||
],
|
||||
AccessControl: [
|
||||
'hasRole(bytes32,address)',
|
||||
'getRoleAdmin(bytes32)',
|
||||
'grantRole(bytes32,address)',
|
||||
'revokeRole(bytes32,address)',
|
||||
'renounceRole(bytes32,address)',
|
||||
],
|
||||
AccessControlEnumerable: ['getRoleMember(bytes32,uint256)', 'getRoleMemberCount(bytes32)'],
|
||||
AccessControlDefaultAdminRules: [
|
||||
'defaultAdminDelay()',
|
||||
'pendingDefaultAdminDelay()',
|
||||
'defaultAdmin()',
|
||||
'pendingDefaultAdmin()',
|
||||
'defaultAdminDelayIncreaseWait()',
|
||||
'changeDefaultAdminDelay(uint48)',
|
||||
'rollbackDefaultAdminDelay()',
|
||||
'beginDefaultAdminTransfer(address)',
|
||||
'acceptDefaultAdminTransfer()',
|
||||
'cancelDefaultAdminTransfer()',
|
||||
],
|
||||
Governor: [
|
||||
'name()',
|
||||
'version()',
|
||||
'COUNTING_MODE()',
|
||||
'hashProposal(address[],uint256[],bytes[],bytes32)',
|
||||
'state(uint256)',
|
||||
'proposalSnapshot(uint256)',
|
||||
'proposalDeadline(uint256)',
|
||||
'votingDelay()',
|
||||
'votingPeriod()',
|
||||
'quorum(uint256)',
|
||||
'getVotes(address,uint256)',
|
||||
'hasVoted(uint256,address)',
|
||||
'propose(address[],uint256[],bytes[],string)',
|
||||
'execute(address[],uint256[],bytes[],bytes32)',
|
||||
'castVote(uint256,uint8)',
|
||||
'castVoteWithReason(uint256,uint8,string)',
|
||||
'castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)',
|
||||
],
|
||||
GovernorWithParams: [
|
||||
'name()',
|
||||
'version()',
|
||||
'COUNTING_MODE()',
|
||||
'hashProposal(address[],uint256[],bytes[],bytes32)',
|
||||
'state(uint256)',
|
||||
'proposalSnapshot(uint256)',
|
||||
'proposalDeadline(uint256)',
|
||||
'votingDelay()',
|
||||
'votingPeriod()',
|
||||
'quorum(uint256)',
|
||||
'getVotes(address,uint256)',
|
||||
'getVotesWithParams(address,uint256,bytes)',
|
||||
'hasVoted(uint256,address)',
|
||||
'propose(address[],uint256[],bytes[],string)',
|
||||
'execute(address[],uint256[],bytes[],bytes32)',
|
||||
'castVote(uint256,uint8)',
|
||||
'castVoteWithReason(uint256,uint8,string)',
|
||||
'castVoteWithReasonAndParams(uint256,uint8,string,bytes)',
|
||||
'castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)',
|
||||
'castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)',
|
||||
],
|
||||
GovernorCancel: ['proposalProposer(uint256)', 'cancel(address[],uint256[],bytes[],bytes32)'],
|
||||
GovernorTimelock: ['timelock()', 'proposalEta(uint256)', 'queue(address[],uint256[],bytes[],bytes32)'],
|
||||
ERC2981: ['royaltyInfo(uint256,uint256)'],
|
||||
};
|
||||
|
||||
const INTERFACE_IDS = {};
|
||||
const FN_SIGNATURES = {};
|
||||
for (const k of Object.getOwnPropertyNames(INTERFACES)) {
|
||||
INTERFACE_IDS[k] = makeInterfaceId.ERC165(INTERFACES[k]);
|
||||
for (const fnName of INTERFACES[k]) {
|
||||
// the interface id of a single function is equivalent to its function signature
|
||||
FN_SIGNATURES[fnName] = makeInterfaceId.ERC165([fnName]);
|
||||
}
|
||||
}
|
||||
|
||||
function shouldSupportInterfaces(interfaces = []) {
|
||||
describe('ERC165', function () {
|
||||
beforeEach(function () {
|
||||
this.contractUnderTest = this.mock || this.token || this.holder || this.accessControl;
|
||||
});
|
||||
|
||||
it('supportsInterface uses less than 30k gas', async function () {
|
||||
for (const k of interfaces) {
|
||||
const interfaceId = INTERFACE_IDS[k] ?? k;
|
||||
expect(await this.contractUnderTest.supportsInterface.estimateGas(interfaceId)).to.be.lte(30000);
|
||||
}
|
||||
});
|
||||
|
||||
it('all interfaces are reported as supported', async function () {
|
||||
for (const k of interfaces) {
|
||||
const interfaceId = INTERFACE_IDS[k] ?? k;
|
||||
expect(await this.contractUnderTest.supportsInterface(interfaceId)).to.equal(true, `does not support ${k}`);
|
||||
}
|
||||
});
|
||||
|
||||
it('all interface functions are in ABI', async function () {
|
||||
for (const k of interfaces) {
|
||||
// skip interfaces for which we don't have a function list
|
||||
if (INTERFACES[k] === undefined) continue;
|
||||
for (const fnName of INTERFACES[k]) {
|
||||
const fnSig = FN_SIGNATURES[fnName];
|
||||
expect(this.contractUnderTest.abi.filter(fn => fn.signature === fnSig).length).to.equal(
|
||||
1,
|
||||
`did not find ${fnName}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
shouldSupportInterfaces,
|
||||
};
|
||||
Reference in New Issue
Block a user