Fix .gitignore: stop tracking ignored files

This commit is contained in:
5t4l1n
2025-07-27 10:39:02 +05:30
parent b42747e9a3
commit 3a87ef0576
625 changed files with 88566 additions and 63 deletions
@@ -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']);
});
@@ -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,
);
});
});
});
@@ -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,
};