From 16598b35de9f223c014b4a3dc6c0b639cd30f2a9 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Mon, 1 Feb 2021 13:49:49 +0100 Subject: [PATCH 01/31] Reorganisation of the repo structure. --- contracts/drafts/README.adoc | 15 ---------- contracts/mocks/AccessControlMock.sol | 2 +- contracts/mocks/ConditionalEscrowMock.sol | 2 +- contracts/mocks/Create2Impl.sol | 2 +- contracts/mocks/ECDSAMock.sol | 2 +- contracts/mocks/EIP712External.sol | 4 +-- contracts/mocks/ERC1155BurnableMock.sol | 2 +- contracts/mocks/ERC1155PausableMock.sol | 2 +- contracts/mocks/ERC1155ReceiverMock.sol | 2 +- .../ERC165/ERC165InterfacesSupported.sol | 2 +- contracts/mocks/ERC165CheckerMock.sol | 2 +- contracts/mocks/ERC165Mock.sol | 2 +- contracts/mocks/ERC1820ImplementerMock.sol | 2 +- contracts/mocks/ERC20BurnableMock.sol | 2 +- contracts/mocks/ERC20CappedMock.sol | 2 +- contracts/mocks/ERC20PausableMock.sol | 2 +- contracts/mocks/ERC20PermitMock.sol | 3 +- contracts/mocks/ERC20SnapshotMock.sol | 2 +- contracts/mocks/ERC721BurnableMock.sol | 2 +- contracts/mocks/ERC721GSNRecipientMock.sol | 4 +-- contracts/mocks/ERC721PausableMock.sol | 2 +- contracts/mocks/ERC721ReceiverMock.sol | 2 +- contracts/mocks/ERC777SenderRecipientMock.sol | 11 ++++---- contracts/mocks/GSNRecipientERC20FeeMock.sol | 4 +-- contracts/mocks/GSNRecipientMock.sol | 2 +- contracts/mocks/GSNRecipientSignatureMock.sol | 4 +-- contracts/mocks/InitializableMock.sol | 2 +- contracts/mocks/MathMock.sol | 2 +- contracts/mocks/MerkleProofWrapper.sol | 2 +- .../MultipleInheritanceInitializableMocks.sol | 4 +-- contracts/mocks/OwnableMock.sol | 2 +- contracts/mocks/PullPaymentMock.sol | 2 +- contracts/mocks/RegressionImplementation.sol | 2 +- contracts/mocks/SafeERC20Helper.sol | 2 +- contracts/mocks/SafeMathMock.sol | 2 +- contracts/mocks/SignedSafeMathMock.sol | 2 +- .../SingleInheritanceInitializableMocks.sol | 2 +- contracts/presets/README.adoc | 22 --------------- contracts/proxy/{ => beacon}/BeaconProxy.sol | 4 +-- contracts/proxy/{ => beacon}/IBeacon.sol | 0 .../proxy/{ => beacon}/UpgradeableBeacon.sol | 4 +-- .../proxy/{ => upgradeable}/ProxyAdmin.sol | 2 +- .../TransparentUpgradeableProxy.sol | 0 .../{ => upgradeable}/UpgradeableProxy.sol | 4 +-- contracts/token/ERC1155/ERC1155.sol | 28 +++++++++++-------- contracts/token/ERC1155/IERC1155.sol | 2 +- .../{ => extensions}/ERC1155Burnable.sol | 2 +- .../{ => extensions}/ERC1155Holder.sol | 2 +- .../{ => extensions}/ERC1155Pausable.sol | 4 +-- .../{ => extensions}/IERC1155MetadataURI.sol | 2 +- .../presets/ERC1155PresetMinterPauser.sol | 10 +++---- .../ERC1155/{ => utils}/ERC1155Receiver.sol | 2 +- .../ERC1155/{ => utils}/IERC1155Receiver.sol | 2 +- contracts/token/ERC20/ERC20.sol | 22 +++++++++------ .../ERC20/{ => extensions}/ERC20Burnable.sol | 9 +++--- .../ERC20/{ => extensions}/ERC20Capped.sol | 2 +- .../ERC20/{ => extensions}/ERC20Pausable.sol | 4 +-- .../ERC20/{ => extensions}/ERC20Snapshot.sol | 6 ++-- .../ERC20/extensions/draft-ERC20Permit.sol} | 10 +++---- .../ERC20/extensions/draft-IERC20Permit.sol} | 0 .../ERC20}/presets/ERC20PresetFixedSupply.sol | 2 +- .../presets/ERC20PresetMinterPauser.sol | 10 +++---- .../token/ERC20/{ => utils}/SafeERC20.sol | 4 +-- .../token/ERC20/{ => utils}/TokenTimelock.sol | 0 contracts/token/ERC721/ERC721.sol | 10 +++---- contracts/token/ERC721/IERC721.sol | 2 +- .../{ => extensions}/ERC721Burnable.sol | 4 +-- .../{ => extensions}/ERC721Pausable.sol | 4 +-- .../{ => extensions}/IERC721Enumerable.sol | 2 +- .../{ => extensions}/IERC721Metadata.sol | 2 +- .../ERC721PresetMinterPauserAutoId.sol | 12 ++++---- .../token/ERC721/{ => utils}/ERC721Holder.sol | 2 +- .../ERC721/{ => utils}/IERC721Receiver.sol | 0 contracts/token/ERC777/ERC777.sol | 25 +++++++++-------- .../presets/ERC777PresetFixedSupply.sol | 2 +- .../ERC777/{ => utils}/IERC777Recipient.sol | 0 .../ERC777/{ => utils}/IERC777Sender.sol | 0 contracts/utils/Arrays.sol | 2 +- contracts/{ => utils}/GSN/Context.sol | 2 +- contracts/{ => utils}/GSN/GSNRecipient.sol | 2 +- .../{ => utils}/GSN/GSNRecipientERC20Fee.sol | 4 +-- .../{ => utils}/GSN/GSNRecipientSignature.sol | 0 contracts/{ => utils}/GSN/IRelayHub.sol | 0 contracts/{ => utils}/GSN/IRelayRecipient.sol | 0 contracts/{ => utils}/GSN/README.adoc | 0 contracts/{proxy => utils}/Initializable.sol | 2 +- .../{ => utils}/access/AccessControl.sol | 6 ++-- contracts/{ => utils}/access/Ownable.sol | 2 +- contracts/{ => utils}/access/README.adoc | 0 .../{ => utils}/access/TimelockController.sol | 0 contracts/{ => utils}/cryptography/ECDSA.sol | 0 .../{ => utils}/cryptography/MerkleProof.sol | 0 .../{ => utils}/cryptography/README.adoc | 0 .../EIP712.sol => utils/draft-EIP712.sol} | 0 .../{ => utils}/introspection/ERC165.sol | 0 .../introspection/ERC165Checker.sol | 0 .../introspection/ERC1820Implementer.sol | 0 .../{ => utils}/introspection/IERC165.sol | 0 .../introspection/IERC1820Implementer.sol | 0 .../introspection/IERC1820Registry.sol | 0 .../{ => utils}/introspection/README.adoc | 0 contracts/{ => utils}/math/Math.sol | 0 contracts/{ => utils}/math/README.adoc | 0 contracts/{ => utils}/math/SafeMath.sol | 0 contracts/{ => utils}/math/SignedSafeMath.sol | 0 .../{ => utils}/payment/PaymentSplitter.sol | 6 ++-- contracts/{ => utils}/payment/PullPayment.sol | 0 contracts/{ => utils}/payment/README.adoc | 0 .../payment/escrow/ConditionalEscrow.sol | 0 .../{ => utils}/payment/escrow/Escrow.sol | 2 +- .../payment/escrow/RefundEscrow.sol | 0 111 files changed, 167 insertions(+), 192 deletions(-) delete mode 100644 contracts/drafts/README.adoc delete mode 100644 contracts/presets/README.adoc rename contracts/proxy/{ => beacon}/BeaconProxy.sol (98%) rename contracts/proxy/{ => beacon}/IBeacon.sol (100%) rename contracts/proxy/{ => beacon}/UpgradeableBeacon.sol (96%) rename contracts/proxy/{ => upgradeable}/ProxyAdmin.sol (98%) rename contracts/proxy/{ => upgradeable}/TransparentUpgradeableProxy.sol (100%) rename contracts/proxy/{ => upgradeable}/UpgradeableProxy.sol (97%) rename contracts/token/ERC1155/{ => extensions}/ERC1155Burnable.sol (97%) rename contracts/token/ERC1155/{ => extensions}/ERC1155Holder.sol (93%) rename contracts/token/ERC1155/{ => extensions}/ERC1155Pausable.sol (93%) rename contracts/token/ERC1155/{ => extensions}/IERC1155MetadataURI.sol (95%) rename contracts/{ => token/ERC1155}/presets/ERC1155PresetMinterPauser.sol (93%) rename contracts/token/ERC1155/{ => utils}/ERC1155Receiver.sol (85%) rename contracts/token/ERC1155/{ => utils}/IERC1155Receiver.sol (97%) rename contracts/token/ERC20/{ => extensions}/ERC20Burnable.sol (77%) rename contracts/token/ERC20/{ => extensions}/ERC20Capped.sol (97%) rename contracts/token/ERC20/{ => extensions}/ERC20Pausable.sol (92%) rename contracts/token/ERC20/{ => extensions}/ERC20Snapshot.sol (98%) rename contracts/{drafts/ERC20Permit.sol => token/ERC20/extensions/draft-ERC20Permit.sol} (93%) rename contracts/{drafts/IERC20Permit.sol => token/ERC20/extensions/draft-IERC20Permit.sol} (100%) rename contracts/{ => token/ERC20}/presets/ERC20PresetFixedSupply.sol (94%) rename contracts/{ => token/ERC20}/presets/ERC20PresetMinterPauser.sol (93%) rename contracts/token/ERC20/{ => utils}/SafeERC20.sol (98%) rename contracts/token/ERC20/{ => utils}/TokenTimelock.sol (100%) rename contracts/token/ERC721/{ => extensions}/ERC721Burnable.sol (91%) rename contracts/token/ERC721/{ => extensions}/ERC721Pausable.sol (92%) rename contracts/token/ERC721/{ => extensions}/IERC721Enumerable.sol (97%) rename contracts/token/ERC721/{ => extensions}/IERC721Metadata.sol (96%) rename contracts/{ => token/ERC721}/presets/ERC721PresetMinterPauserAutoId.sol (93%) rename contracts/token/ERC721/{ => utils}/ERC721Holder.sol (94%) rename contracts/token/ERC721/{ => utils}/IERC721Receiver.sol (100%) rename contracts/{ => token/ERC777}/presets/ERC777PresetFixedSupply.sol (94%) rename contracts/token/ERC777/{ => utils}/IERC777Recipient.sol (100%) rename contracts/token/ERC777/{ => utils}/IERC777Sender.sol (100%) rename contracts/{ => utils}/GSN/Context.sol (65%) rename contracts/{ => utils}/GSN/GSNRecipient.sol (99%) rename contracts/{ => utils}/GSN/GSNRecipientERC20Fee.sol (98%) rename contracts/{ => utils}/GSN/GSNRecipientSignature.sol (100%) rename contracts/{ => utils}/GSN/IRelayHub.sol (100%) rename contracts/{ => utils}/GSN/IRelayRecipient.sol (100%) rename contracts/{ => utils}/GSN/README.adoc (100%) rename contracts/{proxy => utils}/Initializable.sol (98%) rename contracts/{ => utils}/access/AccessControl.sol (98%) rename contracts/{ => utils}/access/Ownable.sol (98%) rename contracts/{ => utils}/access/README.adoc (100%) rename contracts/{ => utils}/access/TimelockController.sol (100%) rename contracts/{ => utils}/cryptography/ECDSA.sol (100%) rename contracts/{ => utils}/cryptography/MerkleProof.sol (100%) rename contracts/{ => utils}/cryptography/README.adoc (100%) rename contracts/{drafts/EIP712.sol => utils/draft-EIP712.sol} (100%) rename contracts/{ => utils}/introspection/ERC165.sol (100%) rename contracts/{ => utils}/introspection/ERC165Checker.sol (100%) rename contracts/{ => utils}/introspection/ERC1820Implementer.sol (100%) rename contracts/{ => utils}/introspection/IERC165.sol (100%) rename contracts/{ => utils}/introspection/IERC1820Implementer.sol (100%) rename contracts/{ => utils}/introspection/IERC1820Registry.sol (100%) rename contracts/{ => utils}/introspection/README.adoc (100%) rename contracts/{ => utils}/math/Math.sol (100%) rename contracts/{ => utils}/math/README.adoc (100%) rename contracts/{ => utils}/math/SafeMath.sol (100%) rename contracts/{ => utils}/math/SignedSafeMath.sol (100%) rename contracts/{ => utils}/payment/PaymentSplitter.sol (97%) rename contracts/{ => utils}/payment/PullPayment.sol (100%) rename contracts/{ => utils}/payment/README.adoc (100%) rename contracts/{ => utils}/payment/escrow/ConditionalEscrow.sol (100%) rename contracts/{ => utils}/payment/escrow/Escrow.sol (98%) rename contracts/{ => utils}/payment/escrow/RefundEscrow.sol (100%) diff --git a/contracts/drafts/README.adoc b/contracts/drafts/README.adoc deleted file mode 100644 index 3efcef91d61..00000000000 --- a/contracts/drafts/README.adoc +++ /dev/null @@ -1,15 +0,0 @@ -= Draft EIPs - -This directory contains implementations of EIPs that are still in Draft status. - -Due to their nature as drafts, the details of these contracts may change and we cannot guarantee their xref:ROOT:releases-stability.adoc[stability]. Minor releases of OpenZeppelin Contracts may contain breaking changes for the contracts in this directory, which will be duly announced in the https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/CHANGELOG.md[changelog]. The EIPs included here are used by projects in production and this may make them less likely to change significantly. - -== Cryptography - -{{EIP712}} - -== ERC 20 - -{{IERC20Permit}} - -{{ERC20Permit}} diff --git a/contracts/mocks/AccessControlMock.sol b/contracts/mocks/AccessControlMock.sol index 340e2080bcd..4b28702e2b9 100644 --- a/contracts/mocks/AccessControlMock.sol +++ b/contracts/mocks/AccessControlMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../access/AccessControl.sol"; +import "../utils/access/AccessControl.sol"; contract AccessControlMock is AccessControl { constructor() { diff --git a/contracts/mocks/ConditionalEscrowMock.sol b/contracts/mocks/ConditionalEscrowMock.sol index 5ceea176145..173bee96fb4 100644 --- a/contracts/mocks/ConditionalEscrowMock.sol +++ b/contracts/mocks/ConditionalEscrowMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../payment/escrow/ConditionalEscrow.sol"; +import "../utils/payment/escrow/ConditionalEscrow.sol"; // mock class using ConditionalEscrow contract ConditionalEscrowMock is ConditionalEscrow { diff --git a/contracts/mocks/Create2Impl.sol b/contracts/mocks/Create2Impl.sol index 7e5cd1a1c04..b062717391c 100644 --- a/contracts/mocks/Create2Impl.sol +++ b/contracts/mocks/Create2Impl.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import "../utils/Create2.sol"; -import "../introspection/ERC1820Implementer.sol"; +import "../utils/introspection/ERC1820Implementer.sol"; contract Create2Impl { function deploy(uint256 value, bytes32 salt, bytes memory code) public { diff --git a/contracts/mocks/ECDSAMock.sol b/contracts/mocks/ECDSAMock.sol index beec44d2603..99f6a7983e0 100644 --- a/contracts/mocks/ECDSAMock.sol +++ b/contracts/mocks/ECDSAMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../cryptography/ECDSA.sol"; +import "../utils/cryptography/ECDSA.sol"; contract ECDSAMock { using ECDSA for bytes32; diff --git a/contracts/mocks/EIP712External.sol b/contracts/mocks/EIP712External.sol index 7c37fb3c94d..cca6b5a1290 100644 --- a/contracts/mocks/EIP712External.sol +++ b/contracts/mocks/EIP712External.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.0; -import "../drafts/EIP712.sol"; -import "../cryptography/ECDSA.sol"; +import "../utils/draft-EIP712.sol"; +import "../utils/cryptography/ECDSA.sol"; contract EIP712External is EIP712 { constructor(string memory name, string memory version) EIP712(name, version) {} diff --git a/contracts/mocks/ERC1155BurnableMock.sol b/contracts/mocks/ERC1155BurnableMock.sol index 24ea6121ce1..8485eecfa59 100644 --- a/contracts/mocks/ERC1155BurnableMock.sol +++ b/contracts/mocks/ERC1155BurnableMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../token/ERC1155/ERC1155Burnable.sol"; +import "../token/ERC1155/extensions/ERC1155Burnable.sol"; contract ERC1155BurnableMock is ERC1155Burnable { constructor(string memory uri) ERC1155(uri) { } diff --git a/contracts/mocks/ERC1155PausableMock.sol b/contracts/mocks/ERC1155PausableMock.sol index 4f7edcccbc3..c4e4dd7beed 100644 --- a/contracts/mocks/ERC1155PausableMock.sol +++ b/contracts/mocks/ERC1155PausableMock.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import "./ERC1155Mock.sol"; -import "../token/ERC1155/ERC1155Pausable.sol"; +import "../token/ERC1155/extensions/ERC1155Pausable.sol"; contract ERC1155PausableMock is ERC1155Mock, ERC1155Pausable { constructor(string memory uri) ERC1155Mock(uri) { } diff --git a/contracts/mocks/ERC1155ReceiverMock.sol b/contracts/mocks/ERC1155ReceiverMock.sol index 6faaaa33658..d20233e2555 100644 --- a/contracts/mocks/ERC1155ReceiverMock.sol +++ b/contracts/mocks/ERC1155ReceiverMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../token/ERC1155/IERC1155Receiver.sol"; +import "../token/ERC1155/utils/IERC1155Receiver.sol"; import "./ERC165Mock.sol"; contract ERC1155ReceiverMock is IERC1155Receiver, ERC165Mock { diff --git a/contracts/mocks/ERC165/ERC165InterfacesSupported.sol b/contracts/mocks/ERC165/ERC165InterfacesSupported.sol index ffe8965bb2f..ecc4579d9c1 100644 --- a/contracts/mocks/ERC165/ERC165InterfacesSupported.sol +++ b/contracts/mocks/ERC165/ERC165InterfacesSupported.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../../introspection/IERC165.sol"; +import "../../utils/introspection/IERC165.sol"; /** * https://eips.ethereum.org/EIPS/eip-214#specification diff --git a/contracts/mocks/ERC165CheckerMock.sol b/contracts/mocks/ERC165CheckerMock.sol index a05f0f53591..bda5cfc78c2 100644 --- a/contracts/mocks/ERC165CheckerMock.sol +++ b/contracts/mocks/ERC165CheckerMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../introspection/ERC165Checker.sol"; +import "../utils/introspection/ERC165Checker.sol"; contract ERC165CheckerMock { using ERC165Checker for address; diff --git a/contracts/mocks/ERC165Mock.sol b/contracts/mocks/ERC165Mock.sol index 54677d3d43d..faeb5a1c1d1 100644 --- a/contracts/mocks/ERC165Mock.sol +++ b/contracts/mocks/ERC165Mock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../introspection/ERC165.sol"; +import "../utils/introspection/ERC165.sol"; contract ERC165Mock is ERC165 { function registerInterface(bytes4 interfaceId) public { diff --git a/contracts/mocks/ERC1820ImplementerMock.sol b/contracts/mocks/ERC1820ImplementerMock.sol index 126d8671d74..a6012d7ffee 100644 --- a/contracts/mocks/ERC1820ImplementerMock.sol +++ b/contracts/mocks/ERC1820ImplementerMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../introspection/ERC1820Implementer.sol"; +import "../utils/introspection/ERC1820Implementer.sol"; contract ERC1820ImplementerMock is ERC1820Implementer { function registerInterfaceForAddress(bytes32 interfaceHash, address account) public { diff --git a/contracts/mocks/ERC20BurnableMock.sol b/contracts/mocks/ERC20BurnableMock.sol index e4bd44cfadd..72d4e0b1681 100644 --- a/contracts/mocks/ERC20BurnableMock.sol +++ b/contracts/mocks/ERC20BurnableMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../token/ERC20/ERC20Burnable.sol"; +import "../token/ERC20/extensions/ERC20Burnable.sol"; contract ERC20BurnableMock is ERC20Burnable { constructor ( diff --git a/contracts/mocks/ERC20CappedMock.sol b/contracts/mocks/ERC20CappedMock.sol index 6cf74e9a39f..e5e3feb5f08 100644 --- a/contracts/mocks/ERC20CappedMock.sol +++ b/contracts/mocks/ERC20CappedMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../token/ERC20/ERC20Capped.sol"; +import "../token/ERC20/extensions/ERC20Capped.sol"; contract ERC20CappedMock is ERC20Capped { constructor (string memory name, string memory symbol, uint256 cap) diff --git a/contracts/mocks/ERC20PausableMock.sol b/contracts/mocks/ERC20PausableMock.sol index 0433e49a82a..6e61800df4b 100644 --- a/contracts/mocks/ERC20PausableMock.sol +++ b/contracts/mocks/ERC20PausableMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../token/ERC20/ERC20Pausable.sol"; +import "../token/ERC20/extensions/ERC20Pausable.sol"; // mock class using ERC20Pausable contract ERC20PausableMock is ERC20Pausable { diff --git a/contracts/mocks/ERC20PermitMock.sol b/contracts/mocks/ERC20PermitMock.sol index 6699cfe7cda..e9f2daf5e6b 100644 --- a/contracts/mocks/ERC20PermitMock.sol +++ b/contracts/mocks/ERC20PermitMock.sol @@ -2,7 +2,8 @@ pragma solidity ^0.8.0; -import "../drafts/ERC20Permit.sol"; + +import "../token/ERC20/extensions/draft-ERC20Permit.sol"; contract ERC20PermitMock is ERC20Permit { constructor ( diff --git a/contracts/mocks/ERC20SnapshotMock.sol b/contracts/mocks/ERC20SnapshotMock.sol index d8db876a01b..792bee1997b 100644 --- a/contracts/mocks/ERC20SnapshotMock.sol +++ b/contracts/mocks/ERC20SnapshotMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../token/ERC20/ERC20Snapshot.sol"; +import "../token/ERC20/extensions/ERC20Snapshot.sol"; contract ERC20SnapshotMock is ERC20Snapshot { diff --git a/contracts/mocks/ERC721BurnableMock.sol b/contracts/mocks/ERC721BurnableMock.sol index d2531b93c37..a1a5893c512 100644 --- a/contracts/mocks/ERC721BurnableMock.sol +++ b/contracts/mocks/ERC721BurnableMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../token/ERC721/ERC721Burnable.sol"; +import "../token/ERC721/extensions/ERC721Burnable.sol"; contract ERC721BurnableMock is ERC721Burnable { constructor(string memory name, string memory symbol) ERC721(name, symbol) { } diff --git a/contracts/mocks/ERC721GSNRecipientMock.sol b/contracts/mocks/ERC721GSNRecipientMock.sol index 96efd5a75eb..ecfc7ce2b07 100644 --- a/contracts/mocks/ERC721GSNRecipientMock.sol +++ b/contracts/mocks/ERC721GSNRecipientMock.sol @@ -3,8 +3,8 @@ pragma solidity ^0.8.0; import "../token/ERC721/ERC721.sol"; -import "../GSN/GSNRecipient.sol"; -import "../GSN/GSNRecipientSignature.sol"; +import "../utils/GSN/GSNRecipient.sol"; +import "../utils/GSN/GSNRecipientSignature.sol"; /** * @title ERC721GSNRecipientMock diff --git a/contracts/mocks/ERC721PausableMock.sol b/contracts/mocks/ERC721PausableMock.sol index 6bebea4a4f4..2133341aaf6 100644 --- a/contracts/mocks/ERC721PausableMock.sol +++ b/contracts/mocks/ERC721PausableMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../token/ERC721/ERC721Pausable.sol"; +import "../token/ERC721/extensions/ERC721Pausable.sol"; /** * @title ERC721PausableMock diff --git a/contracts/mocks/ERC721ReceiverMock.sol b/contracts/mocks/ERC721ReceiverMock.sol index 0ba5035e88f..b33c5241c6c 100644 --- a/contracts/mocks/ERC721ReceiverMock.sol +++ b/contracts/mocks/ERC721ReceiverMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../token/ERC721/IERC721Receiver.sol"; +import "../token/ERC721/utils/IERC721Receiver.sol"; contract ERC721ReceiverMock is IERC721Receiver { enum Error { diff --git a/contracts/mocks/ERC777SenderRecipientMock.sol b/contracts/mocks/ERC777SenderRecipientMock.sol index 9d9cff3f3e1..a1fa7a16004 100644 --- a/contracts/mocks/ERC777SenderRecipientMock.sol +++ b/contracts/mocks/ERC777SenderRecipientMock.sol @@ -2,12 +2,12 @@ pragma solidity ^0.8.0; -import "../utils/Context.sol"; import "../token/ERC777/IERC777.sol"; -import "../token/ERC777/IERC777Sender.sol"; -import "../token/ERC777/IERC777Recipient.sol"; -import "../introspection/IERC1820Registry.sol"; -import "../introspection/ERC1820Implementer.sol"; +import "../token/ERC777/utils/IERC777Sender.sol"; +import "../token/ERC777/utils/IERC777Recipient.sol"; +import "../utils/Context.sol"; +import "../utils/introspection/IERC1820Registry.sol"; +import "../utils/introspection/ERC1820Implementer.sol"; contract ERC777SenderRecipientMock is Context, IERC777Sender, IERC777Recipient, ERC1820Implementer { event TokensToSendCalled( @@ -150,4 +150,3 @@ contract ERC777SenderRecipientMock is Context, IERC777Sender, IERC777Recipient, token.burn(amount, data); } } - diff --git a/contracts/mocks/GSNRecipientERC20FeeMock.sol b/contracts/mocks/GSNRecipientERC20FeeMock.sol index b87b0caad5c..d374809d567 100644 --- a/contracts/mocks/GSNRecipientERC20FeeMock.sol +++ b/contracts/mocks/GSNRecipientERC20FeeMock.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.0; -import "../GSN/GSNRecipient.sol"; -import "../GSN/GSNRecipientERC20Fee.sol"; +import "../utils/GSN/GSNRecipient.sol"; +import "../utils/GSN/GSNRecipientERC20Fee.sol"; contract GSNRecipientERC20FeeMock is GSNRecipient, GSNRecipientERC20Fee { constructor(string memory name, string memory symbol) GSNRecipientERC20Fee(name, symbol) { } diff --git a/contracts/mocks/GSNRecipientMock.sol b/contracts/mocks/GSNRecipientMock.sol index f0c70b79363..d4abeddc0f6 100644 --- a/contracts/mocks/GSNRecipientMock.sol +++ b/contracts/mocks/GSNRecipientMock.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import "./ContextMock.sol"; -import "../GSN/GSNRecipient.sol"; +import "../utils/GSN/GSNRecipient.sol"; // By inheriting from GSNRecipient, Context's internal functions are overridden automatically contract GSNRecipientMock is ContextMock, GSNRecipient { diff --git a/contracts/mocks/GSNRecipientSignatureMock.sol b/contracts/mocks/GSNRecipientSignatureMock.sol index 4ae01b1bfe5..e57f9b56780 100644 --- a/contracts/mocks/GSNRecipientSignatureMock.sol +++ b/contracts/mocks/GSNRecipientSignatureMock.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.0; -import "../GSN/GSNRecipient.sol"; -import "../GSN/GSNRecipientSignature.sol"; +import "../utils/GSN/GSNRecipient.sol"; +import "../utils/GSN/GSNRecipientSignature.sol"; contract GSNRecipientSignatureMock is GSNRecipient, GSNRecipientSignature { constructor(address trustedSigner) GSNRecipientSignature(trustedSigner) { } diff --git a/contracts/mocks/InitializableMock.sol b/contracts/mocks/InitializableMock.sol index aacb30b208a..8f313ed5462 100644 --- a/contracts/mocks/InitializableMock.sol +++ b/contracts/mocks/InitializableMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../proxy/Initializable.sol"; +import "../utils/Initializable.sol"; /** * @title InitializableMock diff --git a/contracts/mocks/MathMock.sol b/contracts/mocks/MathMock.sol index 3f20efa0192..34bf6b6d400 100644 --- a/contracts/mocks/MathMock.sol +++ b/contracts/mocks/MathMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../math/Math.sol"; +import "../utils/math/Math.sol"; contract MathMock { function max(uint256 a, uint256 b) public pure returns (uint256) { diff --git a/contracts/mocks/MerkleProofWrapper.sol b/contracts/mocks/MerkleProofWrapper.sol index 004287e1079..bf1c6e4dff1 100644 --- a/contracts/mocks/MerkleProofWrapper.sol +++ b/contracts/mocks/MerkleProofWrapper.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import { MerkleProof } from "../cryptography/MerkleProof.sol"; +import "../utils/cryptography/MerkleProof.sol"; contract MerkleProofWrapper { function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) public pure returns (bool) { diff --git a/contracts/mocks/MultipleInheritanceInitializableMocks.sol b/contracts/mocks/MultipleInheritanceInitializableMocks.sol index f0095ce9662..81f340a4e38 100644 --- a/contracts/mocks/MultipleInheritanceInitializableMocks.sol +++ b/contracts/mocks/MultipleInheritanceInitializableMocks.sol @@ -2,11 +2,11 @@ pragma solidity ^0.8.0; -import "../proxy/Initializable.sol"; +import "../utils/Initializable.sol"; // Sample contracts showing upgradeability with multiple inheritance. // Child contract inherits from Father and Mother contracts, and Father extends from Gramps. -// +// // Human // / \ // | Gramps diff --git a/contracts/mocks/OwnableMock.sol b/contracts/mocks/OwnableMock.sol index 4751ed4b700..d2f4476a0e9 100644 --- a/contracts/mocks/OwnableMock.sol +++ b/contracts/mocks/OwnableMock.sol @@ -2,6 +2,6 @@ pragma solidity ^0.8.0; -import "../access/Ownable.sol"; +import "../utils/access/Ownable.sol"; contract OwnableMock is Ownable { } diff --git a/contracts/mocks/PullPaymentMock.sol b/contracts/mocks/PullPaymentMock.sol index b9c6ea37faa..233287397a6 100644 --- a/contracts/mocks/PullPaymentMock.sol +++ b/contracts/mocks/PullPaymentMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../payment/PullPayment.sol"; +import "../utils/payment/PullPayment.sol"; // mock class using PullPayment contract PullPaymentMock is PullPayment { diff --git a/contracts/mocks/RegressionImplementation.sol b/contracts/mocks/RegressionImplementation.sol index e11826f211f..c53fc3c4e36 100644 --- a/contracts/mocks/RegressionImplementation.sol +++ b/contracts/mocks/RegressionImplementation.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../proxy/Initializable.sol"; +import "../utils/Initializable.sol"; contract Implementation1 is Initializable { uint internal _value; diff --git a/contracts/mocks/SafeERC20Helper.sol b/contracts/mocks/SafeERC20Helper.sol index 7d347bbda97..d51c38de7f6 100644 --- a/contracts/mocks/SafeERC20Helper.sol +++ b/contracts/mocks/SafeERC20Helper.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import "../utils/Context.sol"; import "../token/ERC20/IERC20.sol"; -import "../token/ERC20/SafeERC20.sol"; +import "../token/ERC20/utils/SafeERC20.sol"; contract ERC20ReturnFalseMock is Context { uint256 private _allowance; diff --git a/contracts/mocks/SafeMathMock.sol b/contracts/mocks/SafeMathMock.sol index 2aacf11fbea..7158cf7406e 100644 --- a/contracts/mocks/SafeMathMock.sol +++ b/contracts/mocks/SafeMathMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../math/SafeMath.sol"; +import "../utils/math/SafeMath.sol"; contract SafeMathMock { function tryAdd(uint256 a, uint256 b) public pure returns (bool flag, uint256 value) { diff --git a/contracts/mocks/SignedSafeMathMock.sol b/contracts/mocks/SignedSafeMathMock.sol index 08afdc66b01..8d10217985e 100644 --- a/contracts/mocks/SignedSafeMathMock.sol +++ b/contracts/mocks/SignedSafeMathMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../math/SignedSafeMath.sol"; +import "../utils/math/SignedSafeMath.sol"; contract SignedSafeMathMock { function mul(int256 a, int256 b) public pure returns (int256) { diff --git a/contracts/mocks/SingleInheritanceInitializableMocks.sol b/contracts/mocks/SingleInheritanceInitializableMocks.sol index f5f81a7b0a2..2c9b75ee4f8 100644 --- a/contracts/mocks/SingleInheritanceInitializableMocks.sol +++ b/contracts/mocks/SingleInheritanceInitializableMocks.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../proxy/Initializable.sol"; +import "../utils/Initializable.sol"; /** * @title MigratableMockV1 diff --git a/contracts/presets/README.adoc b/contracts/presets/README.adoc deleted file mode 100644 index 8f189857639..00000000000 --- a/contracts/presets/README.adoc +++ /dev/null @@ -1,22 +0,0 @@ -= Presets - -[.readme-notice] -NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/presets - -These contracts integrate different Ethereum standards (ERCs) with custom extensions and modules, showcasing common configurations that are ready to deploy **without having to write any Solidity code**. - -They can be used as-is for quick prototyping and testing, but are **also suitable for production environments**. - -TIP: Intermediate and advanced users can use these as starting points when writing their own contracts, extending them with custom functionality as they see fit. - -== Tokens - -{{ERC20PresetMinterPauser}} - -{{ERC721PresetMinterPauserAutoId}} - -{{ERC1155PresetMinterPauser}} - -{{ERC20PresetFixedSupply}} - -{{ERC777PresetFixedSupply}} diff --git a/contracts/proxy/BeaconProxy.sol b/contracts/proxy/beacon/BeaconProxy.sol similarity index 98% rename from contracts/proxy/BeaconProxy.sol rename to contracts/proxy/beacon/BeaconProxy.sol index fa9c1af3190..a453c6248e7 100644 --- a/contracts/proxy/BeaconProxy.sol +++ b/contracts/proxy/beacon/BeaconProxy.sol @@ -2,9 +2,9 @@ pragma solidity ^0.8.0; -import "./Proxy.sol"; -import "../utils/Address.sol"; import "./IBeacon.sol"; +import "../Proxy.sol"; +import "../../utils/Address.sol"; /** * @dev This contract implements a proxy that gets the implementation address for each call from a {UpgradeableBeacon}. diff --git a/contracts/proxy/IBeacon.sol b/contracts/proxy/beacon/IBeacon.sol similarity index 100% rename from contracts/proxy/IBeacon.sol rename to contracts/proxy/beacon/IBeacon.sol diff --git a/contracts/proxy/UpgradeableBeacon.sol b/contracts/proxy/beacon/UpgradeableBeacon.sol similarity index 96% rename from contracts/proxy/UpgradeableBeacon.sol rename to contracts/proxy/beacon/UpgradeableBeacon.sol index c9dc07ddc2c..4ae5f309246 100644 --- a/contracts/proxy/UpgradeableBeacon.sol +++ b/contracts/proxy/beacon/UpgradeableBeacon.sol @@ -3,8 +3,8 @@ pragma solidity ^0.8.0; import "./IBeacon.sol"; -import "../access/Ownable.sol"; -import "../utils/Address.sol"; +import "../../utils/access/Ownable.sol"; +import "../../utils/Address.sol"; /** * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their diff --git a/contracts/proxy/ProxyAdmin.sol b/contracts/proxy/upgradeable/ProxyAdmin.sol similarity index 98% rename from contracts/proxy/ProxyAdmin.sol rename to contracts/proxy/upgradeable/ProxyAdmin.sol index 4ee2124ce03..0ee5b1868b9 100644 --- a/contracts/proxy/ProxyAdmin.sol +++ b/contracts/proxy/upgradeable/ProxyAdmin.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.0; -import "../access/Ownable.sol"; import "./TransparentUpgradeableProxy.sol"; +import "../../utils/access/Ownable.sol"; /** * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an diff --git a/contracts/proxy/TransparentUpgradeableProxy.sol b/contracts/proxy/upgradeable/TransparentUpgradeableProxy.sol similarity index 100% rename from contracts/proxy/TransparentUpgradeableProxy.sol rename to contracts/proxy/upgradeable/TransparentUpgradeableProxy.sol diff --git a/contracts/proxy/UpgradeableProxy.sol b/contracts/proxy/upgradeable/UpgradeableProxy.sol similarity index 97% rename from contracts/proxy/UpgradeableProxy.sol rename to contracts/proxy/upgradeable/UpgradeableProxy.sol index 8dd86464026..6c5917e7977 100644 --- a/contracts/proxy/UpgradeableProxy.sol +++ b/contracts/proxy/upgradeable/UpgradeableProxy.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.0; -import "./Proxy.sol"; -import "../utils/Address.sol"; +import "../Proxy.sol"; +import "../../utils/Address.sol"; /** * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an diff --git a/contracts/token/ERC1155/ERC1155.sol b/contracts/token/ERC1155/ERC1155.sol index dea9f28d07f..7731ce0bddd 100644 --- a/contracts/token/ERC1155/ERC1155.sol +++ b/contracts/token/ERC1155/ERC1155.sol @@ -3,11 +3,11 @@ pragma solidity ^0.8.0; import "./IERC1155.sol"; -import "./IERC1155MetadataURI.sol"; -import "./IERC1155Receiver.sol"; -import "../../utils/Context.sol"; -import "../../introspection/ERC165.sol"; +import "./extensions/IERC1155MetadataURI.sol"; +import "./utils/IERC1155Receiver.sol"; import "../../utils/Address.sol"; +import "../../utils/Context.sol"; +import "../../utils/introspection/ERC165.sol"; /** * @@ -137,8 +137,9 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data); - require(_balances[id][from] >= amount, "ERC1155: insufficient balance for transfer"); - _balances[id][from] -= amount; + uint256 balance_ = _balances[id][from]; + require(balance_ >= amount, "ERC1155: insufficient balance for transfer"); + _balances[id][from] = balance_ - amount; _balances[id][to] += amount; emit TransferSingle(operator, from, to, id, amount); @@ -175,8 +176,9 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { uint256 id = ids[i]; uint256 amount = amounts[i]; - require(_balances[id][from] >= amount, "ERC1155: insufficient balance for transfer"); - _balances[id][from] -= amount; + uint256 balance_ = _balances[id][from]; + require(balance_ >= amount, "ERC1155: insufficient balance for transfer"); + _balances[id][from] = balance_ - amount; _balances[id][to] += amount; } @@ -273,8 +275,9 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), ""); - require(_balances[id][account] >= amount, "ERC1155: burn amount exceeds balance"); - _balances[id][account] -= amount; + uint256 balance_ = _balances[id][account]; + require(balance_ >= amount, "ERC1155: burn amount exceeds balance"); + _balances[id][account] = balance_ - amount; emit TransferSingle(operator, account, address(0), id, amount); } @@ -298,8 +301,9 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { uint256 id = ids[i]; uint256 amount = amounts[i]; - require(_balances[id][account] >= amount, "ERC1155: burn amount exceeds balance"); - _balances[id][account] -= amount; + uint256 balance_ = _balances[id][account]; + require(balance_ >= amount, "ERC1155: burn amount exceeds balance"); + _balances[id][account] = balance_ - amount; } emit TransferBatch(operator, account, address(0), ids, amounts); diff --git a/contracts/token/ERC1155/IERC1155.sol b/contracts/token/ERC1155/IERC1155.sol index 6731963327f..6335adf7a80 100644 --- a/contracts/token/ERC1155/IERC1155.sol +++ b/contracts/token/ERC1155/IERC1155.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../../introspection/IERC165.sol"; +import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the diff --git a/contracts/token/ERC1155/ERC1155Burnable.sol b/contracts/token/ERC1155/extensions/ERC1155Burnable.sol similarity index 97% rename from contracts/token/ERC1155/ERC1155Burnable.sol rename to contracts/token/ERC1155/extensions/ERC1155Burnable.sol index d95b4385340..ddf9dd479a5 100644 --- a/contracts/token/ERC1155/ERC1155Burnable.sol +++ b/contracts/token/ERC1155/extensions/ERC1155Burnable.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "./ERC1155.sol"; +import "../ERC1155.sol"; /** * @dev Extension of {ERC1155} that allows token holders to destroy both their diff --git a/contracts/token/ERC1155/ERC1155Holder.sol b/contracts/token/ERC1155/extensions/ERC1155Holder.sol similarity index 93% rename from contracts/token/ERC1155/ERC1155Holder.sol rename to contracts/token/ERC1155/extensions/ERC1155Holder.sol index 4468f65cc84..93ac85162ec 100644 --- a/contracts/token/ERC1155/ERC1155Holder.sol +++ b/contracts/token/ERC1155/extensions/ERC1155Holder.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "./ERC1155Receiver.sol"; +import "../utils/ERC1155Receiver.sol"; /** * @dev _Available since v3.1._ diff --git a/contracts/token/ERC1155/ERC1155Pausable.sol b/contracts/token/ERC1155/extensions/ERC1155Pausable.sol similarity index 93% rename from contracts/token/ERC1155/ERC1155Pausable.sol rename to contracts/token/ERC1155/extensions/ERC1155Pausable.sol index 934896b2c82..3716e15c56b 100644 --- a/contracts/token/ERC1155/ERC1155Pausable.sol +++ b/contracts/token/ERC1155/extensions/ERC1155Pausable.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.0; -import "./ERC1155.sol"; -import "../../utils/Pausable.sol"; +import "../ERC1155.sol"; +import "../../../utils/Pausable.sol"; /** * @dev ERC1155 token with pausable token transfers, minting and burning. diff --git a/contracts/token/ERC1155/IERC1155MetadataURI.sol b/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol similarity index 95% rename from contracts/token/ERC1155/IERC1155MetadataURI.sol rename to contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol index f636cc2d87a..df55d97bb11 100644 --- a/contracts/token/ERC1155/IERC1155MetadataURI.sol +++ b/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "./IERC1155.sol"; +import "../IERC1155.sol"; /** * @dev Interface of the optional ERC1155MetadataExtension interface, as defined diff --git a/contracts/presets/ERC1155PresetMinterPauser.sol b/contracts/token/ERC1155/presets/ERC1155PresetMinterPauser.sol similarity index 93% rename from contracts/presets/ERC1155PresetMinterPauser.sol rename to contracts/token/ERC1155/presets/ERC1155PresetMinterPauser.sol index 73fabafdd19..a3353810735 100644 --- a/contracts/presets/ERC1155PresetMinterPauser.sol +++ b/contracts/token/ERC1155/presets/ERC1155PresetMinterPauser.sol @@ -2,11 +2,11 @@ pragma solidity ^0.8.0; -import "../access/AccessControl.sol"; -import "../utils/Context.sol"; -import "../token/ERC1155/ERC1155.sol"; -import "../token/ERC1155/ERC1155Burnable.sol"; -import "../token/ERC1155/ERC1155Pausable.sol"; +import "../ERC1155.sol"; +import "../extensions/ERC1155Burnable.sol"; +import "../extensions/ERC1155Pausable.sol"; +import "../../../utils/access/AccessControl.sol"; +import "../../../utils/Context.sol"; /** * @dev {ERC1155} token, including: diff --git a/contracts/token/ERC1155/ERC1155Receiver.sol b/contracts/token/ERC1155/utils/ERC1155Receiver.sol similarity index 85% rename from contracts/token/ERC1155/ERC1155Receiver.sol rename to contracts/token/ERC1155/utils/ERC1155Receiver.sol index 03a6eb58ec7..af713dc8c5e 100644 --- a/contracts/token/ERC1155/ERC1155Receiver.sol +++ b/contracts/token/ERC1155/utils/ERC1155Receiver.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import "./IERC1155Receiver.sol"; -import "../../introspection/ERC165.sol"; +import "../../../utils/introspection/ERC165.sol"; /** * @dev _Available since v3.1._ diff --git a/contracts/token/ERC1155/IERC1155Receiver.sol b/contracts/token/ERC1155/utils/IERC1155Receiver.sol similarity index 97% rename from contracts/token/ERC1155/IERC1155Receiver.sol rename to contracts/token/ERC1155/utils/IERC1155Receiver.sol index 07c441e22a4..a43e54b513e 100644 --- a/contracts/token/ERC1155/IERC1155Receiver.sol +++ b/contracts/token/ERC1155/utils/IERC1155Receiver.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../../introspection/IERC165.sol"; +import "../../../utils/introspection/IERC165.sol"; /** * _Available since v3.1._ diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index 03515b92c87..cf80b942533 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.0; -import "../../utils/Context.sol"; import "./IERC20.sol"; +import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. @@ -149,8 +149,9 @@ contract ERC20 is Context, IERC20 { function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { _transfer(sender, recipient, amount); - require(_allowances[sender][_msgSender()] >= amount, "ERC20: transfer amount exceeds allowance"); - _approve(sender, _msgSender(), _allowances[sender][_msgSender()] - amount); + uint256 allowance_ = _allowances[sender][_msgSender()]; + require(allowance_ >= amount, "ERC20: transfer amount exceeds allowance"); + _approve(sender, _msgSender(), allowance_ - amount); return true; } @@ -187,8 +188,9 @@ contract ERC20 is Context, IERC20 { * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { - require(_allowances[_msgSender()][spender] >= subtractedValue, "ERC20: decreased allowance below zero"); - _approve(_msgSender(), spender, _allowances[_msgSender()][spender] - subtractedValue); + uint256 allowanceSpender = _allowances[_msgSender()][spender]; + require(allowanceSpender >= subtractedValue, "ERC20: decreased allowance below zero"); + _approve(_msgSender(), spender, allowanceSpender - subtractedValue); return true; } @@ -213,8 +215,9 @@ contract ERC20 is Context, IERC20 { _beforeTokenTransfer(sender, recipient, amount); - require(_balances[sender] >= amount, "ERC20: transfer amount exceeds balance"); - _balances[sender] -= amount; + uint256 balance_ = _balances[sender]; + require(balance_ >= amount, "ERC20: transfer amount exceeds balance"); + _balances[sender] = balance_ - amount; _balances[recipient] += amount; emit Transfer(sender, recipient, amount); @@ -255,8 +258,9 @@ contract ERC20 is Context, IERC20 { _beforeTokenTransfer(account, address(0), amount); - require(_balances[account] >= amount, "ERC20: burn amount exceeds balance"); - _balances[account] -= amount; + uint256 balance_ = _balances[account]; + require(balance_ >= amount, "ERC20: burn amount exceeds balance"); + _balances[account] = balance_ - amount; _totalSupply -= amount; emit Transfer(account, address(0), amount); diff --git a/contracts/token/ERC20/ERC20Burnable.sol b/contracts/token/ERC20/extensions/ERC20Burnable.sol similarity index 77% rename from contracts/token/ERC20/ERC20Burnable.sol rename to contracts/token/ERC20/extensions/ERC20Burnable.sol index 73b060cc905..1baa1e78bcf 100644 --- a/contracts/token/ERC20/ERC20Burnable.sol +++ b/contracts/token/ERC20/extensions/ERC20Burnable.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.0; -import "../../utils/Context.sol"; -import "./ERC20.sol"; +import "../ERC20.sol"; +import "../../../utils/Context.sol"; /** * @dev Extension of {ERC20} that allows token holders to destroy both their own @@ -32,8 +32,9 @@ abstract contract ERC20Burnable is Context, ERC20 { * `amount`. */ function burnFrom(address account, uint256 amount) public virtual { - require(allowance(account, _msgSender()) >= amount, "ERC20: burn amount exceeds allowance"); - _approve(account, _msgSender(), allowance(account, _msgSender()) - amount); + uint256 allowance_ = allowance(account, _msgSender()); + require(allowance_ >= amount, "ERC20: burn amount exceeds allowance"); + _approve(account, _msgSender(), allowance_ - amount); _burn(account, amount); } } diff --git a/contracts/token/ERC20/ERC20Capped.sol b/contracts/token/ERC20/extensions/ERC20Capped.sol similarity index 97% rename from contracts/token/ERC20/ERC20Capped.sol rename to contracts/token/ERC20/extensions/ERC20Capped.sol index bef65cf5e1e..b0e79d25802 100644 --- a/contracts/token/ERC20/ERC20Capped.sol +++ b/contracts/token/ERC20/extensions/ERC20Capped.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "./ERC20.sol"; +import "../ERC20.sol"; /** * @dev Extension of {ERC20} that adds a cap to the supply of tokens. diff --git a/contracts/token/ERC20/ERC20Pausable.sol b/contracts/token/ERC20/extensions/ERC20Pausable.sol similarity index 92% rename from contracts/token/ERC20/ERC20Pausable.sol rename to contracts/token/ERC20/extensions/ERC20Pausable.sol index a484fef8112..db0a99a6f29 100644 --- a/contracts/token/ERC20/ERC20Pausable.sol +++ b/contracts/token/ERC20/extensions/ERC20Pausable.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.0; -import "./ERC20.sol"; -import "../../utils/Pausable.sol"; +import "../ERC20.sol"; +import "../../../utils/Pausable.sol"; /** * @dev ERC20 token with pausable token transfers, minting and burning. diff --git a/contracts/token/ERC20/ERC20Snapshot.sol b/contracts/token/ERC20/extensions/ERC20Snapshot.sol similarity index 98% rename from contracts/token/ERC20/ERC20Snapshot.sol rename to contracts/token/ERC20/extensions/ERC20Snapshot.sol index 56494feb2f7..2246b4e3a2d 100644 --- a/contracts/token/ERC20/ERC20Snapshot.sol +++ b/contracts/token/ERC20/extensions/ERC20Snapshot.sol @@ -2,9 +2,9 @@ pragma solidity ^0.8.0; -import "../../utils/Arrays.sol"; -import "../../utils/Counters.sol"; -import "./ERC20.sol"; +import "../ERC20.sol"; +import "../../../utils/Arrays.sol"; +import "../../../utils/Counters.sol"; /** * @dev This contract extends an ERC20 token with a snapshot mechanism. When a snapshot is created, the balances and diff --git a/contracts/drafts/ERC20Permit.sol b/contracts/token/ERC20/extensions/draft-ERC20Permit.sol similarity index 93% rename from contracts/drafts/ERC20Permit.sol rename to contracts/token/ERC20/extensions/draft-ERC20Permit.sol index 7a8b97163ea..4af75e0e789 100644 --- a/contracts/drafts/ERC20Permit.sol +++ b/contracts/token/ERC20/extensions/draft-ERC20Permit.sol @@ -2,11 +2,11 @@ pragma solidity ^0.8.0; -import "../token/ERC20/ERC20.sol"; -import "./IERC20Permit.sol"; -import "../cryptography/ECDSA.sol"; -import "../utils/Counters.sol"; -import "./EIP712.sol"; +import "./draft-IERC20Permit.sol"; +import "../ERC20.sol"; +import "../../../utils/cryptography/ECDSA.sol"; +import "../../../utils/Counters.sol"; +import "../../../utils/draft-EIP712.sol"; /** * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in diff --git a/contracts/drafts/IERC20Permit.sol b/contracts/token/ERC20/extensions/draft-IERC20Permit.sol similarity index 100% rename from contracts/drafts/IERC20Permit.sol rename to contracts/token/ERC20/extensions/draft-IERC20Permit.sol diff --git a/contracts/presets/ERC20PresetFixedSupply.sol b/contracts/token/ERC20/presets/ERC20PresetFixedSupply.sol similarity index 94% rename from contracts/presets/ERC20PresetFixedSupply.sol rename to contracts/token/ERC20/presets/ERC20PresetFixedSupply.sol index b56329d4bbc..4aa0ebf4808 100644 --- a/contracts/presets/ERC20PresetFixedSupply.sol +++ b/contracts/token/ERC20/presets/ERC20PresetFixedSupply.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "../token/ERC20/ERC20Burnable.sol"; +import "../extensions/ERC20Burnable.sol"; /** * @dev {ERC20} token, including: diff --git a/contracts/presets/ERC20PresetMinterPauser.sol b/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol similarity index 93% rename from contracts/presets/ERC20PresetMinterPauser.sol rename to contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol index a8891c4426c..346b0b11262 100644 --- a/contracts/presets/ERC20PresetMinterPauser.sol +++ b/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol @@ -2,11 +2,11 @@ pragma solidity ^0.8.0; -import "../access/AccessControl.sol"; -import "../utils/Context.sol"; -import "../token/ERC20/ERC20.sol"; -import "../token/ERC20/ERC20Burnable.sol"; -import "../token/ERC20/ERC20Pausable.sol"; +import "../ERC20.sol"; +import "../extensions/ERC20Burnable.sol"; +import "../extensions/ERC20Pausable.sol"; +import "../../../utils/access/AccessControl.sol"; +import "../../../utils/Context.sol"; /** * @dev {ERC20} token, including: diff --git a/contracts/token/ERC20/SafeERC20.sol b/contracts/token/ERC20/utils/SafeERC20.sol similarity index 98% rename from contracts/token/ERC20/SafeERC20.sol rename to contracts/token/ERC20/utils/SafeERC20.sol index 8534f6c5822..197da6667d1 100644 --- a/contracts/token/ERC20/SafeERC20.sol +++ b/contracts/token/ERC20/utils/SafeERC20.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.0; -import "./IERC20.sol"; -import "../../utils/Address.sol"; +import "../IERC20.sol"; +import "../../../utils/Address.sol"; /** * @title SafeERC20 diff --git a/contracts/token/ERC20/TokenTimelock.sol b/contracts/token/ERC20/utils/TokenTimelock.sol similarity index 100% rename from contracts/token/ERC20/TokenTimelock.sol rename to contracts/token/ERC20/utils/TokenTimelock.sol diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index 0ca91ee4ce7..977ed2976a6 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -2,16 +2,16 @@ pragma solidity ^0.8.0; -import "../../utils/Context.sol"; import "./IERC721.sol"; -import "./IERC721Metadata.sol"; -import "./IERC721Enumerable.sol"; -import "./IERC721Receiver.sol"; -import "../../introspection/ERC165.sol"; +import "./extensions/IERC721Metadata.sol"; +import "./extensions/IERC721Enumerable.sol"; +import "./utils/IERC721Receiver.sol"; import "../../utils/Address.sol"; +import "../../utils/Context.sol"; import "../../utils/EnumerableSet.sol"; import "../../utils/EnumerableMap.sol"; import "../../utils/Strings.sol"; +import "../../utils/introspection/ERC165.sol"; /** * @title ERC721 Non-Fungible Token Standard basic implementation diff --git a/contracts/token/ERC721/IERC721.sol b/contracts/token/ERC721/IERC721.sol index 4afa6dc52d4..5811e7994ee 100644 --- a/contracts/token/ERC721/IERC721.sol +++ b/contracts/token/ERC721/IERC721.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../../introspection/IERC165.sol"; +import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. diff --git a/contracts/token/ERC721/ERC721Burnable.sol b/contracts/token/ERC721/extensions/ERC721Burnable.sol similarity index 91% rename from contracts/token/ERC721/ERC721Burnable.sol rename to contracts/token/ERC721/extensions/ERC721Burnable.sol index 9a512cc6276..b0512f04817 100644 --- a/contracts/token/ERC721/ERC721Burnable.sol +++ b/contracts/token/ERC721/extensions/ERC721Burnable.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.0; -import "../../utils/Context.sol"; -import "./ERC721.sol"; +import "../ERC721.sol"; +import "../../../utils/Context.sol"; /** * @title ERC721 Burnable Token diff --git a/contracts/token/ERC721/ERC721Pausable.sol b/contracts/token/ERC721/extensions/ERC721Pausable.sol similarity index 92% rename from contracts/token/ERC721/ERC721Pausable.sol rename to contracts/token/ERC721/extensions/ERC721Pausable.sol index 456db1d52aa..bf21378f693 100644 --- a/contracts/token/ERC721/ERC721Pausable.sol +++ b/contracts/token/ERC721/extensions/ERC721Pausable.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.0; -import "./ERC721.sol"; -import "../../utils/Pausable.sol"; +import "../ERC721.sol"; +import "../../../utils/Pausable.sol"; /** * @dev ERC721 token with pausable token transfers, minting and burning. diff --git a/contracts/token/ERC721/IERC721Enumerable.sol b/contracts/token/ERC721/extensions/IERC721Enumerable.sol similarity index 97% rename from contracts/token/ERC721/IERC721Enumerable.sol rename to contracts/token/ERC721/extensions/IERC721Enumerable.sol index 2cb4789658a..6cf0f83698d 100644 --- a/contracts/token/ERC721/IERC721Enumerable.sol +++ b/contracts/token/ERC721/extensions/IERC721Enumerable.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "./IERC721.sol"; +import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension diff --git a/contracts/token/ERC721/IERC721Metadata.sol b/contracts/token/ERC721/extensions/IERC721Metadata.sol similarity index 96% rename from contracts/token/ERC721/IERC721Metadata.sol rename to contracts/token/ERC721/extensions/IERC721Metadata.sol index 24f02f838ed..2379baca95a 100644 --- a/contracts/token/ERC721/IERC721Metadata.sol +++ b/contracts/token/ERC721/extensions/IERC721Metadata.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "./IERC721.sol"; +import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension diff --git a/contracts/presets/ERC721PresetMinterPauserAutoId.sol b/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol similarity index 93% rename from contracts/presets/ERC721PresetMinterPauserAutoId.sol rename to contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol index 2cd9bdaa403..ff33dcca4e4 100644 --- a/contracts/presets/ERC721PresetMinterPauserAutoId.sol +++ b/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol @@ -2,12 +2,12 @@ pragma solidity ^0.8.0; -import "../access/AccessControl.sol"; -import "../utils/Context.sol"; -import "../utils/Counters.sol"; -import "../token/ERC721/ERC721.sol"; -import "../token/ERC721/ERC721Burnable.sol"; -import "../token/ERC721/ERC721Pausable.sol"; +import "../ERC721.sol"; +import "../extensions/ERC721Burnable.sol"; +import "../extensions/ERC721Pausable.sol"; +import "../../../utils/access/AccessControl.sol"; +import "../../../utils/Context.sol"; +import "../../../utils/Counters.sol"; /** * @dev {ERC721} token, including: diff --git a/contracts/token/ERC721/ERC721Holder.sol b/contracts/token/ERC721/utils/ERC721Holder.sol similarity index 94% rename from contracts/token/ERC721/ERC721Holder.sol rename to contracts/token/ERC721/utils/ERC721Holder.sol index 6e4858a6b4c..c65825e0ec8 100644 --- a/contracts/token/ERC721/ERC721Holder.sol +++ b/contracts/token/ERC721/utils/ERC721Holder.sol @@ -7,7 +7,7 @@ import "./IERC721Receiver.sol"; /** * @dev Implementation of the {IERC721Receiver} interface. * - * Accepts all token transfers. + * Accepts all token transfers. * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or {IERC721-setApprovalForAll}. */ contract ERC721Holder is IERC721Receiver { diff --git a/contracts/token/ERC721/IERC721Receiver.sol b/contracts/token/ERC721/utils/IERC721Receiver.sol similarity index 100% rename from contracts/token/ERC721/IERC721Receiver.sol rename to contracts/token/ERC721/utils/IERC721Receiver.sol diff --git a/contracts/token/ERC777/ERC777.sol b/contracts/token/ERC777/ERC777.sol index be21bda10e4..00f2945dcab 100644 --- a/contracts/token/ERC777/ERC777.sol +++ b/contracts/token/ERC777/ERC777.sol @@ -2,13 +2,13 @@ pragma solidity ^0.8.0; -import "../../utils/Context.sol"; import "./IERC777.sol"; -import "./IERC777Recipient.sol"; -import "./IERC777Sender.sol"; -import "../../token/ERC20/IERC20.sol"; +import "./utils/IERC777Sender.sol"; +import "./utils/IERC777Recipient.sol"; +import "../ERC20/IERC20.sol"; import "../../utils/Address.sol"; -import "../../introspection/IERC1820Registry.sol"; +import "../../utils/Context.sol"; +import "../../utils/introspection/IERC1820Registry.sol"; /** * @dev Implementation of the {IERC777} interface. @@ -278,8 +278,9 @@ contract ERC777 is Context, IERC777, IERC20 { _move(spender, holder, recipient, amount, "", ""); - require(_allowances[holder][spender] >= amount, "ERC777: transfer amount exceeds allowance"); - _approve(holder, spender, _allowances[holder][spender] - amount); + uint256 allowance_ = _allowances[holder][spender]; + require(allowance_ >= amount, "ERC777: transfer amount exceeds allowance"); + _approve(holder, spender, allowance_ - amount); _callTokensReceived(spender, holder, recipient, amount, "", "", false); @@ -385,8 +386,9 @@ contract ERC777 is Context, IERC777, IERC20 { _beforeTokenTransfer(operator, from, address(0), amount); // Update state variables - require(_balances[from] >= amount, "ERC777: burn amount exceeds balance"); - _balances[from] -= amount; + uint256 balance_ = _balances[from]; + require(balance_ >= amount, "ERC777: burn amount exceeds balance"); + _balances[from] = balance_ - amount; _totalSupply -= amount; emit Burned(operator, from, amount, data, operatorData); @@ -405,8 +407,9 @@ contract ERC777 is Context, IERC777, IERC20 { { _beforeTokenTransfer(operator, from, to, amount); - require(_balances[from] >= amount, "ERC777: transfer amount exceeds balance"); - _balances[from] -= amount; + uint256 balance_ = _balances[from]; + require(balance_ >= amount, "ERC777: transfer amount exceeds balance"); + _balances[from] = balance_ - amount; _balances[to] += amount; emit Sent(operator, from, to, amount, userData, operatorData); diff --git a/contracts/presets/ERC777PresetFixedSupply.sol b/contracts/token/ERC777/presets/ERC777PresetFixedSupply.sol similarity index 94% rename from contracts/presets/ERC777PresetFixedSupply.sol rename to contracts/token/ERC777/presets/ERC777PresetFixedSupply.sol index 0556daccd0e..fb9a6cef223 100644 --- a/contracts/presets/ERC777PresetFixedSupply.sol +++ b/contracts/token/ERC777/presets/ERC777PresetFixedSupply.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "../token/ERC777/ERC777.sol"; +import "../ERC777.sol"; /** * @dev {ERC777} token, including: diff --git a/contracts/token/ERC777/IERC777Recipient.sol b/contracts/token/ERC777/utils/IERC777Recipient.sol similarity index 100% rename from contracts/token/ERC777/IERC777Recipient.sol rename to contracts/token/ERC777/utils/IERC777Recipient.sol diff --git a/contracts/token/ERC777/IERC777Sender.sol b/contracts/token/ERC777/utils/IERC777Sender.sol similarity index 100% rename from contracts/token/ERC777/IERC777Sender.sol rename to contracts/token/ERC777/utils/IERC777Sender.sol diff --git a/contracts/utils/Arrays.sol b/contracts/utils/Arrays.sol index 4bbaa138c87..9a6e7ae0448 100644 --- a/contracts/utils/Arrays.sol +++ b/contracts/utils/Arrays.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../math/Math.sol"; +import "./math/Math.sol"; /** * @dev Collection of functions related to array types. diff --git a/contracts/GSN/Context.sol b/contracts/utils/GSN/Context.sol similarity index 65% rename from contracts/GSN/Context.sol rename to contracts/utils/GSN/Context.sol index 4a7d7cee8d4..eec27ff16b5 100644 --- a/contracts/GSN/Context.sol +++ b/contracts/utils/GSN/Context.sol @@ -2,4 +2,4 @@ pragma solidity ^0.8.0; -import "../utils/Context.sol"; +import "../Context.sol"; diff --git a/contracts/GSN/GSNRecipient.sol b/contracts/utils/GSN/GSNRecipient.sol similarity index 99% rename from contracts/GSN/GSNRecipient.sol rename to contracts/utils/GSN/GSNRecipient.sol index 8393056f115..bc894f60ea6 100644 --- a/contracts/GSN/GSNRecipient.sol +++ b/contracts/utils/GSN/GSNRecipient.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../utils/Context.sol"; +import "./Context.sol"; import "./IRelayRecipient.sol"; import "./IRelayHub.sol"; diff --git a/contracts/GSN/GSNRecipientERC20Fee.sol b/contracts/utils/GSN/GSNRecipientERC20Fee.sol similarity index 98% rename from contracts/GSN/GSNRecipientERC20Fee.sol rename to contracts/utils/GSN/GSNRecipientERC20Fee.sol index d129643b375..1c124f77cf5 100644 --- a/contracts/GSN/GSNRecipientERC20Fee.sol +++ b/contracts/utils/GSN/GSNRecipientERC20Fee.sol @@ -4,8 +4,8 @@ pragma solidity ^0.8.0; import "./GSNRecipient.sol"; import "../access/Ownable.sol"; -import "../token/ERC20/SafeERC20.sol"; -import "../token/ERC20/ERC20.sol"; +import "../../token/ERC20/ERC20.sol"; +import "../../token/ERC20/utils/SafeERC20.sol"; /** * @dev A xref:ROOT:gsn-strategies.adoc#gsn-strategies[GSN strategy] that charges transaction fees in a special purpose ERC20 diff --git a/contracts/GSN/GSNRecipientSignature.sol b/contracts/utils/GSN/GSNRecipientSignature.sol similarity index 100% rename from contracts/GSN/GSNRecipientSignature.sol rename to contracts/utils/GSN/GSNRecipientSignature.sol diff --git a/contracts/GSN/IRelayHub.sol b/contracts/utils/GSN/IRelayHub.sol similarity index 100% rename from contracts/GSN/IRelayHub.sol rename to contracts/utils/GSN/IRelayHub.sol diff --git a/contracts/GSN/IRelayRecipient.sol b/contracts/utils/GSN/IRelayRecipient.sol similarity index 100% rename from contracts/GSN/IRelayRecipient.sol rename to contracts/utils/GSN/IRelayRecipient.sol diff --git a/contracts/GSN/README.adoc b/contracts/utils/GSN/README.adoc similarity index 100% rename from contracts/GSN/README.adoc rename to contracts/utils/GSN/README.adoc diff --git a/contracts/proxy/Initializable.sol b/contracts/utils/Initializable.sol similarity index 98% rename from contracts/proxy/Initializable.sol rename to contracts/utils/Initializable.sol index 3f0e3c9b95b..c37c89ae955 100644 --- a/contracts/proxy/Initializable.sol +++ b/contracts/utils/Initializable.sol @@ -3,7 +3,7 @@ // solhint-disable-next-line compiler-version pragma solidity ^0.8.0; -import "../utils/Address.sol"; +import "./Address.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed diff --git a/contracts/access/AccessControl.sol b/contracts/utils/access/AccessControl.sol similarity index 98% rename from contracts/access/AccessControl.sol rename to contracts/utils/access/AccessControl.sol index 1871e33a70b..b7fe954684e 100644 --- a/contracts/access/AccessControl.sol +++ b/contracts/utils/access/AccessControl.sol @@ -2,9 +2,9 @@ pragma solidity ^0.8.0; -import "../utils/EnumerableSet.sol"; -import "../utils/Address.sol"; -import "../utils/Context.sol"; +import "../Address.sol"; +import "../Context.sol"; +import "../EnumerableSet.sol"; /** * @dev Contract module that allows children to implement role-based access diff --git a/contracts/access/Ownable.sol b/contracts/utils/access/Ownable.sol similarity index 98% rename from contracts/access/Ownable.sol rename to contracts/utils/access/Ownable.sol index bdad22b22e3..7938a054ece 100644 --- a/contracts/access/Ownable.sol +++ b/contracts/utils/access/Ownable.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../utils/Context.sol"; +import "../Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to diff --git a/contracts/access/README.adoc b/contracts/utils/access/README.adoc similarity index 100% rename from contracts/access/README.adoc rename to contracts/utils/access/README.adoc diff --git a/contracts/access/TimelockController.sol b/contracts/utils/access/TimelockController.sol similarity index 100% rename from contracts/access/TimelockController.sol rename to contracts/utils/access/TimelockController.sol diff --git a/contracts/cryptography/ECDSA.sol b/contracts/utils/cryptography/ECDSA.sol similarity index 100% rename from contracts/cryptography/ECDSA.sol rename to contracts/utils/cryptography/ECDSA.sol diff --git a/contracts/cryptography/MerkleProof.sol b/contracts/utils/cryptography/MerkleProof.sol similarity index 100% rename from contracts/cryptography/MerkleProof.sol rename to contracts/utils/cryptography/MerkleProof.sol diff --git a/contracts/cryptography/README.adoc b/contracts/utils/cryptography/README.adoc similarity index 100% rename from contracts/cryptography/README.adoc rename to contracts/utils/cryptography/README.adoc diff --git a/contracts/drafts/EIP712.sol b/contracts/utils/draft-EIP712.sol similarity index 100% rename from contracts/drafts/EIP712.sol rename to contracts/utils/draft-EIP712.sol diff --git a/contracts/introspection/ERC165.sol b/contracts/utils/introspection/ERC165.sol similarity index 100% rename from contracts/introspection/ERC165.sol rename to contracts/utils/introspection/ERC165.sol diff --git a/contracts/introspection/ERC165Checker.sol b/contracts/utils/introspection/ERC165Checker.sol similarity index 100% rename from contracts/introspection/ERC165Checker.sol rename to contracts/utils/introspection/ERC165Checker.sol diff --git a/contracts/introspection/ERC1820Implementer.sol b/contracts/utils/introspection/ERC1820Implementer.sol similarity index 100% rename from contracts/introspection/ERC1820Implementer.sol rename to contracts/utils/introspection/ERC1820Implementer.sol diff --git a/contracts/introspection/IERC165.sol b/contracts/utils/introspection/IERC165.sol similarity index 100% rename from contracts/introspection/IERC165.sol rename to contracts/utils/introspection/IERC165.sol diff --git a/contracts/introspection/IERC1820Implementer.sol b/contracts/utils/introspection/IERC1820Implementer.sol similarity index 100% rename from contracts/introspection/IERC1820Implementer.sol rename to contracts/utils/introspection/IERC1820Implementer.sol diff --git a/contracts/introspection/IERC1820Registry.sol b/contracts/utils/introspection/IERC1820Registry.sol similarity index 100% rename from contracts/introspection/IERC1820Registry.sol rename to contracts/utils/introspection/IERC1820Registry.sol diff --git a/contracts/introspection/README.adoc b/contracts/utils/introspection/README.adoc similarity index 100% rename from contracts/introspection/README.adoc rename to contracts/utils/introspection/README.adoc diff --git a/contracts/math/Math.sol b/contracts/utils/math/Math.sol similarity index 100% rename from contracts/math/Math.sol rename to contracts/utils/math/Math.sol diff --git a/contracts/math/README.adoc b/contracts/utils/math/README.adoc similarity index 100% rename from contracts/math/README.adoc rename to contracts/utils/math/README.adoc diff --git a/contracts/math/SafeMath.sol b/contracts/utils/math/SafeMath.sol similarity index 100% rename from contracts/math/SafeMath.sol rename to contracts/utils/math/SafeMath.sol diff --git a/contracts/math/SignedSafeMath.sol b/contracts/utils/math/SignedSafeMath.sol similarity index 100% rename from contracts/math/SignedSafeMath.sol rename to contracts/utils/math/SignedSafeMath.sol diff --git a/contracts/payment/PaymentSplitter.sol b/contracts/utils/payment/PaymentSplitter.sol similarity index 97% rename from contracts/payment/PaymentSplitter.sol rename to contracts/utils/payment/PaymentSplitter.sol index f09d101fdbc..5498e7ebcd8 100644 --- a/contracts/payment/PaymentSplitter.sol +++ b/contracts/utils/payment/PaymentSplitter.sol @@ -2,9 +2,9 @@ pragma solidity ^0.8.0; -import "../utils/Context.sol"; -import "../math/SafeMath.sol"; -import "../utils/Address.sol"; +import "../../utils/Address.sol"; +import "../../utils/Context.sol"; +import "../../utils/math/SafeMath.sol"; /** * @title PaymentSplitter diff --git a/contracts/payment/PullPayment.sol b/contracts/utils/payment/PullPayment.sol similarity index 100% rename from contracts/payment/PullPayment.sol rename to contracts/utils/payment/PullPayment.sol diff --git a/contracts/payment/README.adoc b/contracts/utils/payment/README.adoc similarity index 100% rename from contracts/payment/README.adoc rename to contracts/utils/payment/README.adoc diff --git a/contracts/payment/escrow/ConditionalEscrow.sol b/contracts/utils/payment/escrow/ConditionalEscrow.sol similarity index 100% rename from contracts/payment/escrow/ConditionalEscrow.sol rename to contracts/utils/payment/escrow/ConditionalEscrow.sol diff --git a/contracts/payment/escrow/Escrow.sol b/contracts/utils/payment/escrow/Escrow.sol similarity index 98% rename from contracts/payment/escrow/Escrow.sol rename to contracts/utils/payment/escrow/Escrow.sol index 9160c172ab6..c385bf13fcb 100644 --- a/contracts/payment/escrow/Escrow.sol +++ b/contracts/utils/payment/escrow/Escrow.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import "../../access/Ownable.sol"; -import "../../utils/Address.sol"; +import "../../Address.sol"; /** * @title Escrow diff --git a/contracts/payment/escrow/RefundEscrow.sol b/contracts/utils/payment/escrow/RefundEscrow.sol similarity index 100% rename from contracts/payment/escrow/RefundEscrow.sol rename to contracts/utils/payment/escrow/RefundEscrow.sol From 20cf27d3522baa5e4c5ecec00c8d12bf94db5ff1 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Mon, 8 Feb 2021 17:52:38 +0100 Subject: [PATCH 02/31] address issues from offline conversation --- contracts/mocks/ERC1155ReceiverMock.sol | 2 +- contracts/mocks/ERC721ReceiverMock.sol | 2 +- contracts/mocks/ERC777SenderRecipientMock.sol | 4 ++-- contracts/mocks/EnumerableMapMock.sol | 2 +- contracts/mocks/EnumerableSetMock.sol | 2 +- contracts/proxy/{upgradeable => }/UpgradeableProxy.sol | 4 ++-- contracts/proxy/{upgradeable => transparent}/ProxyAdmin.sol | 0 .../TransparentUpgradeableProxy.sol | 2 +- contracts/token/ERC1155/ERC1155.sol | 2 +- contracts/token/ERC1155/{utils => }/IERC1155Receiver.sol | 2 +- contracts/token/ERC1155/utils/ERC1155Receiver.sol | 2 +- contracts/token/ERC721/ERC721.sol | 6 +++--- contracts/token/ERC721/{utils => }/IERC721Receiver.sol | 0 contracts/token/ERC721/utils/ERC721Holder.sol | 2 +- contracts/token/ERC777/ERC777.sol | 4 ++-- contracts/token/ERC777/{utils => }/IERC777Recipient.sol | 0 contracts/token/ERC777/{utils => }/IERC777Sender.sol | 0 contracts/utils/access/AccessControl.sol | 2 +- contracts/utils/{ => enumerable}/EnumerableMap.sol | 0 contracts/utils/{ => enumerable}/EnumerableSet.sol | 0 20 files changed, 19 insertions(+), 19 deletions(-) rename contracts/proxy/{upgradeable => }/UpgradeableProxy.sol (97%) rename contracts/proxy/{upgradeable => transparent}/ProxyAdmin.sol (100%) rename contracts/proxy/{upgradeable => transparent}/TransparentUpgradeableProxy.sol (99%) rename contracts/token/ERC1155/{utils => }/IERC1155Receiver.sol (97%) rename contracts/token/ERC721/{utils => }/IERC721Receiver.sol (100%) rename contracts/token/ERC777/{utils => }/IERC777Recipient.sol (100%) rename contracts/token/ERC777/{utils => }/IERC777Sender.sol (100%) rename contracts/utils/{ => enumerable}/EnumerableMap.sol (100%) rename contracts/utils/{ => enumerable}/EnumerableSet.sol (100%) diff --git a/contracts/mocks/ERC1155ReceiverMock.sol b/contracts/mocks/ERC1155ReceiverMock.sol index d20233e2555..6faaaa33658 100644 --- a/contracts/mocks/ERC1155ReceiverMock.sol +++ b/contracts/mocks/ERC1155ReceiverMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../token/ERC1155/utils/IERC1155Receiver.sol"; +import "../token/ERC1155/IERC1155Receiver.sol"; import "./ERC165Mock.sol"; contract ERC1155ReceiverMock is IERC1155Receiver, ERC165Mock { diff --git a/contracts/mocks/ERC721ReceiverMock.sol b/contracts/mocks/ERC721ReceiverMock.sol index b33c5241c6c..0ba5035e88f 100644 --- a/contracts/mocks/ERC721ReceiverMock.sol +++ b/contracts/mocks/ERC721ReceiverMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../token/ERC721/utils/IERC721Receiver.sol"; +import "../token/ERC721/IERC721Receiver.sol"; contract ERC721ReceiverMock is IERC721Receiver { enum Error { diff --git a/contracts/mocks/ERC777SenderRecipientMock.sol b/contracts/mocks/ERC777SenderRecipientMock.sol index a1fa7a16004..3a92d999c36 100644 --- a/contracts/mocks/ERC777SenderRecipientMock.sol +++ b/contracts/mocks/ERC777SenderRecipientMock.sol @@ -3,8 +3,8 @@ pragma solidity ^0.8.0; import "../token/ERC777/IERC777.sol"; -import "../token/ERC777/utils/IERC777Sender.sol"; -import "../token/ERC777/utils/IERC777Recipient.sol"; +import "../token/ERC777/IERC777Sender.sol"; +import "../token/ERC777/IERC777Recipient.sol"; import "../utils/Context.sol"; import "../utils/introspection/IERC1820Registry.sol"; import "../utils/introspection/ERC1820Implementer.sol"; diff --git a/contracts/mocks/EnumerableMapMock.sol b/contracts/mocks/EnumerableMapMock.sol index ea32f975b80..19a14154e83 100644 --- a/contracts/mocks/EnumerableMapMock.sol +++ b/contracts/mocks/EnumerableMapMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../utils/EnumerableMap.sol"; +import "../utils/enumerable/EnumerableMap.sol"; contract EnumerableMapMock { using EnumerableMap for EnumerableMap.UintToAddressMap; diff --git a/contracts/mocks/EnumerableSetMock.sol b/contracts/mocks/EnumerableSetMock.sol index eb5aa4f6fc5..83762fc0b19 100644 --- a/contracts/mocks/EnumerableSetMock.sol +++ b/contracts/mocks/EnumerableSetMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../utils/EnumerableSet.sol"; +import "../utils/enumerable/EnumerableSet.sol"; // Bytes32Set contract EnumerableBytes32SetMock { diff --git a/contracts/proxy/upgradeable/UpgradeableProxy.sol b/contracts/proxy/UpgradeableProxy.sol similarity index 97% rename from contracts/proxy/upgradeable/UpgradeableProxy.sol rename to contracts/proxy/UpgradeableProxy.sol index 6c5917e7977..8dd86464026 100644 --- a/contracts/proxy/upgradeable/UpgradeableProxy.sol +++ b/contracts/proxy/UpgradeableProxy.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.0; -import "../Proxy.sol"; -import "../../utils/Address.sol"; +import "./Proxy.sol"; +import "../utils/Address.sol"; /** * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an diff --git a/contracts/proxy/upgradeable/ProxyAdmin.sol b/contracts/proxy/transparent/ProxyAdmin.sol similarity index 100% rename from contracts/proxy/upgradeable/ProxyAdmin.sol rename to contracts/proxy/transparent/ProxyAdmin.sol diff --git a/contracts/proxy/upgradeable/TransparentUpgradeableProxy.sol b/contracts/proxy/transparent/TransparentUpgradeableProxy.sol similarity index 99% rename from contracts/proxy/upgradeable/TransparentUpgradeableProxy.sol rename to contracts/proxy/transparent/TransparentUpgradeableProxy.sol index 3ef2d26b664..4ce4eec36d5 100644 --- a/contracts/proxy/upgradeable/TransparentUpgradeableProxy.sol +++ b/contracts/proxy/transparent/TransparentUpgradeableProxy.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "./UpgradeableProxy.sol"; +import "../UpgradeableProxy.sol"; /** * @dev This contract implements a proxy that is upgradeable by an admin. diff --git a/contracts/token/ERC1155/ERC1155.sol b/contracts/token/ERC1155/ERC1155.sol index 7731ce0bddd..574f75b4ea8 100644 --- a/contracts/token/ERC1155/ERC1155.sol +++ b/contracts/token/ERC1155/ERC1155.sol @@ -3,8 +3,8 @@ pragma solidity ^0.8.0; import "./IERC1155.sol"; +import "./IERC1155Receiver.sol"; import "./extensions/IERC1155MetadataURI.sol"; -import "./utils/IERC1155Receiver.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/introspection/ERC165.sol"; diff --git a/contracts/token/ERC1155/utils/IERC1155Receiver.sol b/contracts/token/ERC1155/IERC1155Receiver.sol similarity index 97% rename from contracts/token/ERC1155/utils/IERC1155Receiver.sol rename to contracts/token/ERC1155/IERC1155Receiver.sol index a43e54b513e..ffd61dabc0f 100644 --- a/contracts/token/ERC1155/utils/IERC1155Receiver.sol +++ b/contracts/token/ERC1155/IERC1155Receiver.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../../../utils/introspection/IERC165.sol"; +import "../../utils/introspection/IERC165.sol"; /** * _Available since v3.1._ diff --git a/contracts/token/ERC1155/utils/ERC1155Receiver.sol b/contracts/token/ERC1155/utils/ERC1155Receiver.sol index af713dc8c5e..e499aa0a92d 100644 --- a/contracts/token/ERC1155/utils/ERC1155Receiver.sol +++ b/contracts/token/ERC1155/utils/ERC1155Receiver.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "./IERC1155Receiver.sol"; +import "../IERC1155Receiver.sol"; import "../../../utils/introspection/ERC165.sol"; /** diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index 977ed2976a6..057657a9f8f 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -3,13 +3,13 @@ pragma solidity ^0.8.0; import "./IERC721.sol"; +import "./IERC721Receiver.sol"; import "./extensions/IERC721Metadata.sol"; import "./extensions/IERC721Enumerable.sol"; -import "./utils/IERC721Receiver.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; -import "../../utils/EnumerableSet.sol"; -import "../../utils/EnumerableMap.sol"; +import "../../utils/enumerable/EnumerableSet.sol"; +import "../../utils/enumerable/EnumerableMap.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/ERC165.sol"; diff --git a/contracts/token/ERC721/utils/IERC721Receiver.sol b/contracts/token/ERC721/IERC721Receiver.sol similarity index 100% rename from contracts/token/ERC721/utils/IERC721Receiver.sol rename to contracts/token/ERC721/IERC721Receiver.sol diff --git a/contracts/token/ERC721/utils/ERC721Holder.sol b/contracts/token/ERC721/utils/ERC721Holder.sol index c65825e0ec8..1174ec05375 100644 --- a/contracts/token/ERC721/utils/ERC721Holder.sol +++ b/contracts/token/ERC721/utils/ERC721Holder.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "./IERC721Receiver.sol"; +import "../IERC721Receiver.sol"; /** * @dev Implementation of the {IERC721Receiver} interface. diff --git a/contracts/token/ERC777/ERC777.sol b/contracts/token/ERC777/ERC777.sol index 00f2945dcab..f899d02a4ee 100644 --- a/contracts/token/ERC777/ERC777.sol +++ b/contracts/token/ERC777/ERC777.sol @@ -3,8 +3,8 @@ pragma solidity ^0.8.0; import "./IERC777.sol"; -import "./utils/IERC777Sender.sol"; -import "./utils/IERC777Recipient.sol"; +import "./IERC777Recipient.sol"; +import "./IERC777Sender.sol"; import "../ERC20/IERC20.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; diff --git a/contracts/token/ERC777/utils/IERC777Recipient.sol b/contracts/token/ERC777/IERC777Recipient.sol similarity index 100% rename from contracts/token/ERC777/utils/IERC777Recipient.sol rename to contracts/token/ERC777/IERC777Recipient.sol diff --git a/contracts/token/ERC777/utils/IERC777Sender.sol b/contracts/token/ERC777/IERC777Sender.sol similarity index 100% rename from contracts/token/ERC777/utils/IERC777Sender.sol rename to contracts/token/ERC777/IERC777Sender.sol diff --git a/contracts/utils/access/AccessControl.sol b/contracts/utils/access/AccessControl.sol index b7fe954684e..fc3d4dec1cc 100644 --- a/contracts/utils/access/AccessControl.sol +++ b/contracts/utils/access/AccessControl.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import "../Address.sol"; import "../Context.sol"; -import "../EnumerableSet.sol"; +import "../enumerable/EnumerableSet.sol"; /** * @dev Contract module that allows children to implement role-based access diff --git a/contracts/utils/EnumerableMap.sol b/contracts/utils/enumerable/EnumerableMap.sol similarity index 100% rename from contracts/utils/EnumerableMap.sol rename to contracts/utils/enumerable/EnumerableMap.sol diff --git a/contracts/utils/EnumerableSet.sol b/contracts/utils/enumerable/EnumerableSet.sol similarity index 100% rename from contracts/utils/EnumerableSet.sol rename to contracts/utils/enumerable/EnumerableSet.sol From a0c7afbb69c2aca2898dcac9f506a4a32c86eb30 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Fri, 12 Feb 2021 15:55:12 +0100 Subject: [PATCH 03/31] add a contracts/standalone folder --- .../{utils/payment => standalone}/PaymentSplitter.sol | 6 +++--- .../{utils/access => standalone}/TimelockController.sol | 2 +- .../{token/ERC20/utils => standalone}/TokenTimelock.sol | 8 ++++---- test/{payment => standalone}/PaymentSplitter.test.js | 0 test/{access => standalone}/TimelockController.test.js | 0 test/{token/ERC20 => standalone}/TokenTimelock.test.js | 0 6 files changed, 8 insertions(+), 8 deletions(-) rename contracts/{utils/payment => standalone}/PaymentSplitter.sol (97%) rename contracts/{utils/access => standalone}/TimelockController.sol (99%) rename contracts/{token/ERC20/utils => standalone}/TokenTimelock.sol (91%) rename test/{payment => standalone}/PaymentSplitter.test.js (100%) rename test/{access => standalone}/TimelockController.test.js (100%) rename test/{token/ERC20 => standalone}/TokenTimelock.test.js (100%) diff --git a/contracts/utils/payment/PaymentSplitter.sol b/contracts/standalone/PaymentSplitter.sol similarity index 97% rename from contracts/utils/payment/PaymentSplitter.sol rename to contracts/standalone/PaymentSplitter.sol index 5498e7ebcd8..62a0e92604e 100644 --- a/contracts/utils/payment/PaymentSplitter.sol +++ b/contracts/standalone/PaymentSplitter.sol @@ -2,9 +2,9 @@ pragma solidity ^0.8.0; -import "../../utils/Address.sol"; -import "../../utils/Context.sol"; -import "../../utils/math/SafeMath.sol"; +import "../utils/Address.sol"; +import "../utils/Context.sol"; +import "../utils/math/SafeMath.sol"; /** * @title PaymentSplitter diff --git a/contracts/utils/access/TimelockController.sol b/contracts/standalone/TimelockController.sol similarity index 99% rename from contracts/utils/access/TimelockController.sol rename to contracts/standalone/TimelockController.sol index cba9b689580..a8f31d97bcd 100644 --- a/contracts/utils/access/TimelockController.sol +++ b/contracts/standalone/TimelockController.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "./AccessControl.sol"; +import "../utils/access/AccessControl.sol"; /** * @dev Contract module which acts as a timelocked controller. When set as the diff --git a/contracts/token/ERC20/utils/TokenTimelock.sol b/contracts/standalone/TokenTimelock.sol similarity index 91% rename from contracts/token/ERC20/utils/TokenTimelock.sol rename to contracts/standalone/TokenTimelock.sol index 102f45a82b3..062f9dfd78d 100644 --- a/contracts/token/ERC20/utils/TokenTimelock.sol +++ b/contracts/standalone/TokenTimelock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "./SafeERC20.sol"; +import "../token/ERC20/utils/SafeERC20.sol"; /** * @dev A token holder contract that will allow a beneficiary to extract the @@ -15,13 +15,13 @@ contract TokenTimelock { using SafeERC20 for IERC20; // ERC20 basic token contract being held - IERC20 private _token; + IERC20 private immutable _token; // beneficiary of tokens after they are released - address private _beneficiary; + address private immutable _beneficiary; // timestamp when token release is enabled - uint256 private _releaseTime; + uint256 private immutable _releaseTime; constructor (IERC20 token_, address beneficiary_, uint256 releaseTime_) { // solhint-disable-next-line not-rely-on-time diff --git a/test/payment/PaymentSplitter.test.js b/test/standalone/PaymentSplitter.test.js similarity index 100% rename from test/payment/PaymentSplitter.test.js rename to test/standalone/PaymentSplitter.test.js diff --git a/test/access/TimelockController.test.js b/test/standalone/TimelockController.test.js similarity index 100% rename from test/access/TimelockController.test.js rename to test/standalone/TimelockController.test.js diff --git a/test/token/ERC20/TokenTimelock.test.js b/test/standalone/TokenTimelock.test.js similarity index 100% rename from test/token/ERC20/TokenTimelock.test.js rename to test/standalone/TokenTimelock.test.js From ea9a0c688a11500387b5a870920df2eccd32b3c5 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Mon, 15 Feb 2021 16:52:08 +0100 Subject: [PATCH 04/31] add a migration script that rewrites imports --- .../{extensions => utils}/ERC1155Holder.sol | 2 +- package-lock.json | 155 +++++++++++++++ package.json | 1 + scripts/rewrite-imports.js | 177 ++++++++++++++++++ 4 files changed, 334 insertions(+), 1 deletion(-) rename contracts/token/ERC1155/{extensions => utils}/ERC1155Holder.sol (93%) create mode 100644 scripts/rewrite-imports.js diff --git a/contracts/token/ERC1155/extensions/ERC1155Holder.sol b/contracts/token/ERC1155/utils/ERC1155Holder.sol similarity index 93% rename from contracts/token/ERC1155/extensions/ERC1155Holder.sol rename to contracts/token/ERC1155/utils/ERC1155Holder.sol index 93ac85162ec..4468f65cc84 100644 --- a/contracts/token/ERC1155/extensions/ERC1155Holder.sol +++ b/contracts/token/ERC1155/utils/ERC1155Holder.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../utils/ERC1155Receiver.sol"; +import "./ERC1155Receiver.sol"; /** * @dev _Available since v3.1._ diff --git a/package-lock.json b/package-lock.json index aefe17d6e59..4080cb4e762 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4037,6 +4037,12 @@ "ext": "^1.1.2" } }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -10790,6 +10796,155 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, + "replace-in-file": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/replace-in-file/-/replace-in-file-6.2.0.tgz", + "integrity": "sha512-Im2AF9G/qgkYneOc9QwWwUS/efyyonTUBvzXS2VXuxPawE5yQIjT/e6x4CTijO0Quq48lfAujuo+S89RR2TP2Q==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "glob": "^7.1.6", + "yargs": "^16.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", + "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.5", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.5.tgz", + "integrity": "sha512-jYRGS3zWy20NtDtK2kBgo/TlAoy5YUuhD9/LZ7z7W4j1Fdw2cqD0xEEclf8fxc8xjD6X5Qr+qQQwCEsP8iRiYg==", + "dev": true + } + } + }, "req-cwd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-2.0.0.tgz", diff --git a/package.json b/package.json index 8b86592cc78..3253db69110 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "lodash.zip": "^4.2.0", "micromatch": "^4.0.2", "mocha": "^8.0.1", + "replace-in-file": "^6.2.0", "rimraf": "^3.0.2", "solhint": "^3.2.0", "solidity-coverage": "^0.7.11", diff --git a/scripts/rewrite-imports.js b/scripts/rewrite-imports.js new file mode 100644 index 00000000000..dc539464d8f --- /dev/null +++ b/scripts/rewrite-imports.js @@ -0,0 +1,177 @@ +const path = require('path'); +const replace = require('replace-in-file'); + +const updates = { + '@openzeppelin/contracts/access/AccessControl.sol': + '@openzeppelin/contracts/utils/access/AccessControl.sol', + '@openzeppelin/contracts/access/Ownable.sol': + '@openzeppelin/contracts/utils/access/Ownable.sol', + '@openzeppelin/contracts/access/TimelockController.sol': + '@openzeppelin/contracts/standalone/TimelockController.sol', + '@openzeppelin/contracts/cryptography/ECDSA.sol': + '@openzeppelin/contracts/utils/cryptography/ECDSA.sol', + '@openzeppelin/contracts/cryptography/MerkleProof.sol': + '@openzeppelin/contracts/utils/cryptography/MerkleProof.sol', + '@openzeppelin/contracts/drafts/EIP712.sol': + '@openzeppelin/contracts/utils/drafts-EIP712.sol', + '@openzeppelin/contracts/drafts/ERC20Permit.sol': + '@openzeppelin/contracts/tokens/ERC20/extensions/draft-ERC20Permit.sol', + '@openzeppelin/contracts/drafts/IERC20Permit.sol': + '@openzeppelin/contracts/tokens/ERC20/extensions/draft-IERC20Permit.sol', + '@openzeppelin/contracts/GSN/Context.sol': + '@openzeppelin/contracts/utils/Context.sol', + '@openzeppelin/contracts/GSN/GSNRecipientERC20Fee.sol': + '@openzeppelin/contracts/utils/GSN/GSNRecipientERC20Fee.sol', + '@openzeppelin/contracts/GSN/GSNRecipientSignature.sol': + '@openzeppelin/contracts/utils/GSN/GSNRecipientSignature.sol', + '@openzeppelin/contracts/GSN/GSNRecipient.sol': + '@openzeppelin/contracts/utils/GSN/GSNRecipient.sol', + '@openzeppelin/contracts/GSN/IRelayHub.sol': + '@openzeppelin/contracts/utils/GSN/IRelayHub.sol', + '@openzeppelin/contracts/GSN/IRelayRecipient.sol': + '@openzeppelin/contracts/utils/GSN/IRelayRecipient.sol', + '@openzeppelin/contracts/introspection/ERC165Checker.sol': + '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol', + '@openzeppelin/contracts/introspection/ERC165.sol': + '@openzeppelin/contracts/utils/introspection/ERC165.sol', + '@openzeppelin/contracts/introspection/ERC1820Implementer.sol': + '@openzeppelin/contracts/utils/introspection/ERC1820Implementer.sol', + '@openzeppelin/contracts/introspection/IERC165.sol': + '@openzeppelin/contracts/utils/introspection/IERC165.sol', + '@openzeppelin/contracts/introspection/IERC1820Implementer.sol': + '@openzeppelin/contracts/utils/introspection/IERC1820Implementer.sol', + '@openzeppelin/contracts/introspection/IERC1820Registry.sol': + '@openzeppelin/contracts/utils/introspection/IERC1820Registry.sol', + '@openzeppelin/contracts/math/Math.sol': + '@openzeppelin/contracts/utils/math/Math.sol', + '@openzeppelin/contracts/math/SafeMath.sol': + '@openzeppelin/contracts/utils/math/SafeMath.sol', + '@openzeppelin/contracts/math/SignedSafeMath.sol': + '@openzeppelin/contracts/utils/math/SignedSafeMath.sol', + '@openzeppelin/contracts/payment/escrow/ConditionalEscrow.sol': + '@openzeppelin/contracts/utils/payment/escrow/ConditionalEscrow.sol', + '@openzeppelin/contracts/payment/escrow/Escrow.sol': + '@openzeppelin/contracts/utils/payment/escrow/Escrow.sol', + '@openzeppelin/contracts/payment/escrow/RefundEscrow.sol': + '@openzeppelin/contracts/utils/payment/escrow/RefundEscrow.sol', + '@openzeppelin/contracts/payment/PaymentSplitter.sol': + '@openzeppelin/contracts/standalone/PaymentSplitter.sol', + '@openzeppelin/contracts/payment/PullPayment.sol': + '@openzeppelin/contracts/utils/payment/PullPayment.sol', + '@openzeppelin/contracts/presets/ERC1155PresetMinterPauser.sol': + '@openzeppelin/contracts/tokens/ERC1155/presets/ERC1155PresetMinterPauser.sol', + '@openzeppelin/contracts/presets/ERC20PresetFixedSupply.sol': + '@openzeppelin/contracts/tokens/ERC20/presets/ERC20PresetFixedSupply.sol', + '@openzeppelin/contracts/presets/ERC20PresetMinterPauser.sol': + '@openzeppelin/contracts/tokens/ERC20/presets/ERC20PresetMinterPauser.sol', + '@openzeppelin/contracts/presets/ERC721PresetMinterPauserAutoId.sol': + '@openzeppelin/contracts/tokens/ERC721/presets/ERC721PresetMinterPauserAutoId.sol', + '@openzeppelin/contracts/presets/ERC777PresetFixedSupply.sol': + '@openzeppelin/contracts/tokens/ERC777/presets/ERC777PresetFixedSupply.sol', + '@openzeppelin/contracts/proxy/BeaconProxy.sol': + '@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol', + '@openzeppelin/contracts/proxy/Clones.sol': + null, + '@openzeppelin/contracts/proxy/IBeacon.sol': + '@openzeppelin/contracts/proxy/beacon/IBeacon.sol', + '@openzeppelin/contracts/proxy/Initializable.sol': + '@openzeppelin/contracts/utils/Initializable.sol', + '@openzeppelin/contracts/proxy/ProxyAdmin.sol': + '@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol', + '@openzeppelin/contracts/proxy/Proxy.sol': + null, + '@openzeppelin/contracts/proxy/TransparentUpgradeableProxy.sol': + '@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol', + '@openzeppelin/contracts/proxy/UpgradeableBeacon.sol': + '@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol', + '@openzeppelin/contracts/proxy/UpgradeableProxy.sol': + null, + '@openzeppelin/contracts/token/ERC1155/ERC1155Burnable.sol': + '@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol', + '@openzeppelin/contracts/token/ERC1155/ERC1155Holder.sol': + '@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol', + '@openzeppelin/contracts/token/ERC1155/ERC1155Pausable.sol': + '@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol', + '@openzeppelin/contracts/token/ERC1155/ERC1155Receiver.sol': + '@openzeppelin/contracts/token/ERC1155/utils/ERC1155Receiver.sol', + '@openzeppelin/contracts/token/ERC1155/ERC1155.sol': + null, + '@openzeppelin/contracts/token/ERC1155/IERC1155MetadataURI.sol': + '@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol', + '@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol': + null, + '@openzeppelin/contracts/token/ERC1155/IERC1155.sol': + null, + '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol': + '@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol', + '@openzeppelin/contracts/token/ERC20/ERC20Capped.sol': + '@openzeppelin/contracts/token/ERC20/extensions/ERC20Capped.sol', + '@openzeppelin/contracts/token/ERC20/ERC20Pausable.sol': + '@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol', + '@openzeppelin/contracts/token/ERC20/ERC20Snapshot.sol': + '@openzeppelin/contracts/token/ERC20/extensions/ERC20Snapshot.sol', + '@openzeppelin/contracts/token/ERC20/ERC20.sol': + null, + '@openzeppelin/contracts/token/ERC20/IERC20.sol': + null, + '@openzeppelin/contracts/token/ERC20/SafeERC20.sol': + '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol', + '@openzeppelin/contracts/token/ERC20/TokenTimelock.sol': + '@openzeppelin/contracts/standalone/TokenTimelock.sol', + '@openzeppelin/contracts/token/ERC721/ERC721Burnable.sol': + '@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol', + '@openzeppelin/contracts/token/ERC721/ERC721Holder.sol': + '@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol', + '@openzeppelin/contracts/token/ERC721/ERC721Pausable.sol': + '@openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol', + '@openzeppelin/contracts/token/ERC721/ERC721.sol': + null, + '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol': + '@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol', + '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol': + '@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol', + '@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol': + null, + '@openzeppelin/contracts/token/ERC721/IERC721.sol': + null, + '@openzeppelin/contracts/token/ERC777/ERC777.sol': + null, + '@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol': + null, + '@openzeppelin/contracts/token/ERC777/IERC777Sender.sol': + null, + '@openzeppelin/contracts/token/ERC777/IERC777.sol': + null, + '@openzeppelin/contracts/utils/Address.sol': + null, + '@openzeppelin/contracts/utils/Arrays.sol': + null, + '@openzeppelin/contracts/utils/Context.sol': + null, + '@openzeppelin/contracts/utils/Counters.sol': + null, + '@openzeppelin/contracts/utils/Create2.sol': + null, + '@openzeppelin/contracts/utils/EnumerableMap.sol': + '@openzeppelin/contracts/utils/enumerable/EnumerableMap.sol', + '@openzeppelin/contracts/utils/EnumerableSet.sol': + '@openzeppelin/contracts/utils/enumerable/EnumerableSet.sol', + '@openzeppelin/contracts/utils/Pausable.sol': + null, + '@openzeppelin/contracts/utils/ReentrancyGuard.sol': + null, + '@openzeppelin/contracts/utils/SafeCast.sol': + null, + '@openzeppelin/contracts/utils/Strings.sol': + null, +}; + +(async () => { + const base = process.argv[1] || process.env.LOCATION || '.'; + const files = path.join(base, '**', '*.sol'); + for (const [ from, to ] of Object.entries(updates)) { + if (to) { + await replace({ files, from, to }); + } + } +})().catch(console.error); From 3f3256e14c0f568c64e1ed4148c9ed343d5ea672 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 16 Feb 2021 00:51:06 +0100 Subject: [PATCH 05/31] improve rewrite script --- scripts/rewrite-imports.js | 273 ++++++++++++++----------------------- 1 file changed, 104 insertions(+), 169 deletions(-) diff --git a/scripts/rewrite-imports.js b/scripts/rewrite-imports.js index dc539464d8f..c20c8320751 100644 --- a/scripts/rewrite-imports.js +++ b/scripts/rewrite-imports.js @@ -1,177 +1,112 @@ +const debug = require('debug'); const path = require('path'); const replace = require('replace-in-file'); +const versions = [ + '@openzeppelin/contracts', + '@openzeppelin/contracts-upgradeable', +]; + const updates = { - '@openzeppelin/contracts/access/AccessControl.sol': - '@openzeppelin/contracts/utils/access/AccessControl.sol', - '@openzeppelin/contracts/access/Ownable.sol': - '@openzeppelin/contracts/utils/access/Ownable.sol', - '@openzeppelin/contracts/access/TimelockController.sol': - '@openzeppelin/contracts/standalone/TimelockController.sol', - '@openzeppelin/contracts/cryptography/ECDSA.sol': - '@openzeppelin/contracts/utils/cryptography/ECDSA.sol', - '@openzeppelin/contracts/cryptography/MerkleProof.sol': - '@openzeppelin/contracts/utils/cryptography/MerkleProof.sol', - '@openzeppelin/contracts/drafts/EIP712.sol': - '@openzeppelin/contracts/utils/drafts-EIP712.sol', - '@openzeppelin/contracts/drafts/ERC20Permit.sol': - '@openzeppelin/contracts/tokens/ERC20/extensions/draft-ERC20Permit.sol', - '@openzeppelin/contracts/drafts/IERC20Permit.sol': - '@openzeppelin/contracts/tokens/ERC20/extensions/draft-IERC20Permit.sol', - '@openzeppelin/contracts/GSN/Context.sol': - '@openzeppelin/contracts/utils/Context.sol', - '@openzeppelin/contracts/GSN/GSNRecipientERC20Fee.sol': - '@openzeppelin/contracts/utils/GSN/GSNRecipientERC20Fee.sol', - '@openzeppelin/contracts/GSN/GSNRecipientSignature.sol': - '@openzeppelin/contracts/utils/GSN/GSNRecipientSignature.sol', - '@openzeppelin/contracts/GSN/GSNRecipient.sol': - '@openzeppelin/contracts/utils/GSN/GSNRecipient.sol', - '@openzeppelin/contracts/GSN/IRelayHub.sol': - '@openzeppelin/contracts/utils/GSN/IRelayHub.sol', - '@openzeppelin/contracts/GSN/IRelayRecipient.sol': - '@openzeppelin/contracts/utils/GSN/IRelayRecipient.sol', - '@openzeppelin/contracts/introspection/ERC165Checker.sol': - '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol', - '@openzeppelin/contracts/introspection/ERC165.sol': - '@openzeppelin/contracts/utils/introspection/ERC165.sol', - '@openzeppelin/contracts/introspection/ERC1820Implementer.sol': - '@openzeppelin/contracts/utils/introspection/ERC1820Implementer.sol', - '@openzeppelin/contracts/introspection/IERC165.sol': - '@openzeppelin/contracts/utils/introspection/IERC165.sol', - '@openzeppelin/contracts/introspection/IERC1820Implementer.sol': - '@openzeppelin/contracts/utils/introspection/IERC1820Implementer.sol', - '@openzeppelin/contracts/introspection/IERC1820Registry.sol': - '@openzeppelin/contracts/utils/introspection/IERC1820Registry.sol', - '@openzeppelin/contracts/math/Math.sol': - '@openzeppelin/contracts/utils/math/Math.sol', - '@openzeppelin/contracts/math/SafeMath.sol': - '@openzeppelin/contracts/utils/math/SafeMath.sol', - '@openzeppelin/contracts/math/SignedSafeMath.sol': - '@openzeppelin/contracts/utils/math/SignedSafeMath.sol', - '@openzeppelin/contracts/payment/escrow/ConditionalEscrow.sol': - '@openzeppelin/contracts/utils/payment/escrow/ConditionalEscrow.sol', - '@openzeppelin/contracts/payment/escrow/Escrow.sol': - '@openzeppelin/contracts/utils/payment/escrow/Escrow.sol', - '@openzeppelin/contracts/payment/escrow/RefundEscrow.sol': - '@openzeppelin/contracts/utils/payment/escrow/RefundEscrow.sol', - '@openzeppelin/contracts/payment/PaymentSplitter.sol': - '@openzeppelin/contracts/standalone/PaymentSplitter.sol', - '@openzeppelin/contracts/payment/PullPayment.sol': - '@openzeppelin/contracts/utils/payment/PullPayment.sol', - '@openzeppelin/contracts/presets/ERC1155PresetMinterPauser.sol': - '@openzeppelin/contracts/tokens/ERC1155/presets/ERC1155PresetMinterPauser.sol', - '@openzeppelin/contracts/presets/ERC20PresetFixedSupply.sol': - '@openzeppelin/contracts/tokens/ERC20/presets/ERC20PresetFixedSupply.sol', - '@openzeppelin/contracts/presets/ERC20PresetMinterPauser.sol': - '@openzeppelin/contracts/tokens/ERC20/presets/ERC20PresetMinterPauser.sol', - '@openzeppelin/contracts/presets/ERC721PresetMinterPauserAutoId.sol': - '@openzeppelin/contracts/tokens/ERC721/presets/ERC721PresetMinterPauserAutoId.sol', - '@openzeppelin/contracts/presets/ERC777PresetFixedSupply.sol': - '@openzeppelin/contracts/tokens/ERC777/presets/ERC777PresetFixedSupply.sol', - '@openzeppelin/contracts/proxy/BeaconProxy.sol': - '@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol', - '@openzeppelin/contracts/proxy/Clones.sol': - null, - '@openzeppelin/contracts/proxy/IBeacon.sol': - '@openzeppelin/contracts/proxy/beacon/IBeacon.sol', - '@openzeppelin/contracts/proxy/Initializable.sol': - '@openzeppelin/contracts/utils/Initializable.sol', - '@openzeppelin/contracts/proxy/ProxyAdmin.sol': - '@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol', - '@openzeppelin/contracts/proxy/Proxy.sol': - null, - '@openzeppelin/contracts/proxy/TransparentUpgradeableProxy.sol': - '@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol', - '@openzeppelin/contracts/proxy/UpgradeableBeacon.sol': - '@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol', - '@openzeppelin/contracts/proxy/UpgradeableProxy.sol': - null, - '@openzeppelin/contracts/token/ERC1155/ERC1155Burnable.sol': - '@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol', - '@openzeppelin/contracts/token/ERC1155/ERC1155Holder.sol': - '@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol', - '@openzeppelin/contracts/token/ERC1155/ERC1155Pausable.sol': - '@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol', - '@openzeppelin/contracts/token/ERC1155/ERC1155Receiver.sol': - '@openzeppelin/contracts/token/ERC1155/utils/ERC1155Receiver.sol', - '@openzeppelin/contracts/token/ERC1155/ERC1155.sol': - null, - '@openzeppelin/contracts/token/ERC1155/IERC1155MetadataURI.sol': - '@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol', - '@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol': - null, - '@openzeppelin/contracts/token/ERC1155/IERC1155.sol': - null, - '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol': - '@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol', - '@openzeppelin/contracts/token/ERC20/ERC20Capped.sol': - '@openzeppelin/contracts/token/ERC20/extensions/ERC20Capped.sol', - '@openzeppelin/contracts/token/ERC20/ERC20Pausable.sol': - '@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol', - '@openzeppelin/contracts/token/ERC20/ERC20Snapshot.sol': - '@openzeppelin/contracts/token/ERC20/extensions/ERC20Snapshot.sol', - '@openzeppelin/contracts/token/ERC20/ERC20.sol': - null, - '@openzeppelin/contracts/token/ERC20/IERC20.sol': - null, - '@openzeppelin/contracts/token/ERC20/SafeERC20.sol': - '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol', - '@openzeppelin/contracts/token/ERC20/TokenTimelock.sol': - '@openzeppelin/contracts/standalone/TokenTimelock.sol', - '@openzeppelin/contracts/token/ERC721/ERC721Burnable.sol': - '@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol', - '@openzeppelin/contracts/token/ERC721/ERC721Holder.sol': - '@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol', - '@openzeppelin/contracts/token/ERC721/ERC721Pausable.sol': - '@openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol', - '@openzeppelin/contracts/token/ERC721/ERC721.sol': - null, - '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol': - '@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol', - '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol': - '@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol', - '@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol': - null, - '@openzeppelin/contracts/token/ERC721/IERC721.sol': - null, - '@openzeppelin/contracts/token/ERC777/ERC777.sol': - null, - '@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol': - null, - '@openzeppelin/contracts/token/ERC777/IERC777Sender.sol': - null, - '@openzeppelin/contracts/token/ERC777/IERC777.sol': - null, - '@openzeppelin/contracts/utils/Address.sol': - null, - '@openzeppelin/contracts/utils/Arrays.sol': - null, - '@openzeppelin/contracts/utils/Context.sol': - null, - '@openzeppelin/contracts/utils/Counters.sol': - null, - '@openzeppelin/contracts/utils/Create2.sol': - null, - '@openzeppelin/contracts/utils/EnumerableMap.sol': - '@openzeppelin/contracts/utils/enumerable/EnumerableMap.sol', - '@openzeppelin/contracts/utils/EnumerableSet.sol': - '@openzeppelin/contracts/utils/enumerable/EnumerableSet.sol', - '@openzeppelin/contracts/utils/Pausable.sol': - null, - '@openzeppelin/contracts/utils/ReentrancyGuard.sol': - null, - '@openzeppelin/contracts/utils/SafeCast.sol': - null, - '@openzeppelin/contracts/utils/Strings.sol': - null, + 'access/AccessControl.sol': 'utils/access/AccessControl.sol', + 'access/Ownable.sol': 'utils/access/Ownable.sol', + 'access/TimelockController.sol': 'standalone/TimelockController.sol', + 'cryptography/ECDSA.sol': 'utils/cryptography/ECDSA.sol', + 'cryptography/MerkleProof.sol': 'utils/cryptography/MerkleProof.sol', + 'drafts/EIP712.sol': 'utils/drafts-EIP712.sol', + 'drafts/ERC20Permit.sol': 'tokens/ERC20/extensions/draft-ERC20Permit.sol', + 'drafts/IERC20Permit.sol': 'tokens/ERC20/extensions/draft-IERC20Permit.sol', + 'GSN/Context.sol': 'utils/Context.sol', + 'GSN/GSNRecipientERC20Fee.sol': 'utils/GSN/GSNRecipientERC20Fee.sol', + 'GSN/GSNRecipientSignature.sol': 'utils/GSN/GSNRecipientSignature.sol', + 'GSN/GSNRecipient.sol': 'utils/GSN/GSNRecipient.sol', + 'GSN/IRelayHub.sol': 'utils/GSN/IRelayHub.sol', + 'GSN/IRelayRecipient.sol': 'utils/GSN/IRelayRecipient.sol', + 'introspection/ERC165Checker.sol': 'utils/introspection/ERC165Checker.sol', + 'introspection/ERC165.sol': 'utils/introspection/ERC165.sol', + 'introspection/ERC1820Implementer.sol': 'utils/introspection/ERC1820Implementer.sol', + 'introspection/IERC165.sol': 'utils/introspection/IERC165.sol', + 'introspection/IERC1820Implementer.sol': 'utils/introspection/IERC1820Implementer.sol', + 'introspection/IERC1820Registry.sol': 'utils/introspection/IERC1820Registry.sol', + 'math/Math.sol': 'utils/math/Math.sol', + 'math/SafeMath.sol': 'utils/math/SafeMath.sol', + 'math/SignedSafeMath.sol': 'utils/math/SignedSafeMath.sol', + 'payment/escrow/ConditionalEscrow.sol': 'utils/payment/escrow/ConditionalEscrow.sol', + 'payment/escrow/Escrow.sol': 'utils/payment/escrow/Escrow.sol', + 'payment/escrow/RefundEscrow.sol': 'utils/payment/escrow/RefundEscrow.sol', + 'payment/PaymentSplitter.sol': 'standalone/PaymentSplitter.sol', + 'payment/PullPayment.sol': 'utils/payment/PullPayment.sol', + 'presets/ERC1155PresetMinterPauser.sol': 'tokens/ERC1155/presets/ERC1155PresetMinterPauser.sol', + 'presets/ERC20PresetFixedSupply.sol': 'tokens/ERC20/presets/ERC20PresetFixedSupply.sol', + 'presets/ERC20PresetMinterPauser.sol': 'tokens/ERC20/presets/ERC20PresetMinterPauser.sol', + 'presets/ERC721PresetMinterPauserAutoId.sol': 'tokens/ERC721/presets/ERC721PresetMinterPauserAutoId.sol', + 'presets/ERC777PresetFixedSupply.sol': 'tokens/ERC777/presets/ERC777PresetFixedSupply.sol', + 'proxy/BeaconProxy.sol': 'proxy/beacon/BeaconProxy.sol', + 'proxy/Clones.sol': null, + 'proxy/IBeacon.sol': 'proxy/beacon/IBeacon.sol', + 'proxy/Initializable.sol': 'utils/Initializable.sol', + 'proxy/ProxyAdmin.sol': 'proxy/transparent/ProxyAdmin.sol', + 'proxy/Proxy.sol': null, + 'proxy/TransparentUpgradeableProxy.sol': 'proxy/transparent/TransparentUpgradeableProxy.sol', + 'proxy/UpgradeableBeacon.sol': 'proxy/beacon/UpgradeableBeacon.sol', + 'proxy/UpgradeableProxy.sol': null, + 'token/ERC1155/ERC1155Burnable.sol': 'token/ERC1155/extensions/ERC1155Burnable.sol', + 'token/ERC1155/ERC1155Holder.sol': 'token/ERC1155/utils/ERC1155Holder.sol', + 'token/ERC1155/ERC1155Pausable.sol': 'token/ERC1155/extensions/ERC1155Pausable.sol', + 'token/ERC1155/ERC1155Receiver.sol': 'token/ERC1155/utils/ERC1155Receiver.sol', + 'token/ERC1155/ERC1155.sol': null, + 'token/ERC1155/IERC1155MetadataURI.sol': 'token/ERC1155/extensions/IERC1155MetadataURI.sol', + 'token/ERC1155/IERC1155Receiver.sol': null, + 'token/ERC1155/IERC1155.sol': null, + 'token/ERC20/ERC20Burnable.sol': 'token/ERC20/extensions/ERC20Burnable.sol', + 'token/ERC20/ERC20Capped.sol': 'token/ERC20/extensions/ERC20Capped.sol', + 'token/ERC20/ERC20Pausable.sol': 'token/ERC20/extensions/ERC20Pausable.sol', + 'token/ERC20/ERC20Snapshot.sol': 'token/ERC20/extensions/ERC20Snapshot.sol', + 'token/ERC20/ERC20.sol': null, + 'token/ERC20/IERC20.sol': null, + 'token/ERC20/SafeERC20.sol': 'token/ERC20/utils/SafeERC20.sol', + 'token/ERC20/TokenTimelock.sol': 'standalone/TokenTimelock.sol', + 'token/ERC721/ERC721Burnable.sol': 'token/ERC721/extensions/ERC721Burnable.sol', + 'token/ERC721/ERC721Holder.sol': 'token/ERC721/utils/ERC721Holder.sol', + 'token/ERC721/ERC721Pausable.sol': 'token/ERC721/extensions/ERC721Pausable.sol', + 'token/ERC721/ERC721.sol': null, + 'token/ERC721/IERC721Enumerable.sol': 'token/ERC721/extensions/IERC721Enumerable.sol', + 'token/ERC721/IERC721Metadata.sol': 'token/ERC721/extensions/IERC721Metadata.sol', + 'token/ERC721/IERC721Receiver.sol': null, + 'token/ERC721/IERC721.sol': null, + 'token/ERC777/ERC777.sol': null, + 'token/ERC777/IERC777Recipient.sol': null, + 'token/ERC777/IERC777Sender.sol': null, + 'token/ERC777/IERC777.sol': null, + 'utils/Address.sol': null, + 'utils/Arrays.sol': null, + 'utils/Context.sol': null, + 'utils/Counters.sol': null, + 'utils/Create2.sol': null, + 'utils/EnumerableMap.sol': 'utils/enumerable/EnumerableMap.sol', + 'utils/EnumerableSet.sol': 'utils/enumerable/EnumerableSet.sol', + 'utils/Pausable.sol': null, + 'utils/ReentrancyGuard.sol': null, + 'utils/SafeCast.sol': null, + 'utils/Strings.sol': null, }; (async () => { - const base = process.argv[1] || process.env.LOCATION || '.'; - const files = path.join(base, '**', '*.sol'); - for (const [ from, to ] of Object.entries(updates)) { - if (to) { - await replace({ files, from, to }); - } - } + const logs = await replace({ + files: ( + process.argv.length > 2 + ? process.argv.slice(2) + : [ 'contracts' ] + ).map(file => path.extname(file) === '.sol' ? file : path.join(file, '**', '*.sol')), + from: Object.entries(updates) + .filter(([ from, to ]) => to) + .flatMap(([ from, to ]) => versions.map(version => path.join(version, from))), + to: Object.entries(updates) + .filter(([ from, to ]) => to) + .flatMap(([ from, to ]) => versions.map(version => path.join(version, to))), + }); + + debug('rewrite-migration')('started'); + logs.filter(({ hasChanged }) => hasChanged).forEach(({ file }) => debug('rewrite-migration:updated')(file)); + debug('rewrite-migration')('finished'); })().catch(console.error); From f0f2795c08061211a1d9679ed99dc19de1c8d634 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 16 Feb 2021 01:23:42 +0100 Subject: [PATCH 06/31] improve file/directory differenciation --- scripts/rewrite-imports.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/scripts/rewrite-imports.js b/scripts/rewrite-imports.js index c20c8320751..cee9553fbbe 100644 --- a/scripts/rewrite-imports.js +++ b/scripts/rewrite-imports.js @@ -1,4 +1,5 @@ const debug = require('debug'); +const fs = require('fs'); const path = require('path'); const replace = require('replace-in-file'); @@ -92,12 +93,10 @@ const updates = { }; (async () => { + debug('rewrite-migration')('started'); const logs = await replace({ - files: ( - process.argv.length > 2 - ? process.argv.slice(2) - : [ 'contracts' ] - ).map(file => path.extname(file) === '.sol' ? file : path.join(file, '**', '*.sol')), + files: (process.argv.length > 2 ? process.argv.slice(2) : [ 'contracts' ]) + .map(file => fs.statSync(file).isDirectory() ? path.join(file, '**', '*.sol') : file), from: Object.entries(updates) .filter(([ from, to ]) => to) .flatMap(([ from, to ]) => versions.map(version => path.join(version, from))), @@ -105,8 +104,6 @@ const updates = { .filter(([ from, to ]) => to) .flatMap(([ from, to ]) => versions.map(version => path.join(version, to))), }); - - debug('rewrite-migration')('started'); logs.filter(({ hasChanged }) => hasChanged).forEach(({ file }) => debug('rewrite-migration:updated')(file)); debug('rewrite-migration')('finished'); })().catch(console.error); From af0caf561c06952cb7fd93b3ac6d2356d0e8dda6 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 18 Feb 2021 15:02:54 +0100 Subject: [PATCH 07/31] add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38a94bdc263..6b6d526e3b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * `Context`: making `_msgData` return `bytes calldata` instead of `bytes memory` ([#2492](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2492)) * `ERC20`: Removed the `_setDecimals` function and the storage slot associated to decimals. ([#2502](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2502)) * `Strings`: addition of a `toHexString` function. ([#2504](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2504)) + * Overall reorganisation of the contract folder to improve clarity and discoverability. ([#2503](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2503)) ## 3.4.0 (2021-02-02) From 0ddd2b8ee3a630e7ac009c6b87ca27cd4a52f4f5 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 18 Feb 2021 16:30:45 +0100 Subject: [PATCH 08/31] package replace-in-file under scripts/ to avoid dependencies --- package.json | 1 - .../replace-in-file/helpers/combine-config.js | 60 ++++++++++++ .../replace-in-file/helpers/error-handler.js | 9 ++ .../helpers/get-paths-async.js | 26 ++++++ .../replace-in-file/helpers/get-paths-sync.js | 42 +++++++++ scripts/replace-in-file/helpers/glob-async.js | 34 +++++++ .../replace-in-file/helpers/load-config.js | 23 +++++ .../helpers/make-replacements.js | 75 +++++++++++++++ .../replace-in-file/helpers/parse-config.js | 67 ++++++++++++++ .../replace-in-file/helpers/replace-async.js | 45 +++++++++ .../replace-in-file/helpers/replace-sync.js | 30 ++++++ .../helpers/success-handler.js | 18 ++++ scripts/replace-in-file/index.js | 92 +++++++++++++++++++ scripts/rewrite-imports.js | 66 +++++++------ 14 files changed, 557 insertions(+), 31 deletions(-) create mode 100644 scripts/replace-in-file/helpers/combine-config.js create mode 100644 scripts/replace-in-file/helpers/error-handler.js create mode 100644 scripts/replace-in-file/helpers/get-paths-async.js create mode 100644 scripts/replace-in-file/helpers/get-paths-sync.js create mode 100644 scripts/replace-in-file/helpers/glob-async.js create mode 100644 scripts/replace-in-file/helpers/load-config.js create mode 100644 scripts/replace-in-file/helpers/make-replacements.js create mode 100644 scripts/replace-in-file/helpers/parse-config.js create mode 100644 scripts/replace-in-file/helpers/replace-async.js create mode 100644 scripts/replace-in-file/helpers/replace-sync.js create mode 100644 scripts/replace-in-file/helpers/success-handler.js create mode 100644 scripts/replace-in-file/index.js diff --git a/package.json b/package.json index 3253db69110..8b86592cc78 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,6 @@ "lodash.zip": "^4.2.0", "micromatch": "^4.0.2", "mocha": "^8.0.1", - "replace-in-file": "^6.2.0", "rimraf": "^3.0.2", "solhint": "^3.2.0", "solidity-coverage": "^0.7.11", diff --git a/scripts/replace-in-file/helpers/combine-config.js b/scripts/replace-in-file/helpers/combine-config.js new file mode 100644 index 00000000000..ddf8f8ee6f3 --- /dev/null +++ b/scripts/replace-in-file/helpers/combine-config.js @@ -0,0 +1,60 @@ +'use strict'; + +/** + * Dependencies + */ +const parseConfig = require('./parse-config'); + +/** + * Combine CLI script arguments with config options + */ +module.exports = function combineConfig(config, argv) { + + //Extract options from config + let { + from, to, files, ignore, encoding, verbose, + allowEmptyPaths, disableGlobs, isRegex, dry, quiet, + } = config; + + //Get from/to parameters from CLI args if not defined in options + if (typeof from === 'undefined') { + from = argv._.shift(); + } + if (typeof to === 'undefined') { + to = argv._.shift(); + } + + //Get files and ignored files + if (typeof files === 'undefined') { + files = argv._; + } + if (typeof ignore === 'undefined' && typeof argv.ignore !== 'undefined') { + ignore = argv.ignore; + } + + //Other parameters + if (typeof encoding === 'undefined') { + encoding = argv.encoding; + } + if (typeof disableGlobs === 'undefined') { + disableGlobs = !!argv.disableGlobs; + } + if (typeof isRegex === 'undefined') { + isRegex = !!argv.isRegex; + } + if (typeof verbose === 'undefined') { + verbose = !!argv.verbose; + } + if (typeof dry === 'undefined') { + dry = !!argv.dry; + } + if (typeof quiet === 'undefined') { + quiet = !!argv.quiet; + } + + //Return through parser to validate + return parseConfig({ + from, to, files, ignore, encoding, verbose, + allowEmptyPaths, disableGlobs, isRegex, dry, quiet, + }); +}; diff --git a/scripts/replace-in-file/helpers/error-handler.js b/scripts/replace-in-file/helpers/error-handler.js new file mode 100644 index 00000000000..6c80213fa0a --- /dev/null +++ b/scripts/replace-in-file/helpers/error-handler.js @@ -0,0 +1,9 @@ +'use strict'; + +/** + * Error handler + */ +module.exports = function errorHandler(error, exitCode = 1) { + console.error(error); + process.exit(exitCode); +}; diff --git a/scripts/replace-in-file/helpers/get-paths-async.js b/scripts/replace-in-file/helpers/get-paths-async.js new file mode 100644 index 00000000000..83cfe4312be --- /dev/null +++ b/scripts/replace-in-file/helpers/get-paths-async.js @@ -0,0 +1,26 @@ +'use strict'; + +/** + * Dependencies + */ +const globAsync = require('./glob-async'); + +/** + * Get paths asynchrously + */ +module.exports = function getPathsAsync(patterns, config) { + + //Extract relevant config + const {ignore, disableGlobs, allowEmptyPaths, glob: cfg} = config; + + //Not using globs? + if (disableGlobs) { + return Promise.resolve(patterns); + } + + //Expand globs and flatten paths + return Promise + .all(patterns + .map(pattern => globAsync(pattern, ignore, allowEmptyPaths, cfg))) + .then(paths => [].concat.apply([], paths)); +}; diff --git a/scripts/replace-in-file/helpers/get-paths-sync.js b/scripts/replace-in-file/helpers/get-paths-sync.js new file mode 100644 index 00000000000..a3f3440dabd --- /dev/null +++ b/scripts/replace-in-file/helpers/get-paths-sync.js @@ -0,0 +1,42 @@ +'use strict'; + +/** + * Dependencies + */ +const glob = require('glob'); + +/** + * Get paths (sync) + */ +module.exports = function getPathsSync(patterns, config) { + + //Extract relevant config + const {ignore, disableGlobs, glob: globConfig, cwd} = config; + + //Not using globs? + if (disableGlobs) { + return patterns; + } + + //Prepare glob config + const cfg = Object.assign({ignore}, globConfig, {nodir: true}); + + //Append CWD configuration if given (#56) + //istanbul ignore if + if (cwd) { + cfg.cwd = cwd; + } + + //Get paths + const paths = patterns.map(pattern => glob.sync(pattern, cfg)); + const flattened = [].concat.apply([], paths); + + //Prefix each path with CWD if given (#56) + //istanbul ignore if + if (cwd) { + return flattened.map(path => `${cwd}${path}`); + } + + //Return flattened + return flattened; +}; diff --git a/scripts/replace-in-file/helpers/glob-async.js b/scripts/replace-in-file/helpers/glob-async.js new file mode 100644 index 00000000000..792ddadc6e5 --- /dev/null +++ b/scripts/replace-in-file/helpers/glob-async.js @@ -0,0 +1,34 @@ +'use strict'; + +/** + * Dependencies + */ +const glob = require('glob'); + +/** + * Async wrapper for glob + */ +module.exports = function globAsync(pattern, ignore, allowEmptyPaths, cfg) { + + //Prepare glob config + cfg = Object.assign({ignore}, cfg, {nodir: true}); + + //Return promise + return new Promise((resolve, reject) => { + glob(pattern, cfg, (error, files) => { + + //istanbul ignore if: hard to make glob error + if (error) { + return reject(error); + } + + //Error if no files match, unless allowed + if (!allowEmptyPaths && files.length === 0) { + return reject(new Error('No files match the pattern: ' + pattern)); + } + + //Resolve + resolve(files); + }); + }); +}; diff --git a/scripts/replace-in-file/helpers/load-config.js b/scripts/replace-in-file/helpers/load-config.js new file mode 100644 index 00000000000..cc190c19e49 --- /dev/null +++ b/scripts/replace-in-file/helpers/load-config.js @@ -0,0 +1,23 @@ +'use strict'; + +/** + * Dependencies + */ +const path = require('path'); + +/** + * Helper to load options from a config file + */ +module.exports = function loadConfig(file) { + + //No config file provided? + if (!file) { + return {}; + } + + //Resolve path + file = path.resolve(file); + + //Try to load + return require(file); +}; diff --git a/scripts/replace-in-file/helpers/make-replacements.js b/scripts/replace-in-file/helpers/make-replacements.js new file mode 100644 index 00000000000..0876d7b821c --- /dev/null +++ b/scripts/replace-in-file/helpers/make-replacements.js @@ -0,0 +1,75 @@ +'use strict'; + +/** + * Get replacement helper + */ +function getReplacement(replace, isArray, i) { + if (isArray && typeof replace[i] === 'undefined') { + return null; + } + if (isArray) { + return replace[i]; + } + return replace; +} + +/** + * Helper to make replacements + */ +module.exports = function makeReplacements(contents, from, to, file, count) { + + //Turn into array + if (!Array.isArray(from)) { + from = [from]; + } + + //Check if replace value is an array and prepare result + const isArray = Array.isArray(to); + const result = {file}; + + //Counting? Initialize number of matches + if (count) { + result.numMatches = 0; + result.numReplacements = 0; + } + + //Make replacements + const newContents = from.reduce((contents, item, i) => { + + //Call function if given, passing in the filename + if (typeof item === 'function') { + item = item(file); + } + + //Get replacement value + let replacement = getReplacement(to, isArray, i); + if (replacement === null) { + return contents; + } + + //Call function if given, appending the filename + if (typeof replacement === 'function') { + const original = replacement; + replacement = (...args) => original(...args, file); + } + + //Count matches + if (count) { + const matches = contents.match(item); + if (matches) { + const replacements = matches.filter(match => match !== replacement); + result.numMatches += matches.length; + result.numReplacements += replacements.length; + } + } + + //Make replacement + return contents.replace(item, replacement); + }, contents); + + //Check if changed + result.hasChanged = (newContents !== contents); + + //Return result and new contents + return [result, newContents]; +}; diff --git a/scripts/replace-in-file/helpers/parse-config.js b/scripts/replace-in-file/helpers/parse-config.js new file mode 100644 index 00000000000..41d87a12694 --- /dev/null +++ b/scripts/replace-in-file/helpers/parse-config.js @@ -0,0 +1,67 @@ +'use strict'; + +/** + * Defaults + */ +const defaults = { + ignore: [], + encoding: 'utf-8', + disableGlobs: false, + allowEmptyPaths: false, + countMatches: false, + isRegex: false, + verbose: false, + quiet: false, + dry: false, + glob: {}, + cwd: null, +}; + +/** + * Parse config + */ +module.exports = function parseConfig(config) { + + //Validate config + if (typeof config !== 'object' || config === null) { + throw new Error('Must specify configuration object'); + } + + //Fix glob + config.glob = config.glob || {}; + + //Extract data + const {files, from, to, ignore, encoding} = config; + + //Validate values + if (typeof files === 'undefined') { + throw new Error('Must specify file or files'); + } + if (typeof from === 'undefined') { + throw new Error('Must specify string or regex to replace'); + } + if (typeof to === 'undefined') { + throw new Error('Must specify a replacement (can be blank string)'); + } + + //Ensure arrays + if (!Array.isArray(files)) { + config.files = [files]; + } + if (!Array.isArray(ignore)) { + if (typeof ignore === 'undefined') { + config.ignore = []; + } + else { + config.ignore = [ignore]; + } + } + + //Use default encoding if invalid + if (typeof encoding !== 'string' || encoding === '') { + config.encoding = 'utf-8'; + } + + //Merge config with defaults + return Object.assign({}, defaults, config); +}; diff --git a/scripts/replace-in-file/helpers/replace-async.js b/scripts/replace-in-file/helpers/replace-async.js new file mode 100644 index 00000000000..5167d4bfc75 --- /dev/null +++ b/scripts/replace-in-file/helpers/replace-async.js @@ -0,0 +1,45 @@ +'use strict'; + +/** + * Dependencies + */ +const fs = require('fs'); +const makeReplacements = require('./make-replacements'); + +/** + * Helper to replace in a single file (async) + */ +module.exports = function replaceAsync(file, from, to, config) { + + //Extract relevant config + const {encoding, dry, countMatches} = config; + + //Wrap in promise + return new Promise((resolve, reject) => { + fs.readFile(file, encoding, (error, contents) => { + //istanbul ignore if + if (error) { + return reject(error); + } + + //Make replacements + const [result, newContents] = makeReplacements( + contents, from, to, file, countMatches + ); + + //Not changed or dry run? + if (!result.hasChanged || dry) { + return resolve(result); + } + + //Write to file + fs.writeFile(file, newContents, encoding, error => { + //istanbul ignore if + if (error) { + return reject(error); + } + resolve(result); + }); + }); + }); +}; diff --git a/scripts/replace-in-file/helpers/replace-sync.js b/scripts/replace-in-file/helpers/replace-sync.js new file mode 100644 index 00000000000..ada3519fdf8 --- /dev/null +++ b/scripts/replace-in-file/helpers/replace-sync.js @@ -0,0 +1,30 @@ +'use strict'; + +/** + * Dependencies + */ +const fs = require('fs'); +const makeReplacements = require('./make-replacements'); + +/** + * Helper to replace in a single file (sync) + */ +module.exports = function replaceSync(file, from, to, config) { + + //Extract relevant config and read file contents + const {encoding, dry, countMatches} = config; + const contents = fs.readFileSync(file, encoding); + + //Replace contents and check if anything changed + const [result, newContents] = makeReplacements( + contents, from, to, file, countMatches + ); + + //Contents changed and not a dry run? Write to file + if (result.hasChanged && !dry) { + fs.writeFileSync(file, newContents, encoding); + } + + //Return result + return result; +}; diff --git a/scripts/replace-in-file/helpers/success-handler.js b/scripts/replace-in-file/helpers/success-handler.js new file mode 100644 index 00000000000..cc526204148 --- /dev/null +++ b/scripts/replace-in-file/helpers/success-handler.js @@ -0,0 +1,18 @@ +'use strict'; + +/** + * Success handler + */ +module.exports = function successHandler(results, verbose) { + const changed = results.filter(result => result.hasChanged); + const numChanges = changed.length; + if (numChanges > 0) { + console.log(`${numChanges} file(s) were changed`); + if (verbose) { + changed.forEach(result => console.log('-', result.file)); + } + } + else { + console.log('No files were changed'); + } +}; diff --git a/scripts/replace-in-file/index.js b/scripts/replace-in-file/index.js new file mode 100644 index 00000000000..0394579e394 --- /dev/null +++ b/scripts/replace-in-file/index.js @@ -0,0 +1,92 @@ +'use strict'; + +/** + * Dependencies + */ +const parseConfig = require('./helpers/parse-config'); +const getPathsSync = require('./helpers/get-paths-sync'); +const getPathsAsync = require('./helpers/get-paths-async'); +const replaceSync = require('./helpers/replace-sync'); +const replaceAsync = require('./helpers/replace-async'); + +/** + * Replace in file helper + */ +function replaceInFile(config, cb) { + + //Parse config + try { + config = parseConfig(config); + } + catch (error) { + if (typeof cb === 'function') { + return cb(error, null); + } + return Promise.reject(error); + } + + //Get config + const {files, from, to, dry, verbose} = config; + + //Dry run? + //istanbul ignore if: No need to test console logs + if (dry && verbose) { + console.log('Dry run, not making actual changes'); + } + + //Find paths + return getPathsAsync(files, config) + + //Make replacements + .then(paths => Promise.all( + paths.map(file => replaceAsync(file, from, to, config)) + )) + + //Success handler + .then(results => { + if (typeof cb === 'function') { + cb(null, results); + } + return results; + }) + + //Error handler + .catch(error => { + if (typeof cb === 'function') { + cb(error); + } + else { + throw error; + } + }); +} + +/** + * Sync API + */ +function replaceInFileSync(config) { + + //Parse config + config = parseConfig(config); + + //Get config, paths, and initialize changed files + const {files, from, to, dry, verbose} = config; + const paths = getPathsSync(files, config); + + //Dry run? + //istanbul ignore if: No need to test console logs + if (dry && verbose) { + console.log('Dry run, not making actual changes'); + } + + //Process synchronously and return results + return paths.map(path => replaceSync(path, from, to, config)); +} + +// Self-reference to support named import +replaceInFile.replaceInFile = replaceInFile; +replaceInFile.replaceInFileSync = replaceInFileSync; +replaceInFile.sync = replaceInFileSync; + +//Export +module.exports = replaceInFile; diff --git a/scripts/rewrite-imports.js b/scripts/rewrite-imports.js index cee9553fbbe..fd8c2c16016 100644 --- a/scripts/rewrite-imports.js +++ b/scripts/rewrite-imports.js @@ -1,9 +1,14 @@ -const debug = require('debug'); +'use strict'; + +// const debug = require('debug'); const fs = require('fs'); const path = require('path'); -const replace = require('replace-in-file'); +// const replace = require('replace-in-file'); +const replace = require('./replace-in-file') +const successHandler = require('./replace-in-file/helpers/success-handler') const versions = [ + '', '@openzeppelin/contracts', '@openzeppelin/contracts-upgradeable', ]; @@ -43,58 +48,58 @@ const updates = { 'presets/ERC721PresetMinterPauserAutoId.sol': 'tokens/ERC721/presets/ERC721PresetMinterPauserAutoId.sol', 'presets/ERC777PresetFixedSupply.sol': 'tokens/ERC777/presets/ERC777PresetFixedSupply.sol', 'proxy/BeaconProxy.sol': 'proxy/beacon/BeaconProxy.sol', - 'proxy/Clones.sol': null, + 'proxy/Clones.sol': undefined, 'proxy/IBeacon.sol': 'proxy/beacon/IBeacon.sol', 'proxy/Initializable.sol': 'utils/Initializable.sol', 'proxy/ProxyAdmin.sol': 'proxy/transparent/ProxyAdmin.sol', - 'proxy/Proxy.sol': null, + 'proxy/Proxy.sol': undefined, 'proxy/TransparentUpgradeableProxy.sol': 'proxy/transparent/TransparentUpgradeableProxy.sol', 'proxy/UpgradeableBeacon.sol': 'proxy/beacon/UpgradeableBeacon.sol', - 'proxy/UpgradeableProxy.sol': null, + 'proxy/UpgradeableProxy.sol': undefined, 'token/ERC1155/ERC1155Burnable.sol': 'token/ERC1155/extensions/ERC1155Burnable.sol', 'token/ERC1155/ERC1155Holder.sol': 'token/ERC1155/utils/ERC1155Holder.sol', 'token/ERC1155/ERC1155Pausable.sol': 'token/ERC1155/extensions/ERC1155Pausable.sol', 'token/ERC1155/ERC1155Receiver.sol': 'token/ERC1155/utils/ERC1155Receiver.sol', - 'token/ERC1155/ERC1155.sol': null, + 'token/ERC1155/ERC1155.sol': undefined, 'token/ERC1155/IERC1155MetadataURI.sol': 'token/ERC1155/extensions/IERC1155MetadataURI.sol', - 'token/ERC1155/IERC1155Receiver.sol': null, - 'token/ERC1155/IERC1155.sol': null, + 'token/ERC1155/IERC1155Receiver.sol': undefined, + 'token/ERC1155/IERC1155.sol': undefined, 'token/ERC20/ERC20Burnable.sol': 'token/ERC20/extensions/ERC20Burnable.sol', 'token/ERC20/ERC20Capped.sol': 'token/ERC20/extensions/ERC20Capped.sol', 'token/ERC20/ERC20Pausable.sol': 'token/ERC20/extensions/ERC20Pausable.sol', 'token/ERC20/ERC20Snapshot.sol': 'token/ERC20/extensions/ERC20Snapshot.sol', - 'token/ERC20/ERC20.sol': null, - 'token/ERC20/IERC20.sol': null, + 'token/ERC20/ERC20.sol': undefined, + 'token/ERC20/IERC20.sol': undefined, 'token/ERC20/SafeERC20.sol': 'token/ERC20/utils/SafeERC20.sol', 'token/ERC20/TokenTimelock.sol': 'standalone/TokenTimelock.sol', 'token/ERC721/ERC721Burnable.sol': 'token/ERC721/extensions/ERC721Burnable.sol', 'token/ERC721/ERC721Holder.sol': 'token/ERC721/utils/ERC721Holder.sol', 'token/ERC721/ERC721Pausable.sol': 'token/ERC721/extensions/ERC721Pausable.sol', - 'token/ERC721/ERC721.sol': null, + 'token/ERC721/ERC721.sol': undefined, 'token/ERC721/IERC721Enumerable.sol': 'token/ERC721/extensions/IERC721Enumerable.sol', 'token/ERC721/IERC721Metadata.sol': 'token/ERC721/extensions/IERC721Metadata.sol', - 'token/ERC721/IERC721Receiver.sol': null, - 'token/ERC721/IERC721.sol': null, - 'token/ERC777/ERC777.sol': null, - 'token/ERC777/IERC777Recipient.sol': null, - 'token/ERC777/IERC777Sender.sol': null, - 'token/ERC777/IERC777.sol': null, - 'utils/Address.sol': null, - 'utils/Arrays.sol': null, - 'utils/Context.sol': null, - 'utils/Counters.sol': null, - 'utils/Create2.sol': null, + 'token/ERC721/IERC721Receiver.sol': undefined, + 'token/ERC721/IERC721.sol': undefined, + 'token/ERC777/ERC777.sol': undefined, + 'token/ERC777/IERC777Recipient.sol': undefined, + 'token/ERC777/IERC777Sender.sol': undefined, + 'token/ERC777/IERC777.sol': undefined, + 'utils/Address.sol': undefined, + 'utils/Arrays.sol': undefined, + 'utils/Context.sol': undefined, + 'utils/Counters.sol': undefined, + 'utils/Create2.sol': undefined, 'utils/EnumerableMap.sol': 'utils/enumerable/EnumerableMap.sol', 'utils/EnumerableSet.sol': 'utils/enumerable/EnumerableSet.sol', - 'utils/Pausable.sol': null, - 'utils/ReentrancyGuard.sol': null, - 'utils/SafeCast.sol': null, - 'utils/Strings.sol': null, + 'utils/Pausable.sol': undefined, + 'utils/ReentrancyGuard.sol': undefined, + 'utils/SafeCast.sol': undefined, + 'utils/Strings.sol': undefined, }; (async () => { - debug('rewrite-migration')('started'); - const logs = await replace({ + // debug('rewrite-migration')('started'); + const results = await replace({ files: (process.argv.length > 2 ? process.argv.slice(2) : [ 'contracts' ]) .map(file => fs.statSync(file).isDirectory() ? path.join(file, '**', '*.sol') : file), from: Object.entries(updates) @@ -104,6 +109,7 @@ const updates = { .filter(([ from, to ]) => to) .flatMap(([ from, to ]) => versions.map(version => path.join(version, to))), }); - logs.filter(({ hasChanged }) => hasChanged).forEach(({ file }) => debug('rewrite-migration:updated')(file)); - debug('rewrite-migration')('finished'); + successHandler(results, true); + // results.filter(({ hasChanged }) => hasChanged).forEach(({ file }) => debug('rewrite-migration:updated')(file)); + // debug('rewrite-migration')('finished'); })().catch(console.error); From bcd8ec40280061ee0c8a267bfdda0be5f7ad1bc9 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 18 Feb 2021 16:34:27 +0100 Subject: [PATCH 09/31] add readme and version for replace-in-file --- scripts/replace-in-file/README.md | 476 ++++++++++++++++++++++++++++++ scripts/replace-in-file/version | 1 + 2 files changed, 477 insertions(+) create mode 100644 scripts/replace-in-file/README.md create mode 100644 scripts/replace-in-file/version diff --git a/scripts/replace-in-file/README.md b/scripts/replace-in-file/README.md new file mode 100644 index 00000000000..0af91453d09 --- /dev/null +++ b/scripts/replace-in-file/README.md @@ -0,0 +1,476 @@ +# Replace in file + +[![npm version](https://img.shields.io/npm/v/replace-in-file.svg)](https://www.npmjs.com/package/replace-in-file) +[![node dependencies](https://david-dm.org/adamreisnz/replace-in-file.svg)](https://david-dm.org/adamreisnz/replace-in-file) +[![build status](https://travis-ci.org/adamreisnz/replace-in-file.svg?branch=master)](https://travis-ci.org/adamreisnz/replace-in-file) +[![coverage status](https://coveralls.io/repos/github/adamreisnz/replace-in-file/badge.svg?branch=master)](https://coveralls.io/github/adamreisnz/replace-in-file?branch=master) +[![github issues](https://img.shields.io/github/issues/adamreisnz/replace-in-file.svg)](https://github.com/adamreisnz/replace-in-file/issues) + +A simple utility to quickly replace text in one or more files or globs. Works synchronously or asynchronously with either promises or callbacks. Make a single replacement or multiple replacements at once. + +> Hey there 👋🏼, thank you for using `replace-in-file`! + +> Sorry for the interruption, but as you probably know, I don’t get paid for maintaining this package, and I also haven't put up a donation thingy of any kind. + +> However, I _am_ trying to grow our start-up [Hello Club](https://helloclub.com/?source=npm) internationally, and would _really_ appreciate it if you could have a quick look on our [website](https://helloclub.com/?source=npm) to see what we're all about. 👀 + +> As the name implies, we offer an [all-in-one club and membership management solution](https://helloclub.com/?source=npm) complete with booking system, automated membership renewals, online payments and integrated access and light control. + +> Clubs that have switched to Hello Club have been saving so much time managing their members and finances, and the members themselves really enjoy using it, with overwhelmingly positive feedback. + +> Check us out if you belong to any kind of club or if you know someone who helps run a club! + +> Thank you so much for your time, now go and replace some data in your files! 🎉 + +# Index +- [Installation](#installation) +- [Basic usage](#basic-usage) + - [Asynchronous replacement with `async`/`await`](#asynchronous-replacement-with-asyncawait) + - [Asynchronous replacement with promises](asynchronous-replacement-with-promises) + - [Asynchronous replacement with callback](#asynchronous-replacement-with-callback) + - [Synchronous replacement](#synchronous-replacement) + - [Return value](#return-value) + - [Counting matches and replacements](#counting-matches-and-replacements) +- [Advanced usage](#advanced-usage) + - [Replace a single file or glob](#replace-a-single-file-or-glob) + - [Replace multiple files or globs](#replace-multiple-files-or-globs) + - [Replace first occurrence only](#replace-first-occurrence-only) + - [Replace all occurrences](#replace-all-occurrences) + - [Multiple values with the same replacement](#multiple-values-with-the-same-replacement) + - [Custom regular expressions](#custom-regular-expressions) + - [Multiple values with different replacements](#multiple-values-with-different-replacements) + - [Using callbacks for `from`](#using-callbacks-for-from) + - [Using callbacks for `to`](#using-callbacks-for-to) + - [Ignore a single file or glob](#ignore-a-single-file-or-glob) + - [Ignore multiple files or globs](#ignore-multiple-files-or-globs) + - [Allow empty/invalid paths](#allow-emptyinvalid-paths) + - [Disable globs](#disable-globs) + - [Specify glob configuration](#specify-glob-configuration) + - [Making replacements on network drives](#making-replacements-on-network-drives) + - [Specify character encoding](#specify-character-encoding) + - [Dry run](#dry-run) +- [CLI usage](#cli-usage) +- [A note on using globs with the CLI](#a-note-on-using-globs-with-the-cli) +- [Version information](#version-information) +- [License](#license) + +## Installation +```shell +# Using npm, installing to local project +npm i --save replace-in-file + +# Using npm, installing globally for global cli usage +npm i -g replace-in-file + +# Using yarn +yarn add replace-in-file +``` + +## Basic usage + +```js +//Load the library and specify options +const replace = require('replace-in-file'); +const options = { + files: 'path/to/file', + from: /foo/g, + to: 'bar', +}; +``` + +### Asynchronous replacement with `async`/`await` + +```js +try { + const results = await replace(options) + console.log('Replacement results:', results); +} +catch (error) { + console.error('Error occurred:', error); +} +``` + +### Asynchronous replacement with promises + +```js +replace(options) + .then(results => { + console.log('Replacement results:', results); + }) + .catch(error => { + console.error('Error occurred:', error); + }); +``` + +### Asynchronous replacement with callback + +```js +replace(options, (error, results) => { + if (error) { + return console.error('Error occurred:', error); + } + console.log('Replacement results:', results); +}); +``` + +### Synchronous replacement + +```js +try { + const results = replace.sync(options); + console.log('Replacement results:', results); +} +catch (error) { + console.error('Error occurred:', error); +} +``` + +### Return value + +The return value of the library is an array of replacement results against each file that was processed. This includes files in which no replacements were made. + +Each result contains the following values: + +- `file`: The path to the file that was processed +- `hasChanged`: Flag to indicate if the file was changed or not + +```js +const results = replace.sync({ + files: 'path/to/files/*.html', + from: /foo/g, + to: 'bar', +}); + +console.log(results); + +// [ +// { +// file: 'path/to/files/file1.html', +// hasChanged: true, +// }, +// { +// file: 'path/to/files/file2.html', +// hasChanged: true, +// }, +// { +// file: 'path/to/files/file3.html', +// hasChanged: false, +// }, +// ] + +``` + +To get an array of changed files, simply map the results as follows: + +```js +const changedFiles = results + .filter(result => result.hasChanged) + .map(result => result.file); +``` + +### Counting matches and replacements +By setting the `countMatches` configuration flag to `true`, the number of matches and replacements per file will be counted and present in the results array. + +- `numMatches`: Indicates the number of times a match was found in the file +- `numReplacements`: Indicates the number of times a replacement was made in the file + +Note that the number of matches can be higher than the number of replacements if a match and replacement are the same string. + +```js +const results = replace.sync({ + files: 'path/to/files/*.html', + from: /foo/g, + to: 'bar', + countMatches: true, +}); + +console.log(results); + +// [ +// { +// file: 'path/to/files/file1.html', +// hasChanged: true, +// numMatches: 3, +// numReplacements: 3, +// }, +// { +// file: 'path/to/files/file2.html', +// hasChanged: true, +// numMatches: 1, +// numReplacements: 1, +// }, +// { +// file: 'path/to/files/file3.html', +// hasChanged: false, +// numMatches: 0, +// numReplacements: 0, +// }, +// ] +``` + +## Advanced usage + +### Replace a single file or glob +```js +const options = { + files: 'path/to/file', +}; +``` + +### Replace multiple files or globs + +```js +const options = { + files: [ + 'path/to/file', + 'path/to/other/file', + 'path/to/files/*.html', + 'another/**/*.path', + ], +}; +``` + +### Replace first occurrence only + +```js +const options = { + from: 'foo', + to: 'bar', +}; +``` + +### Replace all occurrences +Please note that the value specified in the `from` parameter is passed straight to the native [String replace method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace). As such, if you pass a string as the `from` parameter, it will _only replace the first occurrence_. + +To replace multiple occurrences at once, you must use a regular expression for the `from` parameter with the global flag enabled, e.g. `/foo/g`. + +```js +const options = { + from: /foo/g, + to: 'bar', +}; +``` + +### Multiple values with the same replacement + +These will be replaced sequentially. + +```js +const options = { + from: [/foo/g, /baz/g], + to: 'bar', +}; +``` + +### Multiple values with different replacements + +These will be replaced sequentially. + +```js +const options = { + from: [/foo/g, /baz/g], + to: ['bar', 'bax'], +}; +``` + +### Custom regular expressions + +Use the [RegExp](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) constructor to create any regular expression. + +```js +const str = 'foo'; +const regex = new RegExp('^' + str + 'bar', 'i'); +const options = { + from: regex, + to: 'bar', +}; +``` + +### Using callbacks for `from` +You can also specify a callback that returns a string or a regular expression. The callback receives the name of the file in which the replacement is being performed, thereby allowing the user to tailor the search string. The following example uses a callback to produce a search string dependent on the filename: + +```js +const options = { + files: 'path/to/file', + from: (file) => new RegExp(file, 'g'), + to: 'bar', +}; +``` + +### Using callbacks for `to` +As the `to` parameter is passed to the native [String replace method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace), you can also specify a callback. The following example uses a callback to convert matching strings to lowercase: + +```js +const options = { + files: 'path/to/file', + from: /SomePattern[A-Za-z-]+/g, + to: (match) => match.toLowerCase(), +}; +``` + +This callback provides for an extra argument above the String replace method, which is the name of the file in which the replacement is being performed. The following example replaces the matched string with the filename: + +```js +const options = { + files: 'path/to/file', + from: /SomePattern[A-Za-z-]+/g, + to: (...args) => args.pop(), +}; +``` + +### Ignore a single file or glob + +```js +const options = { + ignore: 'path/to/ignored/file', +}; +``` + +### Ignore multiple files or globs + +```js +const options = { + ignore: [ + 'path/to/ignored/file', + 'path/to/other/ignored_file', + 'path/to/ignored_files/*.html', + 'another/**/*.ignore', + ], +}; +``` + +Please note that there is an [open issue with Glob](https://github.com/isaacs/node-glob/issues/309) that causes ignored patterns to be ignored when using a `./` prefix in your files glob. To work around this, simply remove the prefix, e.g. use `**/*` instead of `./**/*`. + +### Allow empty/invalid paths +If set to true, empty or invalid paths will fail silently and no error will be thrown. For asynchronous replacement only. Defaults to `false`. + +```js +const options = { + allowEmptyPaths: true, +}; +``` + +### Disable globs +You can disable globs if needed using this flag. Use this when you run into issues with file paths like files like `//SERVER/share/file.txt`. Defaults to `false`. + +```js +const options = { + disableGlobs: true, +}; +``` + +### Specify glob configuration +Specify configuration passed to the [glob](https://www.npmjs.com/package/glob) call: + +```js +const options = { + glob: { + //Glob settings here + }, +}; +``` + +Please note that the setting `nodir` will always be passed as `false`. + +### Making replacements on network drives +To make replacements in files on network drives, you may need to specify the UNC path as the `cwd` config option. This will then be passed to glob and prefixed to your paths accordingly. See [#56](https://github.com/adamreisnz/replace-in-file/issues/56) for more details. + +### Specify character encoding +Use a different character encoding for reading/writing files. Defaults to `utf-8`. + +```js +const options = { + encoding: 'utf8', +}; +``` + +### Dry run +To do a dry run without actually making replacements, for testing purposes. Defaults to `false`. + +```js +const options = { + dry: true, +}; +``` + +## CLI usage + +```sh +replace-in-file from to some/file.js,some/**/glob.js + [--configFile=replace-config.js] + [--ignore=ignore/files.js,ignore/**/glob.js] + [--encoding=utf-8] + [--disableGlobs] + [--isRegex] + [--verbose] + [--quiet] + [--dry] +``` + +Multiple files or globs can be replaced by providing a comma separated list. + +The flags `--disableGlobs`, `--ignore` and `--encoding` are supported in the CLI. + +The setting `allowEmptyPaths` is not supported in the CLI as the replacement is +synchronous, and this setting is only relevant for asynchronous replacement. + +To list the changed files, use the `--verbose` flag. Success output can be suppressed by using the `--quiet` flag. + +To do a dry run without making any actual changes, use `--dry`. + +A regular expression may be used for the `from` parameter by specifying the `--isRegex` flag. + +The `from` and `to` parameters, as well as the files list, can be omitted if you provide this +information in a configuration file. You can provide a path to a configuration file +(either Javascript or JSON) with the `--configFile` flag. This path will be resolved using +Node’s built in `path.resolve()`, so you can pass in an absolute or relative path. + +## A note on using globs with the CLI +When using the CLI, the glob pattern is handled by the operating system. But if you specify the glob pattern in the configuration file, the package will use the glob module from the Node modules, and this can lead to different behaviour despite using the same pattern. + +For example, the following will only look at top level files: + +```js +//config.js +module.exports = { + from: /cat/g, + to: 'dog', +}; +``` + +```sh +replace-in-file ** --configFile=config.js +``` + +However, this example is recursive: + +```js +//config.js +module.exports = { + files: '**', + from: /cat/g, + to: 'dog', +}; +``` + +```sh +replace-in-file --configFile=config.js +``` + +If you want to do a recursive file search as an argument you must use: + +```sh +replace-in-file $(ls l {,**/}*) --configFile=config.js +``` + +## Version information +From version 3.0.0 onwards, replace in file requires Node 6 or higher. If you need support for Node 4 or 5, please use version 2.x.x. + +From version 5.0.0 onwards, replace in file requires Node 8 or higher. If you need support for Node 6, please use version 4.x.x. + +See the [Changelog](CHANGELOG.md) for more information. + +## License +(MIT License) + +Copyright 2015-2020, Adam Reis, Co-founder at [Hello Club](https://helloclub.com/?source=npm) diff --git a/scripts/replace-in-file/version b/scripts/replace-in-file/version new file mode 100644 index 00000000000..6abaeb2f907 --- /dev/null +++ b/scripts/replace-in-file/version @@ -0,0 +1 @@ +6.2.0 From e32a07c5ce3557e7275d48fc45da0b447f7ad037 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 18 Feb 2021 19:12:37 +0100 Subject: [PATCH 10/31] remove utils/GSN/Context.sol (already at utils/Context.sol) --- contracts/utils/GSN/Context.sol | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 contracts/utils/GSN/Context.sol diff --git a/contracts/utils/GSN/Context.sol b/contracts/utils/GSN/Context.sol deleted file mode 100644 index eec27ff16b5..00000000000 --- a/contracts/utils/GSN/Context.sol +++ /dev/null @@ -1,5 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -import "../Context.sol"; From a1e5919987b682d73abda8e57da0480ec36833c2 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 18 Feb 2021 19:20:29 +0100 Subject: [PATCH 11/31] move draft-EIP712 to utils/cryptography --- contracts/mocks/EIP712External.sol | 2 +- .../ERC20/extensions/draft-ERC20Permit.sol | 2 +- contracts/utils/cryptography/ECDSA.sol | 19 ++++++++++++++++--- .../utils/{ => cryptography}/draft-EIP712.sol | 4 +++- 4 files changed, 21 insertions(+), 6 deletions(-) rename contracts/utils/{ => cryptography}/draft-EIP712.sol (97%) diff --git a/contracts/mocks/EIP712External.sol b/contracts/mocks/EIP712External.sol index cca6b5a1290..943556f2533 100644 --- a/contracts/mocks/EIP712External.sol +++ b/contracts/mocks/EIP712External.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../utils/draft-EIP712.sol"; +import "../utils/cryptography/draft-EIP712.sol"; import "../utils/cryptography/ECDSA.sol"; contract EIP712External is EIP712 { diff --git a/contracts/token/ERC20/extensions/draft-ERC20Permit.sol b/contracts/token/ERC20/extensions/draft-ERC20Permit.sol index 4af75e0e789..1f5cdc2cb71 100644 --- a/contracts/token/ERC20/extensions/draft-ERC20Permit.sol +++ b/contracts/token/ERC20/extensions/draft-ERC20Permit.sol @@ -4,9 +4,9 @@ pragma solidity ^0.8.0; import "./draft-IERC20Permit.sol"; import "../ERC20.sol"; +import "../../../utils/cryptography/draft-EIP712.sol"; import "../../../utils/cryptography/ECDSA.sol"; import "../../../utils/Counters.sol"; -import "../../../utils/draft-EIP712.sol"; /** * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in diff --git a/contracts/utils/cryptography/ECDSA.sol b/contracts/utils/cryptography/ECDSA.sol index e70815df1fd..76dab5d2113 100644 --- a/contracts/utils/cryptography/ECDSA.sol +++ b/contracts/utils/cryptography/ECDSA.sol @@ -72,9 +72,9 @@ library ECDSA { /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This - * replicates the behavior of the - * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`] - * JSON-RPC method. + * produces hash corresponding to the one signed with the + * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] + * JSON-RPC method as part of EIP-191. * * See {recover}. */ @@ -83,4 +83,17 @@ library ECDSA { // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } + + /** + * @dev Returns an Ethereum Signed Typed Data, created from a + * `domainSeparator` and a `structHash`. This produces hash corresponding + * to the one signed with the + * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] + * JSON-RPC method as part of EIP-712. + * + * See {recover}. + */ + function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { + return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); + } } diff --git a/contracts/utils/draft-EIP712.sol b/contracts/utils/cryptography/draft-EIP712.sol similarity index 97% rename from contracts/utils/draft-EIP712.sol rename to contracts/utils/cryptography/draft-EIP712.sol index 68ee9de4a22..044f50aae1e 100644 --- a/contracts/utils/draft-EIP712.sol +++ b/contracts/utils/cryptography/draft-EIP712.sol @@ -2,6 +2,8 @@ pragma solidity ^0.8.0; +import "./ECDSA.sol"; + /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * @@ -95,6 +97,6 @@ abstract contract EIP712 { * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { - return keccak256(abi.encodePacked("\x19\x01", _domainSeparatorV4(), structHash)); + return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); } } From 5bd4344d7d9e64bb6134699f5140f9a79a054a7b Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 18 Feb 2021 19:25:12 +0100 Subject: [PATCH 12/31] move SafeCast to utils/math --- contracts/mocks/SafeCastMock.sol | 2 +- contracts/utils/{ => math}/SafeCast.sol | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename contracts/utils/{ => math}/SafeCast.sol (100%) diff --git a/contracts/mocks/SafeCastMock.sol b/contracts/mocks/SafeCastMock.sol index 5d8e6b0fbc9..9baf9dd2090 100644 --- a/contracts/mocks/SafeCastMock.sol +++ b/contracts/mocks/SafeCastMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../utils/SafeCast.sol"; +import "../utils/math/SafeCast.sol"; contract SafeCastMock { using SafeCast for uint; diff --git a/contracts/utils/SafeCast.sol b/contracts/utils/math/SafeCast.sol similarity index 100% rename from contracts/utils/SafeCast.sol rename to contracts/utils/math/SafeCast.sol From 7b6c6b21697de8ba9ddfb6f5fe20ed25164f15ab Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 18 Feb 2021 19:47:05 +0100 Subject: [PATCH 13/31] fix some lint incosistency in SafeCast --- contracts/utils/math/SafeCast.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/contracts/utils/math/SafeCast.sol b/contracts/utils/math/SafeCast.sol index 860ef0b7a2d..5415462c19a 100644 --- a/contracts/utils/math/SafeCast.sol +++ b/contracts/utils/math/SafeCast.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.0; - /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. @@ -19,7 +18,6 @@ pragma solidity ^0.8.0; * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { - /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). From 320de67935706c2d4738b38cb0221971db768000 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 18 Feb 2021 21:21:14 +0100 Subject: [PATCH 14/31] second wave of reorg --- .../{utils => }/access/AccessControl.sol | 6 ++--- contracts/{utils => }/access/Ownable.sol | 2 +- contracts/{utils => }/access/README.adoc | 0 contracts/mocks/AccessControlMock.sol | 2 +- contracts/mocks/ConditionalEscrowMock.sol | 2 +- contracts/mocks/EnumerableMapMock.sol | 2 +- contracts/mocks/EnumerableSetMock.sol | 2 +- contracts/mocks/OwnableMock.sol | 2 +- contracts/mocks/PausableMock.sol | 2 +- contracts/mocks/PullPaymentMock.sol | 2 +- contracts/mocks/ReentrancyMock.sol | 2 +- contracts/proxy/beacon/UpgradeableBeacon.sol | 2 +- contracts/proxy/transparent/ProxyAdmin.sol | 2 +- contracts/{utils => security}/Pausable.sol | 2 +- .../payment => security}/PullPayment.sol | 2 +- .../{utils => security}/ReentrancyGuard.sol | 0 contracts/standalone/TimelockController.sol | 2 +- .../ERC1155/extensions/ERC1155Pausable.sol | 2 +- .../presets/ERC1155PresetMinterPauser.sol | 2 +- .../token/ERC20/extensions/ERC20Pausable.sol | 2 +- .../ERC20/presets/ERC20PresetMinterPauser.sol | 2 +- contracts/token/ERC721/ERC721.sol | 4 ++-- .../ERC721/extensions/ERC721Pausable.sol | 2 +- .../ERC721PresetMinterPauserAutoId.sol | 2 +- .../escrow/ConditionalEscrow.sol | 0 .../utils/{payment => }/escrow/Escrow.sol | 2 +- .../{payment => }/escrow/RefundEscrow.sol | 0 contracts/utils/payment/README.adoc | 22 ------------------- .../{enumerable => structs}/EnumerableMap.sol | 0 .../{enumerable => structs}/EnumerableSet.sol | 0 30 files changed, 26 insertions(+), 48 deletions(-) rename contracts/{utils => }/access/AccessControl.sol (98%) rename contracts/{utils => }/access/Ownable.sol (98%) rename contracts/{utils => }/access/README.adoc (100%) rename contracts/{utils => security}/Pausable.sol (98%) rename contracts/{utils/payment => security}/PullPayment.sol (98%) rename contracts/{utils => security}/ReentrancyGuard.sol (100%) rename contracts/utils/{payment => }/escrow/ConditionalEscrow.sol (100%) rename contracts/utils/{payment => }/escrow/Escrow.sol (98%) rename contracts/utils/{payment => }/escrow/RefundEscrow.sol (100%) delete mode 100644 contracts/utils/payment/README.adoc rename contracts/utils/{enumerable => structs}/EnumerableMap.sol (100%) rename contracts/utils/{enumerable => structs}/EnumerableSet.sol (100%) diff --git a/contracts/utils/access/AccessControl.sol b/contracts/access/AccessControl.sol similarity index 98% rename from contracts/utils/access/AccessControl.sol rename to contracts/access/AccessControl.sol index fc3d4dec1cc..13f810b3ee4 100644 --- a/contracts/utils/access/AccessControl.sol +++ b/contracts/access/AccessControl.sol @@ -2,9 +2,9 @@ pragma solidity ^0.8.0; -import "../Address.sol"; -import "../Context.sol"; -import "../enumerable/EnumerableSet.sol"; +import "../utils/Address.sol"; +import "../utils/Context.sol"; +import "../utils/structs/EnumerableSet.sol"; /** * @dev Contract module that allows children to implement role-based access diff --git a/contracts/utils/access/Ownable.sol b/contracts/access/Ownable.sol similarity index 98% rename from contracts/utils/access/Ownable.sol rename to contracts/access/Ownable.sol index 7938a054ece..bdad22b22e3 100644 --- a/contracts/utils/access/Ownable.sol +++ b/contracts/access/Ownable.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../Context.sol"; +import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to diff --git a/contracts/utils/access/README.adoc b/contracts/access/README.adoc similarity index 100% rename from contracts/utils/access/README.adoc rename to contracts/access/README.adoc diff --git a/contracts/mocks/AccessControlMock.sol b/contracts/mocks/AccessControlMock.sol index 4b28702e2b9..340e2080bcd 100644 --- a/contracts/mocks/AccessControlMock.sol +++ b/contracts/mocks/AccessControlMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../utils/access/AccessControl.sol"; +import "../access/AccessControl.sol"; contract AccessControlMock is AccessControl { constructor() { diff --git a/contracts/mocks/ConditionalEscrowMock.sol b/contracts/mocks/ConditionalEscrowMock.sol index 173bee96fb4..ececf0521d5 100644 --- a/contracts/mocks/ConditionalEscrowMock.sol +++ b/contracts/mocks/ConditionalEscrowMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../utils/payment/escrow/ConditionalEscrow.sol"; +import "../utils/escrow/ConditionalEscrow.sol"; // mock class using ConditionalEscrow contract ConditionalEscrowMock is ConditionalEscrow { diff --git a/contracts/mocks/EnumerableMapMock.sol b/contracts/mocks/EnumerableMapMock.sol index 19a14154e83..bacbf6743e6 100644 --- a/contracts/mocks/EnumerableMapMock.sol +++ b/contracts/mocks/EnumerableMapMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../utils/enumerable/EnumerableMap.sol"; +import "../utils/structs/EnumerableMap.sol"; contract EnumerableMapMock { using EnumerableMap for EnumerableMap.UintToAddressMap; diff --git a/contracts/mocks/EnumerableSetMock.sol b/contracts/mocks/EnumerableSetMock.sol index 83762fc0b19..26f6f60c21f 100644 --- a/contracts/mocks/EnumerableSetMock.sol +++ b/contracts/mocks/EnumerableSetMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../utils/enumerable/EnumerableSet.sol"; +import "../utils/structs/EnumerableSet.sol"; // Bytes32Set contract EnumerableBytes32SetMock { diff --git a/contracts/mocks/OwnableMock.sol b/contracts/mocks/OwnableMock.sol index d2f4476a0e9..4751ed4b700 100644 --- a/contracts/mocks/OwnableMock.sol +++ b/contracts/mocks/OwnableMock.sol @@ -2,6 +2,6 @@ pragma solidity ^0.8.0; -import "../utils/access/Ownable.sol"; +import "../access/Ownable.sol"; contract OwnableMock is Ownable { } diff --git a/contracts/mocks/PausableMock.sol b/contracts/mocks/PausableMock.sol index fb8a1b81fa1..eebc2be4a39 100644 --- a/contracts/mocks/PausableMock.sol +++ b/contracts/mocks/PausableMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../utils/Pausable.sol"; +import "../security/Pausable.sol"; contract PausableMock is Pausable { bool public drasticMeasureTaken; diff --git a/contracts/mocks/PullPaymentMock.sol b/contracts/mocks/PullPaymentMock.sol index 233287397a6..929659da6a3 100644 --- a/contracts/mocks/PullPaymentMock.sol +++ b/contracts/mocks/PullPaymentMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../utils/payment/PullPayment.sol"; +import "../security/PullPayment.sol"; // mock class using PullPayment contract PullPaymentMock is PullPayment { diff --git a/contracts/mocks/ReentrancyMock.sol b/contracts/mocks/ReentrancyMock.sol index 0333e9059b0..c561dbbb9d5 100644 --- a/contracts/mocks/ReentrancyMock.sol +++ b/contracts/mocks/ReentrancyMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../utils/ReentrancyGuard.sol"; +import "../security/ReentrancyGuard.sol"; import "./ReentrancyAttack.sol"; contract ReentrancyMock is ReentrancyGuard { diff --git a/contracts/proxy/beacon/UpgradeableBeacon.sol b/contracts/proxy/beacon/UpgradeableBeacon.sol index 4ae5f309246..aac40d00958 100644 --- a/contracts/proxy/beacon/UpgradeableBeacon.sol +++ b/contracts/proxy/beacon/UpgradeableBeacon.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import "./IBeacon.sol"; -import "../../utils/access/Ownable.sol"; +import "../../access/Ownable.sol"; import "../../utils/Address.sol"; /** diff --git a/contracts/proxy/transparent/ProxyAdmin.sol b/contracts/proxy/transparent/ProxyAdmin.sol index 0ee5b1868b9..f68c9ae0422 100644 --- a/contracts/proxy/transparent/ProxyAdmin.sol +++ b/contracts/proxy/transparent/ProxyAdmin.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import "./TransparentUpgradeableProxy.sol"; -import "../../utils/access/Ownable.sol"; +import "../../access/Ownable.sol"; /** * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an diff --git a/contracts/utils/Pausable.sol b/contracts/security/Pausable.sol similarity index 98% rename from contracts/utils/Pausable.sol rename to contracts/security/Pausable.sol index 9a56f3293ae..dd0db6e6bf1 100644 --- a/contracts/utils/Pausable.sol +++ b/contracts/security/Pausable.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "./Context.sol"; +import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop diff --git a/contracts/utils/payment/PullPayment.sol b/contracts/security/PullPayment.sol similarity index 98% rename from contracts/utils/payment/PullPayment.sol rename to contracts/security/PullPayment.sol index 05617f66d01..bacc6849e2b 100644 --- a/contracts/utils/payment/PullPayment.sol +++ b/contracts/security/PullPayment.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "./escrow/Escrow.sol"; +import "../utils/escrow/Escrow.sol"; /** * @dev Simple implementation of a diff --git a/contracts/utils/ReentrancyGuard.sol b/contracts/security/ReentrancyGuard.sol similarity index 100% rename from contracts/utils/ReentrancyGuard.sol rename to contracts/security/ReentrancyGuard.sol diff --git a/contracts/standalone/TimelockController.sol b/contracts/standalone/TimelockController.sol index a8f31d97bcd..a39cef0089e 100644 --- a/contracts/standalone/TimelockController.sol +++ b/contracts/standalone/TimelockController.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../utils/access/AccessControl.sol"; +import "../access/AccessControl.sol"; /** * @dev Contract module which acts as a timelocked controller. When set as the diff --git a/contracts/token/ERC1155/extensions/ERC1155Pausable.sol b/contracts/token/ERC1155/extensions/ERC1155Pausable.sol index 3716e15c56b..abfae3cfe69 100644 --- a/contracts/token/ERC1155/extensions/ERC1155Pausable.sol +++ b/contracts/token/ERC1155/extensions/ERC1155Pausable.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import "../ERC1155.sol"; -import "../../../utils/Pausable.sol"; +import "../../../security/Pausable.sol"; /** * @dev ERC1155 token with pausable token transfers, minting and burning. diff --git a/contracts/token/ERC1155/presets/ERC1155PresetMinterPauser.sol b/contracts/token/ERC1155/presets/ERC1155PresetMinterPauser.sol index a3353810735..1274cebc735 100644 --- a/contracts/token/ERC1155/presets/ERC1155PresetMinterPauser.sol +++ b/contracts/token/ERC1155/presets/ERC1155PresetMinterPauser.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; import "../ERC1155.sol"; import "../extensions/ERC1155Burnable.sol"; import "../extensions/ERC1155Pausable.sol"; -import "../../../utils/access/AccessControl.sol"; +import "../../../access/AccessControl.sol"; import "../../../utils/Context.sol"; /** diff --git a/contracts/token/ERC20/extensions/ERC20Pausable.sol b/contracts/token/ERC20/extensions/ERC20Pausable.sol index db0a99a6f29..f08656d023a 100644 --- a/contracts/token/ERC20/extensions/ERC20Pausable.sol +++ b/contracts/token/ERC20/extensions/ERC20Pausable.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import "../ERC20.sol"; -import "../../../utils/Pausable.sol"; +import "../../../security/Pausable.sol"; /** * @dev ERC20 token with pausable token transfers, minting and burning. diff --git a/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol b/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol index 346b0b11262..367ae433409 100644 --- a/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol +++ b/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; import "../ERC20.sol"; import "../extensions/ERC20Burnable.sol"; import "../extensions/ERC20Pausable.sol"; -import "../../../utils/access/AccessControl.sol"; +import "../../../access/AccessControl.sol"; import "../../../utils/Context.sol"; /** diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index 057657a9f8f..becbcce2545 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -8,8 +8,8 @@ import "./extensions/IERC721Metadata.sol"; import "./extensions/IERC721Enumerable.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; -import "../../utils/enumerable/EnumerableSet.sol"; -import "../../utils/enumerable/EnumerableMap.sol"; +import "../../utils/structs/EnumerableSet.sol"; +import "../../utils/structs/EnumerableMap.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/ERC165.sol"; diff --git a/contracts/token/ERC721/extensions/ERC721Pausable.sol b/contracts/token/ERC721/extensions/ERC721Pausable.sol index bf21378f693..9f2fabf7bd4 100644 --- a/contracts/token/ERC721/extensions/ERC721Pausable.sol +++ b/contracts/token/ERC721/extensions/ERC721Pausable.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import "../ERC721.sol"; -import "../../../utils/Pausable.sol"; +import "../../../security/Pausable.sol"; /** * @dev ERC721 token with pausable token transfers, minting and burning. diff --git a/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol b/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol index ff33dcca4e4..38e288d17a7 100644 --- a/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol +++ b/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; import "../ERC721.sol"; import "../extensions/ERC721Burnable.sol"; import "../extensions/ERC721Pausable.sol"; -import "../../../utils/access/AccessControl.sol"; +import "../../../access/AccessControl.sol"; import "../../../utils/Context.sol"; import "../../../utils/Counters.sol"; diff --git a/contracts/utils/payment/escrow/ConditionalEscrow.sol b/contracts/utils/escrow/ConditionalEscrow.sol similarity index 100% rename from contracts/utils/payment/escrow/ConditionalEscrow.sol rename to contracts/utils/escrow/ConditionalEscrow.sol diff --git a/contracts/utils/payment/escrow/Escrow.sol b/contracts/utils/escrow/Escrow.sol similarity index 98% rename from contracts/utils/payment/escrow/Escrow.sol rename to contracts/utils/escrow/Escrow.sol index c385bf13fcb..6f236b1896b 100644 --- a/contracts/utils/payment/escrow/Escrow.sol +++ b/contracts/utils/escrow/Escrow.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import "../../access/Ownable.sol"; -import "../../Address.sol"; +import "../Address.sol"; /** * @title Escrow diff --git a/contracts/utils/payment/escrow/RefundEscrow.sol b/contracts/utils/escrow/RefundEscrow.sol similarity index 100% rename from contracts/utils/payment/escrow/RefundEscrow.sol rename to contracts/utils/escrow/RefundEscrow.sol diff --git a/contracts/utils/payment/README.adoc b/contracts/utils/payment/README.adoc deleted file mode 100644 index 7d6151d9067..00000000000 --- a/contracts/utils/payment/README.adoc +++ /dev/null @@ -1,22 +0,0 @@ -= Payment - -[.readme-notice] -NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/payment - -Utilities related to sending and receiving payments. Examples are {PullPayment}, which implements the best security practices when sending funds to third parties, and {PaymentSplitter} to receive incoming payments among a number of beneficiaries. - -TIP: When transferring funds to and from untrusted third parties, there is always a security risk of reentrancy. If you would like to learn more about this and ways to protect against it, check out our blog post https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. - -== Utilities - -{{PaymentSplitter}} - -{{PullPayment}} - -== Escrow - -{{Escrow}} - -{{ConditionalEscrow}} - -{{RefundEscrow}} diff --git a/contracts/utils/enumerable/EnumerableMap.sol b/contracts/utils/structs/EnumerableMap.sol similarity index 100% rename from contracts/utils/enumerable/EnumerableMap.sol rename to contracts/utils/structs/EnumerableMap.sol diff --git a/contracts/utils/enumerable/EnumerableSet.sol b/contracts/utils/structs/EnumerableSet.sol similarity index 100% rename from contracts/utils/enumerable/EnumerableSet.sol rename to contracts/utils/structs/EnumerableSet.sol From cd6a1dd768e83d51f16a1d1ad2196365a7392d8f Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 18 Feb 2021 21:31:35 +0100 Subject: [PATCH 15/31] wave 2.2 of reorg --- contracts/{standalone => governance}/TimelockController.sol | 0 .../{standalone => token/ERC20/utils}/TokenTimelock.sol | 2 +- contracts/{standalone => utils}/PaymentSplitter.sol | 6 +++--- 3 files changed, 4 insertions(+), 4 deletions(-) rename contracts/{standalone => governance}/TimelockController.sol (100%) rename contracts/{standalone => token/ERC20/utils}/TokenTimelock.sol (97%) rename contracts/{standalone => utils}/PaymentSplitter.sol (98%) diff --git a/contracts/standalone/TimelockController.sol b/contracts/governance/TimelockController.sol similarity index 100% rename from contracts/standalone/TimelockController.sol rename to contracts/governance/TimelockController.sol diff --git a/contracts/standalone/TokenTimelock.sol b/contracts/token/ERC20/utils/TokenTimelock.sol similarity index 97% rename from contracts/standalone/TokenTimelock.sol rename to contracts/token/ERC20/utils/TokenTimelock.sol index 062f9dfd78d..ff237142067 100644 --- a/contracts/standalone/TokenTimelock.sol +++ b/contracts/token/ERC20/utils/TokenTimelock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../token/ERC20/utils/SafeERC20.sol"; +import "./SafeERC20.sol"; /** * @dev A token holder contract that will allow a beneficiary to extract the diff --git a/contracts/standalone/PaymentSplitter.sol b/contracts/utils/PaymentSplitter.sol similarity index 98% rename from contracts/standalone/PaymentSplitter.sol rename to contracts/utils/PaymentSplitter.sol index 62a0e92604e..b44faae8905 100644 --- a/contracts/standalone/PaymentSplitter.sol +++ b/contracts/utils/PaymentSplitter.sol @@ -2,9 +2,9 @@ pragma solidity ^0.8.0; -import "../utils/Address.sol"; -import "../utils/Context.sol"; -import "../utils/math/SafeMath.sol"; +import "./Address.sol"; +import "./Context.sol"; +import "./math/SafeMath.sol"; /** * @title PaymentSplitter From b598398355c48c905627b481df363f6e614c3e3b Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 18 Feb 2021 23:45:58 +0100 Subject: [PATCH 16/31] clean & flatten rewrite script --- scripts/replace-in-file/README.md | 476 ------------------ .../replace-in-file/helpers/combine-config.js | 60 --- .../replace-in-file/helpers/error-handler.js | 9 - .../helpers/get-paths-async.js | 26 - .../replace-in-file/helpers/get-paths-sync.js | 42 -- scripts/replace-in-file/helpers/glob-async.js | 34 -- .../replace-in-file/helpers/load-config.js | 23 - .../helpers/make-replacements.js | 75 --- .../replace-in-file/helpers/parse-config.js | 67 --- .../replace-in-file/helpers/replace-async.js | 45 -- .../replace-in-file/helpers/replace-sync.js | 30 -- .../helpers/success-handler.js | 18 - scripts/replace-in-file/index.js | 92 ---- scripts/replace-in-file/version | 1 - scripts/rewrite-imports.js | 68 ++- 15 files changed, 52 insertions(+), 1014 deletions(-) delete mode 100644 scripts/replace-in-file/README.md delete mode 100644 scripts/replace-in-file/helpers/combine-config.js delete mode 100644 scripts/replace-in-file/helpers/error-handler.js delete mode 100644 scripts/replace-in-file/helpers/get-paths-async.js delete mode 100644 scripts/replace-in-file/helpers/get-paths-sync.js delete mode 100644 scripts/replace-in-file/helpers/glob-async.js delete mode 100644 scripts/replace-in-file/helpers/load-config.js delete mode 100644 scripts/replace-in-file/helpers/make-replacements.js delete mode 100644 scripts/replace-in-file/helpers/parse-config.js delete mode 100644 scripts/replace-in-file/helpers/replace-async.js delete mode 100644 scripts/replace-in-file/helpers/replace-sync.js delete mode 100644 scripts/replace-in-file/helpers/success-handler.js delete mode 100644 scripts/replace-in-file/index.js delete mode 100644 scripts/replace-in-file/version diff --git a/scripts/replace-in-file/README.md b/scripts/replace-in-file/README.md deleted file mode 100644 index 0af91453d09..00000000000 --- a/scripts/replace-in-file/README.md +++ /dev/null @@ -1,476 +0,0 @@ -# Replace in file - -[![npm version](https://img.shields.io/npm/v/replace-in-file.svg)](https://www.npmjs.com/package/replace-in-file) -[![node dependencies](https://david-dm.org/adamreisnz/replace-in-file.svg)](https://david-dm.org/adamreisnz/replace-in-file) -[![build status](https://travis-ci.org/adamreisnz/replace-in-file.svg?branch=master)](https://travis-ci.org/adamreisnz/replace-in-file) -[![coverage status](https://coveralls.io/repos/github/adamreisnz/replace-in-file/badge.svg?branch=master)](https://coveralls.io/github/adamreisnz/replace-in-file?branch=master) -[![github issues](https://img.shields.io/github/issues/adamreisnz/replace-in-file.svg)](https://github.com/adamreisnz/replace-in-file/issues) - -A simple utility to quickly replace text in one or more files or globs. Works synchronously or asynchronously with either promises or callbacks. Make a single replacement or multiple replacements at once. - -> Hey there 👋🏼, thank you for using `replace-in-file`! - -> Sorry for the interruption, but as you probably know, I don’t get paid for maintaining this package, and I also haven't put up a donation thingy of any kind. - -> However, I _am_ trying to grow our start-up [Hello Club](https://helloclub.com/?source=npm) internationally, and would _really_ appreciate it if you could have a quick look on our [website](https://helloclub.com/?source=npm) to see what we're all about. 👀 - -> As the name implies, we offer an [all-in-one club and membership management solution](https://helloclub.com/?source=npm) complete with booking system, automated membership renewals, online payments and integrated access and light control. - -> Clubs that have switched to Hello Club have been saving so much time managing their members and finances, and the members themselves really enjoy using it, with overwhelmingly positive feedback. - -> Check us out if you belong to any kind of club or if you know someone who helps run a club! - -> Thank you so much for your time, now go and replace some data in your files! 🎉 - -# Index -- [Installation](#installation) -- [Basic usage](#basic-usage) - - [Asynchronous replacement with `async`/`await`](#asynchronous-replacement-with-asyncawait) - - [Asynchronous replacement with promises](asynchronous-replacement-with-promises) - - [Asynchronous replacement with callback](#asynchronous-replacement-with-callback) - - [Synchronous replacement](#synchronous-replacement) - - [Return value](#return-value) - - [Counting matches and replacements](#counting-matches-and-replacements) -- [Advanced usage](#advanced-usage) - - [Replace a single file or glob](#replace-a-single-file-or-glob) - - [Replace multiple files or globs](#replace-multiple-files-or-globs) - - [Replace first occurrence only](#replace-first-occurrence-only) - - [Replace all occurrences](#replace-all-occurrences) - - [Multiple values with the same replacement](#multiple-values-with-the-same-replacement) - - [Custom regular expressions](#custom-regular-expressions) - - [Multiple values with different replacements](#multiple-values-with-different-replacements) - - [Using callbacks for `from`](#using-callbacks-for-from) - - [Using callbacks for `to`](#using-callbacks-for-to) - - [Ignore a single file or glob](#ignore-a-single-file-or-glob) - - [Ignore multiple files or globs](#ignore-multiple-files-or-globs) - - [Allow empty/invalid paths](#allow-emptyinvalid-paths) - - [Disable globs](#disable-globs) - - [Specify glob configuration](#specify-glob-configuration) - - [Making replacements on network drives](#making-replacements-on-network-drives) - - [Specify character encoding](#specify-character-encoding) - - [Dry run](#dry-run) -- [CLI usage](#cli-usage) -- [A note on using globs with the CLI](#a-note-on-using-globs-with-the-cli) -- [Version information](#version-information) -- [License](#license) - -## Installation -```shell -# Using npm, installing to local project -npm i --save replace-in-file - -# Using npm, installing globally for global cli usage -npm i -g replace-in-file - -# Using yarn -yarn add replace-in-file -``` - -## Basic usage - -```js -//Load the library and specify options -const replace = require('replace-in-file'); -const options = { - files: 'path/to/file', - from: /foo/g, - to: 'bar', -}; -``` - -### Asynchronous replacement with `async`/`await` - -```js -try { - const results = await replace(options) - console.log('Replacement results:', results); -} -catch (error) { - console.error('Error occurred:', error); -} -``` - -### Asynchronous replacement with promises - -```js -replace(options) - .then(results => { - console.log('Replacement results:', results); - }) - .catch(error => { - console.error('Error occurred:', error); - }); -``` - -### Asynchronous replacement with callback - -```js -replace(options, (error, results) => { - if (error) { - return console.error('Error occurred:', error); - } - console.log('Replacement results:', results); -}); -``` - -### Synchronous replacement - -```js -try { - const results = replace.sync(options); - console.log('Replacement results:', results); -} -catch (error) { - console.error('Error occurred:', error); -} -``` - -### Return value - -The return value of the library is an array of replacement results against each file that was processed. This includes files in which no replacements were made. - -Each result contains the following values: - -- `file`: The path to the file that was processed -- `hasChanged`: Flag to indicate if the file was changed or not - -```js -const results = replace.sync({ - files: 'path/to/files/*.html', - from: /foo/g, - to: 'bar', -}); - -console.log(results); - -// [ -// { -// file: 'path/to/files/file1.html', -// hasChanged: true, -// }, -// { -// file: 'path/to/files/file2.html', -// hasChanged: true, -// }, -// { -// file: 'path/to/files/file3.html', -// hasChanged: false, -// }, -// ] - -``` - -To get an array of changed files, simply map the results as follows: - -```js -const changedFiles = results - .filter(result => result.hasChanged) - .map(result => result.file); -``` - -### Counting matches and replacements -By setting the `countMatches` configuration flag to `true`, the number of matches and replacements per file will be counted and present in the results array. - -- `numMatches`: Indicates the number of times a match was found in the file -- `numReplacements`: Indicates the number of times a replacement was made in the file - -Note that the number of matches can be higher than the number of replacements if a match and replacement are the same string. - -```js -const results = replace.sync({ - files: 'path/to/files/*.html', - from: /foo/g, - to: 'bar', - countMatches: true, -}); - -console.log(results); - -// [ -// { -// file: 'path/to/files/file1.html', -// hasChanged: true, -// numMatches: 3, -// numReplacements: 3, -// }, -// { -// file: 'path/to/files/file2.html', -// hasChanged: true, -// numMatches: 1, -// numReplacements: 1, -// }, -// { -// file: 'path/to/files/file3.html', -// hasChanged: false, -// numMatches: 0, -// numReplacements: 0, -// }, -// ] -``` - -## Advanced usage - -### Replace a single file or glob -```js -const options = { - files: 'path/to/file', -}; -``` - -### Replace multiple files or globs - -```js -const options = { - files: [ - 'path/to/file', - 'path/to/other/file', - 'path/to/files/*.html', - 'another/**/*.path', - ], -}; -``` - -### Replace first occurrence only - -```js -const options = { - from: 'foo', - to: 'bar', -}; -``` - -### Replace all occurrences -Please note that the value specified in the `from` parameter is passed straight to the native [String replace method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace). As such, if you pass a string as the `from` parameter, it will _only replace the first occurrence_. - -To replace multiple occurrences at once, you must use a regular expression for the `from` parameter with the global flag enabled, e.g. `/foo/g`. - -```js -const options = { - from: /foo/g, - to: 'bar', -}; -``` - -### Multiple values with the same replacement - -These will be replaced sequentially. - -```js -const options = { - from: [/foo/g, /baz/g], - to: 'bar', -}; -``` - -### Multiple values with different replacements - -These will be replaced sequentially. - -```js -const options = { - from: [/foo/g, /baz/g], - to: ['bar', 'bax'], -}; -``` - -### Custom regular expressions - -Use the [RegExp](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) constructor to create any regular expression. - -```js -const str = 'foo'; -const regex = new RegExp('^' + str + 'bar', 'i'); -const options = { - from: regex, - to: 'bar', -}; -``` - -### Using callbacks for `from` -You can also specify a callback that returns a string or a regular expression. The callback receives the name of the file in which the replacement is being performed, thereby allowing the user to tailor the search string. The following example uses a callback to produce a search string dependent on the filename: - -```js -const options = { - files: 'path/to/file', - from: (file) => new RegExp(file, 'g'), - to: 'bar', -}; -``` - -### Using callbacks for `to` -As the `to` parameter is passed to the native [String replace method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace), you can also specify a callback. The following example uses a callback to convert matching strings to lowercase: - -```js -const options = { - files: 'path/to/file', - from: /SomePattern[A-Za-z-]+/g, - to: (match) => match.toLowerCase(), -}; -``` - -This callback provides for an extra argument above the String replace method, which is the name of the file in which the replacement is being performed. The following example replaces the matched string with the filename: - -```js -const options = { - files: 'path/to/file', - from: /SomePattern[A-Za-z-]+/g, - to: (...args) => args.pop(), -}; -``` - -### Ignore a single file or glob - -```js -const options = { - ignore: 'path/to/ignored/file', -}; -``` - -### Ignore multiple files or globs - -```js -const options = { - ignore: [ - 'path/to/ignored/file', - 'path/to/other/ignored_file', - 'path/to/ignored_files/*.html', - 'another/**/*.ignore', - ], -}; -``` - -Please note that there is an [open issue with Glob](https://github.com/isaacs/node-glob/issues/309) that causes ignored patterns to be ignored when using a `./` prefix in your files glob. To work around this, simply remove the prefix, e.g. use `**/*` instead of `./**/*`. - -### Allow empty/invalid paths -If set to true, empty or invalid paths will fail silently and no error will be thrown. For asynchronous replacement only. Defaults to `false`. - -```js -const options = { - allowEmptyPaths: true, -}; -``` - -### Disable globs -You can disable globs if needed using this flag. Use this when you run into issues with file paths like files like `//SERVER/share/file.txt`. Defaults to `false`. - -```js -const options = { - disableGlobs: true, -}; -``` - -### Specify glob configuration -Specify configuration passed to the [glob](https://www.npmjs.com/package/glob) call: - -```js -const options = { - glob: { - //Glob settings here - }, -}; -``` - -Please note that the setting `nodir` will always be passed as `false`. - -### Making replacements on network drives -To make replacements in files on network drives, you may need to specify the UNC path as the `cwd` config option. This will then be passed to glob and prefixed to your paths accordingly. See [#56](https://github.com/adamreisnz/replace-in-file/issues/56) for more details. - -### Specify character encoding -Use a different character encoding for reading/writing files. Defaults to `utf-8`. - -```js -const options = { - encoding: 'utf8', -}; -``` - -### Dry run -To do a dry run without actually making replacements, for testing purposes. Defaults to `false`. - -```js -const options = { - dry: true, -}; -``` - -## CLI usage - -```sh -replace-in-file from to some/file.js,some/**/glob.js - [--configFile=replace-config.js] - [--ignore=ignore/files.js,ignore/**/glob.js] - [--encoding=utf-8] - [--disableGlobs] - [--isRegex] - [--verbose] - [--quiet] - [--dry] -``` - -Multiple files or globs can be replaced by providing a comma separated list. - -The flags `--disableGlobs`, `--ignore` and `--encoding` are supported in the CLI. - -The setting `allowEmptyPaths` is not supported in the CLI as the replacement is -synchronous, and this setting is only relevant for asynchronous replacement. - -To list the changed files, use the `--verbose` flag. Success output can be suppressed by using the `--quiet` flag. - -To do a dry run without making any actual changes, use `--dry`. - -A regular expression may be used for the `from` parameter by specifying the `--isRegex` flag. - -The `from` and `to` parameters, as well as the files list, can be omitted if you provide this -information in a configuration file. You can provide a path to a configuration file -(either Javascript or JSON) with the `--configFile` flag. This path will be resolved using -Node’s built in `path.resolve()`, so you can pass in an absolute or relative path. - -## A note on using globs with the CLI -When using the CLI, the glob pattern is handled by the operating system. But if you specify the glob pattern in the configuration file, the package will use the glob module from the Node modules, and this can lead to different behaviour despite using the same pattern. - -For example, the following will only look at top level files: - -```js -//config.js -module.exports = { - from: /cat/g, - to: 'dog', -}; -``` - -```sh -replace-in-file ** --configFile=config.js -``` - -However, this example is recursive: - -```js -//config.js -module.exports = { - files: '**', - from: /cat/g, - to: 'dog', -}; -``` - -```sh -replace-in-file --configFile=config.js -``` - -If you want to do a recursive file search as an argument you must use: - -```sh -replace-in-file $(ls l {,**/}*) --configFile=config.js -``` - -## Version information -From version 3.0.0 onwards, replace in file requires Node 6 or higher. If you need support for Node 4 or 5, please use version 2.x.x. - -From version 5.0.0 onwards, replace in file requires Node 8 or higher. If you need support for Node 6, please use version 4.x.x. - -See the [Changelog](CHANGELOG.md) for more information. - -## License -(MIT License) - -Copyright 2015-2020, Adam Reis, Co-founder at [Hello Club](https://helloclub.com/?source=npm) diff --git a/scripts/replace-in-file/helpers/combine-config.js b/scripts/replace-in-file/helpers/combine-config.js deleted file mode 100644 index ddf8f8ee6f3..00000000000 --- a/scripts/replace-in-file/helpers/combine-config.js +++ /dev/null @@ -1,60 +0,0 @@ -'use strict'; - -/** - * Dependencies - */ -const parseConfig = require('./parse-config'); - -/** - * Combine CLI script arguments with config options - */ -module.exports = function combineConfig(config, argv) { - - //Extract options from config - let { - from, to, files, ignore, encoding, verbose, - allowEmptyPaths, disableGlobs, isRegex, dry, quiet, - } = config; - - //Get from/to parameters from CLI args if not defined in options - if (typeof from === 'undefined') { - from = argv._.shift(); - } - if (typeof to === 'undefined') { - to = argv._.shift(); - } - - //Get files and ignored files - if (typeof files === 'undefined') { - files = argv._; - } - if (typeof ignore === 'undefined' && typeof argv.ignore !== 'undefined') { - ignore = argv.ignore; - } - - //Other parameters - if (typeof encoding === 'undefined') { - encoding = argv.encoding; - } - if (typeof disableGlobs === 'undefined') { - disableGlobs = !!argv.disableGlobs; - } - if (typeof isRegex === 'undefined') { - isRegex = !!argv.isRegex; - } - if (typeof verbose === 'undefined') { - verbose = !!argv.verbose; - } - if (typeof dry === 'undefined') { - dry = !!argv.dry; - } - if (typeof quiet === 'undefined') { - quiet = !!argv.quiet; - } - - //Return through parser to validate - return parseConfig({ - from, to, files, ignore, encoding, verbose, - allowEmptyPaths, disableGlobs, isRegex, dry, quiet, - }); -}; diff --git a/scripts/replace-in-file/helpers/error-handler.js b/scripts/replace-in-file/helpers/error-handler.js deleted file mode 100644 index 6c80213fa0a..00000000000 --- a/scripts/replace-in-file/helpers/error-handler.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; - -/** - * Error handler - */ -module.exports = function errorHandler(error, exitCode = 1) { - console.error(error); - process.exit(exitCode); -}; diff --git a/scripts/replace-in-file/helpers/get-paths-async.js b/scripts/replace-in-file/helpers/get-paths-async.js deleted file mode 100644 index 83cfe4312be..00000000000 --- a/scripts/replace-in-file/helpers/get-paths-async.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -/** - * Dependencies - */ -const globAsync = require('./glob-async'); - -/** - * Get paths asynchrously - */ -module.exports = function getPathsAsync(patterns, config) { - - //Extract relevant config - const {ignore, disableGlobs, allowEmptyPaths, glob: cfg} = config; - - //Not using globs? - if (disableGlobs) { - return Promise.resolve(patterns); - } - - //Expand globs and flatten paths - return Promise - .all(patterns - .map(pattern => globAsync(pattern, ignore, allowEmptyPaths, cfg))) - .then(paths => [].concat.apply([], paths)); -}; diff --git a/scripts/replace-in-file/helpers/get-paths-sync.js b/scripts/replace-in-file/helpers/get-paths-sync.js deleted file mode 100644 index a3f3440dabd..00000000000 --- a/scripts/replace-in-file/helpers/get-paths-sync.js +++ /dev/null @@ -1,42 +0,0 @@ -'use strict'; - -/** - * Dependencies - */ -const glob = require('glob'); - -/** - * Get paths (sync) - */ -module.exports = function getPathsSync(patterns, config) { - - //Extract relevant config - const {ignore, disableGlobs, glob: globConfig, cwd} = config; - - //Not using globs? - if (disableGlobs) { - return patterns; - } - - //Prepare glob config - const cfg = Object.assign({ignore}, globConfig, {nodir: true}); - - //Append CWD configuration if given (#56) - //istanbul ignore if - if (cwd) { - cfg.cwd = cwd; - } - - //Get paths - const paths = patterns.map(pattern => glob.sync(pattern, cfg)); - const flattened = [].concat.apply([], paths); - - //Prefix each path with CWD if given (#56) - //istanbul ignore if - if (cwd) { - return flattened.map(path => `${cwd}${path}`); - } - - //Return flattened - return flattened; -}; diff --git a/scripts/replace-in-file/helpers/glob-async.js b/scripts/replace-in-file/helpers/glob-async.js deleted file mode 100644 index 792ddadc6e5..00000000000 --- a/scripts/replace-in-file/helpers/glob-async.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict'; - -/** - * Dependencies - */ -const glob = require('glob'); - -/** - * Async wrapper for glob - */ -module.exports = function globAsync(pattern, ignore, allowEmptyPaths, cfg) { - - //Prepare glob config - cfg = Object.assign({ignore}, cfg, {nodir: true}); - - //Return promise - return new Promise((resolve, reject) => { - glob(pattern, cfg, (error, files) => { - - //istanbul ignore if: hard to make glob error - if (error) { - return reject(error); - } - - //Error if no files match, unless allowed - if (!allowEmptyPaths && files.length === 0) { - return reject(new Error('No files match the pattern: ' + pattern)); - } - - //Resolve - resolve(files); - }); - }); -}; diff --git a/scripts/replace-in-file/helpers/load-config.js b/scripts/replace-in-file/helpers/load-config.js deleted file mode 100644 index cc190c19e49..00000000000 --- a/scripts/replace-in-file/helpers/load-config.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; - -/** - * Dependencies - */ -const path = require('path'); - -/** - * Helper to load options from a config file - */ -module.exports = function loadConfig(file) { - - //No config file provided? - if (!file) { - return {}; - } - - //Resolve path - file = path.resolve(file); - - //Try to load - return require(file); -}; diff --git a/scripts/replace-in-file/helpers/make-replacements.js b/scripts/replace-in-file/helpers/make-replacements.js deleted file mode 100644 index 0876d7b821c..00000000000 --- a/scripts/replace-in-file/helpers/make-replacements.js +++ /dev/null @@ -1,75 +0,0 @@ -'use strict'; - -/** - * Get replacement helper - */ -function getReplacement(replace, isArray, i) { - if (isArray && typeof replace[i] === 'undefined') { - return null; - } - if (isArray) { - return replace[i]; - } - return replace; -} - -/** - * Helper to make replacements - */ -module.exports = function makeReplacements(contents, from, to, file, count) { - - //Turn into array - if (!Array.isArray(from)) { - from = [from]; - } - - //Check if replace value is an array and prepare result - const isArray = Array.isArray(to); - const result = {file}; - - //Counting? Initialize number of matches - if (count) { - result.numMatches = 0; - result.numReplacements = 0; - } - - //Make replacements - const newContents = from.reduce((contents, item, i) => { - - //Call function if given, passing in the filename - if (typeof item === 'function') { - item = item(file); - } - - //Get replacement value - let replacement = getReplacement(to, isArray, i); - if (replacement === null) { - return contents; - } - - //Call function if given, appending the filename - if (typeof replacement === 'function') { - const original = replacement; - replacement = (...args) => original(...args, file); - } - - //Count matches - if (count) { - const matches = contents.match(item); - if (matches) { - const replacements = matches.filter(match => match !== replacement); - result.numMatches += matches.length; - result.numReplacements += replacements.length; - } - } - - //Make replacement - return contents.replace(item, replacement); - }, contents); - - //Check if changed - result.hasChanged = (newContents !== contents); - - //Return result and new contents - return [result, newContents]; -}; diff --git a/scripts/replace-in-file/helpers/parse-config.js b/scripts/replace-in-file/helpers/parse-config.js deleted file mode 100644 index 41d87a12694..00000000000 --- a/scripts/replace-in-file/helpers/parse-config.js +++ /dev/null @@ -1,67 +0,0 @@ -'use strict'; - -/** - * Defaults - */ -const defaults = { - ignore: [], - encoding: 'utf-8', - disableGlobs: false, - allowEmptyPaths: false, - countMatches: false, - isRegex: false, - verbose: false, - quiet: false, - dry: false, - glob: {}, - cwd: null, -}; - -/** - * Parse config - */ -module.exports = function parseConfig(config) { - - //Validate config - if (typeof config !== 'object' || config === null) { - throw new Error('Must specify configuration object'); - } - - //Fix glob - config.glob = config.glob || {}; - - //Extract data - const {files, from, to, ignore, encoding} = config; - - //Validate values - if (typeof files === 'undefined') { - throw new Error('Must specify file or files'); - } - if (typeof from === 'undefined') { - throw new Error('Must specify string or regex to replace'); - } - if (typeof to === 'undefined') { - throw new Error('Must specify a replacement (can be blank string)'); - } - - //Ensure arrays - if (!Array.isArray(files)) { - config.files = [files]; - } - if (!Array.isArray(ignore)) { - if (typeof ignore === 'undefined') { - config.ignore = []; - } - else { - config.ignore = [ignore]; - } - } - - //Use default encoding if invalid - if (typeof encoding !== 'string' || encoding === '') { - config.encoding = 'utf-8'; - } - - //Merge config with defaults - return Object.assign({}, defaults, config); -}; diff --git a/scripts/replace-in-file/helpers/replace-async.js b/scripts/replace-in-file/helpers/replace-async.js deleted file mode 100644 index 5167d4bfc75..00000000000 --- a/scripts/replace-in-file/helpers/replace-async.js +++ /dev/null @@ -1,45 +0,0 @@ -'use strict'; - -/** - * Dependencies - */ -const fs = require('fs'); -const makeReplacements = require('./make-replacements'); - -/** - * Helper to replace in a single file (async) - */ -module.exports = function replaceAsync(file, from, to, config) { - - //Extract relevant config - const {encoding, dry, countMatches} = config; - - //Wrap in promise - return new Promise((resolve, reject) => { - fs.readFile(file, encoding, (error, contents) => { - //istanbul ignore if - if (error) { - return reject(error); - } - - //Make replacements - const [result, newContents] = makeReplacements( - contents, from, to, file, countMatches - ); - - //Not changed or dry run? - if (!result.hasChanged || dry) { - return resolve(result); - } - - //Write to file - fs.writeFile(file, newContents, encoding, error => { - //istanbul ignore if - if (error) { - return reject(error); - } - resolve(result); - }); - }); - }); -}; diff --git a/scripts/replace-in-file/helpers/replace-sync.js b/scripts/replace-in-file/helpers/replace-sync.js deleted file mode 100644 index ada3519fdf8..00000000000 --- a/scripts/replace-in-file/helpers/replace-sync.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; - -/** - * Dependencies - */ -const fs = require('fs'); -const makeReplacements = require('./make-replacements'); - -/** - * Helper to replace in a single file (sync) - */ -module.exports = function replaceSync(file, from, to, config) { - - //Extract relevant config and read file contents - const {encoding, dry, countMatches} = config; - const contents = fs.readFileSync(file, encoding); - - //Replace contents and check if anything changed - const [result, newContents] = makeReplacements( - contents, from, to, file, countMatches - ); - - //Contents changed and not a dry run? Write to file - if (result.hasChanged && !dry) { - fs.writeFileSync(file, newContents, encoding); - } - - //Return result - return result; -}; diff --git a/scripts/replace-in-file/helpers/success-handler.js b/scripts/replace-in-file/helpers/success-handler.js deleted file mode 100644 index cc526204148..00000000000 --- a/scripts/replace-in-file/helpers/success-handler.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; - -/** - * Success handler - */ -module.exports = function successHandler(results, verbose) { - const changed = results.filter(result => result.hasChanged); - const numChanges = changed.length; - if (numChanges > 0) { - console.log(`${numChanges} file(s) were changed`); - if (verbose) { - changed.forEach(result => console.log('-', result.file)); - } - } - else { - console.log('No files were changed'); - } -}; diff --git a/scripts/replace-in-file/index.js b/scripts/replace-in-file/index.js deleted file mode 100644 index 0394579e394..00000000000 --- a/scripts/replace-in-file/index.js +++ /dev/null @@ -1,92 +0,0 @@ -'use strict'; - -/** - * Dependencies - */ -const parseConfig = require('./helpers/parse-config'); -const getPathsSync = require('./helpers/get-paths-sync'); -const getPathsAsync = require('./helpers/get-paths-async'); -const replaceSync = require('./helpers/replace-sync'); -const replaceAsync = require('./helpers/replace-async'); - -/** - * Replace in file helper - */ -function replaceInFile(config, cb) { - - //Parse config - try { - config = parseConfig(config); - } - catch (error) { - if (typeof cb === 'function') { - return cb(error, null); - } - return Promise.reject(error); - } - - //Get config - const {files, from, to, dry, verbose} = config; - - //Dry run? - //istanbul ignore if: No need to test console logs - if (dry && verbose) { - console.log('Dry run, not making actual changes'); - } - - //Find paths - return getPathsAsync(files, config) - - //Make replacements - .then(paths => Promise.all( - paths.map(file => replaceAsync(file, from, to, config)) - )) - - //Success handler - .then(results => { - if (typeof cb === 'function') { - cb(null, results); - } - return results; - }) - - //Error handler - .catch(error => { - if (typeof cb === 'function') { - cb(error); - } - else { - throw error; - } - }); -} - -/** - * Sync API - */ -function replaceInFileSync(config) { - - //Parse config - config = parseConfig(config); - - //Get config, paths, and initialize changed files - const {files, from, to, dry, verbose} = config; - const paths = getPathsSync(files, config); - - //Dry run? - //istanbul ignore if: No need to test console logs - if (dry && verbose) { - console.log('Dry run, not making actual changes'); - } - - //Process synchronously and return results - return paths.map(path => replaceSync(path, from, to, config)); -} - -// Self-reference to support named import -replaceInFile.replaceInFile = replaceInFile; -replaceInFile.replaceInFileSync = replaceInFileSync; -replaceInFile.sync = replaceInFileSync; - -//Export -module.exports = replaceInFile; diff --git a/scripts/replace-in-file/version b/scripts/replace-in-file/version deleted file mode 100644 index 6abaeb2f907..00000000000 --- a/scripts/replace-in-file/version +++ /dev/null @@ -1 +0,0 @@ -6.2.0 diff --git a/scripts/rewrite-imports.js b/scripts/rewrite-imports.js index fd8c2c16016..e7e4ab24c60 100644 --- a/scripts/rewrite-imports.js +++ b/scripts/rewrite-imports.js @@ -1,14 +1,8 @@ -'use strict'; - -// const debug = require('debug'); const fs = require('fs'); +const glob = require('glob'); const path = require('path'); -// const replace = require('replace-in-file'); -const replace = require('./replace-in-file') -const successHandler = require('./replace-in-file/helpers/success-handler') const versions = [ - '', '@openzeppelin/contracts', '@openzeppelin/contracts-upgradeable', ]; @@ -97,19 +91,61 @@ const updates = { 'utils/Strings.sol': undefined, }; +const globAsync = (pattern) => + new Promise((resolve, reject) => { + glob(pattern, (error, files) => error ? reject(error) : resolve(files)); + }); + +const getPathsAsync = (patterns) => + Promise.all(patterns.map(globAsync)).then(paths => [].concat.apply([], paths)); + +const replaceAsync = (file, from, to, encoding = 'utf-8') => + new Promise((resolve, reject) => { + fs.readFile(file, encoding, (error, contents) => { + if (error) { + return reject(error); + } + + const newContents = from.reduce((contents, item, i) => contents.replace(item, to[i]), contents); + + if (contents === newContents) { + return resolve({ file, hasChanged: false }); + } + + fs.writeFile(file, newContents, encoding, error => error ? reject(error) : resolve({ file, hasChanged: true })); + }); + }); + +const replaceInFiles = (files, from, to) => + getPathsAsync(files) + .then(paths => Promise.all(paths.map(file => replaceAsync(file, from, to)))) + .then(results => { + return results; + }) + .catch(error => { + throw error; + }); + (async () => { - // debug('rewrite-migration')('started'); - const results = await replace({ - files: (process.argv.length > 2 ? process.argv.slice(2) : [ 'contracts' ]) + const results = await replaceInFiles( + /* files */ + (process.argv.length > 2 ? process.argv.slice(2) : [ 'contracts' ]) .map(file => fs.statSync(file).isDirectory() ? path.join(file, '**', '*.sol') : file), - from: Object.entries(updates) + /* from */ + Object.entries(updates) .filter(([ from, to ]) => to) .flatMap(([ from, to ]) => versions.map(version => path.join(version, from))), - to: Object.entries(updates) + /* to */ + Object.entries(updates) .filter(([ from, to ]) => to) .flatMap(([ from, to ]) => versions.map(version => path.join(version, to))), - }); - successHandler(results, true); - // results.filter(({ hasChanged }) => hasChanged).forEach(({ file }) => debug('rewrite-migration:updated')(file)); - // debug('rewrite-migration')('finished'); + ); + + const changed = results.filter(result => result.hasChanged); + if (changed.length) { + console.log(`${changed.length} file(s) were changed`); + changed.forEach(result => console.log('-', result.file)); + } else { + console.log('No files were changed'); + } })().catch(console.error); From 23ce7b7a6d4cb63d15cd377e147e7afbe21c7f5a Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Fri, 19 Feb 2021 01:45:55 +0100 Subject: [PATCH 17/31] update rewrite mapping --- scripts/rewrite-imports.js | 54 +++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/scripts/rewrite-imports.js b/scripts/rewrite-imports.js index e7e4ab24c60..3ba57152233 100644 --- a/scripts/rewrite-imports.js +++ b/scripts/rewrite-imports.js @@ -8,20 +8,20 @@ const versions = [ ]; const updates = { - 'access/AccessControl.sol': 'utils/access/AccessControl.sol', - 'access/Ownable.sol': 'utils/access/Ownable.sol', - 'access/TimelockController.sol': 'standalone/TimelockController.sol', + 'access/AccessControl.sol': undefined, + 'access/Ownable.sol': undefined, + 'access/TimelockController.sol': 'governance/TimelockController.sol', 'cryptography/ECDSA.sol': 'utils/cryptography/ECDSA.sol', 'cryptography/MerkleProof.sol': 'utils/cryptography/MerkleProof.sol', - 'drafts/EIP712.sol': 'utils/drafts-EIP712.sol', - 'drafts/ERC20Permit.sol': 'tokens/ERC20/extensions/draft-ERC20Permit.sol', - 'drafts/IERC20Permit.sol': 'tokens/ERC20/extensions/draft-IERC20Permit.sol', + 'drafts/EIP712.sol': 'utils/cryptography/draft-EIP712.sol', + 'drafts/ERC20Permit.sol': 'token/ERC20/extensions/draft-ERC20Permit.sol', + 'drafts/IERC20Permit.sol': 'token/ERC20/extensions/draft-IERC20Permit.sol', 'GSN/Context.sol': 'utils/Context.sol', - 'GSN/GSNRecipientERC20Fee.sol': 'utils/GSN/GSNRecipientERC20Fee.sol', - 'GSN/GSNRecipientSignature.sol': 'utils/GSN/GSNRecipientSignature.sol', - 'GSN/GSNRecipient.sol': 'utils/GSN/GSNRecipient.sol', - 'GSN/IRelayHub.sol': 'utils/GSN/IRelayHub.sol', - 'GSN/IRelayRecipient.sol': 'utils/GSN/IRelayRecipient.sol', + 'GSN/GSNRecipientERC20Fee.sol': undefined, + 'GSN/GSNRecipientSignature.sol': undefined, + 'GSN/GSNRecipient.sol': undefined, + 'GSN/IRelayHub.sol': undefined, + 'GSN/IRelayRecipient.sol': undefined, 'introspection/ERC165Checker.sol': 'utils/introspection/ERC165Checker.sol', 'introspection/ERC165.sol': 'utils/introspection/ERC165.sol', 'introspection/ERC1820Implementer.sol': 'utils/introspection/ERC1820Implementer.sol', @@ -31,16 +31,16 @@ const updates = { 'math/Math.sol': 'utils/math/Math.sol', 'math/SafeMath.sol': 'utils/math/SafeMath.sol', 'math/SignedSafeMath.sol': 'utils/math/SignedSafeMath.sol', - 'payment/escrow/ConditionalEscrow.sol': 'utils/payment/escrow/ConditionalEscrow.sol', - 'payment/escrow/Escrow.sol': 'utils/payment/escrow/Escrow.sol', - 'payment/escrow/RefundEscrow.sol': 'utils/payment/escrow/RefundEscrow.sol', - 'payment/PaymentSplitter.sol': 'standalone/PaymentSplitter.sol', - 'payment/PullPayment.sol': 'utils/payment/PullPayment.sol', - 'presets/ERC1155PresetMinterPauser.sol': 'tokens/ERC1155/presets/ERC1155PresetMinterPauser.sol', - 'presets/ERC20PresetFixedSupply.sol': 'tokens/ERC20/presets/ERC20PresetFixedSupply.sol', - 'presets/ERC20PresetMinterPauser.sol': 'tokens/ERC20/presets/ERC20PresetMinterPauser.sol', - 'presets/ERC721PresetMinterPauserAutoId.sol': 'tokens/ERC721/presets/ERC721PresetMinterPauserAutoId.sol', - 'presets/ERC777PresetFixedSupply.sol': 'tokens/ERC777/presets/ERC777PresetFixedSupply.sol', + 'payment/escrow/ConditionalEscrow.sol': 'utils/escrow/ConditionalEscrow.sol', + 'payment/escrow/Escrow.sol': 'utils/escrow/Escrow.sol', + 'payment/escrow/RefundEscrow.sol': 'utils/escrow/RefundEscrow.sol', + 'payment/PaymentSplitter.sol': 'utils/PaymentSplitter.sol', + 'payment/PullPayment.sol': 'security/PullPayment.sol', + 'presets/ERC1155PresetMinterPauser.sol': 'token/ERC1155/presets/ERC1155PresetMinterPauser.sol', + 'presets/ERC20PresetFixedSupply.sol': 'token/ERC20/presets/ERC20PresetFixedSupply.sol', + 'presets/ERC20PresetMinterPauser.sol': 'token/ERC20/presets/ERC20PresetMinterPauser.sol', + 'presets/ERC721PresetMinterPauserAutoId.sol': 'token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol', + 'presets/ERC777PresetFixedSupply.sol': 'token/ERC777/presets/ERC777PresetFixedSupply.sol', 'proxy/BeaconProxy.sol': 'proxy/beacon/BeaconProxy.sol', 'proxy/Clones.sol': undefined, 'proxy/IBeacon.sol': 'proxy/beacon/IBeacon.sol', @@ -65,7 +65,7 @@ const updates = { 'token/ERC20/ERC20.sol': undefined, 'token/ERC20/IERC20.sol': undefined, 'token/ERC20/SafeERC20.sol': 'token/ERC20/utils/SafeERC20.sol', - 'token/ERC20/TokenTimelock.sol': 'standalone/TokenTimelock.sol', + 'token/ERC20/TokenTimelock.sol': 'token/ERC20/utils//TokenTimelock.sol', 'token/ERC721/ERC721Burnable.sol': 'token/ERC721/extensions/ERC721Burnable.sol', 'token/ERC721/ERC721Holder.sol': 'token/ERC721/utils/ERC721Holder.sol', 'token/ERC721/ERC721Pausable.sol': 'token/ERC721/extensions/ERC721Pausable.sol', @@ -83,11 +83,11 @@ const updates = { 'utils/Context.sol': undefined, 'utils/Counters.sol': undefined, 'utils/Create2.sol': undefined, - 'utils/EnumerableMap.sol': 'utils/enumerable/EnumerableMap.sol', - 'utils/EnumerableSet.sol': 'utils/enumerable/EnumerableSet.sol', - 'utils/Pausable.sol': undefined, - 'utils/ReentrancyGuard.sol': undefined, - 'utils/SafeCast.sol': undefined, + 'utils/EnumerableMap.sol': 'utils/structs/EnumerableMap.sol', + 'utils/EnumerableSet.sol': 'utils/structs/EnumerableSet.sol', + 'utils/Pausable.sol': 'security/Pausable.sol', + 'utils/ReentrancyGuard.sol': 'security/ReentrancyGuard.sol', + 'utils/SafeCast.sol': 'utils/math/SafeCast.sol', 'utils/Strings.sol': undefined, }; From 0d71a30c821386b15f5af4aa664f990682cca293 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Thu, 18 Feb 2021 22:57:14 -0300 Subject: [PATCH 18/31] remove dependencies from rewrite-imports --- scripts/rewrite-imports.js | 157 ++++++++++++++++++++----------------- 1 file changed, 84 insertions(+), 73 deletions(-) diff --git a/scripts/rewrite-imports.js b/scripts/rewrite-imports.js index 3ba57152233..504b6003199 100644 --- a/scripts/rewrite-imports.js +++ b/scripts/rewrite-imports.js @@ -1,5 +1,4 @@ -const fs = require('fs'); -const glob = require('glob'); +const { promises: fs } = require('fs'); const path = require('path'); const versions = [ @@ -7,7 +6,7 @@ const versions = [ '@openzeppelin/contracts-upgradeable', ]; -const updates = { +const pathUpdates = { 'access/AccessControl.sol': undefined, 'access/Ownable.sol': undefined, 'access/TimelockController.sol': 'governance/TimelockController.sol', @@ -42,110 +41,122 @@ const updates = { 'presets/ERC721PresetMinterPauserAutoId.sol': 'token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol', 'presets/ERC777PresetFixedSupply.sol': 'token/ERC777/presets/ERC777PresetFixedSupply.sol', 'proxy/BeaconProxy.sol': 'proxy/beacon/BeaconProxy.sol', - 'proxy/Clones.sol': undefined, + // 'proxy/Clones.sol': undefined, 'proxy/IBeacon.sol': 'proxy/beacon/IBeacon.sol', 'proxy/Initializable.sol': 'utils/Initializable.sol', 'proxy/ProxyAdmin.sol': 'proxy/transparent/ProxyAdmin.sol', - 'proxy/Proxy.sol': undefined, + // 'proxy/Proxy.sol': undefined, 'proxy/TransparentUpgradeableProxy.sol': 'proxy/transparent/TransparentUpgradeableProxy.sol', 'proxy/UpgradeableBeacon.sol': 'proxy/beacon/UpgradeableBeacon.sol', - 'proxy/UpgradeableProxy.sol': undefined, + // 'proxy/UpgradeableProxy.sol': undefined, 'token/ERC1155/ERC1155Burnable.sol': 'token/ERC1155/extensions/ERC1155Burnable.sol', 'token/ERC1155/ERC1155Holder.sol': 'token/ERC1155/utils/ERC1155Holder.sol', 'token/ERC1155/ERC1155Pausable.sol': 'token/ERC1155/extensions/ERC1155Pausable.sol', 'token/ERC1155/ERC1155Receiver.sol': 'token/ERC1155/utils/ERC1155Receiver.sol', - 'token/ERC1155/ERC1155.sol': undefined, + // 'token/ERC1155/ERC1155.sol': undefined, 'token/ERC1155/IERC1155MetadataURI.sol': 'token/ERC1155/extensions/IERC1155MetadataURI.sol', - 'token/ERC1155/IERC1155Receiver.sol': undefined, - 'token/ERC1155/IERC1155.sol': undefined, + // 'token/ERC1155/IERC1155Receiver.sol': undefined, + // 'token/ERC1155/IERC1155.sol': undefined, 'token/ERC20/ERC20Burnable.sol': 'token/ERC20/extensions/ERC20Burnable.sol', 'token/ERC20/ERC20Capped.sol': 'token/ERC20/extensions/ERC20Capped.sol', 'token/ERC20/ERC20Pausable.sol': 'token/ERC20/extensions/ERC20Pausable.sol', 'token/ERC20/ERC20Snapshot.sol': 'token/ERC20/extensions/ERC20Snapshot.sol', - 'token/ERC20/ERC20.sol': undefined, - 'token/ERC20/IERC20.sol': undefined, + // 'token/ERC20/ERC20.sol': undefined, + // 'token/ERC20/IERC20.sol': undefined, 'token/ERC20/SafeERC20.sol': 'token/ERC20/utils/SafeERC20.sol', 'token/ERC20/TokenTimelock.sol': 'token/ERC20/utils//TokenTimelock.sol', 'token/ERC721/ERC721Burnable.sol': 'token/ERC721/extensions/ERC721Burnable.sol', 'token/ERC721/ERC721Holder.sol': 'token/ERC721/utils/ERC721Holder.sol', 'token/ERC721/ERC721Pausable.sol': 'token/ERC721/extensions/ERC721Pausable.sol', - 'token/ERC721/ERC721.sol': undefined, + // 'token/ERC721/ERC721.sol': undefined, 'token/ERC721/IERC721Enumerable.sol': 'token/ERC721/extensions/IERC721Enumerable.sol', 'token/ERC721/IERC721Metadata.sol': 'token/ERC721/extensions/IERC721Metadata.sol', - 'token/ERC721/IERC721Receiver.sol': undefined, - 'token/ERC721/IERC721.sol': undefined, - 'token/ERC777/ERC777.sol': undefined, - 'token/ERC777/IERC777Recipient.sol': undefined, - 'token/ERC777/IERC777Sender.sol': undefined, - 'token/ERC777/IERC777.sol': undefined, - 'utils/Address.sol': undefined, - 'utils/Arrays.sol': undefined, - 'utils/Context.sol': undefined, - 'utils/Counters.sol': undefined, - 'utils/Create2.sol': undefined, + // 'token/ERC721/IERC721Receiver.sol': undefined, + // 'token/ERC721/IERC721.sol': undefined, + // 'token/ERC777/ERC777.sol': undefined, + // 'token/ERC777/IERC777Recipient.sol': undefined, + // 'token/ERC777/IERC777Sender.sol': undefined, + // 'token/ERC777/IERC777.sol': undefined, + // 'utils/Address.sol': undefined, + // 'utils/Arrays.sol': undefined, + // 'utils/Context.sol': undefined, + // 'utils/Counters.sol': undefined, + // 'utils/Create2.sol': undefined, 'utils/EnumerableMap.sol': 'utils/structs/EnumerableMap.sol', 'utils/EnumerableSet.sol': 'utils/structs/EnumerableSet.sol', 'utils/Pausable.sol': 'security/Pausable.sol', 'utils/ReentrancyGuard.sol': 'security/ReentrancyGuard.sol', 'utils/SafeCast.sol': 'utils/math/SafeCast.sol', - 'utils/Strings.sol': undefined, + // 'utils/Strings.sol': undefined, }; -const globAsync = (pattern) => - new Promise((resolve, reject) => { - glob(pattern, (error, files) => error ? reject(error) : resolve(files)); - }); +async function main () { + const files = await listFilesRecursively('contracts'); + const solidityFiles = files.filter(f => f.match(/\.sol$/)); -const getPathsAsync = (patterns) => - Promise.all(patterns.map(globAsync)).then(paths => [].concat.apply([], paths)); + const updatedFiles = []; -const replaceAsync = (file, from, to, encoding = 'utf-8') => - new Promise((resolve, reject) => { - fs.readFile(file, encoding, (error, contents) => { - if (error) { - return reject(error); - } - - const newContents = from.reduce((contents, item, i) => contents.replace(item, to[i]), contents); + for (const file of solidityFiles) { + const updated = await updateFile(file, updateImportPaths); + if (updated) { + updatedFiles.push(file); + } + } - if (contents === newContents) { - return resolve({ file, hasChanged: false }); - } + if (updatedFiles.length > 0) { + console.log(`${updatedFiles.length} file(s) were updated`); + for (const c of updatedFiles) { + console.log('-', c); + } + } else { + console.log('No files were updated'); + } +} - fs.writeFile(file, newContents, encoding, error => error ? reject(error) : resolve({ file, hasChanged: true })); - }); - }); +async function listFilesRecursively (dir) { + const queue = [dir]; + const files = []; -const replaceInFiles = (files, from, to) => - getPathsAsync(files) - .then(paths => Promise.all(paths.map(file => replaceAsync(file, from, to)))) - .then(results => { - return results; - }) - .catch(error => { - throw error; - }); + while (queue.length > 0) { + const top = queue.shift(); + for (const e of await fs.readdir(top, { withFileTypes: true })) { + const p = path.join(top, e.name); + if (e.isDirectory()) { + queue.push(p); + } else if (e.isFile()) { + files.push(p); + } + } + } -(async () => { - const results = await replaceInFiles( - /* files */ - (process.argv.length > 2 ? process.argv.slice(2) : [ 'contracts' ]) - .map(file => fs.statSync(file).isDirectory() ? path.join(file, '**', '*.sol') : file), - /* from */ - Object.entries(updates) - .filter(([ from, to ]) => to) - .flatMap(([ from, to ]) => versions.map(version => path.join(version, from))), - /* to */ - Object.entries(updates) - .filter(([ from, to ]) => to) - .flatMap(([ from, to ]) => versions.map(version => path.join(version, to))), - ); + return files; +} - const changed = results.filter(result => result.hasChanged); - if (changed.length) { - console.log(`${changed.length} file(s) were changed`); - changed.forEach(result => console.log('-', result.file)); +async function updateFile (file, update) { + const content = await fs.readFile(file, 'utf8'); + const updatedContent = update(content); + if (updatedContent !== content) { + await fs.writeFile(file, updatedContent); + return true; } else { - console.log('No files were changed'); + return false; + } +} + +function updateImportPaths (source) { + for (const [oldPath, newPath] of Object.entries(pathUpdates)) { + for (const ver of versions) { + source = source.replace( + ver + '/' + oldPath, + ver + '/' + newPath, + ); + } } -})().catch(console.error); + + return source; +} + +main().catch(e => { + console.error(e); + process.exit(1); +}); From 4bb064f5901a7d5a4906af5de7afbf45c1377663 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Fri, 19 Feb 2021 10:55:29 +0100 Subject: [PATCH 19/31] support files & dirs as args in rewrite-import.js --- scripts/rewrite-imports.js | 50 +++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/scripts/rewrite-imports.js b/scripts/rewrite-imports.js index 504b6003199..998395cc7b2 100644 --- a/scripts/rewrite-imports.js +++ b/scripts/rewrite-imports.js @@ -7,8 +7,8 @@ const versions = [ ]; const pathUpdates = { - 'access/AccessControl.sol': undefined, - 'access/Ownable.sol': undefined, + // 'access/AccessControl.sol': undefined, + // 'access/Ownable.sol': undefined, 'access/TimelockController.sol': 'governance/TimelockController.sol', 'cryptography/ECDSA.sol': 'utils/cryptography/ECDSA.sol', 'cryptography/MerkleProof.sol': 'utils/cryptography/MerkleProof.sol', @@ -16,11 +16,11 @@ const pathUpdates = { 'drafts/ERC20Permit.sol': 'token/ERC20/extensions/draft-ERC20Permit.sol', 'drafts/IERC20Permit.sol': 'token/ERC20/extensions/draft-IERC20Permit.sol', 'GSN/Context.sol': 'utils/Context.sol', - 'GSN/GSNRecipientERC20Fee.sol': undefined, - 'GSN/GSNRecipientSignature.sol': undefined, - 'GSN/GSNRecipient.sol': undefined, - 'GSN/IRelayHub.sol': undefined, - 'GSN/IRelayRecipient.sol': undefined, + // 'GSN/GSNRecipientERC20Fee.sol': undefined, + // 'GSN/GSNRecipientSignature.sol': undefined, + // 'GSN/GSNRecipient.sol': undefined, + // 'GSN/IRelayHub.sol': undefined, + // 'GSN/IRelayRecipient.sol': undefined, 'introspection/ERC165Checker.sol': 'utils/introspection/ERC165Checker.sol', 'introspection/ERC165.sol': 'utils/introspection/ERC165.sol', 'introspection/ERC1820Implementer.sol': 'utils/introspection/ERC1820Implementer.sol', @@ -91,14 +91,12 @@ const pathUpdates = { }; async function main () { - const files = await listFilesRecursively('contracts'); - const solidityFiles = files.filter(f => f.match(/\.sol$/)); + const paths = process.argv.length > 2 ? process.argv.slice(2) : [ 'contracts' ]; + const files = await listFilesRecursively(paths, /\.sol$/); const updatedFiles = []; - - for (const file of solidityFiles) { - const updated = await updateFile(file, updateImportPaths); - if (updated) { + for (const file of files) { + if (await updateFile(file, updateImportPaths)) { updatedFiles.push(file); } } @@ -113,18 +111,20 @@ async function main () { } } -async function listFilesRecursively (dir) { - const queue = [dir]; +async function listFilesRecursively (paths, filter = undefined) { + const queue = Array.isArray(paths) ? paths : [ paths ]; const files = []; while (queue.length > 0) { const top = queue.shift(); - for (const e of await fs.readdir(top, { withFileTypes: true })) { - const p = path.join(top, e.name); - if (e.isDirectory()) { - queue.push(p); - } else if (e.isFile()) { - files.push(p); + const stat = await fs.stat(top); + if (stat.isFile()) { + if (!filter || top.match(filter)) { + files.push(top); + } + } else if (stat.isDirectory()) { + for (const name of await fs.readdir(top)) { + queue.push(path.join(top, name)); } } } @@ -144,11 +144,11 @@ async function updateFile (file, update) { } function updateImportPaths (source) { - for (const [oldPath, newPath] of Object.entries(pathUpdates)) { - for (const ver of versions) { + for (const [ oldPath, newPath ] of Object.entries(pathUpdates)) { + for (const version of versions) { source = source.replace( - ver + '/' + oldPath, - ver + '/' + newPath, + path.join(version, oldPath), + path.join(version, newPath), ); } } From d1fc5a2de319c13e184c1a17f7424c9dd793ad97 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Fri, 19 Feb 2021 14:51:16 +0100 Subject: [PATCH 20/31] fix merging error --- contracts/mocks/ERC1155ReceiverMock.sol | 2 +- contracts/mocks/ERC165StorageMock.sol | 2 +- contracts/{ => utils}/introspection/ERC165Storage.sol | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename contracts/{ => utils}/introspection/ERC165Storage.sol (100%) diff --git a/contracts/mocks/ERC1155ReceiverMock.sol b/contracts/mocks/ERC1155ReceiverMock.sol index c3a60d6b94b..a8babdc0d63 100644 --- a/contracts/mocks/ERC1155ReceiverMock.sol +++ b/contracts/mocks/ERC1155ReceiverMock.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.0; -import "../introspection/ERC165.sol"; import "../token/ERC1155/IERC1155Receiver.sol"; +import "../utils/introspection/ERC165.sol"; contract ERC1155ReceiverMock is IERC1155Receiver, ERC165 { bytes4 private _recRetval; diff --git a/contracts/mocks/ERC165StorageMock.sol b/contracts/mocks/ERC165StorageMock.sol index 36262d37d3c..4b0bae90865 100644 --- a/contracts/mocks/ERC165StorageMock.sol +++ b/contracts/mocks/ERC165StorageMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "../introspection/ERC165Storage.sol"; +import "../utils/introspection/ERC165Storage.sol"; contract ERC165StorageMock is ERC165Storage { function registerInterface(bytes4 interfaceId) public { diff --git a/contracts/introspection/ERC165Storage.sol b/contracts/utils/introspection/ERC165Storage.sol similarity index 100% rename from contracts/introspection/ERC165Storage.sol rename to contracts/utils/introspection/ERC165Storage.sol From 7bc8eb472a57d4e585f6d687a4bb169606605395 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Fri, 19 Feb 2021 15:05:16 +0100 Subject: [PATCH 21/31] reorganize tests according to the new contract structure --- test/{standalone => governance}/TimelockController.test.js | 0 test/proxy/{ => beacon}/BeaconProxy.test.js | 0 test/proxy/{ => beacon}/UpgradeableBeacon.test.js | 0 .../{ => transparent}/TransparentUpgradeableProxy.behaviour.js | 0 .../proxy/{ => transparent}/TransparentUpgradeableProxy.test.js | 2 +- test/{utils => security}/Pausable.test.js | 0 test/{payment => security}/PullPayment.test.js | 0 test/{utils => security}/ReentrancyGuard.test.js | 0 test/token/ERC1155/ERC1155.behavior.js | 2 +- test/token/ERC1155/{ => extensions}/ERC1155Burnable.test.js | 0 test/token/ERC1155/{ => extensions}/ERC1155Pausable.test.js | 0 .../ERC1155}/presets/ERC1155PresetMinterPauser.test.js | 0 test/token/ERC1155/{ => utils}/ERC1155Holder.test.js | 2 +- .../ERC20/{behaviors => extensions}/ERC20Burnable.behavior.js | 0 test/token/ERC20/{ => extensions}/ERC20Burnable.test.js | 2 +- .../ERC20/{behaviors => extensions}/ERC20Capped.behavior.js | 0 test/token/ERC20/{ => extensions}/ERC20Capped.test.js | 2 +- test/token/ERC20/{ => extensions}/ERC20Pausable.test.js | 0 test/token/ERC20/{ => extensions}/ERC20Snapshot.test.js | 0 .../ERC20/extensions/draft-ERC20Permit.test.js} | 2 +- test/{ => token/ERC20}/presets/ERC20PresetFixedSupply.test.js | 0 test/{ => token/ERC20}/presets/ERC20PresetMinterPauser.test.js | 0 test/token/ERC20/{ => utils}/SafeERC20.test.js | 0 test/{standalone => token/ERC20/utils}/TokenTimelock.test.js | 0 test/token/ERC721/ERC721.test.js | 2 +- test/token/ERC721/{ => extensions}/ERC721Burnable.test.js | 0 test/token/ERC721/{ => extensions}/ERC721Pausable.test.js | 0 .../ERC721}/presets/ERC721PresetMinterPauserAutoId.test.js | 0 test/token/ERC721/{ => utils}/ERC721Holder.test.js | 0 test/{ => token/ERC777}/presets/ERC777PresetFixedSupply.test.js | 0 test/{proxy => utils}/Initializable.test.js | 0 test/{standalone => utils}/PaymentSplitter.test.js | 0 test/{ => utils}/cryptography/ECDSA.test.js | 2 +- test/{ => utils}/cryptography/MerkleProof.test.js | 2 +- .../EIP712.test.js => utils/cryptography/draft-EIP712.test.js} | 2 +- test/{payment => utils}/escrow/ConditionalEscrow.test.js | 0 test/{payment => utils}/escrow/Escrow.behavior.js | 0 test/{payment => utils}/escrow/Escrow.test.js | 0 test/{payment => utils}/escrow/RefundEscrow.test.js | 0 test/{ => utils}/introspection/ERC165.test.js | 0 test/{ => utils}/introspection/ERC165Checker.test.js | 0 test/{ => utils}/introspection/ERC165Storage.test.js | 0 test/{ => utils}/introspection/ERC1820Implementer.test.js | 0 test/{ => utils}/introspection/SupportsInterface.behavior.js | 0 test/{ => utils}/math/Math.test.js | 0 test/utils/{ => math}/SafeCast.test.js | 0 test/{ => utils}/math/SafeMath.test.js | 0 test/{ => utils}/math/SignedSafeMath.test.js | 0 test/utils/{ => structs}/EnumerableMap.test.js | 0 test/utils/{ => structs}/EnumerableSet.behavior.js | 0 test/utils/{ => structs}/EnumerableSet.test.js | 0 51 files changed, 10 insertions(+), 10 deletions(-) rename test/{standalone => governance}/TimelockController.test.js (100%) rename test/proxy/{ => beacon}/BeaconProxy.test.js (100%) rename test/proxy/{ => beacon}/UpgradeableBeacon.test.js (100%) rename test/proxy/{ => transparent}/TransparentUpgradeableProxy.behaviour.js (100%) rename test/proxy/{ => transparent}/TransparentUpgradeableProxy.test.js (88%) rename test/{utils => security}/Pausable.test.js (100%) rename test/{payment => security}/PullPayment.test.js (100%) rename test/{utils => security}/ReentrancyGuard.test.js (100%) rename test/token/ERC1155/{ => extensions}/ERC1155Burnable.test.js (100%) rename test/token/ERC1155/{ => extensions}/ERC1155Pausable.test.js (100%) rename test/{ => token/ERC1155}/presets/ERC1155PresetMinterPauser.test.js (100%) rename test/token/ERC1155/{ => utils}/ERC1155Holder.test.js (95%) rename test/token/ERC20/{behaviors => extensions}/ERC20Burnable.behavior.js (100%) rename test/token/ERC20/{ => extensions}/ERC20Burnable.test.js (85%) rename test/token/ERC20/{behaviors => extensions}/ERC20Capped.behavior.js (100%) rename test/token/ERC20/{ => extensions}/ERC20Capped.test.js (89%) rename test/token/ERC20/{ => extensions}/ERC20Pausable.test.js (100%) rename test/token/ERC20/{ => extensions}/ERC20Snapshot.test.js (100%) rename test/{drafts/ERC20Permit.test.js => token/ERC20/extensions/draft-ERC20Permit.test.js} (98%) rename test/{ => token/ERC20}/presets/ERC20PresetFixedSupply.test.js (100%) rename test/{ => token/ERC20}/presets/ERC20PresetMinterPauser.test.js (100%) rename test/token/ERC20/{ => utils}/SafeERC20.test.js (100%) rename test/{standalone => token/ERC20/utils}/TokenTimelock.test.js (100%) rename test/token/ERC721/{ => extensions}/ERC721Burnable.test.js (100%) rename test/token/ERC721/{ => extensions}/ERC721Pausable.test.js (100%) rename test/{ => token/ERC721}/presets/ERC721PresetMinterPauserAutoId.test.js (100%) rename test/token/ERC721/{ => utils}/ERC721Holder.test.js (100%) rename test/{ => token/ERC777}/presets/ERC777PresetFixedSupply.test.js (100%) rename test/{proxy => utils}/Initializable.test.js (100%) rename test/{standalone => utils}/PaymentSplitter.test.js (100%) rename test/{ => utils}/cryptography/ECDSA.test.js (98%) rename test/{ => utils}/cryptography/MerkleProof.test.js (96%) rename test/{drafts/EIP712.test.js => utils/cryptography/draft-EIP712.test.js} (95%) rename test/{payment => utils}/escrow/ConditionalEscrow.test.js (100%) rename test/{payment => utils}/escrow/Escrow.behavior.js (100%) rename test/{payment => utils}/escrow/Escrow.test.js (100%) rename test/{payment => utils}/escrow/RefundEscrow.test.js (100%) rename test/{ => utils}/introspection/ERC165.test.js (100%) rename test/{ => utils}/introspection/ERC165Checker.test.js (100%) rename test/{ => utils}/introspection/ERC165Storage.test.js (100%) rename test/{ => utils}/introspection/ERC1820Implementer.test.js (100%) rename test/{ => utils}/introspection/SupportsInterface.behavior.js (100%) rename test/{ => utils}/math/Math.test.js (100%) rename test/utils/{ => math}/SafeCast.test.js (100%) rename test/{ => utils}/math/SafeMath.test.js (100%) rename test/{ => utils}/math/SignedSafeMath.test.js (100%) rename test/utils/{ => structs}/EnumerableMap.test.js (100%) rename test/utils/{ => structs}/EnumerableSet.behavior.js (100%) rename test/utils/{ => structs}/EnumerableSet.test.js (100%) diff --git a/test/standalone/TimelockController.test.js b/test/governance/TimelockController.test.js similarity index 100% rename from test/standalone/TimelockController.test.js rename to test/governance/TimelockController.test.js diff --git a/test/proxy/BeaconProxy.test.js b/test/proxy/beacon/BeaconProxy.test.js similarity index 100% rename from test/proxy/BeaconProxy.test.js rename to test/proxy/beacon/BeaconProxy.test.js diff --git a/test/proxy/UpgradeableBeacon.test.js b/test/proxy/beacon/UpgradeableBeacon.test.js similarity index 100% rename from test/proxy/UpgradeableBeacon.test.js rename to test/proxy/beacon/UpgradeableBeacon.test.js diff --git a/test/proxy/TransparentUpgradeableProxy.behaviour.js b/test/proxy/transparent/TransparentUpgradeableProxy.behaviour.js similarity index 100% rename from test/proxy/TransparentUpgradeableProxy.behaviour.js rename to test/proxy/transparent/TransparentUpgradeableProxy.behaviour.js diff --git a/test/proxy/TransparentUpgradeableProxy.test.js b/test/proxy/transparent/TransparentUpgradeableProxy.test.js similarity index 88% rename from test/proxy/TransparentUpgradeableProxy.test.js rename to test/proxy/transparent/TransparentUpgradeableProxy.test.js index 984fb2c063a..cf8206996bc 100644 --- a/test/proxy/TransparentUpgradeableProxy.test.js +++ b/test/proxy/transparent/TransparentUpgradeableProxy.test.js @@ -1,4 +1,4 @@ -const shouldBehaveLikeUpgradeableProxy = require('./UpgradeableProxy.behaviour'); +const shouldBehaveLikeUpgradeableProxy = require('../UpgradeableProxy.behaviour'); const shouldBehaveLikeTransparentUpgradeableProxy = require('./TransparentUpgradeableProxy.behaviour'); const TransparentUpgradeableProxy = artifacts.require('TransparentUpgradeableProxy'); diff --git a/test/utils/Pausable.test.js b/test/security/Pausable.test.js similarity index 100% rename from test/utils/Pausable.test.js rename to test/security/Pausable.test.js diff --git a/test/payment/PullPayment.test.js b/test/security/PullPayment.test.js similarity index 100% rename from test/payment/PullPayment.test.js rename to test/security/PullPayment.test.js diff --git a/test/utils/ReentrancyGuard.test.js b/test/security/ReentrancyGuard.test.js similarity index 100% rename from test/utils/ReentrancyGuard.test.js rename to test/security/ReentrancyGuard.test.js diff --git a/test/token/ERC1155/ERC1155.behavior.js b/test/token/ERC1155/ERC1155.behavior.js index 62fc9f7b94e..13b08ac638c 100644 --- a/test/token/ERC1155/ERC1155.behavior.js +++ b/test/token/ERC1155/ERC1155.behavior.js @@ -3,7 +3,7 @@ const { ZERO_ADDRESS } = constants; const { expect } = require('chai'); -const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior'); +const { shouldSupportInterfaces } = require('../../utils/introspection/SupportsInterface.behavior'); const ERC1155ReceiverMock = artifacts.require('ERC1155ReceiverMock'); diff --git a/test/token/ERC1155/ERC1155Burnable.test.js b/test/token/ERC1155/extensions/ERC1155Burnable.test.js similarity index 100% rename from test/token/ERC1155/ERC1155Burnable.test.js rename to test/token/ERC1155/extensions/ERC1155Burnable.test.js diff --git a/test/token/ERC1155/ERC1155Pausable.test.js b/test/token/ERC1155/extensions/ERC1155Pausable.test.js similarity index 100% rename from test/token/ERC1155/ERC1155Pausable.test.js rename to test/token/ERC1155/extensions/ERC1155Pausable.test.js diff --git a/test/presets/ERC1155PresetMinterPauser.test.js b/test/token/ERC1155/presets/ERC1155PresetMinterPauser.test.js similarity index 100% rename from test/presets/ERC1155PresetMinterPauser.test.js rename to test/token/ERC1155/presets/ERC1155PresetMinterPauser.test.js diff --git a/test/token/ERC1155/ERC1155Holder.test.js b/test/token/ERC1155/utils/ERC1155Holder.test.js similarity index 95% rename from test/token/ERC1155/ERC1155Holder.test.js rename to test/token/ERC1155/utils/ERC1155Holder.test.js index 957061e4bd2..41225c23823 100644 --- a/test/token/ERC1155/ERC1155Holder.test.js +++ b/test/token/ERC1155/utils/ERC1155Holder.test.js @@ -5,7 +5,7 @@ const ERC1155Mock = artifacts.require('ERC1155Mock'); const { expect } = require('chai'); -const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior'); +const { shouldSupportInterfaces } = require('../../../utils/introspection/SupportsInterface.behavior'); contract('ERC1155Holder', function (accounts) { const [creator] = accounts; diff --git a/test/token/ERC20/behaviors/ERC20Burnable.behavior.js b/test/token/ERC20/extensions/ERC20Burnable.behavior.js similarity index 100% rename from test/token/ERC20/behaviors/ERC20Burnable.behavior.js rename to test/token/ERC20/extensions/ERC20Burnable.behavior.js diff --git a/test/token/ERC20/ERC20Burnable.test.js b/test/token/ERC20/extensions/ERC20Burnable.test.js similarity index 85% rename from test/token/ERC20/ERC20Burnable.test.js rename to test/token/ERC20/extensions/ERC20Burnable.test.js index 11631a7e023..8aa4fb66c5c 100644 --- a/test/token/ERC20/ERC20Burnable.test.js +++ b/test/token/ERC20/extensions/ERC20Burnable.test.js @@ -1,6 +1,6 @@ const { BN } = require('@openzeppelin/test-helpers'); -const { shouldBehaveLikeERC20Burnable } = require('./behaviors/ERC20Burnable.behavior'); +const { shouldBehaveLikeERC20Burnable } = require('./ERC20Burnable.behavior'); const ERC20BurnableMock = artifacts.require('ERC20BurnableMock'); contract('ERC20Burnable', function (accounts) { diff --git a/test/token/ERC20/behaviors/ERC20Capped.behavior.js b/test/token/ERC20/extensions/ERC20Capped.behavior.js similarity index 100% rename from test/token/ERC20/behaviors/ERC20Capped.behavior.js rename to test/token/ERC20/extensions/ERC20Capped.behavior.js diff --git a/test/token/ERC20/ERC20Capped.test.js b/test/token/ERC20/extensions/ERC20Capped.test.js similarity index 89% rename from test/token/ERC20/ERC20Capped.test.js rename to test/token/ERC20/extensions/ERC20Capped.test.js index 3b7e75e3e59..76532cefd8f 100644 --- a/test/token/ERC20/ERC20Capped.test.js +++ b/test/token/ERC20/extensions/ERC20Capped.test.js @@ -1,5 +1,5 @@ const { BN, ether, expectRevert } = require('@openzeppelin/test-helpers'); -const { shouldBehaveLikeERC20Capped } = require('./behaviors/ERC20Capped.behavior'); +const { shouldBehaveLikeERC20Capped } = require('./ERC20Capped.behavior'); const ERC20Capped = artifacts.require('ERC20CappedMock'); diff --git a/test/token/ERC20/ERC20Pausable.test.js b/test/token/ERC20/extensions/ERC20Pausable.test.js similarity index 100% rename from test/token/ERC20/ERC20Pausable.test.js rename to test/token/ERC20/extensions/ERC20Pausable.test.js diff --git a/test/token/ERC20/ERC20Snapshot.test.js b/test/token/ERC20/extensions/ERC20Snapshot.test.js similarity index 100% rename from test/token/ERC20/ERC20Snapshot.test.js rename to test/token/ERC20/extensions/ERC20Snapshot.test.js diff --git a/test/drafts/ERC20Permit.test.js b/test/token/ERC20/extensions/draft-ERC20Permit.test.js similarity index 98% rename from test/drafts/ERC20Permit.test.js rename to test/token/ERC20/extensions/draft-ERC20Permit.test.js index 2ba38e37c3c..9aa64456110 100644 --- a/test/drafts/ERC20Permit.test.js +++ b/test/token/ERC20/extensions/draft-ERC20Permit.test.js @@ -10,7 +10,7 @@ const Wallet = require('ethereumjs-wallet').default; const ERC20PermitMock = artifacts.require('ERC20PermitMock'); -const { EIP712Domain, domainSeparator } = require('../helpers/eip712'); +const { EIP712Domain, domainSeparator } = require('../../../helpers/eip712'); const Permit = [ { name: 'owner', type: 'address' }, diff --git a/test/presets/ERC20PresetFixedSupply.test.js b/test/token/ERC20/presets/ERC20PresetFixedSupply.test.js similarity index 100% rename from test/presets/ERC20PresetFixedSupply.test.js rename to test/token/ERC20/presets/ERC20PresetFixedSupply.test.js diff --git a/test/presets/ERC20PresetMinterPauser.test.js b/test/token/ERC20/presets/ERC20PresetMinterPauser.test.js similarity index 100% rename from test/presets/ERC20PresetMinterPauser.test.js rename to test/token/ERC20/presets/ERC20PresetMinterPauser.test.js diff --git a/test/token/ERC20/SafeERC20.test.js b/test/token/ERC20/utils/SafeERC20.test.js similarity index 100% rename from test/token/ERC20/SafeERC20.test.js rename to test/token/ERC20/utils/SafeERC20.test.js diff --git a/test/standalone/TokenTimelock.test.js b/test/token/ERC20/utils/TokenTimelock.test.js similarity index 100% rename from test/standalone/TokenTimelock.test.js rename to test/token/ERC20/utils/TokenTimelock.test.js diff --git a/test/token/ERC721/ERC721.test.js b/test/token/ERC721/ERC721.test.js index d3d585429bd..8aeb94d9b0f 100644 --- a/test/token/ERC721/ERC721.test.js +++ b/test/token/ERC721/ERC721.test.js @@ -3,7 +3,7 @@ const { ZERO_ADDRESS } = constants; const { expect } = require('chai'); -const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior'); +const { shouldSupportInterfaces } = require('../../utils/introspection/SupportsInterface.behavior'); const ERC721Mock = artifacts.require('ERC721Mock'); const ERC721ReceiverMock = artifacts.require('ERC721ReceiverMock'); diff --git a/test/token/ERC721/ERC721Burnable.test.js b/test/token/ERC721/extensions/ERC721Burnable.test.js similarity index 100% rename from test/token/ERC721/ERC721Burnable.test.js rename to test/token/ERC721/extensions/ERC721Burnable.test.js diff --git a/test/token/ERC721/ERC721Pausable.test.js b/test/token/ERC721/extensions/ERC721Pausable.test.js similarity index 100% rename from test/token/ERC721/ERC721Pausable.test.js rename to test/token/ERC721/extensions/ERC721Pausable.test.js diff --git a/test/presets/ERC721PresetMinterPauserAutoId.test.js b/test/token/ERC721/presets/ERC721PresetMinterPauserAutoId.test.js similarity index 100% rename from test/presets/ERC721PresetMinterPauserAutoId.test.js rename to test/token/ERC721/presets/ERC721PresetMinterPauserAutoId.test.js diff --git a/test/token/ERC721/ERC721Holder.test.js b/test/token/ERC721/utils/ERC721Holder.test.js similarity index 100% rename from test/token/ERC721/ERC721Holder.test.js rename to test/token/ERC721/utils/ERC721Holder.test.js diff --git a/test/presets/ERC777PresetFixedSupply.test.js b/test/token/ERC777/presets/ERC777PresetFixedSupply.test.js similarity index 100% rename from test/presets/ERC777PresetFixedSupply.test.js rename to test/token/ERC777/presets/ERC777PresetFixedSupply.test.js diff --git a/test/proxy/Initializable.test.js b/test/utils/Initializable.test.js similarity index 100% rename from test/proxy/Initializable.test.js rename to test/utils/Initializable.test.js diff --git a/test/standalone/PaymentSplitter.test.js b/test/utils/PaymentSplitter.test.js similarity index 100% rename from test/standalone/PaymentSplitter.test.js rename to test/utils/PaymentSplitter.test.js diff --git a/test/cryptography/ECDSA.test.js b/test/utils/cryptography/ECDSA.test.js similarity index 98% rename from test/cryptography/ECDSA.test.js rename to test/utils/cryptography/ECDSA.test.js index 4a360a8a301..9062b6913f9 100644 --- a/test/cryptography/ECDSA.test.js +++ b/test/utils/cryptography/ECDSA.test.js @@ -1,5 +1,5 @@ const { expectRevert } = require('@openzeppelin/test-helpers'); -const { toEthSignedMessageHash, fixSignature } = require('../helpers/sign'); +const { toEthSignedMessageHash, fixSignature } = require('../../helpers/sign'); const { expect } = require('chai'); diff --git a/test/cryptography/MerkleProof.test.js b/test/utils/cryptography/MerkleProof.test.js similarity index 96% rename from test/cryptography/MerkleProof.test.js rename to test/utils/cryptography/MerkleProof.test.js index 9c6e65b899b..0ef5b3b08e9 100644 --- a/test/cryptography/MerkleProof.test.js +++ b/test/utils/cryptography/MerkleProof.test.js @@ -1,6 +1,6 @@ require('@openzeppelin/test-helpers'); -const { MerkleTree } = require('../helpers/merkleTree.js'); +const { MerkleTree } = require('../../helpers/merkleTree.js'); const { keccakFromString, bufferToHex } = require('ethereumjs-util'); const { expect } = require('chai'); diff --git a/test/drafts/EIP712.test.js b/test/utils/cryptography/draft-EIP712.test.js similarity index 95% rename from test/drafts/EIP712.test.js rename to test/utils/cryptography/draft-EIP712.test.js index ef7a55e766a..9e26a87c6d2 100644 --- a/test/drafts/EIP712.test.js +++ b/test/utils/cryptography/draft-EIP712.test.js @@ -1,7 +1,7 @@ const ethSigUtil = require('eth-sig-util'); const Wallet = require('ethereumjs-wallet').default; -const { EIP712Domain, domainSeparator } = require('../helpers/eip712'); +const { EIP712Domain, domainSeparator } = require('../../helpers/eip712'); const EIP712 = artifacts.require('EIP712External'); diff --git a/test/payment/escrow/ConditionalEscrow.test.js b/test/utils/escrow/ConditionalEscrow.test.js similarity index 100% rename from test/payment/escrow/ConditionalEscrow.test.js rename to test/utils/escrow/ConditionalEscrow.test.js diff --git a/test/payment/escrow/Escrow.behavior.js b/test/utils/escrow/Escrow.behavior.js similarity index 100% rename from test/payment/escrow/Escrow.behavior.js rename to test/utils/escrow/Escrow.behavior.js diff --git a/test/payment/escrow/Escrow.test.js b/test/utils/escrow/Escrow.test.js similarity index 100% rename from test/payment/escrow/Escrow.test.js rename to test/utils/escrow/Escrow.test.js diff --git a/test/payment/escrow/RefundEscrow.test.js b/test/utils/escrow/RefundEscrow.test.js similarity index 100% rename from test/payment/escrow/RefundEscrow.test.js rename to test/utils/escrow/RefundEscrow.test.js diff --git a/test/introspection/ERC165.test.js b/test/utils/introspection/ERC165.test.js similarity index 100% rename from test/introspection/ERC165.test.js rename to test/utils/introspection/ERC165.test.js diff --git a/test/introspection/ERC165Checker.test.js b/test/utils/introspection/ERC165Checker.test.js similarity index 100% rename from test/introspection/ERC165Checker.test.js rename to test/utils/introspection/ERC165Checker.test.js diff --git a/test/introspection/ERC165Storage.test.js b/test/utils/introspection/ERC165Storage.test.js similarity index 100% rename from test/introspection/ERC165Storage.test.js rename to test/utils/introspection/ERC165Storage.test.js diff --git a/test/introspection/ERC1820Implementer.test.js b/test/utils/introspection/ERC1820Implementer.test.js similarity index 100% rename from test/introspection/ERC1820Implementer.test.js rename to test/utils/introspection/ERC1820Implementer.test.js diff --git a/test/introspection/SupportsInterface.behavior.js b/test/utils/introspection/SupportsInterface.behavior.js similarity index 100% rename from test/introspection/SupportsInterface.behavior.js rename to test/utils/introspection/SupportsInterface.behavior.js diff --git a/test/math/Math.test.js b/test/utils/math/Math.test.js similarity index 100% rename from test/math/Math.test.js rename to test/utils/math/Math.test.js diff --git a/test/utils/SafeCast.test.js b/test/utils/math/SafeCast.test.js similarity index 100% rename from test/utils/SafeCast.test.js rename to test/utils/math/SafeCast.test.js diff --git a/test/math/SafeMath.test.js b/test/utils/math/SafeMath.test.js similarity index 100% rename from test/math/SafeMath.test.js rename to test/utils/math/SafeMath.test.js diff --git a/test/math/SignedSafeMath.test.js b/test/utils/math/SignedSafeMath.test.js similarity index 100% rename from test/math/SignedSafeMath.test.js rename to test/utils/math/SignedSafeMath.test.js diff --git a/test/utils/EnumerableMap.test.js b/test/utils/structs/EnumerableMap.test.js similarity index 100% rename from test/utils/EnumerableMap.test.js rename to test/utils/structs/EnumerableMap.test.js diff --git a/test/utils/EnumerableSet.behavior.js b/test/utils/structs/EnumerableSet.behavior.js similarity index 100% rename from test/utils/EnumerableSet.behavior.js rename to test/utils/structs/EnumerableSet.behavior.js diff --git a/test/utils/EnumerableSet.test.js b/test/utils/structs/EnumerableSet.test.js similarity index 100% rename from test/utils/EnumerableSet.test.js rename to test/utils/structs/EnumerableSet.test.js From afb97b6f6b1c05b0ebe0794ce6a44e6c90e5388c Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Fri, 19 Feb 2021 18:49:39 +0100 Subject: [PATCH 22/31] refactor rewrite-import.js to be usage as a js module --- package.json | 3 +++ scripts/rewrite-imports.js | 18 ++++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) mode change 100644 => 100755 scripts/rewrite-imports.js diff --git a/package.json b/package.json index fa558cabdb3..7c74a50d525 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,9 @@ "!/contracts/mocks", "/test/behaviors" ], + "bin": { + "rewrite-imports": "scripts/rewrite-imports.js" + }, "scripts": { "compile": "hardhat compile", "coverage": "hardhat coverage", diff --git a/scripts/rewrite-imports.js b/scripts/rewrite-imports.js old mode 100644 new mode 100755 index 998395cc7b2..d554a820e11 --- a/scripts/rewrite-imports.js +++ b/scripts/rewrite-imports.js @@ -1,3 +1,5 @@ +#!/usr/bin/env node + const { promises: fs } = require('fs'); const path = require('path'); @@ -90,8 +92,7 @@ const pathUpdates = { // 'utils/Strings.sol': undefined, }; -async function main () { - const paths = process.argv.length > 2 ? process.argv.slice(2) : [ 'contracts' ]; +async function main (paths = [ 'contracts' ]) { const files = await listFilesRecursively(paths, /\.sol$/); const updatedFiles = []; @@ -156,7 +157,12 @@ function updateImportPaths (source) { return source; } -main().catch(e => { - console.error(e); - process.exit(1); -}); +module.exports = main; + +if (require.main === module) { + const args = process.argv.length > 2 ? process.argv.slice(2) : undefined; + main(args).catch(e => { + console.error(e); + process.exit(1); + }); +} From e8fd5db88c553541cc2742f7a15c7e4ce6619288 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Fri, 19 Feb 2021 19:05:02 +0100 Subject: [PATCH 23/31] fix npm pack --- scripts/prepack.sh | 2 +- scripts/remove-ignored-artifacts.js | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/scripts/prepack.sh b/scripts/prepack.sh index bc4f7a24977..adecce2a2bd 100755 --- a/scripts/prepack.sh +++ b/scripts/prepack.sh @@ -5,6 +5,6 @@ set -euo pipefail # cross platform `mkdir -p` node -e 'fs.mkdirSync("build/contracts", { recursive: true })' -cp artifacts/*.json build/contracts +cp artifacts/**/*.json build/contracts node scripts/remove-ignored-artifacts.js diff --git a/scripts/remove-ignored-artifacts.js b/scripts/remove-ignored-artifacts.js index 8c013deccc4..c29e68a4258 100644 --- a/scripts/remove-ignored-artifacts.js +++ b/scripts/remove-ignored-artifacts.js @@ -23,7 +23,12 @@ const ignorePatternsSubtrees = ignorePatterns .concat(ignorePatterns.map(pat => path.join(pat, '**/*'))) .map(p => p.replace(/^\//, '')); -const solcOutput = readJSON('cache/solc-output.json'); +const buildinfo = 'artifacts/build-info'; +const filenames = fs.readdirSync(buildinfo); +if (filenames.length !== 1) { + throw new Error(`There should only be one file in ${buildinfo}`); +} +const solcOutput = readJSON(path.join(buildinfo, filenames[0])); const artifactsDir = 'build/contracts'; From 391f8e237cde9d2f7381c8dd8bcc9de7e29ca318 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Fri, 19 Feb 2021 19:06:54 +0100 Subject: [PATCH 24/31] rename migration script --- package.json | 2 +- scripts/{rewrite-imports.js => migrate-imports.js} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename scripts/{rewrite-imports.js => migrate-imports.js} (100%) diff --git a/package.json b/package.json index 7c74a50d525..575448ee164 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "/test/behaviors" ], "bin": { - "rewrite-imports": "scripts/rewrite-imports.js" + "openzeppelin-contracts-migrate-imports": "scripts/migrate-imports.js" }, "scripts": { "compile": "hardhat compile", diff --git a/scripts/rewrite-imports.js b/scripts/migrate-imports.js similarity index 100% rename from scripts/rewrite-imports.js rename to scripts/migrate-imports.js From a2a61989106b48ca5fe663ef3325531f04719263 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 19 Feb 2021 15:35:40 -0300 Subject: [PATCH 25/31] add how to upgrade section to changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65d96ad1b03..4589765512f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,16 @@ * `Initializable`: Make initializer check stricter during construction. ([#2531](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2531)) * Overall reorganisation of the contract folder to improve clarity and discoverability. ([#2503](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2503)) +### How to upgrade from 3.x + +Since this version has moved a few contracts to different directories, users upgrading from a previous version will need to adjust their import statements. To make this easier, the package includes a script that will migrate import statements automatically. After upgrading to the latest version of the package, run: + +``` +npx openzeppelin-contracts-migrate-imports +``` + +Make sure you're using git or another version control system to be able to recover from any potential error in our script. + ## 3.4.0 (2021-02-02) * `BeaconProxy`: added new kind of proxy that allows simultaneous atomic upgrades. ([#2411](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2411)) From f12532f90a9dcc4581622f2ee7c93faf22693bb5 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 19 Feb 2021 19:26:48 -0300 Subject: [PATCH 26/31] adjust documentation to new file structure --- contracts/access/README.adoc | 86 --------------------- contracts/governance/README.adoc | 91 +++++++++++++++++++++++ contracts/metatx/README.adoc | 2 +- contracts/proxy/README.adoc | 10 +-- contracts/security/README.adoc | 20 +++++ contracts/token/ERC1155/README.adoc | 8 +- contracts/token/ERC20/README.adoc | 16 ++++ contracts/token/ERC721/README.adoc | 8 +- contracts/token/ERC777/README.adoc | 6 ++ contracts/utils/README.adoc | 54 ++++++++++++-- contracts/utils/cryptography/README.adoc | 16 ---- contracts/utils/introspection/README.adoc | 33 -------- contracts/utils/math/README.adoc | 14 ---- contracts/utils/math/SafeMath.sol | 3 + contracts/utils/math/SignedSafeMath.sol | 6 +- scripts/migrate-imports.js | 2 +- 16 files changed, 206 insertions(+), 169 deletions(-) create mode 100644 contracts/governance/README.adoc create mode 100644 contracts/security/README.adoc delete mode 100644 contracts/utils/cryptography/README.adoc delete mode 100644 contracts/utils/introspection/README.adoc delete mode 100644 contracts/utils/math/README.adoc diff --git a/contracts/access/README.adoc b/contracts/access/README.adoc index c1431c1200e..e59bba0fce1 100644 --- a/contracts/access/README.adoc +++ b/contracts/access/README.adoc @@ -7,7 +7,6 @@ This directory provides ways to restrict who can access the functions of a contr - {AccessControl} provides a general role based access control mechanism. Multiple hierarchical roles can be created and assigned each to multiple accounts. - {Ownable} is a simpler mechanism with a single owner "role" that can be assigned to a single account. This simpler mechanism can be useful for quick tests but projects with production concerns are likely to outgrow it. -- {TimelockController} is used in combination with one of the above two mechanisms. By assigning a role to an instance of the `TimelockController` contract, the access to the functions controlled by that role will be delayed by some amount of time. == Authorization @@ -16,88 +15,3 @@ This directory provides ways to restrict who can access the functions of a contr {{AccessControl}} {{AccessControlEnumerable}} - -== Timelock - -{{TimelockController}} - -[[timelock-terminology]] -==== Terminology - -* *Operation:* A transaction (or a set of transactions) that is the subject of the timelock. It has to be scheduled by a proposer and executed by an executor. The timelock enforces a minimum delay between the proposition and the execution (see xref:access-control.adoc#operation_lifecycle[operation lifecycle]). If the operation contains multiple transactions (batch mode), they are executed atomically. Operations are identified by the hash of their content. -* *Operation status:* -** *Unset:* An operation that is not part of the timelock mechanism. -** *Pending:* An operation that has been scheduled, before the timer expires. -** *Ready:* An operation that has been scheduled, after the timer expires. -** *Done:* An operation that has been executed. -* *Predecessor*: An (optional) dependency between operations. An operation can depend on another operation (its predecessor), forcing the execution order of these two operations. -* *Role*: -** *Proposer:* An address (smart contract or EOA) that is in charge of scheduling (and cancelling) operations. -** *Executor:* An address (smart contract or EOA) that is in charge of executing operations. - -[[timelock-operation]] -==== Operation structure - -Operation executed by the xref:api:access.adoc#TimelockController[`TimelockControler`] can contain one or multiple subsequent calls. Depending on whether you need to multiple calls to be executed atomically, you can either use simple or batched operations. - -Both operations contain: - -* *Target*, the address of the smart contract that the timelock should operate on. -* *Value*, in wei, that should be sent with the transaction. Most of the time this will be 0. Ether can be deposited before-end or passed along when executing the transaction. -* *Data*, containing the encoded function selector and parameters of the call. This can be produced using a number of tools. For example, a maintenance operation granting role `ROLE` to `ACCOUNT` can be encode using web3js as follows: - -```javascript -const data = timelock.contract.methods.grantRole(ROLE, ACCOUNT).encodeABI() -``` - -* *Predecessor*, that specifies a dependency between operations. This dependency is optional. Use `bytes32(0)` if the operation does not have any dependency. -* *Salt*, used to disambiguate two otherwise identical operations. This can be any random value. - -In the case of batched operations, `target`, `value` and `data` are specified as arrays, which must be of the same length. - -[[timelock-operation-lifecycle]] -==== Operation lifecycle - -Timelocked operations are identified by a unique id (their hash) and follow a specific lifecycle: - -`Unset` -> `Pending` -> `Pending` + `Ready` -> `Done` - -* By calling xref:api:access.adoc#TimelockController-schedule-address-uint256-bytes-bytes32-bytes32-uint256-[`schedule`] (or xref:api:access.adoc#TimelockController-scheduleBatch-address---uint256---bytes---bytes32-bytes32-uint256-[`scheduleBatch`]), a proposer moves the operation from the `Unset` to the `Pending` state. This starts a timer that must be longer than the minimum delay. The timer expires at a timestamp accessible through the xref:api:access.adoc#TimelockController-getTimestamp-bytes32-[`getTimestamp`] method. -* Once the timer expires, the operation automatically gets the `Ready` state. At this point, it can be executed. -* By calling xref:api:access.adoc#TimelockController-TimelockController-execute-address-uint256-bytes-bytes32-bytes32-[`execute`] (or xref:api:access.adoc#TimelockController-executeBatch-address---uint256---bytes---bytes32-bytes32-[`executeBatch`]), an executor triggers the operation's underlying transactions and moves it to the `Done` state. If the operation has a predecessor, it has to be in the `Done` state for this transition to succeed. -* xref:api:access.adoc#TimelockController-TimelockController-cancel-bytes32-[`cancel`] allows proposers to cancel any `Pending` operation. This resets the operation to the `Unset` state. It is thus possible for a proposer to re-schedule an operation that has been cancelled. In this case, the timer restarts when the operation is re-scheduled. - -Operations status can be queried using the functions: - -* xref:api:access.adoc#TimelockController-isOperationPending-bytes32-[`isOperationPending(bytes32)`] -* xref:api:access.adoc#TimelockController-isOperationReady-bytes32-[`isOperationReady(bytes32)`] -* xref:api:access.adoc#TimelockController-isOperationDone-bytes32-[`isOperationDone(bytes32)`] - -[[timelock-roles]] -==== Roles - -[[timelock-admin]] -===== Admin - -The admins are in charge of managing proposers and executors. For the timelock to be self-governed, this role should only be given to the timelock itself. Upon deployment, both the timelock and the deployer have this role. After further configuration and testing, the deployer can renounce this role such that all further maintenance operations have to go through the timelock process. - -This role is identified by the *TIMELOCK_ADMIN_ROLE* value: `0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5` - -[[timelock-proposer]] -===== Proposer - -The proposers are in charge of scheduling (and cancelling) operations. This is a critical role, that should be given to governing entities. This could be an EOA, a multisig, or a DAO. - -WARNING: *Proposer fight:* Having multiple proposers, while providing redundancy in case one becomes unavailable, can be dangerous. As proposer have their say on all operations, they could cancel operations they disagree with, including operations to remove them for the proposers. - -This role is identified by the *PROPOSER_ROLE* value: `0xb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1` - -[[timelock-executor]] -===== Executor - -The executors are in charge of executing the operations scheduled by the proposers once the timelock expires. Logic dictates that multisig or DAO that are proposers should also be executors in order to guarantee operations that have been scheduled will eventually be executed. However, having additional executor can reduce the cost (the executing transaction does not require validation by the multisig or DAO that proposed it), while ensuring whoever is in charge of execution cannot trigger actions that have not been scheduled by the proposers. - -This role is identified by the *EXECUTOR_ROLE* value: `0xd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63` - - -WARNING: A live contract without at least one proposer and one executor is locked. Make sure these roles are filled by reliable entities before the deployer renounces its administrative rights in favour of the timelock contract itself. See the {AccessControl} documentation to learn more about role management. diff --git a/contracts/governance/README.adoc b/contracts/governance/README.adoc new file mode 100644 index 00000000000..4dc967f8efa --- /dev/null +++ b/contracts/governance/README.adoc @@ -0,0 +1,91 @@ += Governance + +[.readme-notice] +NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/access + +This directory includes primitives for on-chain governance. We currently only offer the {TimelockController} contract, that can be used as a component in a governance systems to introduce a delay between a proposal and its execution. + +== Timelock + +{{TimelockController}} + +[[timelock-terminology]] +==== Terminology + +* *Operation:* A transaction (or a set of transactions) that is the subject of the timelock. It has to be scheduled by a proposer and executed by an executor. The timelock enforces a minimum delay between the proposition and the execution (see xref:access-control.adoc#operation_lifecycle[operation lifecycle]). If the operation contains multiple transactions (batch mode), they are executed atomically. Operations are identified by the hash of their content. +* *Operation status:* +** *Unset:* An operation that is not part of the timelock mechanism. +** *Pending:* An operation that has been scheduled, before the timer expires. +** *Ready:* An operation that has been scheduled, after the timer expires. +** *Done:* An operation that has been executed. +* *Predecessor*: An (optional) dependency between operations. An operation can depend on another operation (its predecessor), forcing the execution order of these two operations. +* *Role*: +** *Proposer:* An address (smart contract or EOA) that is in charge of scheduling (and cancelling) operations. +** *Executor:* An address (smart contract or EOA) that is in charge of executing operations. + +[[timelock-operation]] +==== Operation structure + +Operation executed by the xref:api:access.adoc#TimelockController[`TimelockControler`] can contain one or multiple subsequent calls. Depending on whether you need to multiple calls to be executed atomically, you can either use simple or batched operations. + +Both operations contain: + +* *Target*, the address of the smart contract that the timelock should operate on. +* *Value*, in wei, that should be sent with the transaction. Most of the time this will be 0. Ether can be deposited before-end or passed along when executing the transaction. +* *Data*, containing the encoded function selector and parameters of the call. This can be produced using a number of tools. For example, a maintenance operation granting role `ROLE` to `ACCOUNT` can be encode using web3js as follows: + +```javascript +const data = timelock.contract.methods.grantRole(ROLE, ACCOUNT).encodeABI() +``` + +* *Predecessor*, that specifies a dependency between operations. This dependency is optional. Use `bytes32(0)` if the operation does not have any dependency. +* *Salt*, used to disambiguate two otherwise identical operations. This can be any random value. + +In the case of batched operations, `target`, `value` and `data` are specified as arrays, which must be of the same length. + +[[timelock-operation-lifecycle]] +==== Operation lifecycle + +Timelocked operations are identified by a unique id (their hash) and follow a specific lifecycle: + +`Unset` -> `Pending` -> `Pending` + `Ready` -> `Done` + +* By calling xref:api:access.adoc#TimelockController-schedule-address-uint256-bytes-bytes32-bytes32-uint256-[`schedule`] (or xref:api:access.adoc#TimelockController-scheduleBatch-address---uint256---bytes---bytes32-bytes32-uint256-[`scheduleBatch`]), a proposer moves the operation from the `Unset` to the `Pending` state. This starts a timer that must be longer than the minimum delay. The timer expires at a timestamp accessible through the xref:api:access.adoc#TimelockController-getTimestamp-bytes32-[`getTimestamp`] method. +* Once the timer expires, the operation automatically gets the `Ready` state. At this point, it can be executed. +* By calling xref:api:access.adoc#TimelockController-TimelockController-execute-address-uint256-bytes-bytes32-bytes32-[`execute`] (or xref:api:access.adoc#TimelockController-executeBatch-address---uint256---bytes---bytes32-bytes32-[`executeBatch`]), an executor triggers the operation's underlying transactions and moves it to the `Done` state. If the operation has a predecessor, it has to be in the `Done` state for this transition to succeed. +* xref:api:access.adoc#TimelockController-TimelockController-cancel-bytes32-[`cancel`] allows proposers to cancel any `Pending` operation. This resets the operation to the `Unset` state. It is thus possible for a proposer to re-schedule an operation that has been cancelled. In this case, the timer restarts when the operation is re-scheduled. + +Operations status can be queried using the functions: + +* xref:api:access.adoc#TimelockController-isOperationPending-bytes32-[`isOperationPending(bytes32)`] +* xref:api:access.adoc#TimelockController-isOperationReady-bytes32-[`isOperationReady(bytes32)`] +* xref:api:access.adoc#TimelockController-isOperationDone-bytes32-[`isOperationDone(bytes32)`] + +[[timelock-roles]] +==== Roles + +[[timelock-admin]] +===== Admin + +The admins are in charge of managing proposers and executors. For the timelock to be self-governed, this role should only be given to the timelock itself. Upon deployment, both the timelock and the deployer have this role. After further configuration and testing, the deployer can renounce this role such that all further maintenance operations have to go through the timelock process. + +This role is identified by the *TIMELOCK_ADMIN_ROLE* value: `0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5` + +[[timelock-proposer]] +===== Proposer + +The proposers are in charge of scheduling (and cancelling) operations. This is a critical role, that should be given to governing entities. This could be an EOA, a multisig, or a DAO. + +WARNING: *Proposer fight:* Having multiple proposers, while providing redundancy in case one becomes unavailable, can be dangerous. As proposer have their say on all operations, they could cancel operations they disagree with, including operations to remove them for the proposers. + +This role is identified by the *PROPOSER_ROLE* value: `0xb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1` + +[[timelock-executor]] +===== Executor + +The executors are in charge of executing the operations scheduled by the proposers once the timelock expires. Logic dictates that multisig or DAO that are proposers should also be executors in order to guarantee operations that have been scheduled will eventually be executed. However, having additional executor can reduce the cost (the executing transaction does not require validation by the multisig or DAO that proposed it), while ensuring whoever is in charge of execution cannot trigger actions that have not been scheduled by the proposers. + +This role is identified by the *EXECUTOR_ROLE* value: `0xd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63` + + +WARNING: A live contract without at least one proposer and one executor is locked. Make sure these roles are filled by reliable entities before the deployer renounces its administrative rights in favour of the timelock contract itself. See the {AccessControl} documentation to learn more about role management. diff --git a/contracts/metatx/README.adoc b/contracts/metatx/README.adoc index 51a97913fa4..eccdeaf9740 100644 --- a/contracts/metatx/README.adoc +++ b/contracts/metatx/README.adoc @@ -1,7 +1,7 @@ = Meta Transactions [.readme-notice] -NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/math +NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/metatx == Core diff --git a/contracts/proxy/README.adoc b/contracts/proxy/README.adoc index 452ad91333f..ea6bf3a389d 100644 --- a/contracts/proxy/README.adoc +++ b/contracts/proxy/README.adoc @@ -21,8 +21,12 @@ CAUTION: Using upgradeable proxies correctly and securely is a difficult task th {{UpgradeableProxy}} +== Transparent Proxy + {{TransparentUpgradeableProxy}} +{{ProxyAdmin}} + == Beacon {{BeaconProxy}} @@ -34,9 +38,3 @@ CAUTION: Using upgradeable proxies correctly and securely is a difficult task th == Minimal Clones {{Clones}} - -== Utilities - -{{Initializable}} - -{{ProxyAdmin}} diff --git a/contracts/security/README.adoc b/contracts/security/README.adoc new file mode 100644 index 00000000000..66f398fece5 --- /dev/null +++ b/contracts/security/README.adoc @@ -0,0 +1,20 @@ += Security + +[.readme-notice] +NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/security + +These contracts aim to cover common security practices. + +* {PullPayment}: A pattern that can be used to avoid reentrancy attacks. +* {ReentrancyGuard}: A modifier that can prevent reentrancy during certain functions. +* {Pausable}: A common emergency response mechanism that can pause functionality while a remediation is pending. + +TIP: For an overview on reentrancy and the possible mechanisms to prevent it, read our article https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. + +== Contracts + +{{PullPayment}} + +{{ReentrancyGuard}} + +{{Pausable}} diff --git a/contracts/token/ERC1155/README.adoc b/contracts/token/ERC1155/README.adoc index e804746957a..c1dc83e155e 100644 --- a/contracts/token/ERC1155/README.adoc +++ b/contracts/token/ERC1155/README.adoc @@ -32,6 +32,12 @@ NOTE: This core set of contracts is designed to be unopinionated, allowing devel {{ERC1155Burnable}} -== Convenience +== Presets + +These contracts are preconfigured combinations of the above features. They can be used through inheritance or as models to copy and paste their source code. + +{{ERC1155PresetMinterPauser}} + +== Utilities {{ERC1155Holder}} diff --git a/contracts/token/ERC20/README.adoc b/contracts/token/ERC20/README.adoc index 60ecb4dfcd5..b8bfb00ca62 100644 --- a/contracts/token/ERC20/README.adoc +++ b/contracts/token/ERC20/README.adoc @@ -48,6 +48,22 @@ NOTE: This core set of contracts is designed to be unopinionated, allowing devel {{ERC20Capped}} +== Draft EIPs + +The following EIPs are still in Draft status. Due to their nature as drafts, the details of these contracts may change and we cannot guarantee their xref:ROOT:releases-stability.adoc[stability]. Minor releases of OpenZeppelin Contracts may contain breaking changes for the contracts in this directory, which will be duly announced in the https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/CHANGELOG.md[changelog]. The EIPs included here are used by projects in production and this may make them less likely to change significantly. + +{{IERC20Permit}} + +{{ERC20Permit}} + +== Presets + +These contracts are preconfigured combinations of the above features. They can be used through inheritance or as models to copy and paste their source code. + +{{ERC20PresetMinterPauser}} + +{{ERC20PresetFixedSupply}} + == Utilities {{SafeERC20}} diff --git a/contracts/token/ERC721/README.adoc b/contracts/token/ERC721/README.adoc index 08642217d51..07b73d50cbc 100644 --- a/contracts/token/ERC721/README.adoc +++ b/contracts/token/ERC721/README.adoc @@ -39,6 +39,12 @@ NOTE: This core set of contracts is designed to be unopinionated, allowing devel {{ERC721Burnable}} -== Convenience +== Presets + +These contracts are preconfigured combinations of the above features. They can be used through inheritance or as models to copy and paste their source code. + +{{ERC721PresetMinterPauserAutoId}} + +== Utilities {{ERC721Holder}} diff --git a/contracts/token/ERC777/README.adoc b/contracts/token/ERC777/README.adoc index 4dee8a661ac..d8f25f06010 100644 --- a/contracts/token/ERC777/README.adoc +++ b/contracts/token/ERC777/README.adoc @@ -22,3 +22,9 @@ Additionally there are interfaces used to develop contracts that react to token {{IERC777Sender}} {{IERC777Recipient}} + +== Presets + +These contracts are preconfigured combinations of features. They can be used through inheritance or as models to copy and paste their source code. + +{{ERC777PresetFixedSupply}} diff --git a/contracts/utils/README.adoc b/contracts/utils/README.adoc index 3773c411fb1..f4ed4c94fb2 100644 --- a/contracts/utils/README.adoc +++ b/contracts/utils/README.adoc @@ -5,11 +5,6 @@ NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/ Miscellaneous contracts and libraries containing utility functions you can use to improve security, work with new data types, or safely use low-level primitives. -Security tools include: - - * {Pausable}: provides a simple way to halt activity in your contracts (often in response to an external threat). - * {ReentrancyGuard}: protects you from https://blog.openzeppelin.com/reentrancy-after-istanbul/[reentrant calls]. - The {Address}, {Arrays} and {Strings} libraries provide more operations related to these native data types, while {SafeCast} adds ways to safely convert between the different signed and unsigned numeric types. For new data types: @@ -27,11 +22,54 @@ As of v3.0, {EnumerableMap} supports `uint256 -> address` (`UintToAddressMap`), Finally, {Create2} contains all necessary utilities to safely use the https://blog.openzeppelin.com/getting-the-most-out-of-create2/[`CREATE2` EVM opcode], without having to deal with low-level assembly. -== Contracts +== Math + +{{Math}} + +{{SafeCast}} + +{{SafeMath}} + +{{SignedSafeMath}} + +== Cryptography + +{{ECDSA}} + +{{MerkleProof}} + +{{EIP712}} + +== Introspection + +This set of interfaces and contracts deal with https://en.wikipedia.org/wiki/Type_introspection[type introspection] of contracts, that is, examining which functions can be called on them. This is usually referred to as a contract's _interface_. + +Ethereum contracts have no native concept of an interface, so applications must usually simply trust they are not making an incorrect call. For trusted setups this is a non-issue, but often unknown and untrusted third-party addresses need to be interacted with. There may even not be any direct calls to them! (e.g. `ERC20` tokens may be sent to a contract that lacks a way to transfer them out of it, locking them forever). In these cases, a contract _declaring_ its interface can be very helpful in preventing errors. + +There are two main ways to approach this. + +* Locally, where a contract implements `IERC165` and declares an interface, and a second one queries it directly via `ERC165Checker`. +* Globally, where a global and unique registry (`IERC1820Registry`) is used to register implementers of a certain interface (`IERC1820Implementer`). It is then the registry that is queried, which allows for more complex setups, like contracts implementing interfaces for externally-owned accounts. + +Note that, in all cases, accounts simply _declare_ their interfaces, but they are not required to actually implement them. This mechanism can therefore be used to both prevent errors and allow for complex interactions (see `ERC777`), but it must not be relied on for security. + +{{IERC165}} + +{{ERC165}} + +{{ERC165Storage}} + +{{ERC165Checker}} + +{{IERC1820Registry}} + +{{IERC1820Implementer}} + +{{ERC1820Implementer}} -{{Pausable}} +== General -{{ReentrancyGuard}} +{{Initializable}} == Libraries diff --git a/contracts/utils/cryptography/README.adoc b/contracts/utils/cryptography/README.adoc deleted file mode 100644 index 05e16ec91f8..00000000000 --- a/contracts/utils/cryptography/README.adoc +++ /dev/null @@ -1,16 +0,0 @@ -= Cryptography - -[.readme-notice] -NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/cryptography - -This collection of libraries provides simple and safe ways to use different cryptographic primitives. - -The following related EIPs are in draft status and can be found in the drafts directory. - -- {EIP712} - -== Libraries - -{{ECDSA}} - -{{MerkleProof}} diff --git a/contracts/utils/introspection/README.adoc b/contracts/utils/introspection/README.adoc deleted file mode 100644 index 0668de417e2..00000000000 --- a/contracts/utils/introspection/README.adoc +++ /dev/null @@ -1,33 +0,0 @@ -= Introspection - -[.readme-notice] -NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/introspection - -This set of interfaces and contracts deal with https://en.wikipedia.org/wiki/Type_introspection[type introspection] of contracts, that is, examining which functions can be called on them. This is usually referred to as a contract's _interface_. - -Ethereum contracts have no native concept of an interface, so applications must usually simply trust they are not making an incorrect call. For trusted setups this is a non-issue, but often unknown and untrusted third-party addresses need to be interacted with. There may even not be any direct calls to them! (e.g. `ERC20` tokens may be sent to a contract that lacks a way to transfer them out of it, locking them forever). In these cases, a contract _declaring_ its interface can be very helpful in preventing errors. - -There are two main ways to approach this. - -* Locally, where a contract implements `IERC165` and declares an interface, and a second one queries it directly via `ERC165Checker`. -* Globally, where a global and unique registry (`IERC1820Registry`) is used to register implementers of a certain interface (`IERC1820Implementer`). It is then the registry that is queried, which allows for more complex setups, like contracts implementing interfaces for externally-owned accounts. - -Note that, in all cases, accounts simply _declare_ their interfaces, but they are not required to actually implement them. This mechanism can therefore be used to both prevent errors and allow for complex interactions (see `ERC777`), but it must not be relied on for security. - -== Local - -{{IERC165}} - -{{ERC165}} - -{{ERC165Storage}} - -{{ERC165Checker}} - -== Global - -{{IERC1820Registry}} - -{{IERC1820Implementer}} - -{{ERC1820Implementer}} diff --git a/contracts/utils/math/README.adoc b/contracts/utils/math/README.adoc deleted file mode 100644 index b03d441bae3..00000000000 --- a/contracts/utils/math/README.adoc +++ /dev/null @@ -1,14 +0,0 @@ -= Math - -[.readme-notice] -NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/math - -These are math-related utilities. - -== Libraries - -{{SafeMath}} - -{{SignedSafeMath}} - -{{Math}} diff --git a/contracts/utils/math/SafeMath.sol b/contracts/utils/math/SafeMath.sol index a9a3bdc8c14..127464feff9 100644 --- a/contracts/utils/math/SafeMath.sol +++ b/contracts/utils/math/SafeMath.sol @@ -4,6 +4,9 @@ pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations. + * + * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler + * now has built in overflow checking. */ library SafeMath { /** diff --git a/contracts/utils/math/SignedSafeMath.sol b/contracts/utils/math/SignedSafeMath.sol index 15530c27b4e..d54b8ff307a 100644 --- a/contracts/utils/math/SignedSafeMath.sol +++ b/contracts/utils/math/SignedSafeMath.sol @@ -3,8 +3,10 @@ pragma solidity ^0.8.0; /** - * @title SignedSafeMath - * @dev Signed math operations that revert on error. + * @dev Wrappers over Solidity's arithmetic operations. + * + * NOTE: `SignedSafeMath` is no longer needed starting with Solidity 0.8. The compiler + * now has built in overflow checking. */ library SignedSafeMath { /** diff --git a/scripts/migrate-imports.js b/scripts/migrate-imports.js index d554a820e11..a4a6e00162d 100755 --- a/scripts/migrate-imports.js +++ b/scripts/migrate-imports.js @@ -66,7 +66,7 @@ const pathUpdates = { // 'token/ERC20/ERC20.sol': undefined, // 'token/ERC20/IERC20.sol': undefined, 'token/ERC20/SafeERC20.sol': 'token/ERC20/utils/SafeERC20.sol', - 'token/ERC20/TokenTimelock.sol': 'token/ERC20/utils//TokenTimelock.sol', + 'token/ERC20/TokenTimelock.sol': 'token/ERC20/utils/TokenTimelock.sol', 'token/ERC721/ERC721Burnable.sol': 'token/ERC721/extensions/ERC721Burnable.sol', 'token/ERC721/ERC721Holder.sol': 'token/ERC721/utils/ERC721Holder.sol', 'token/ERC721/ERC721Pausable.sol': 'token/ERC721/extensions/ERC721Pausable.sol', From e7487403e28ef810fc434cd4d7ed7f2505dab1e3 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 19 Feb 2021 19:30:37 -0300 Subject: [PATCH 27/31] reorganize utils docs and remove duplicate --- contracts/utils/README.adoc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/contracts/utils/README.adoc b/contracts/utils/README.adoc index f4ed4c94fb2..fc6adc6f342 100644 --- a/contracts/utils/README.adoc +++ b/contracts/utils/README.adoc @@ -67,24 +67,24 @@ Note that, in all cases, accounts simply _declare_ their interfaces, but they ar {{ERC1820Implementer}} -== General +== Data Structures -{{Initializable}} +{{EnumerableMap}} + +{{EnumerableSet}} == Libraries +{{Create2}} + {{Address}} {{Arrays}} {{Counters}} -{{Create2}} - -{{EnumerableMap}} +{{Strings}} -{{EnumerableSet}} +== Other -{{SafeCast}} - -{{Strings}} +{{Initializable}} From e3688cf196e4c5b69d98c1e5421d6ec5ba240a9a Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 19 Feb 2021 19:32:13 -0300 Subject: [PATCH 28/31] fix crossreference --- contracts/utils/cryptography/ECDSA.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/utils/cryptography/ECDSA.sol b/contracts/utils/cryptography/ECDSA.sol index 76dab5d2113..b3ea4077403 100644 --- a/contracts/utils/cryptography/ECDSA.sol +++ b/contracts/utils/cryptography/ECDSA.sol @@ -47,7 +47,7 @@ library ECDSA { } /** - * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`, + * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { From 5d4dd931269591d06f966d116c02ec206249f376 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 19 Feb 2021 19:54:49 -0300 Subject: [PATCH 29/31] add tests for migrate-imports.js and fix for upgradeable --- scripts/migrate-imports.js | 36 +++++++++++++++++++++--------------- test/migrate-imports.test.js | 25 +++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 15 deletions(-) create mode 100644 test/migrate-imports.test.js diff --git a/scripts/migrate-imports.js b/scripts/migrate-imports.js index a4a6e00162d..63acce83c6e 100755 --- a/scripts/migrate-imports.js +++ b/scripts/migrate-imports.js @@ -3,11 +3,6 @@ const { promises: fs } = require('fs'); const path = require('path'); -const versions = [ - '@openzeppelin/contracts', - '@openzeppelin/contracts-upgradeable', -]; - const pathUpdates = { // 'access/AccessControl.sol': undefined, // 'access/Ownable.sol': undefined, @@ -112,15 +107,15 @@ async function main (paths = [ 'contracts' ]) { } } -async function listFilesRecursively (paths, filter = undefined) { - const queue = Array.isArray(paths) ? paths : [ paths ]; +async function listFilesRecursively (paths, filter) { + const queue = paths; const files = []; while (queue.length > 0) { const top = queue.shift(); const stat = await fs.stat(top); if (stat.isFile()) { - if (!filter || top.match(filter)) { + if (top.match(filter)) { files.push(top); } } else if (stat.isDirectory()) { @@ -146,18 +141,29 @@ async function updateFile (file, update) { function updateImportPaths (source) { for (const [ oldPath, newPath ] of Object.entries(pathUpdates)) { - for (const version of versions) { - source = source.replace( - path.join(version, oldPath), - path.join(version, newPath), - ); - } + source = source.replace( + path.join('@openzeppelin/contracts', oldPath), + path.join('@openzeppelin/contracts', newPath), + ); + source = source.replace( + path.join('@openzeppelin/contracts-upgradeable', getUpgradeablePath(oldPath)), + path.join('@openzeppelin/contracts-upgradeable', getUpgradeablePath(newPath)), + ); } return source; } -module.exports = main; +function getUpgradeablePath (file) { + const { dir, name, ext } = path.parse(file); + const upgradeableName = name + 'Upgradeable'; + return path.format({ dir, ext, name: upgradeableName }); +} + +module.exports = { + pathUpdates, + updateImportPaths, +}; if (require.main === module) { const args = process.argv.length > 2 ? process.argv.slice(2) : undefined; diff --git a/test/migrate-imports.test.js b/test/migrate-imports.test.js new file mode 100644 index 00000000000..a85fce21e13 --- /dev/null +++ b/test/migrate-imports.test.js @@ -0,0 +1,25 @@ +const path = require('path'); +const { promises: fs, constants: { F_OK } } = require('fs'); +const { expect } = require('chai'); + +const { pathUpdates, updateImportPaths } = require('../scripts/migrate-imports.js'); + +describe('migrate-imports.js', function () { + it('every new path exists', async function () { + for (const p of Object.values(pathUpdates)) { + await fs.access(path.join('contracts', p), F_OK); + } + }); + + it('replaces import paths in a file', async function () { + const source = ` +import '@openzeppelin/contracts/math/Math.sol'; +import '@openzeppelin/contracts-upgradeable/math/MathUpgradeable.sol'; + `; + const expected = ` +import '@openzeppelin/contracts/utils/math/Math.sol'; +import '@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol'; + `; + expect(updateImportPaths(source)).to.equal(expected); + }); +}); From f5b0b13ccb4cd106c23d01780b62df4a230b2a0c Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 19 Feb 2021 20:24:02 -0300 Subject: [PATCH 30/31] fix prepack script --- scripts/prepack.sh | 4 +++- scripts/remove-ignored-artifacts.js | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/prepack.sh b/scripts/prepack.sh index adecce2a2bd..6f1bd4c32f1 100755 --- a/scripts/prepack.sh +++ b/scripts/prepack.sh @@ -1,10 +1,12 @@ #!/usr/bin/env bash set -euo pipefail +shopt -s globstar # cross platform `mkdir -p` node -e 'fs.mkdirSync("build/contracts", { recursive: true })' -cp artifacts/**/*.json build/contracts +cp artifacts/contracts/**/*.json build/contracts +rm build/contracts/*.dbg.json node scripts/remove-ignored-artifacts.js diff --git a/scripts/remove-ignored-artifacts.js b/scripts/remove-ignored-artifacts.js index c29e68a4258..95cf89c9298 100644 --- a/scripts/remove-ignored-artifacts.js +++ b/scripts/remove-ignored-artifacts.js @@ -28,7 +28,7 @@ const filenames = fs.readdirSync(buildinfo); if (filenames.length !== 1) { throw new Error(`There should only be one file in ${buildinfo}`); } -const solcOutput = readJSON(path.join(buildinfo, filenames[0])); +const solcOutput = readJSON(path.join(buildinfo, filenames[0])).output; const artifactsDir = 'build/contracts'; From 96cbe162cbfec0e760f49530828e1b4520e55bb8 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Mon, 22 Feb 2021 13:38:24 -0300 Subject: [PATCH 31/31] revert code change (bad merge?) --- contracts/token/ERC20/extensions/ERC20Burnable.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/token/ERC20/extensions/ERC20Burnable.sol b/contracts/token/ERC20/extensions/ERC20Burnable.sol index 1baa1e78bcf..2335742ad9e 100644 --- a/contracts/token/ERC20/extensions/ERC20Burnable.sol +++ b/contracts/token/ERC20/extensions/ERC20Burnable.sol @@ -32,9 +32,9 @@ abstract contract ERC20Burnable is Context, ERC20 { * `amount`. */ function burnFrom(address account, uint256 amount) public virtual { - uint256 allowance_ = allowance(account, _msgSender()); - require(allowance_ >= amount, "ERC20: burn amount exceeds allowance"); - _approve(account, _msgSender(), allowance_ - amount); + uint256 currentAllowance = allowance(account, _msgSender()); + require(currentAllowance >= amount, "ERC20: burn amount exceeds allowance"); + _approve(account, _msgSender(), currentAllowance - amount); _burn(account, amount); } }