Skip to content

Commit

Permalink
Add support to defender deploy (#416)
Browse files Browse the repository at this point in the history
Co-authored-by: Eric Lau <ericglau@outlook.com>
Co-authored-by: makiopen <piotr.makarewicz@openzeppelin.com>
  • Loading branch information
3 people authored Dec 16, 2024
1 parent 355d098 commit b829f16
Show file tree
Hide file tree
Showing 20 changed files with 391 additions and 60 deletions.
1 change: 1 addition & 0 deletions packages/core/get-imports.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './src/get-imports';
1 change: 1 addition & 0 deletions packages/core/get-imports.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('./dist/get-imports');
86 changes: 86 additions & 0 deletions packages/core/src/get-imports.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import test from 'ava';

import { getImports } from './get-imports';
import { buildERC20 } from './erc20';
import { buildERC721 } from './erc721';
import { generateSources } from './generate/sources';
import { buildGeneric } from './build-generic';

test('erc20 basic', t => {
const c = buildERC20({ name: 'MyToken', symbol: 'MTK', permit: false });
const sources = getImports(c);
const files = Object.keys(sources).sort();

t.deepEqual(files, [
'@openzeppelin/contracts/interfaces/draft-IERC6093.sol',
'@openzeppelin/contracts/token/ERC20/ERC20.sol',
'@openzeppelin/contracts/token/ERC20/IERC20.sol',
'@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol',
'@openzeppelin/contracts/utils/Context.sol',
]);
});

test('erc721 auto increment', t => {
const c = buildERC721({ name: 'MyToken', symbol: 'MTK', mintable: true, incremental: true });
const sources = getImports(c);
const files = Object.keys(sources).sort();

t.deepEqual(files, [
'@openzeppelin/contracts/access/Ownable.sol',
'@openzeppelin/contracts/interfaces/draft-IERC6093.sol',
'@openzeppelin/contracts/token/ERC721/ERC721.sol',
'@openzeppelin/contracts/token/ERC721/IERC721.sol',
'@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol',
'@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol',
'@openzeppelin/contracts/token/ERC721/utils/ERC721Utils.sol',
'@openzeppelin/contracts/utils/Context.sol',
'@openzeppelin/contracts/utils/Panic.sol',
'@openzeppelin/contracts/utils/Strings.sol',
'@openzeppelin/contracts/utils/introspection/ERC165.sol',
'@openzeppelin/contracts/utils/introspection/IERC165.sol',
'@openzeppelin/contracts/utils/math/Math.sol',
'@openzeppelin/contracts/utils/math/SafeCast.sol',
'@openzeppelin/contracts/utils/math/SignedMath.sol',
]);
});

test('erc721 auto increment uups', t => {
const c = buildERC721({ name: 'MyToken', symbol: 'MTK', mintable: true, incremental: true, upgradeable: 'uups' });
const sources = getImports(c);
const files = Object.keys(sources).sort();

t.deepEqual(files, [
'@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol',
'@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol',
'@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol',
'@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol',
'@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol',
'@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol',
'@openzeppelin/contracts/interfaces/IERC1967.sol',
'@openzeppelin/contracts/interfaces/draft-IERC1822.sol',
'@openzeppelin/contracts/interfaces/draft-IERC6093.sol',
'@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol',
'@openzeppelin/contracts/proxy/beacon/IBeacon.sol',
'@openzeppelin/contracts/token/ERC721/IERC721.sol',
'@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol',
'@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol',
'@openzeppelin/contracts/token/ERC721/utils/ERC721Utils.sol',
'@openzeppelin/contracts/utils/Address.sol',
'@openzeppelin/contracts/utils/Errors.sol',
'@openzeppelin/contracts/utils/Panic.sol',
'@openzeppelin/contracts/utils/StorageSlot.sol',
'@openzeppelin/contracts/utils/Strings.sol',
'@openzeppelin/contracts/utils/introspection/IERC165.sol',
'@openzeppelin/contracts/utils/math/Math.sol',
'@openzeppelin/contracts/utils/math/SafeCast.sol',
'@openzeppelin/contracts/utils/math/SignedMath.sol',
]);
});

test('can get imports for all combinations', t => {
for (const { options } of generateSources('all')) {
const c = buildGeneric(options);
getImports(c);
}
t.pass();
});
45 changes: 45 additions & 0 deletions packages/core/src/get-imports.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import type { Contract } from './contract';
import { reachable } from './utils/transitive-closure';

import contracts from '../openzeppelin-contracts';
import { withHelpers } from './options';

export interface SolcInputSources {
[source: string]: {
content: string;
};
}

/**
* Gets the source code for all imports of a contract, including all transitive dependencies,
* in a format compatible with the Solidity compiler input's `sources` field.
*
* Does not include the contract itself (use `printContract` for that if needed).
*
* @param c The contract to get imports for.
* @returns A record of import paths to `content` that contains the source code for each contract.
*/
export function getImports(c: Contract): SolcInputSources {
const { transformImport } = withHelpers(c);

const result: SolcInputSources = {};

const fileName = c.name + '.sol';

const dependencies = {
[fileName]: c.imports.map(i => transformImport(i).path),
...contracts.dependencies,
};

const allImports = reachable(dependencies, fileName);

for (const importPath of allImports) {
const source = contracts.sources[importPath];
if (source === undefined) {
throw new Error(`Source for ${importPath} not found`);
}
result[importPath] = { content: source };
}

return result;
}
4 changes: 2 additions & 2 deletions packages/core/src/scripts/prepare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ async function main() {
);

for (const [sourceFile, { ast }] of Object.entries(buildInfo.output.sources)) {
if (sourceFile.startsWith('@openzeppelin/contracts')) {
if (sourceFile.startsWith('@openzeppelin/contracts') || sourceFile.startsWith('@openzeppelin/community-contracts')) {
const sourceDependencies = (dependencies[sourceFile] ??= new Set());
for (const imp of findAll('ImportDirective', ast)) {
sourceDependencies.add(imp.absolutePath);
Expand All @@ -35,7 +35,7 @@ async function main() {
}

for (const [sourceFile, { content }] of Object.entries(buildInfo.input.sources)) {
if (sourceFile.startsWith('@openzeppelin/contracts')) {
if (sourceFile.startsWith('@openzeppelin/contracts') || sourceFile.startsWith('@openzeppelin/community-contracts')) {
sources[sourceFile] = content;
}
}
Expand Down
Loading

0 comments on commit b829f16

Please sign in to comment.