migrate-imports.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #!/usr/bin/env node
  2. const { promises: fs } = require('fs');
  3. const path = require('path');
  4. const pathUpdates = {
  5. // 'access/AccessControl.sol': undefined,
  6. // 'access/Ownable.sol': undefined,
  7. 'access/TimelockController.sol': 'governance/TimelockController.sol',
  8. 'cryptography/ECDSA.sol': 'utils/cryptography/ECDSA.sol',
  9. 'cryptography/MerkleProof.sol': 'utils/cryptography/MerkleProof.sol',
  10. 'drafts/EIP712.sol': 'utils/cryptography/EIP712.sol',
  11. 'drafts/ERC20Permit.sol': 'token/ERC20/extensions/ERC20Permit.sol',
  12. 'drafts/IERC20Permit.sol': 'token/ERC20/extensions/IERC20Permit.sol',
  13. 'GSN/Context.sol': 'utils/Context.sol',
  14. // 'GSN/GSNRecipientERC20Fee.sol': undefined,
  15. // 'GSN/GSNRecipientSignature.sol': undefined,
  16. // 'GSN/GSNRecipient.sol': undefined,
  17. // 'GSN/IRelayHub.sol': undefined,
  18. // 'GSN/IRelayRecipient.sol': undefined,
  19. 'introspection/ERC165Checker.sol': 'utils/introspection/ERC165Checker.sol',
  20. 'introspection/ERC165.sol': 'utils/introspection/ERC165.sol',
  21. 'introspection/ERC1820Implementer.sol': 'utils/introspection/ERC1820Implementer.sol',
  22. 'introspection/IERC165.sol': 'utils/introspection/IERC165.sol',
  23. 'introspection/IERC1820Implementer.sol': 'utils/introspection/IERC1820Implementer.sol',
  24. 'introspection/IERC1820Registry.sol': 'utils/introspection/IERC1820Registry.sol',
  25. 'math/Math.sol': 'utils/math/Math.sol',
  26. 'math/SafeMath.sol': 'utils/math/SafeMath.sol',
  27. 'math/SignedSafeMath.sol': 'utils/math/SignedSafeMath.sol',
  28. 'payment/escrow/ConditionalEscrow.sol': 'utils/escrow/ConditionalEscrow.sol',
  29. 'payment/escrow/Escrow.sol': 'utils/escrow/Escrow.sol',
  30. 'payment/escrow/RefundEscrow.sol': 'utils/escrow/RefundEscrow.sol',
  31. 'payment/PaymentSplitter.sol': 'finance/PaymentSplitter.sol',
  32. 'utils/PaymentSplitter.sol': 'finance/PaymentSplitter.sol',
  33. 'payment/PullPayment.sol': 'security/PullPayment.sol',
  34. 'presets/ERC1155PresetMinterPauser.sol': 'token/ERC1155/presets/ERC1155PresetMinterPauser.sol',
  35. 'presets/ERC20PresetFixedSupply.sol': 'token/ERC20/presets/ERC20PresetFixedSupply.sol',
  36. 'presets/ERC20PresetMinterPauser.sol': 'token/ERC20/presets/ERC20PresetMinterPauser.sol',
  37. 'presets/ERC721PresetMinterPauserAutoId.sol': 'token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol',
  38. 'presets/ERC777PresetFixedSupply.sol': 'token/ERC777/presets/ERC777PresetFixedSupply.sol',
  39. 'proxy/BeaconProxy.sol': 'proxy/beacon/BeaconProxy.sol',
  40. // 'proxy/Clones.sol': undefined,
  41. 'proxy/IBeacon.sol': 'proxy/beacon/IBeacon.sol',
  42. 'proxy/Initializable.sol': 'proxy/utils/Initializable.sol',
  43. 'utils/Initializable.sol': 'proxy/utils/Initializable.sol',
  44. 'proxy/ProxyAdmin.sol': 'proxy/transparent/ProxyAdmin.sol',
  45. // 'proxy/Proxy.sol': undefined,
  46. 'proxy/TransparentUpgradeableProxy.sol': 'proxy/transparent/TransparentUpgradeableProxy.sol',
  47. 'proxy/UpgradeableBeacon.sol': 'proxy/beacon/UpgradeableBeacon.sol',
  48. 'proxy/UpgradeableProxy.sol': 'proxy/ERC1967/ERC1967Proxy.sol',
  49. 'token/ERC1155/ERC1155Burnable.sol': 'token/ERC1155/extensions/ERC1155Burnable.sol',
  50. 'token/ERC1155/ERC1155Holder.sol': 'token/ERC1155/utils/ERC1155Holder.sol',
  51. 'token/ERC1155/ERC1155Pausable.sol': 'token/ERC1155/extensions/ERC1155Pausable.sol',
  52. 'token/ERC1155/ERC1155Receiver.sol': 'token/ERC1155/utils/ERC1155Receiver.sol',
  53. // 'token/ERC1155/ERC1155.sol': undefined,
  54. 'token/ERC1155/IERC1155MetadataURI.sol': 'token/ERC1155/extensions/IERC1155MetadataURI.sol',
  55. // 'token/ERC1155/IERC1155Receiver.sol': undefined,
  56. // 'token/ERC1155/IERC1155.sol': undefined,
  57. 'token/ERC20/ERC20Burnable.sol': 'token/ERC20/extensions/ERC20Burnable.sol',
  58. 'token/ERC20/ERC20Capped.sol': 'token/ERC20/extensions/ERC20Capped.sol',
  59. 'token/ERC20/ERC20Pausable.sol': 'token/ERC20/extensions/ERC20Pausable.sol',
  60. 'token/ERC20/ERC20Snapshot.sol': 'token/ERC20/extensions/ERC20Snapshot.sol',
  61. // 'token/ERC20/ERC20.sol': undefined,
  62. // 'token/ERC20/IERC20.sol': undefined,
  63. 'token/ERC20/SafeERC20.sol': 'token/ERC20/utils/SafeERC20.sol',
  64. 'token/ERC20/TokenTimelock.sol': 'token/ERC20/utils/TokenTimelock.sol',
  65. 'token/ERC721/ERC721Burnable.sol': 'token/ERC721/extensions/ERC721Burnable.sol',
  66. 'token/ERC721/ERC721Holder.sol': 'token/ERC721/utils/ERC721Holder.sol',
  67. 'token/ERC721/ERC721Pausable.sol': 'token/ERC721/extensions/ERC721Pausable.sol',
  68. // 'token/ERC721/ERC721.sol': undefined,
  69. 'token/ERC721/IERC721Enumerable.sol': 'token/ERC721/extensions/IERC721Enumerable.sol',
  70. 'token/ERC721/IERC721Metadata.sol': 'token/ERC721/extensions/IERC721Metadata.sol',
  71. // 'token/ERC721/IERC721Receiver.sol': undefined,
  72. // 'token/ERC721/IERC721.sol': undefined,
  73. // 'token/ERC777/ERC777.sol': undefined,
  74. // 'token/ERC777/IERC777Recipient.sol': undefined,
  75. // 'token/ERC777/IERC777Sender.sol': undefined,
  76. // 'token/ERC777/IERC777.sol': undefined,
  77. // 'utils/Address.sol': undefined,
  78. // 'utils/Arrays.sol': undefined,
  79. // 'utils/Context.sol': undefined,
  80. // 'utils/Counters.sol': undefined,
  81. // 'utils/Create2.sol': undefined,
  82. 'utils/EnumerableMap.sol': 'utils/structs/EnumerableMap.sol',
  83. 'utils/EnumerableSet.sol': 'utils/structs/EnumerableSet.sol',
  84. 'utils/Pausable.sol': 'security/Pausable.sol',
  85. 'utils/ReentrancyGuard.sol': 'security/ReentrancyGuard.sol',
  86. 'utils/SafeCast.sol': 'utils/math/SafeCast.sol',
  87. // 'utils/Strings.sol': undefined,
  88. 'utils/cryptography/draft-EIP712.sol': 'utils/cryptography/EIP712.sol',
  89. 'token/ERC20/extensions/draft-ERC20Permit.sol': 'token/ERC20/extensions/ERC20Permit.sol',
  90. 'token/ERC20/extensions/draft-IERC20Permit.sol': 'token/ERC20/extensions/IERC20Permit.sol',
  91. };
  92. async function main (paths = [ 'contracts' ]) {
  93. const files = await listFilesRecursively(paths, /\.sol$/);
  94. const updatedFiles = [];
  95. for (const file of files) {
  96. if (await updateFile(file, updateImportPaths)) {
  97. updatedFiles.push(file);
  98. }
  99. }
  100. if (updatedFiles.length > 0) {
  101. console.log(`${updatedFiles.length} file(s) were updated`);
  102. for (const c of updatedFiles) {
  103. console.log('-', c);
  104. }
  105. } else {
  106. console.log('No files were updated');
  107. }
  108. }
  109. async function listFilesRecursively (paths, filter) {
  110. const queue = paths;
  111. const files = [];
  112. while (queue.length > 0) {
  113. const top = queue.shift();
  114. const stat = await fs.stat(top);
  115. if (stat.isFile()) {
  116. if (top.match(filter)) {
  117. files.push(top);
  118. }
  119. } else if (stat.isDirectory()) {
  120. for (const name of await fs.readdir(top)) {
  121. queue.push(path.join(top, name));
  122. }
  123. }
  124. }
  125. return files;
  126. }
  127. async function updateFile (file, update) {
  128. const content = await fs.readFile(file, 'utf8');
  129. const updatedContent = update(content);
  130. if (updatedContent !== content) {
  131. await fs.writeFile(file, updatedContent);
  132. return true;
  133. } else {
  134. return false;
  135. }
  136. }
  137. function updateImportPaths (source) {
  138. for (const [ oldPath, newPath ] of Object.entries(pathUpdates)) {
  139. source = source.replace(
  140. path.join('@openzeppelin/contracts', oldPath),
  141. path.join('@openzeppelin/contracts', newPath),
  142. );
  143. source = source.replace(
  144. path.join('@openzeppelin/contracts-upgradeable', getUpgradeablePath(oldPath)),
  145. path.join('@openzeppelin/contracts-upgradeable', getUpgradeablePath(newPath)),
  146. );
  147. }
  148. return source;
  149. }
  150. function getUpgradeablePath (file) {
  151. const { dir, name, ext } = path.parse(file);
  152. const upgradeableName = name + 'Upgradeable';
  153. return path.format({ dir, ext, name: upgradeableName });
  154. }
  155. module.exports = {
  156. pathUpdates,
  157. updateImportPaths,
  158. getUpgradeablePath,
  159. };
  160. if (require.main === module) {
  161. const args = process.argv.length > 2 ? process.argv.slice(2) : undefined;
  162. main(args).catch(e => {
  163. console.error(e);
  164. process.exit(1);
  165. });
  166. }