From bb64458928d08759e1f36cc0c11a8e76c976de0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ernesto=20Garc=C3=ADa?= Date: Mon, 3 Jul 2023 12:02:06 -0600 Subject: [PATCH] Implement recommendations from 5.0 audit Phase 1A (#4398) Co-authored-by: Francisco Giordano Co-authored-by: Hadrien Croubois --- contracts/governance/TimelockController.sol | 5 +- contracts/governance/utils/IVotes.sol | 4 +- contracts/interfaces/draft-IERC6093.sol | 1 + contracts/token/ERC1155/ERC1155.sol | 173 ++++++++++------ contracts/token/ERC1155/IERC1155.sol | 14 +- .../ERC1155/extensions/ERC1155Pausable.sol | 7 +- .../ERC1155/extensions/ERC1155Supply.sol | 41 ++-- contracts/token/ERC20/ERC20.sol | 96 ++++----- contracts/token/ERC20/IERC20.sol | 19 +- .../token/ERC20/extensions/ERC20Burnable.sol | 18 +- .../token/ERC20/extensions/ERC20Capped.sol | 4 +- .../token/ERC20/extensions/ERC20FlashMint.sol | 42 ++-- .../token/ERC20/extensions/ERC20Pausable.sol | 6 +- .../token/ERC20/extensions/ERC20Votes.sol | 11 +- .../token/ERC20/extensions/ERC20Wrapper.sol | 18 +- contracts/token/ERC721/ERC721.sol | 4 +- .../ERC721/extensions/ERC721Pausable.sol | 2 +- contracts/utils/Nonces.sol | 2 +- contracts/utils/structs/Checkpoints.sol | 9 +- scripts/generate/templates/Checkpoints.js | 7 +- test/governance/utils/Votes.behavior.js | 16 +- test/token/ERC1155/ERC1155.behavior.js | 195 +++++++++++------- test/token/ERC1155/ERC1155.test.js | 74 +++---- .../extensions/ERC1155Burnable.test.js | 18 +- .../extensions/ERC1155Pausable.test.js | 26 +-- .../ERC1155/extensions/ERC1155Supply.test.js | 40 ++-- .../extensions/ERC1155URIStorage.test.js | 6 +- .../token/ERC1155/utils/ERC1155Holder.test.js | 12 +- test/token/ERC20/ERC20.behavior.js | 122 +++++------ test/token/ERC20/ERC20.test.js | 144 +++++++------ .../extensions/ERC20Burnable.behavior.js | 60 +++--- .../ERC20/extensions/ERC20Capped.behavior.js | 4 +- .../ERC20/extensions/ERC20FlashMint.test.js | 48 ++--- .../ERC20/extensions/ERC20Pausable.test.js | 24 +-- .../token/ERC20/extensions/ERC20Votes.test.js | 38 ++-- .../ERC20/extensions/ERC20Wrapper.test.js | 17 ++ test/token/ERC20/extensions/ERC4626.test.js | 110 +++++----- .../ERC721/extensions/ERC721Votes.test.js | 8 +- 38 files changed, 779 insertions(+), 666 deletions(-) diff --git a/contracts/governance/TimelockController.sol b/contracts/governance/TimelockController.sol index 45d8642e8..56a25fe30 100644 --- a/contracts/governance/TimelockController.sol +++ b/contracts/governance/TimelockController.sol @@ -427,8 +427,9 @@ contract TimelockController is AccessControl, ERC721Holder, ERC1155Holder { * an operation where the timelock is the target and the data is the ABI-encoded call to this function. */ function updateDelay(uint256 newDelay) external virtual { - if (msg.sender != address(this)) { - revert TimelockUnauthorizedCaller(msg.sender); + address sender = _msgSender(); + if (sender != address(this)) { + revert TimelockUnauthorizedCaller(sender); } emit MinDelayChange(_minDelay, newDelay); _minDelay = newDelay; diff --git a/contracts/governance/utils/IVotes.sol b/contracts/governance/utils/IVotes.sol index a8a20856f..ee17721ff 100644 --- a/contracts/governance/utils/IVotes.sol +++ b/contracts/governance/utils/IVotes.sol @@ -19,9 +19,9 @@ interface IVotes { event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); /** - * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes. + * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of voting units. */ - event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance); + event DelegateVotesChanged(address indexed delegate, uint256 previousVotes, uint256 newVotes); /** * @dev Returns the current amount of votes that `account` has. diff --git a/contracts/interfaces/draft-IERC6093.sol b/contracts/interfaces/draft-IERC6093.sol index fbe31051a..08e77553c 100644 --- a/contracts/interfaces/draft-IERC6093.sol +++ b/contracts/interfaces/draft-IERC6093.sol @@ -118,6 +118,7 @@ interface IERC1155Errors { * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. + * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); diff --git a/contracts/token/ERC1155/ERC1155.sol b/contracts/token/ERC1155/ERC1155.sol index 9d70714fa..a9028f323 100644 --- a/contracts/token/ERC1155/ERC1155.sol +++ b/contracts/token/ERC1155/ERC1155.sol @@ -58,16 +58,12 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER * Clients calling this function must replace the `\{id\}` substring with the * actual token type ID. */ - function uri(uint256) public view virtual returns (string memory) { + function uri(uint256 /* id */) public view virtual returns (string memory) { return _uri; } /** * @dev See {IERC1155-balanceOf}. - * - * Requirements: - * - * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) public view virtual returns (uint256) { return _balances[id][account]; @@ -114,11 +110,12 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER /** * @dev See {IERC1155-safeTransferFrom}. */ - function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes memory data) public virtual { - if (from != _msgSender() && !isApprovedForAll(from, _msgSender())) { - revert ERC1155MissingApprovalForAll(_msgSender(), from); + function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) public virtual { + address sender = _msgSender(); + if (from != sender && !isApprovedForAll(from, sender)) { + revert ERC1155MissingApprovalForAll(sender, from); } - _safeTransferFrom(from, to, id, amount, data); + _safeTransferFrom(from, to, id, value, data); } /** @@ -128,17 +125,18 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER address from, address to, uint256[] memory ids, - uint256[] memory amounts, + uint256[] memory values, bytes memory data ) public virtual { - if (from != _msgSender() && !isApprovedForAll(from, _msgSender())) { - revert ERC1155MissingApprovalForAll(_msgSender(), from); + address sender = _msgSender(); + if (from != sender && !isApprovedForAll(from, sender)) { + revert ERC1155MissingApprovalForAll(sender, from); } - _safeBatchTransferFrom(from, to, ids, amounts, data); + _safeBatchTransferFrom(from, to, ids, values, data); } /** - * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. Will mint (or burn) if `from` (or `to`) is the zero address. + * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. Will mint (or burn) if `from` (or `to`) is the zero address. * * Emits a {TransferSingle} event if the arrays contain one element, and {TransferBatch} otherwise. * @@ -146,75 +144,96 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER * * - If `to` refers to a smart contract, it must implement either {IERC1155Receiver-onERC1155Received} * or {IERC1155Receiver-onERC1155BatchReceived} and return the acceptance magic value. + * - `ids` and `values` must have the same length. + * + * NOTE: The ERC-1155 acceptance check is not performed in this function. See {_updateWithAcceptanceCheck} instead. */ - function _update( - address from, - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) internal virtual { - if (ids.length != amounts.length) { - revert ERC1155InvalidArrayLength(ids.length, amounts.length); + function _update(address from, address to, uint256[] memory ids, uint256[] memory values) internal virtual { + if (ids.length != values.length) { + revert ERC1155InvalidArrayLength(ids.length, values.length); } address operator = _msgSender(); for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids.unsafeMemoryAccess(i); - uint256 amount = amounts.unsafeMemoryAccess(i); + uint256 value = values.unsafeMemoryAccess(i); if (from != address(0)) { uint256 fromBalance = _balances[id][from]; - if (fromBalance < amount) { - revert ERC1155InsufficientBalance(from, fromBalance, amount, id); + if (fromBalance < value) { + revert ERC1155InsufficientBalance(from, fromBalance, value, id); } unchecked { - _balances[id][from] = fromBalance - amount; + // Overflow not possible: value <= fromBalance + _balances[id][from] = fromBalance - value; } } if (to != address(0)) { - _balances[id][to] += amount; + _balances[id][to] += value; } } if (ids.length == 1) { uint256 id = ids.unsafeMemoryAccess(0); - uint256 amount = amounts.unsafeMemoryAccess(0); - emit TransferSingle(operator, from, to, id, amount); - if (to != address(0)) { - _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data); - } + uint256 value = values.unsafeMemoryAccess(0); + emit TransferSingle(operator, from, to, id, value); } else { - emit TransferBatch(operator, from, to, ids, amounts); - if (to != address(0)) { - _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data); + emit TransferBatch(operator, from, to, ids, values); + } + } + + /** + * @dev Version of {_update} that performs the token acceptance check by calling {IERC1155Receiver-onERC1155Received} + * or {IERC1155Receiver-onERC1155BatchReceived} on the receiver address if it contains code (eg. is a smart contract + * at the moment of execution). + * + * IMPORTANT: Overriding this function is discouraged because it poses a reentrancy risk from the receiver. So any + * update to the contract state after this function would break the check-effect-interaction pattern. Consider + * overriding {_update} instead. + */ + function _updateWithAcceptanceCheck( + address from, + address to, + uint256[] memory ids, + uint256[] memory values, + bytes memory data + ) internal virtual { + _update(from, to, ids, values); + if (to != address(0)) { + address operator = _msgSender(); + if (ids.length == 1) { + uint256 id = ids.unsafeMemoryAccess(0); + uint256 value = values.unsafeMemoryAccess(0); + _doSafeTransferAcceptanceCheck(operator, from, to, id, value, data); + } else { + _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, values, data); } } } /** - * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. + * @dev Transfers a `value` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. - * - `from` must have a balance of tokens of type `id` of at least `amount`. + * - `from` must have a balance of tokens of type `id` of at least `value` amount. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ - function _safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes memory data) internal { + function _safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } - (uint256[] memory ids, uint256[] memory amounts) = _asSingletonArrays(id, amount); - _update(from, to, ids, amounts, data); + (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); + _updateWithAcceptanceCheck(from, to, ids, values, data); } /** @@ -226,12 +245,13 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER * * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. + * - `ids` and `values` must have the same length. */ function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, - uint256[] memory amounts, + uint256[] memory values, bytes memory data ) internal { if (to == address(0)) { @@ -240,7 +260,7 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } - _update(from, to, ids, amounts, data); + _updateWithAcceptanceCheck(from, to, ids, values, data); } /** @@ -249,7 +269,7 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * By this mechanism, any occurrence of the `\{id\}` substring in either the - * URI or any of the amounts in the JSON file at said URI will be replaced by + * URI or any of the values in the JSON file at said URI will be replaced by * clients with the token type ID. * * For example, the `https://token-cdn-domain/\{id\}.json` URI would be @@ -267,7 +287,7 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER } /** - * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`. + * @dev Creates a `value` amount of tokens of type `id`, and assigns them to `to`. * * Emits a {TransferSingle} event. * @@ -277,12 +297,12 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ - function _mint(address to, uint256 id, uint256 amount, bytes memory data) internal { + function _mint(address to, uint256 id, uint256 value, bytes memory data) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } - (uint256[] memory ids, uint256[] memory amounts) = _asSingletonArrays(id, amount); - _update(address(0), to, ids, amounts, data); + (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); + _updateWithAcceptanceCheck(address(0), to, ids, values, data); } /** @@ -292,33 +312,34 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER * * Requirements: * - * - `ids` and `amounts` must have the same length. + * - `ids` and `values` must have the same length. + * - `to` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ - function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal { + function _mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } - _update(address(0), to, ids, amounts, data); + _updateWithAcceptanceCheck(address(0), to, ids, values, data); } /** - * @dev Destroys `amount` tokens of token type `id` from `from` + * @dev Destroys a `value` amount of tokens of type `id` from `from` * * Emits a {TransferSingle} event. * * Requirements: * * - `from` cannot be the zero address. - * - `from` must have at least `amount` tokens of token type `id`. + * - `from` must have at least `value` amount of tokens of type `id`. */ - function _burn(address from, uint256 id, uint256 amount) internal { + function _burn(address from, uint256 id, uint256 value) internal { if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } - (uint256[] memory ids, uint256[] memory amounts) = _asSingletonArrays(id, amount); - _update(from, address(0), ids, amounts, ""); + (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); + _updateWithAcceptanceCheck(from, address(0), ids, values, ""); } /** @@ -328,38 +349,48 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER * * Requirements: * - * - `ids` and `amounts` must have the same length. + * - `from` cannot be the zero address. + * - `from` must have at least `value` amount of tokens of type `id`. + * - `ids` and `values` must have the same length. */ - function _burnBatch(address from, uint256[] memory ids, uint256[] memory amounts) internal { + function _burnBatch(address from, uint256[] memory ids, uint256[] memory values) internal { if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } - _update(from, address(0), ids, amounts, ""); + _updateWithAcceptanceCheck(from, address(0), ids, values, ""); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. + * + * Requirements: + * + * - `operator` cannot be the zero address. */ function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { - if (owner == operator) { - revert ERC1155InvalidOperator(operator); + if (operator == address(0)) { + revert ERC1155InvalidOperator(address(0)); } _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } + /** + * @dev Performs an acceptance check by calling {IERC1155-onERC1155Received} on the `to` address + * if it contains code at the moment of execution. + */ function _doSafeTransferAcceptanceCheck( address operator, address from, address to, uint256 id, - uint256 amount, + uint256 value, bytes memory data ) private { if (to.code.length > 0) { - try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) { + try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) { if (response != IERC1155Receiver.onERC1155Received.selector) { // Tokens rejected revert ERC1155InvalidReceiver(to); @@ -378,16 +409,20 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER } } + /** + * @dev Performs a batch acceptance check by calling {IERC1155-onERC1155BatchReceived} on the `to` address + * if it contains code at the moment of execution. + */ function _doSafeBatchTransferAcceptanceCheck( address operator, address from, address to, uint256[] memory ids, - uint256[] memory amounts, + uint256[] memory values, bytes memory data ) private { if (to.code.length > 0) { - try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns ( + try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns ( bytes4 response ) { if (response != IERC1155Receiver.onERC1155BatchReceived.selector) { @@ -408,20 +443,28 @@ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IER } } + /** + * @dev Creates an array in memory with only one value for each of the elements provided. + */ function _asSingletonArrays( uint256 element1, uint256 element2 ) private pure returns (uint256[] memory array1, uint256[] memory array2) { /// @solidity memory-safe-assembly assembly { + // Load the free memory pointer array1 := mload(0x40) + // Set array length to 1 mstore(array1, 1) + // Store the single element at the next word after the length (where content starts) mstore(add(array1, 0x20), element1) + // Repeat for next array locating it right after the first array array2 := add(array1, 0x40) mstore(array2, 1) mstore(add(array2, 0x20), element2) + // Update the free memory pointer by pointing after the second array mstore(0x40, add(array2, 0x40)) } } diff --git a/contracts/token/ERC1155/IERC1155.sol b/contracts/token/ERC1155/IERC1155.sol index c450eec2f..1b0b0ae9d 100644 --- a/contracts/token/ERC1155/IERC1155.sol +++ b/contracts/token/ERC1155/IERC1155.sol @@ -13,7 +13,7 @@ import {IERC165} from "../../utils/introspection/IERC165.sol"; */ interface IERC1155 is IERC165 { /** - * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. + * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); @@ -45,7 +45,7 @@ interface IERC1155 is IERC165 { event URI(string value, uint256 indexed id); /** - * @dev Returns the amount of tokens of token type `id` owned by `account`. + * @dev Returns the value of tokens of token type `id` owned by `account`. * * Requirements: * @@ -84,7 +84,7 @@ interface IERC1155 is IERC165 { function isApprovedForAll(address account, address operator) external view returns (bool); /** - * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. + * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. * * WARNING: This function can potentially allow a reentrancy attack when transferring tokens * to an untrusted contract, when invoking {onERC1155Received} on the receiver. @@ -97,11 +97,11 @@ interface IERC1155 is IERC165 { * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. - * - `from` must have a balance of tokens of type `id` of at least `amount`. + * - `from` must have a balance of tokens of type `id` of at least `value` amount. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ - function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external; + function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. @@ -116,7 +116,7 @@ interface IERC1155 is IERC165 { * * Requirements: * - * - `ids` and `amounts` must have the same length. + * - `ids` and `values` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ @@ -124,7 +124,7 @@ interface IERC1155 is IERC165 { address from, address to, uint256[] calldata ids, - uint256[] calldata amounts, + uint256[] calldata values, bytes calldata data ) external; } diff --git a/contracts/token/ERC1155/extensions/ERC1155Pausable.sol b/contracts/token/ERC1155/extensions/ERC1155Pausable.sol index 05aa8a780..960cd3b6e 100644 --- a/contracts/token/ERC1155/extensions/ERC1155Pausable.sol +++ b/contracts/token/ERC1155/extensions/ERC1155Pausable.sol @@ -17,7 +17,7 @@ import {Pausable} from "../../../security/Pausable.sol"; * addition to inheriting this contract, you must define both functions, invoking the * {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate * access control, e.g. using {AccessControl} or {Ownable}. Not doing so will - * make the contract unpausable. + * make the contract pause mechanism of the contract unreachable, and thus unusable. * * _Available since v3.1._ */ @@ -33,9 +33,8 @@ abstract contract ERC1155Pausable is ERC1155, Pausable { address from, address to, uint256[] memory ids, - uint256[] memory amounts, - bytes memory data + uint256[] memory values ) internal virtual override whenNotPaused { - super._update(from, to, ids, amounts, data); + super._update(from, to, ids, values); } } diff --git a/contracts/token/ERC1155/extensions/ERC1155Supply.sol b/contracts/token/ERC1155/extensions/ERC1155Supply.sol index eefa0ebf7..ef2736339 100644 --- a/contracts/token/ERC1155/extensions/ERC1155Supply.sol +++ b/contracts/token/ERC1155/extensions/ERC1155Supply.sol @@ -15,20 +15,22 @@ import {ERC1155} from "../ERC1155.sol"; * * NOTE: This contract implies a global limit of 2**256 - 1 to the number of tokens * that can be minted. + * + * CAUTION: This extension should not be added in an upgrade to an already deployed contract. */ abstract contract ERC1155Supply is ERC1155 { mapping(uint256 => uint256) private _totalSupply; uint256 private _totalSupplyAll; /** - * @dev Total amount of tokens in with a given id. + * @dev Total value of tokens in with a given id. */ function totalSupply(uint256 id) public view virtual returns (uint256) { return _totalSupply[id]; } /** - * @dev Total amount of tokens. + * @dev Total value of tokens. */ function totalSupply() public view virtual returns (uint256) { return _totalSupplyAll; @@ -48,35 +50,38 @@ abstract contract ERC1155Supply is ERC1155 { address from, address to, uint256[] memory ids, - uint256[] memory amounts, - bytes memory data + uint256[] memory values ) internal virtual override { + super._update(from, to, ids, values); + if (from == address(0)) { - uint256 totalMintAmount = 0; + uint256 totalMintValue = 0; for (uint256 i = 0; i < ids.length; ++i) { - uint256 amount = amounts[i]; - _totalSupply[ids[i]] += amount; - totalMintAmount += amount; + uint256 value = values[i]; + // Overflow check required: The rest of the code assumes that totalSupply never overflows + _totalSupply[ids[i]] += value; + totalMintValue += value; } - _totalSupplyAll += totalMintAmount; + // Overflow check required: The rest of the code assumes that totalSupplyAll never overflows + _totalSupplyAll += totalMintValue; } if (to == address(0)) { - uint256 totalBurnAmount = 0; + uint256 totalBurnValue = 0; for (uint256 i = 0; i < ids.length; ++i) { - uint256 id = ids[i]; - uint256 amount = amounts[i]; - _totalSupply[id] -= amount; + uint256 value = values[i]; + unchecked { - // Overflow not possible: sum(amounts[i]) <= sum(totalSupply(i)) <= totalSupplyAll - totalBurnAmount += amount; + // Overflow not possible: values[i] <= balanceOf(from, ids[i]) <= totalSupply(ids[i]) + _totalSupply[ids[i]] -= value; + // Overflow not possible: sum_i(values[i]) <= sum_i(totalSupply(ids[i])) <= totalSupplyAll + totalBurnValue += value; } } unchecked { - // Overflow not possible: totalBurnAmount = sum(amounts[i]) <= sum(totalSupply(i)) <= totalSupplyAll - _totalSupplyAll -= totalBurnAmount; + // Overflow not possible: totalBurnValue = sum_i(values[i]) <= sum_i(totalSupply(ids[i])) <= totalSupplyAll + _totalSupplyAll -= totalBurnValue; } } - super._update(from, to, ids, amounts, data); } } diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index d43880da6..abaf258c8 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -113,11 +113,11 @@ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { * Requirements: * * - `to` cannot be the zero address. - * - the caller must have a balance of at least `amount`. + * - the caller must have a balance of at least `value`. */ - function transfer(address to, uint256 amount) public virtual returns (bool) { + function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); - _transfer(owner, to, amount); + _transfer(owner, to, value); return true; } @@ -131,16 +131,16 @@ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { /** * @dev See {IERC20-approve}. * - * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on + * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ - function approve(address spender, uint256 amount) public virtual returns (bool) { + function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); - _approve(owner, spender, amount); + _approve(owner, spender, value); return true; } @@ -156,14 +156,14 @@ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { * Requirements: * * - `from` and `to` cannot be the zero address. - * - `from` must have a balance of at least `amount`. + * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least - * `amount`. + * `value`. */ - function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) { + function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); - _spendAllowance(from, spender, amount); - _transfer(from, to, amount); + _spendAllowance(from, spender, value); + _transfer(from, to, value); return true; } @@ -198,6 +198,9 @@ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `requestedDecrease`. + * + * NOTE: Although this function is designed to avoid double spending with {approval}, + * it can still be frontrunned, preventing any attempt of allowance reduction. */ function decreaseAllowance(address spender, uint256 requestedDecrease) public virtual returns (bool) { address owner = _msgSender(); @@ -213,7 +216,7 @@ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { } /** - * @dev Moves `amount` of tokens from `from` to `to`. + * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. @@ -222,83 +225,84 @@ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { * * NOTE: This function is not virtual, {_update} should be overridden instead. */ - function _transfer(address from, address to, uint256 amount) internal { + function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } - _update(from, to, amount); + _update(from, to, value); } /** - * @dev Transfers `amount` of tokens from `from` to `to`, or alternatively mints (or burns) if `from` (or `to`) is + * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` (or `to`) is * the zero address. All customizations to transfers, mints, and burns should be done by overriding this function. * * Emits a {Transfer} event. */ - function _update(address from, address to, uint256 amount) internal virtual { + function _update(address from, address to, uint256 value) internal virtual { if (from == address(0)) { - _totalSupply += amount; + // Overflow check required: The rest of the code assumes that totalSupply never overflows + _totalSupply += value; } else { uint256 fromBalance = _balances[from]; - if (fromBalance < amount) { - revert ERC20InsufficientBalance(from, fromBalance, amount); + if (fromBalance < value) { + revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { - // Overflow not possible: amount <= fromBalance <= totalSupply. - _balances[from] = fromBalance - amount; + // Overflow not possible: value <= fromBalance <= totalSupply. + _balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { - // Overflow not possible: amount <= totalSupply or amount <= fromBalance <= totalSupply. - _totalSupply -= amount; + // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. + _totalSupply -= value; } } else { unchecked { - // Overflow not possible: balance + amount is at most totalSupply, which we know fits into a uint256. - _balances[to] += amount; + // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. + _balances[to] += value; } } - emit Transfer(from, to, amount); + emit Transfer(from, to, value); } /** - * @dev Creates `amount` tokens and assigns them to `account`, by transferring it from address(0). + * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ - function _mint(address account, uint256 amount) internal { + function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } - _update(address(0), account, amount); + _update(address(0), account, value); } /** - * @dev Destroys `amount` tokens from `account`, by transferring it to address(0). + * @dev Destroys a `value` amount of tokens from `account`, by transferring it to address(0). * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ - function _burn(address account, uint256 amount) internal { + function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } - _update(account, address(0), amount); + _update(account, address(0), value); } /** - * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. @@ -310,8 +314,8 @@ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ - function _approve(address owner, address spender, uint256 amount) internal virtual { - _approve(owner, spender, amount, true); + function _approve(address owner, address spender, uint256 value) internal virtual { + _approve(owner, spender, value, true); } /** @@ -324,42 +328,42 @@ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to true * using the following override: * ``` - * function _approve(address owner, address spender, uint256 amount, bool) internal virtual override { - * super._approve(owner, spender, amount, true); + * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { + * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ - function _approve(address owner, address spender, uint256 amount, bool emitEvent) internal virtual { + function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } - _allowances[owner][spender] = amount; + _allowances[owner][spender] = value; if (emitEvent) { - emit Approval(owner, spender, amount); + emit Approval(owner, spender, value); } } /** - * @dev Updates `owner` s allowance for `spender` based on spent `amount`. + * @dev Updates `owner` s allowance for `spender` based on spent `value`. * - * Does not update the allowance amount in case of infinite allowance. + * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ - function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { + function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { - if (currentAllowance < amount) { - revert ERC20InsufficientAllowance(spender, currentAllowance, amount); + if (currentAllowance < value) { + revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { - _approve(owner, spender, currentAllowance - amount, false); + _approve(owner, spender, currentAllowance - value, false); } } } diff --git a/contracts/token/ERC20/IERC20.sol b/contracts/token/ERC20/IERC20.sol index a19535a30..eed63a606 100644 --- a/contracts/token/ERC20/IERC20.sol +++ b/contracts/token/ERC20/IERC20.sol @@ -22,23 +22,23 @@ interface IERC20 { event Approval(address indexed owner, address indexed spender, uint256 value); /** - * @dev Returns the amount of tokens in existence. + * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** - * @dev Returns the amount of tokens owned by `account`. + * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** - * @dev Moves `amount` tokens from the caller's account to `to`. + * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ - function transfer(address to, uint256 amount) external returns (bool); + function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be @@ -50,7 +50,8 @@ interface IERC20 { function allowance(address owner, address spender) external view returns (uint256); /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. + * @dev Sets a `value` amount of tokens as the allowance of `spender` over the + * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * @@ -63,16 +64,16 @@ interface IERC20 { * * Emits an {Approval} event. */ - function approve(address spender, uint256 amount) external returns (bool); + function approve(address spender, uint256 value) external returns (bool); /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's + * @dev Moves a `value` amount of tokens from `from` to `to` using the + * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ - function transferFrom(address from, address to, uint256 amount) external returns (bool); + function transferFrom(address from, address to, uint256 value) external returns (bool); } diff --git a/contracts/token/ERC20/extensions/ERC20Burnable.sol b/contracts/token/ERC20/extensions/ERC20Burnable.sol index 2a6d28963..e5b43a780 100644 --- a/contracts/token/ERC20/extensions/ERC20Burnable.sol +++ b/contracts/token/ERC20/extensions/ERC20Burnable.sol @@ -13,27 +13,27 @@ import {Context} from "../../../utils/Context.sol"; */ abstract contract ERC20Burnable is Context, ERC20 { /** - * @dev Destroys `amount` tokens from the caller. + * @dev Destroys a `value` amount of tokens from the caller. * * See {ERC20-_burn}. */ - function burn(uint256 amount) public virtual { - _burn(_msgSender(), amount); + function burn(uint256 value) public virtual { + _burn(_msgSender(), value); } /** - * @dev Destroys `amount` tokens from `account`, deducting from the caller's - * allowance. + * @dev Destroys a `value` amount of tokens from `account`, deducting from + * the caller's allowance. * * See {ERC20-_burn} and {ERC20-allowance}. * * Requirements: * * - the caller must have allowance for ``accounts``'s tokens of at least - * `amount`. + * `value`. */ - function burnFrom(address account, uint256 amount) public virtual { - _spendAllowance(account, _msgSender(), amount); - _burn(account, amount); + function burnFrom(address account, uint256 value) public virtual { + _spendAllowance(account, _msgSender(), value); + _burn(account, value); } } diff --git a/contracts/token/ERC20/extensions/ERC20Capped.sol b/contracts/token/ERC20/extensions/ERC20Capped.sol index 98ec71443..943d01644 100644 --- a/contracts/token/ERC20/extensions/ERC20Capped.sol +++ b/contracts/token/ERC20/extensions/ERC20Capped.sol @@ -42,8 +42,8 @@ abstract contract ERC20Capped is ERC20 { /** * @dev See {ERC20-_update}. */ - function _update(address from, address to, uint256 amount) internal virtual override { - super._update(from, to, amount); + function _update(address from, address to, uint256 value) internal virtual override { + super._update(from, to, value); if (from == address(0)) { uint256 maxSupply = cap(); diff --git a/contracts/token/ERC20/extensions/ERC20FlashMint.sol b/contracts/token/ERC20/extensions/ERC20FlashMint.sol index b63c75f71..0583af5df 100644 --- a/contracts/token/ERC20/extensions/ERC20FlashMint.sol +++ b/contracts/token/ERC20/extensions/ERC20FlashMint.sol @@ -14,6 +14,10 @@ import {ERC20} from "../ERC20.sol"; * Adds the {flashLoan} method, which provides flash loan support at the token * level. By default there is no fee, but this can be changed by overriding {flashFee}. * + * NOTE: When this extension is used along with the {ERC20Capped} or {ERC20Votes} extensions, + * {maxFlashLoan} will not correctly reflect the maximum that can be flash minted. We recommend + * overriding {maxFlashLoan} so that it correctly reflects the supply cap. + * * _Available since v4.1._ */ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender { @@ -25,7 +29,7 @@ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender { error ERC3156UnsupportedToken(address token); /** - * @dev The requested loan exceeds the max loan amount for `token`. + * @dev The requested loan exceeds the max loan value for `token`. */ error ERC3156ExceededMaxLoan(uint256 maxLoan); @@ -38,6 +42,10 @@ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender { * @dev Returns the maximum amount of tokens available for loan. * @param token The address of the token that is requested. * @return The amount of token that can be loaned. + * + * NOTE: This function does not consider any form of supply cap, so in case + * it's used in a token with a cap like {ERC20Capped}, make sure to override this + * function to integrate the cap instead of `type(uint256).max`. */ function maxFlashLoan(address token) public view virtual returns (uint256) { return token == address(this) ? type(uint256).max - totalSupply() : 0; @@ -48,14 +56,14 @@ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender { * the {_flashFee} function which returns the fee applied when doing flash * loans. * @param token The token to be flash loaned. - * @param amount The amount of tokens to be loaned. + * @param value The amount of tokens to be loaned. * @return The fees applied to the corresponding flash loan. */ - function flashFee(address token, uint256 amount) public view virtual returns (uint256) { + function flashFee(address token, uint256 value) public view virtual returns (uint256) { if (token != address(this)) { revert ERC3156UnsupportedToken(token); } - return _flashFee(token, amount); + return _flashFee(token, value); } /** @@ -63,13 +71,13 @@ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender { * implementation has 0 fees. This function can be overloaded to make * the flash loan mechanism deflationary. * @param token The token to be flash loaned. - * @param amount The amount of tokens to be loaned. + * @param value The amount of tokens to be loaned. * @return The fees applied to the corresponding flash loan. */ - function _flashFee(address token, uint256 amount) internal view virtual returns (uint256) { + function _flashFee(address token, uint256 value) internal view virtual returns (uint256) { // silence warning about unused variable without the addition of bytecode. token; - amount; + value; return 0; } @@ -87,13 +95,13 @@ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender { * @dev Performs a flash loan. New tokens are minted and sent to the * `receiver`, who is required to implement the {IERC3156FlashBorrower} * interface. By the end of the flash loan, the receiver is expected to own - * amount + fee tokens and have them approved back to the token contract itself so + * value + fee tokens and have them approved back to the token contract itself so * they can be burned. * @param receiver The receiver of the flash loan. Should implement the * {IERC3156FlashBorrower-onFlashLoan} interface. * @param token The token to be flash loaned. Only `address(this)` is * supported. - * @param amount The amount of tokens to be loaned. + * @param value The amount of tokens to be loaned. * @param data An arbitrary datafield that is passed to the receiver. * @return `true` if the flash loan was successful. */ @@ -103,24 +111,24 @@ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender { function flashLoan( IERC3156FlashBorrower receiver, address token, - uint256 amount, + uint256 value, bytes calldata data ) public virtual returns (bool) { uint256 maxLoan = maxFlashLoan(token); - if (amount > maxLoan) { + if (value > maxLoan) { revert ERC3156ExceededMaxLoan(maxLoan); } - uint256 fee = flashFee(token, amount); - _mint(address(receiver), amount); - if (receiver.onFlashLoan(msg.sender, token, amount, fee, data) != _RETURN_VALUE) { + uint256 fee = flashFee(token, value); + _mint(address(receiver), value); + if (receiver.onFlashLoan(_msgSender(), token, value, fee, data) != _RETURN_VALUE) { revert ERC3156InvalidReceiver(address(receiver)); } address flashFeeReceiver = _flashFeeReceiver(); - _spendAllowance(address(receiver), address(this), amount + fee); + _spendAllowance(address(receiver), address(this), value + fee); if (fee == 0 || flashFeeReceiver == address(0)) { - _burn(address(receiver), amount + fee); + _burn(address(receiver), value + fee); } else { - _burn(address(receiver), amount); + _burn(address(receiver), value); _transfer(address(receiver), flashFeeReceiver, fee); } return true; diff --git a/contracts/token/ERC20/extensions/ERC20Pausable.sol b/contracts/token/ERC20/extensions/ERC20Pausable.sol index 59f451639..6fff5058f 100644 --- a/contracts/token/ERC20/extensions/ERC20Pausable.sol +++ b/contracts/token/ERC20/extensions/ERC20Pausable.sol @@ -17,7 +17,7 @@ import {Pausable} from "../../../security/Pausable.sol"; * addition to inheriting this contract, you must define both functions, invoking the * {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate * access control, e.g. using {AccessControl} or {Ownable}. Not doing so will - * make the contract unpausable. + * make the contract pause mechanism of the contract unreachable, and thus unusable. */ abstract contract ERC20Pausable is ERC20, Pausable { /** @@ -27,7 +27,7 @@ abstract contract ERC20Pausable is ERC20, Pausable { * * - the contract must not be paused. */ - function _update(address from, address to, uint256 amount) internal virtual override whenNotPaused { - super._update(from, to, amount); + function _update(address from, address to, uint256 value) internal virtual override whenNotPaused { + super._update(from, to, value); } } diff --git a/contracts/token/ERC20/extensions/ERC20Votes.sol b/contracts/token/ERC20/extensions/ERC20Votes.sol index db5f71241..c27115eaa 100644 --- a/contracts/token/ERC20/extensions/ERC20Votes.sol +++ b/contracts/token/ERC20/extensions/ERC20Votes.sol @@ -41,8 +41,8 @@ abstract contract ERC20Votes is ERC20, Votes { * * Emits a {IVotes-DelegateVotesChanged} event. */ - function _update(address from, address to, uint256 amount) internal virtual override { - super._update(from, to, amount); + function _update(address from, address to, uint256 value) internal virtual override { + super._update(from, to, value); if (from == address(0)) { uint256 supply = totalSupply(); uint256 cap = _maxSupply(); @@ -50,11 +50,14 @@ abstract contract ERC20Votes is ERC20, Votes { revert ERC20ExceededSafeSupply(supply, cap); } } - _transferVotingUnits(from, to, amount); + _transferVotingUnits(from, to, value); } /** - * @dev Returns the balance of `account`. + * @dev Returns the voting units of an `account`. + * + * WARNING: Overriding this function may compromise the internal vote accounting. + * `ERC20Votes` assumes tokens map to voting units 1:1 and this is not easy to change. */ function _getVotingUnits(address account) internal view virtual override returns (uint256) { return balanceOf(account); diff --git a/contracts/token/ERC20/extensions/ERC20Wrapper.sol b/contracts/token/ERC20/extensions/ERC20Wrapper.sol index 2cbff6223..c9e33d00a 100644 --- a/contracts/token/ERC20/extensions/ERC20Wrapper.sol +++ b/contracts/token/ERC20/extensions/ERC20Wrapper.sol @@ -51,22 +51,28 @@ abstract contract ERC20Wrapper is ERC20 { /** * @dev Allow a user to deposit underlying tokens and mint the corresponding number of wrapped tokens. */ - function depositFor(address account, uint256 amount) public virtual returns (bool) { + function depositFor(address account, uint256 value) public virtual returns (bool) { address sender = _msgSender(); if (sender == address(this)) { revert ERC20InvalidSender(address(this)); } - SafeERC20.safeTransferFrom(_underlying, sender, address(this), amount); - _mint(account, amount); + if (account == address(this)) { + revert ERC20InvalidReceiver(account); + } + SafeERC20.safeTransferFrom(_underlying, sender, address(this), value); + _mint(account, value); return true; } /** * @dev Allow a user to burn a number of wrapped tokens and withdraw the corresponding number of underlying tokens. */ - function withdrawTo(address account, uint256 amount) public virtual returns (bool) { - _burn(_msgSender(), amount); - SafeERC20.safeTransfer(_underlying, account, amount); + function withdrawTo(address account, uint256 value) public virtual returns (bool) { + if (account == address(this)) { + revert ERC20InvalidReceiver(account); + } + _burn(_msgSender(), value); + SafeERC20.safeTransfer(_underlying, account, value); return true; } diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index ba2b1573f..25ac69fa9 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -486,7 +486,7 @@ abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Er * that `ownerOf(tokenId)` is `a`. */ // solhint-disable-next-line func-name-mixedcase - function __unsafe_increaseBalance(address account, uint256 amount) internal { - _balances[account] += amount; + function __unsafe_increaseBalance(address account, uint256 value) internal { + _balances[account] += value; } } diff --git a/contracts/token/ERC721/extensions/ERC721Pausable.sol b/contracts/token/ERC721/extensions/ERC721Pausable.sol index a4effc549..5777ac36e 100644 --- a/contracts/token/ERC721/extensions/ERC721Pausable.sol +++ b/contracts/token/ERC721/extensions/ERC721Pausable.sol @@ -17,7 +17,7 @@ import {Pausable} from "../../../security/Pausable.sol"; * addition to inheriting this contract, you must define both functions, invoking the * {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate * access control, e.g. using {AccessControl} or {Ownable}. Not doing so will - * make the contract unpausable. + * make the contract pause mechanism of the contract unreachable, and thus unusable. */ abstract contract ERC721Pausable is ERC721, Pausable { /** diff --git a/contracts/utils/Nonces.sol b/contracts/utils/Nonces.sol index f8ea1dfd3..d5458b10a 100644 --- a/contracts/utils/Nonces.sol +++ b/contracts/utils/Nonces.sol @@ -13,7 +13,7 @@ abstract contract Nonces { mapping(address => uint256) private _nonces; /** - * @dev Returns an address nonce. + * @dev Returns an the next unused nonce for an address. */ function nonces(address owner) public view virtual returns (uint256) { return _nonces[owner]; diff --git a/contracts/utils/structs/Checkpoints.sol b/contracts/utils/structs/Checkpoints.sol index 47ad91bbf..56b7035b9 100644 --- a/contracts/utils/structs/Checkpoints.sol +++ b/contracts/utils/structs/Checkpoints.sol @@ -5,13 +5,12 @@ pragma solidity ^0.8.19; import {Math} from "../math/Math.sol"; -import {SafeCast} from "../math/SafeCast.sol"; /** - * @dev This library defines the `History` struct, for checkpointing values as they change at different points in + * @dev This library defines the `Trace*` struct, for checkpointing values as they change at different points in * time, and later looking up past values by block number. See {Votes} as an example. * - * To create a history of checkpoints define a variable type `Checkpoints.History` in your contract, and store a new + * To create a history of checkpoints define a variable type `Checkpoints.Trace*` in your contract, and store a new * checkpoint for the current transaction block using the {push} function. * * _Available since v4.5._ @@ -35,6 +34,8 @@ library Checkpoints { * @dev Pushes a (`key`, `value`) pair into a Trace224 so that it is stored as the checkpoint. * * Returns previous value and new value. + * + * IMPORTANT: Never accept `key` as a user input, since an arbitrary `type(uint32).max` key set will disable the library. */ function push(Trace224 storage self, uint32 key, uint224 value) internal returns (uint224, uint224) { return _insert(self._checkpoints, key, value); @@ -220,6 +221,8 @@ library Checkpoints { * @dev Pushes a (`key`, `value`) pair into a Trace160 so that it is stored as the checkpoint. * * Returns previous value and new value. + * + * IMPORTANT: Never accept `key` as a user input, since an arbitrary `type(uint96).max` key set will disable the library. */ function push(Trace160 storage self, uint96 key, uint160 value) internal returns (uint160, uint160) { return _insert(self._checkpoints, key, value); diff --git a/scripts/generate/templates/Checkpoints.js b/scripts/generate/templates/Checkpoints.js index d5ab745a0..d635c8462 100644 --- a/scripts/generate/templates/Checkpoints.js +++ b/scripts/generate/templates/Checkpoints.js @@ -6,13 +6,12 @@ const header = `\ pragma solidity ^0.8.19; import {Math} from "../math/Math.sol"; -import {SafeCast} from "../math/SafeCast.sol"; /** - * @dev This library defines the \`History\` struct, for checkpointing values as they change at different points in + * @dev This library defines the \`Trace*\` struct, for checkpointing values as they change at different points in * time, and later looking up past values by block number. See {Votes} as an example. * - * To create a history of checkpoints define a variable type \`Checkpoints.History\` in your contract, and store a new + * To create a history of checkpoints define a variable type \`Checkpoints.Trace*\` in your contract, and store a new * checkpoint for the current transaction block using the {push} function. * * _Available since v4.5._ @@ -40,6 +39,8 @@ struct ${opts.checkpointTypeName} { * @dev Pushes a (\`key\`, \`value\`) pair into a ${opts.historyTypeName} so that it is stored as the checkpoint. * * Returns previous value and new value. + * + * IMPORTANT: Never accept \`key\` as a user input, since an arbitrary \`type(${opts.keyTypeName}).max\` key set will disable the library. */ function push( ${opts.historyTypeName} storage self, diff --git a/test/governance/utils/Votes.behavior.js b/test/governance/utils/Votes.behavior.js index 20ebdba4f..5836cc351 100644 --- a/test/governance/utils/Votes.behavior.js +++ b/test/governance/utils/Votes.behavior.js @@ -70,8 +70,8 @@ function shouldBehaveLikeVotes(accounts, tokens, { mode = 'blocknumber', fungibl }); expectEvent(receipt, 'DelegateVotesChanged', { delegate: accounts[1], - previousBalance: '0', - newBalance: weight, + previousVotes: '0', + newVotes: weight, }); expect(await this.votes.delegates(accounts[1])).to.be.equal(accounts[1]); @@ -100,13 +100,13 @@ function shouldBehaveLikeVotes(accounts, tokens, { mode = 'blocknumber', fungibl }); expectEvent(receipt, 'DelegateVotesChanged', { delegate: accounts[1], - previousBalance: weight, - newBalance: '0', + previousVotes: weight, + newVotes: '0', }); expectEvent(receipt, 'DelegateVotesChanged', { delegate: accounts[2], - previousBalance: '0', - newBalance: weight, + previousVotes: '0', + newVotes: weight, }); expect(await this.votes.delegates(accounts[1])).to.be.equal(accounts[2]); @@ -152,8 +152,8 @@ function shouldBehaveLikeVotes(accounts, tokens, { mode = 'blocknumber', fungibl }); expectEvent(receipt, 'DelegateVotesChanged', { delegate: delegatee, - previousBalance: '0', - newBalance: weight, + previousVotes: '0', + newVotes: weight, }); expect(await this.votes.delegates(delegator.address)).to.be.equal(delegatee); diff --git a/test/token/ERC1155/ERC1155.behavior.js b/test/token/ERC1155/ERC1155.behavior.js index 4bf4a7319..8df30a814 100644 --- a/test/token/ERC1155/ERC1155.behavior.js +++ b/test/token/ERC1155/ERC1155.behavior.js @@ -14,8 +14,8 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m const secondTokenId = new BN(2); const unknownTokenId = new BN(3); - const firstAmount = new BN(1000); - const secondAmount = new BN(2000); + const firstTokenValue = new BN(1000); + const secondTokenValue = new BN(2000); const RECEIVER_SINGLE_MAGIC_VALUE = '0xf23a6e61'; const RECEIVER_BATCH_MAGIC_VALUE = '0xbc197c81'; @@ -38,18 +38,18 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m context('when accounts own some tokens', function () { beforeEach(async function () { - await this.token.$_mint(firstTokenHolder, firstTokenId, firstAmount, '0x', { + await this.token.$_mint(firstTokenHolder, firstTokenId, firstTokenValue, '0x', { from: minter, }); - await this.token.$_mint(secondTokenHolder, secondTokenId, secondAmount, '0x', { + await this.token.$_mint(secondTokenHolder, secondTokenId, secondTokenValue, '0x', { from: minter, }); }); it('returns the amount of tokens owned by the given addresses', async function () { - expect(await this.token.balanceOf(firstTokenHolder, firstTokenId)).to.be.bignumber.equal(firstAmount); + expect(await this.token.balanceOf(firstTokenHolder, firstTokenId)).to.be.bignumber.equal(firstTokenValue); - expect(await this.token.balanceOf(secondTokenHolder, secondTokenId)).to.be.bignumber.equal(secondAmount); + expect(await this.token.balanceOf(secondTokenHolder, secondTokenId)).to.be.bignumber.equal(secondTokenValue); expect(await this.token.balanceOf(firstTokenHolder, unknownTokenId)).to.be.bignumber.equal('0'); }); @@ -99,10 +99,10 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m context('when accounts own some tokens', function () { beforeEach(async function () { - await this.token.$_mint(firstTokenHolder, firstTokenId, firstAmount, '0x', { + await this.token.$_mint(firstTokenHolder, firstTokenId, firstTokenValue, '0x', { from: minter, }); - await this.token.$_mint(secondTokenHolder, secondTokenId, secondAmount, '0x', { + await this.token.$_mint(secondTokenHolder, secondTokenId, secondTokenValue, '0x', { from: minter, }); }); @@ -113,8 +113,8 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m [secondTokenId, firstTokenId, unknownTokenId], ); expect(result).to.be.an('array'); - expect(result[0]).to.be.a.bignumber.equal(secondAmount); - expect(result[1]).to.be.a.bignumber.equal(firstAmount); + expect(result[0]).to.be.a.bignumber.equal(secondTokenValue); + expect(result[1]).to.be.a.bignumber.equal(firstTokenValue); expect(result[2]).to.be.a.bignumber.equal('0'); }); @@ -125,9 +125,9 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m ); expect(result).to.be.an('array'); expect(result[0]).to.be.a.bignumber.equal(result[2]); - expect(result[0]).to.be.a.bignumber.equal(firstAmount); - expect(result[1]).to.be.a.bignumber.equal(secondAmount); - expect(result[2]).to.be.a.bignumber.equal(firstAmount); + expect(result[0]).to.be.a.bignumber.equal(firstTokenValue); + expect(result[1]).to.be.a.bignumber.equal(secondTokenValue); + expect(result[2]).to.be.a.bignumber.equal(firstTokenValue); }); }); }); @@ -151,38 +151,38 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m expect(await this.token.isApprovedForAll(multiTokenHolder, proxy)).to.be.equal(false); }); - it('reverts if attempting to approve self as an operator', async function () { + it('reverts if attempting to approve zero address as an operator', async function () { await expectRevertCustomError( - this.token.setApprovalForAll(multiTokenHolder, true, { from: multiTokenHolder }), + this.token.setApprovalForAll(constants.ZERO_ADDRESS, true, { from: multiTokenHolder }), 'ERC1155InvalidOperator', - [multiTokenHolder], + [constants.ZERO_ADDRESS], ); }); }); describe('safeTransferFrom', function () { beforeEach(async function () { - await this.token.$_mint(multiTokenHolder, firstTokenId, firstAmount, '0x', { + await this.token.$_mint(multiTokenHolder, firstTokenId, firstTokenValue, '0x', { from: minter, }); - await this.token.$_mint(multiTokenHolder, secondTokenId, secondAmount, '0x', { + await this.token.$_mint(multiTokenHolder, secondTokenId, secondTokenValue, '0x', { from: minter, }); }); it('reverts when transferring more than balance', async function () { await expectRevertCustomError( - this.token.safeTransferFrom(multiTokenHolder, recipient, firstTokenId, firstAmount.addn(1), '0x', { + this.token.safeTransferFrom(multiTokenHolder, recipient, firstTokenId, firstTokenValue.addn(1), '0x', { from: multiTokenHolder, }), 'ERC1155InsufficientBalance', - [multiTokenHolder, firstAmount, firstAmount.addn(1), firstTokenId], + [multiTokenHolder, firstTokenValue, firstTokenValue.addn(1), firstTokenId], ); }); it('reverts when transferring to zero address', async function () { await expectRevertCustomError( - this.token.safeTransferFrom(multiTokenHolder, ZERO_ADDRESS, firstTokenId, firstAmount, '0x', { + this.token.safeTransferFrom(multiTokenHolder, ZERO_ADDRESS, firstTokenId, firstTokenValue, '0x', { from: multiTokenHolder, }), 'ERC1155InvalidReceiver', @@ -219,7 +219,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m multiTokenHolder, recipient, firstTokenId, - firstAmount, + firstTokenValue, '0x', { from: multiTokenHolder, @@ -231,12 +231,12 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m operator: multiTokenHolder, from: multiTokenHolder, id: firstTokenId, - value: firstAmount, + value: firstTokenValue, }); it('preserves existing balances which are not transferred by multiTokenHolder', async function () { const balance1 = await this.token.balanceOf(multiTokenHolder, secondTokenId); - expect(balance1).to.be.a.bignumber.equal(secondAmount); + expect(balance1).to.be.a.bignumber.equal(secondTokenValue); const balance2 = await this.token.balanceOf(recipient, secondTokenId); expect(balance2).to.be.a.bignumber.equal('0'); @@ -251,7 +251,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m it('reverts', async function () { await expectRevertCustomError( - this.token.safeTransferFrom(multiTokenHolder, recipient, firstTokenId, firstAmount, '0x', { + this.token.safeTransferFrom(multiTokenHolder, recipient, firstTokenId, firstTokenValue, '0x', { from: proxy, }), 'ERC1155MissingApprovalForAll', @@ -268,7 +268,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m multiTokenHolder, recipient, firstTokenId, - firstAmount, + firstTokenValue, '0x', { from: proxy, @@ -280,7 +280,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m operator: proxy, from: multiTokenHolder, id: firstTokenId, - value: firstAmount, + value: firstTokenValue, }); it("preserves operator's balances not involved in the transfer", async function () { @@ -309,7 +309,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m multiTokenHolder, this.receiver.address, firstTokenId, - firstAmount, + firstTokenValue, '0x', { from: multiTokenHolder }, ); @@ -320,7 +320,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m operator: multiTokenHolder, from: multiTokenHolder, id: firstTokenId, - value: firstAmount, + value: firstTokenValue, }); it('calls onERC1155Received', async function () { @@ -328,7 +328,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m operator: multiTokenHolder, from: multiTokenHolder, id: firstTokenId, - value: firstAmount, + value: firstTokenValue, data: null, }); }); @@ -342,7 +342,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m multiTokenHolder, this.receiver.address, firstTokenId, - firstAmount, + firstTokenValue, data, { from: multiTokenHolder }, ); @@ -353,7 +353,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m operator: multiTokenHolder, from: multiTokenHolder, id: firstTokenId, - value: firstAmount, + value: firstTokenValue, }); it('calls onERC1155Received', async function () { @@ -361,7 +361,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m operator: multiTokenHolder, from: multiTokenHolder, id: firstTokenId, - value: firstAmount, + value: firstTokenValue, data, }); }); @@ -375,7 +375,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m it('reverts', async function () { await expectRevertCustomError( - this.token.safeTransferFrom(multiTokenHolder, this.receiver.address, firstTokenId, firstAmount, '0x', { + this.token.safeTransferFrom(multiTokenHolder, this.receiver.address, firstTokenId, firstTokenValue, '0x', { from: multiTokenHolder, }), 'ERC1155InvalidReceiver', @@ -396,9 +396,16 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m it('reverts', async function () { await expectRevert( - this.token.safeTransferFrom(multiTokenHolder, this.receiver.address, firstTokenId, firstAmount, '0x', { - from: multiTokenHolder, - }), + this.token.safeTransferFrom( + multiTokenHolder, + this.receiver.address, + firstTokenId, + firstTokenValue, + '0x', + { + from: multiTokenHolder, + }, + ), 'ERC1155ReceiverMock: reverting on receive', ); }); @@ -415,9 +422,16 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m it('reverts', async function () { await expectRevertCustomError( - this.token.safeTransferFrom(multiTokenHolder, this.receiver.address, firstTokenId, firstAmount, '0x', { - from: multiTokenHolder, - }), + this.token.safeTransferFrom( + multiTokenHolder, + this.receiver.address, + firstTokenId, + firstTokenValue, + '0x', + { + from: multiTokenHolder, + }, + ), 'ERC1155InvalidReceiver', [this.receiver.address], ); @@ -435,9 +449,16 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m it('reverts', async function () { await expectRevertCustomError( - this.token.safeTransferFrom(multiTokenHolder, this.receiver.address, firstTokenId, firstAmount, '0x', { - from: multiTokenHolder, - }), + this.token.safeTransferFrom( + multiTokenHolder, + this.receiver.address, + firstTokenId, + firstTokenValue, + '0x', + { + from: multiTokenHolder, + }, + ), 'CustomError', [RECEIVER_SINGLE_MAGIC_VALUE], ); @@ -455,9 +476,16 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m it('reverts', async function () { await expectRevert.unspecified( - this.token.safeTransferFrom(multiTokenHolder, this.receiver.address, firstTokenId, firstAmount, '0x', { - from: multiTokenHolder, - }), + this.token.safeTransferFrom( + multiTokenHolder, + this.receiver.address, + firstTokenId, + firstTokenValue, + '0x', + { + from: multiTokenHolder, + }, + ), ); }); }); @@ -467,9 +495,16 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m it('reverts', async function () { const invalidReceiver = this.token; await expectRevert.unspecified( - this.token.safeTransferFrom(multiTokenHolder, invalidReceiver.address, firstTokenId, firstAmount, '0x', { - from: multiTokenHolder, - }), + this.token.safeTransferFrom( + multiTokenHolder, + invalidReceiver.address, + firstTokenId, + firstTokenValue, + '0x', + { + from: multiTokenHolder, + }, + ), ); }); }); @@ -477,49 +512,49 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m describe('safeBatchTransferFrom', function () { beforeEach(async function () { - await this.token.$_mint(multiTokenHolder, firstTokenId, firstAmount, '0x', { + await this.token.$_mint(multiTokenHolder, firstTokenId, firstTokenValue, '0x', { from: minter, }); - await this.token.$_mint(multiTokenHolder, secondTokenId, secondAmount, '0x', { + await this.token.$_mint(multiTokenHolder, secondTokenId, secondTokenValue, '0x', { from: minter, }); }); - it('reverts when transferring amount more than any of balances', async function () { + it('reverts when transferring value more than any of balances', async function () { await expectRevertCustomError( this.token.safeBatchTransferFrom( multiTokenHolder, recipient, [firstTokenId, secondTokenId], - [firstAmount, secondAmount.addn(1)], + [firstTokenValue, secondTokenValue.addn(1)], '0x', { from: multiTokenHolder }, ), 'ERC1155InsufficientBalance', - [multiTokenHolder, secondAmount, secondAmount.addn(1), secondTokenId], + [multiTokenHolder, secondTokenValue, secondTokenValue.addn(1), secondTokenId], ); }); - it("reverts when ids array length doesn't match amounts array length", async function () { + it("reverts when ids array length doesn't match values array length", async function () { const ids1 = [firstTokenId]; - const amounts1 = [firstAmount, secondAmount]; + const tokenValues1 = [firstTokenValue, secondTokenValue]; await expectRevertCustomError( - this.token.safeBatchTransferFrom(multiTokenHolder, recipient, ids1, amounts1, '0x', { + this.token.safeBatchTransferFrom(multiTokenHolder, recipient, ids1, tokenValues1, '0x', { from: multiTokenHolder, }), 'ERC1155InvalidArrayLength', - [ids1.length, amounts1.length], + [ids1.length, tokenValues1.length], ); const ids2 = [firstTokenId, secondTokenId]; - const amounts2 = [firstAmount]; + const tokenValues2 = [firstTokenValue]; await expectRevertCustomError( - this.token.safeBatchTransferFrom(multiTokenHolder, recipient, ids2, amounts2, '0x', { + this.token.safeBatchTransferFrom(multiTokenHolder, recipient, ids2, tokenValues2, '0x', { from: multiTokenHolder, }), 'ERC1155InvalidArrayLength', - [ids2.length, amounts2.length], + [ids2.length, tokenValues2.length], ); }); @@ -529,7 +564,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m multiTokenHolder, ZERO_ADDRESS, [firstTokenId, secondTokenId], - [firstAmount, secondAmount], + [firstTokenValue, secondTokenValue], '0x', { from: multiTokenHolder }, ), @@ -540,7 +575,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m it('reverts when transferring from zero address', async function () { await expectRevertCustomError( - this.token.$_safeBatchTransferFrom(ZERO_ADDRESS, multiTokenHolder, [firstTokenId], [firstAmount], '0x'), + this.token.$_safeBatchTransferFrom(ZERO_ADDRESS, multiTokenHolder, [firstTokenId], [firstTokenValue], '0x'), 'ERC1155InvalidSender', [ZERO_ADDRESS], ); @@ -579,7 +614,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m multiTokenHolder, recipient, [firstTokenId, secondTokenId], - [firstAmount, secondAmount], + [firstTokenValue, secondTokenValue], '0x', { from: multiTokenHolder }, ); @@ -589,7 +624,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m operator: multiTokenHolder, from: multiTokenHolder, ids: [firstTokenId, secondTokenId], - values: [firstAmount, secondAmount], + values: [firstTokenValue, secondTokenValue], }); }); @@ -605,7 +640,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m multiTokenHolder, recipient, [firstTokenId, secondTokenId], - [firstAmount, secondAmount], + [firstTokenValue, secondTokenValue], '0x', { from: proxy }, ), @@ -623,7 +658,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m multiTokenHolder, recipient, [firstTokenId, secondTokenId], - [firstAmount, secondAmount], + [firstTokenValue, secondTokenValue], '0x', { from: proxy }, ); @@ -633,7 +668,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m operator: proxy, from: multiTokenHolder, ids: [firstTokenId, secondTokenId], - values: [firstAmount, secondAmount], + values: [firstTokenValue, secondTokenValue], }); it("preserves operator's balances not involved in the transfer", async function () { @@ -661,7 +696,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m multiTokenHolder, this.receiver.address, [firstTokenId, secondTokenId], - [firstAmount, secondAmount], + [firstTokenValue, secondTokenValue], '0x', { from: multiTokenHolder }, ); @@ -672,7 +707,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m operator: multiTokenHolder, from: multiTokenHolder, ids: [firstTokenId, secondTokenId], - values: [firstAmount, secondAmount], + values: [firstTokenValue, secondTokenValue], }); it('calls onERC1155BatchReceived', async function () { @@ -680,7 +715,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m operator: multiTokenHolder, from: multiTokenHolder, // ids: [firstTokenId, secondTokenId], - // values: [firstAmount, secondAmount], + // values: [firstTokenValue, secondTokenValue], data: null, }); }); @@ -694,7 +729,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m multiTokenHolder, this.receiver.address, [firstTokenId, secondTokenId], - [firstAmount, secondAmount], + [firstTokenValue, secondTokenValue], data, { from: multiTokenHolder }, ); @@ -705,7 +740,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m operator: multiTokenHolder, from: multiTokenHolder, ids: [firstTokenId, secondTokenId], - values: [firstAmount, secondAmount], + values: [firstTokenValue, secondTokenValue], }); it('calls onERC1155Received', async function () { @@ -713,7 +748,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m operator: multiTokenHolder, from: multiTokenHolder, // ids: [firstTokenId, secondTokenId], - // values: [firstAmount, secondAmount], + // values: [firstTokenValue, secondTokenValue], data, }); }); @@ -735,7 +770,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m multiTokenHolder, this.receiver.address, [firstTokenId, secondTokenId], - [firstAmount, secondAmount], + [firstTokenValue, secondTokenValue], '0x', { from: multiTokenHolder }, ), @@ -761,7 +796,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m multiTokenHolder, this.receiver.address, [firstTokenId, secondTokenId], - [firstAmount, secondAmount], + [firstTokenValue, secondTokenValue], '0x', { from: multiTokenHolder }, ), @@ -785,7 +820,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m multiTokenHolder, this.receiver.address, [firstTokenId, secondTokenId], - [firstAmount, secondAmount], + [firstTokenValue, secondTokenValue], '0x', { from: multiTokenHolder }, ), @@ -810,7 +845,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m multiTokenHolder, this.receiver.address, [firstTokenId, secondTokenId], - [firstAmount, secondAmount], + [firstTokenValue, secondTokenValue], '0x', { from: multiTokenHolder }, ), @@ -835,7 +870,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m multiTokenHolder, this.receiver.address, [firstTokenId, secondTokenId], - [firstAmount, secondAmount], + [firstTokenValue, secondTokenValue], '0x', { from: multiTokenHolder }, ), @@ -852,7 +887,7 @@ function shouldBehaveLikeERC1155([minter, firstTokenHolder, secondTokenHolder, m multiTokenHolder, invalidReceiver.address, [firstTokenId, secondTokenId], - [firstAmount, secondAmount], + [firstTokenValue, secondTokenValue], '0x', { from: multiTokenHolder }, ), diff --git a/test/token/ERC1155/ERC1155.test.js b/test/token/ERC1155/ERC1155.test.js index 23555dd54..58d747a4b 100644 --- a/test/token/ERC1155/ERC1155.test.js +++ b/test/token/ERC1155/ERC1155.test.js @@ -21,19 +21,19 @@ contract('ERC1155', function (accounts) { describe('internal functions', function () { const tokenId = new BN(1990); - const mintAmount = new BN(9001); - const burnAmount = new BN(3000); + const mintValue = new BN(9001); + const burnValue = new BN(3000); const tokenBatchIds = [new BN(2000), new BN(2010), new BN(2020)]; - const mintAmounts = [new BN(5000), new BN(10000), new BN(42195)]; - const burnAmounts = [new BN(5000), new BN(9001), new BN(195)]; + const mintValues = [new BN(5000), new BN(10000), new BN(42195)]; + const burnValues = [new BN(5000), new BN(9001), new BN(195)]; const data = '0x12345678'; describe('_mint', function () { it('reverts with a zero destination address', async function () { await expectRevertCustomError( - this.token.$_mint(ZERO_ADDRESS, tokenId, mintAmount, data), + this.token.$_mint(ZERO_ADDRESS, tokenId, mintValue, data), 'ERC1155InvalidReceiver', [ZERO_ADDRESS], ); @@ -41,7 +41,7 @@ contract('ERC1155', function (accounts) { context('with minted tokens', function () { beforeEach(async function () { - this.receipt = await this.token.$_mint(tokenHolder, tokenId, mintAmount, data, { from: operator }); + this.receipt = await this.token.$_mint(tokenHolder, tokenId, mintValue, data, { from: operator }); }); it('emits a TransferSingle event', function () { @@ -50,12 +50,12 @@ contract('ERC1155', function (accounts) { from: ZERO_ADDRESS, to: tokenHolder, id: tokenId, - value: mintAmount, + value: mintValue, }); }); - it('credits the minted amount of tokens', async function () { - expect(await this.token.balanceOf(tokenHolder, tokenId)).to.be.bignumber.equal(mintAmount); + it('credits the minted token value', async function () { + expect(await this.token.balanceOf(tokenHolder, tokenId)).to.be.bignumber.equal(mintValue); }); }); }); @@ -63,7 +63,7 @@ contract('ERC1155', function (accounts) { describe('_mintBatch', function () { it('reverts with a zero destination address', async function () { await expectRevertCustomError( - this.token.$_mintBatch(ZERO_ADDRESS, tokenBatchIds, mintAmounts, data), + this.token.$_mintBatch(ZERO_ADDRESS, tokenBatchIds, mintValues, data), 'ERC1155InvalidReceiver', [ZERO_ADDRESS], ); @@ -71,21 +71,21 @@ contract('ERC1155', function (accounts) { it('reverts if length of inputs do not match', async function () { await expectRevertCustomError( - this.token.$_mintBatch(tokenBatchHolder, tokenBatchIds, mintAmounts.slice(1), data), + this.token.$_mintBatch(tokenBatchHolder, tokenBatchIds, mintValues.slice(1), data), 'ERC1155InvalidArrayLength', - [tokenBatchIds.length, mintAmounts.length - 1], + [tokenBatchIds.length, mintValues.length - 1], ); await expectRevertCustomError( - this.token.$_mintBatch(tokenBatchHolder, tokenBatchIds.slice(1), mintAmounts, data), + this.token.$_mintBatch(tokenBatchHolder, tokenBatchIds.slice(1), mintValues, data), 'ERC1155InvalidArrayLength', - [tokenBatchIds.length - 1, mintAmounts.length], + [tokenBatchIds.length - 1, mintValues.length], ); }); context('with minted batch of tokens', function () { beforeEach(async function () { - this.receipt = await this.token.$_mintBatch(tokenBatchHolder, tokenBatchIds, mintAmounts, data, { + this.receipt = await this.token.$_mintBatch(tokenBatchHolder, tokenBatchIds, mintValues, data, { from: operator, }); }); @@ -105,7 +105,7 @@ contract('ERC1155', function (accounts) { ); for (let i = 0; i < holderBatchBalances.length; i++) { - expect(holderBatchBalances[i]).to.be.bignumber.equal(mintAmounts[i]); + expect(holderBatchBalances[i]).to.be.bignumber.equal(mintValues[i]); } }); }); @@ -113,33 +113,33 @@ contract('ERC1155', function (accounts) { describe('_burn', function () { it("reverts when burning the zero account's tokens", async function () { - await expectRevertCustomError(this.token.$_burn(ZERO_ADDRESS, tokenId, mintAmount), 'ERC1155InvalidSender', [ + await expectRevertCustomError(this.token.$_burn(ZERO_ADDRESS, tokenId, mintValue), 'ERC1155InvalidSender', [ ZERO_ADDRESS, ]); }); it('reverts when burning a non-existent token id', async function () { await expectRevertCustomError( - this.token.$_burn(tokenHolder, tokenId, mintAmount), + this.token.$_burn(tokenHolder, tokenId, mintValue), 'ERC1155InsufficientBalance', - [tokenHolder, 0, mintAmount, tokenId], + [tokenHolder, 0, mintValue, tokenId], ); }); it('reverts when burning more than available tokens', async function () { - await this.token.$_mint(tokenHolder, tokenId, mintAmount, data, { from: operator }); + await this.token.$_mint(tokenHolder, tokenId, mintValue, data, { from: operator }); await expectRevertCustomError( - this.token.$_burn(tokenHolder, tokenId, mintAmount.addn(1)), + this.token.$_burn(tokenHolder, tokenId, mintValue.addn(1)), 'ERC1155InsufficientBalance', - [tokenHolder, mintAmount, mintAmount.addn(1), tokenId], + [tokenHolder, mintValue, mintValue.addn(1), tokenId], ); }); context('with minted-then-burnt tokens', function () { beforeEach(async function () { - await this.token.$_mint(tokenHolder, tokenId, mintAmount, data); - this.receipt = await this.token.$_burn(tokenHolder, tokenId, burnAmount, { from: operator }); + await this.token.$_mint(tokenHolder, tokenId, mintValue, data); + this.receipt = await this.token.$_burn(tokenHolder, tokenId, burnValue, { from: operator }); }); it('emits a TransferSingle event', function () { @@ -148,12 +148,12 @@ contract('ERC1155', function (accounts) { from: tokenHolder, to: ZERO_ADDRESS, id: tokenId, - value: burnAmount, + value: burnValue, }); }); it('accounts for both minting and burning', async function () { - expect(await this.token.balanceOf(tokenHolder, tokenId)).to.be.bignumber.equal(mintAmount.sub(burnAmount)); + expect(await this.token.balanceOf(tokenHolder, tokenId)).to.be.bignumber.equal(mintValue.sub(burnValue)); }); }); }); @@ -161,7 +161,7 @@ contract('ERC1155', function (accounts) { describe('_burnBatch', function () { it("reverts when burning the zero account's tokens", async function () { await expectRevertCustomError( - this.token.$_burnBatch(ZERO_ADDRESS, tokenBatchIds, burnAmounts), + this.token.$_burnBatch(ZERO_ADDRESS, tokenBatchIds, burnValues), 'ERC1155InvalidSender', [ZERO_ADDRESS], ); @@ -169,30 +169,30 @@ contract('ERC1155', function (accounts) { it('reverts if length of inputs do not match', async function () { await expectRevertCustomError( - this.token.$_burnBatch(tokenBatchHolder, tokenBatchIds, burnAmounts.slice(1)), + this.token.$_burnBatch(tokenBatchHolder, tokenBatchIds, burnValues.slice(1)), 'ERC1155InvalidArrayLength', - [tokenBatchIds.length, burnAmounts.length - 1], + [tokenBatchIds.length, burnValues.length - 1], ); await expectRevertCustomError( - this.token.$_burnBatch(tokenBatchHolder, tokenBatchIds.slice(1), burnAmounts), + this.token.$_burnBatch(tokenBatchHolder, tokenBatchIds.slice(1), burnValues), 'ERC1155InvalidArrayLength', - [tokenBatchIds.length - 1, burnAmounts.length], + [tokenBatchIds.length - 1, burnValues.length], ); }); it('reverts when burning a non-existent token id', async function () { await expectRevertCustomError( - this.token.$_burnBatch(tokenBatchHolder, tokenBatchIds, burnAmounts), + this.token.$_burnBatch(tokenBatchHolder, tokenBatchIds, burnValues), 'ERC1155InsufficientBalance', - [tokenBatchHolder, 0, tokenBatchIds[0], burnAmounts[0]], + [tokenBatchHolder, 0, tokenBatchIds[0], burnValues[0]], ); }); context('with minted-then-burnt tokens', function () { beforeEach(async function () { - await this.token.$_mintBatch(tokenBatchHolder, tokenBatchIds, mintAmounts, data); - this.receipt = await this.token.$_burnBatch(tokenBatchHolder, tokenBatchIds, burnAmounts, { from: operator }); + await this.token.$_mintBatch(tokenBatchHolder, tokenBatchIds, mintValues, data); + this.receipt = await this.token.$_burnBatch(tokenBatchHolder, tokenBatchIds, burnValues, { from: operator }); }); it('emits a TransferBatch event', function () { @@ -201,7 +201,7 @@ contract('ERC1155', function (accounts) { from: tokenBatchHolder, to: ZERO_ADDRESS, // ids: tokenBatchIds, - // values: burnAmounts, + // values: burnValues, }); }); @@ -212,7 +212,7 @@ contract('ERC1155', function (accounts) { ); for (let i = 0; i < holderBatchBalances.length; i++) { - expect(holderBatchBalances[i]).to.be.bignumber.equal(mintAmounts[i].sub(burnAmounts[i])); + expect(holderBatchBalances[i]).to.be.bignumber.equal(mintValues[i].sub(burnValues[i])); } }); }); diff --git a/test/token/ERC1155/extensions/ERC1155Burnable.test.js b/test/token/ERC1155/extensions/ERC1155Burnable.test.js index 65a2f95f4..fc94db052 100644 --- a/test/token/ERC1155/extensions/ERC1155Burnable.test.js +++ b/test/token/ERC1155/extensions/ERC1155Burnable.test.js @@ -12,32 +12,32 @@ contract('ERC1155Burnable', function (accounts) { const uri = 'https://token.com'; const tokenIds = [new BN('42'), new BN('1137')]; - const amounts = [new BN('3000'), new BN('9902')]; + const values = [new BN('3000'), new BN('9902')]; beforeEach(async function () { this.token = await ERC1155Burnable.new(uri); - await this.token.$_mint(holder, tokenIds[0], amounts[0], '0x'); - await this.token.$_mint(holder, tokenIds[1], amounts[1], '0x'); + await this.token.$_mint(holder, tokenIds[0], values[0], '0x'); + await this.token.$_mint(holder, tokenIds[1], values[1], '0x'); }); describe('burn', function () { it('holder can burn their tokens', async function () { - await this.token.burn(holder, tokenIds[0], amounts[0].subn(1), { from: holder }); + await this.token.burn(holder, tokenIds[0], values[0].subn(1), { from: holder }); expect(await this.token.balanceOf(holder, tokenIds[0])).to.be.bignumber.equal('1'); }); it("approved operators can burn the holder's tokens", async function () { await this.token.setApprovalForAll(operator, true, { from: holder }); - await this.token.burn(holder, tokenIds[0], amounts[0].subn(1), { from: operator }); + await this.token.burn(holder, tokenIds[0], values[0].subn(1), { from: operator }); expect(await this.token.balanceOf(holder, tokenIds[0])).to.be.bignumber.equal('1'); }); it("unapproved accounts cannot burn the holder's tokens", async function () { await expectRevertCustomError( - this.token.burn(holder, tokenIds[0], amounts[0].subn(1), { from: other }), + this.token.burn(holder, tokenIds[0], values[0].subn(1), { from: other }), 'ERC1155MissingApprovalForAll', [other, holder], ); @@ -46,7 +46,7 @@ contract('ERC1155Burnable', function (accounts) { describe('burnBatch', function () { it('holder can burn their tokens', async function () { - await this.token.burnBatch(holder, tokenIds, [amounts[0].subn(1), amounts[1].subn(2)], { from: holder }); + await this.token.burnBatch(holder, tokenIds, [values[0].subn(1), values[1].subn(2)], { from: holder }); expect(await this.token.balanceOf(holder, tokenIds[0])).to.be.bignumber.equal('1'); expect(await this.token.balanceOf(holder, tokenIds[1])).to.be.bignumber.equal('2'); @@ -54,7 +54,7 @@ contract('ERC1155Burnable', function (accounts) { it("approved operators can burn the holder's tokens", async function () { await this.token.setApprovalForAll(operator, true, { from: holder }); - await this.token.burnBatch(holder, tokenIds, [amounts[0].subn(1), amounts[1].subn(2)], { from: operator }); + await this.token.burnBatch(holder, tokenIds, [values[0].subn(1), values[1].subn(2)], { from: operator }); expect(await this.token.balanceOf(holder, tokenIds[0])).to.be.bignumber.equal('1'); expect(await this.token.balanceOf(holder, tokenIds[1])).to.be.bignumber.equal('2'); @@ -62,7 +62,7 @@ contract('ERC1155Burnable', function (accounts) { it("unapproved accounts cannot burn the holder's tokens", async function () { await expectRevertCustomError( - this.token.burnBatch(holder, tokenIds, [amounts[0].subn(1), amounts[1].subn(2)], { from: other }), + this.token.burnBatch(holder, tokenIds, [values[0].subn(1), values[1].subn(2)], { from: other }), 'ERC1155MissingApprovalForAll', [other, holder], ); diff --git a/test/token/ERC1155/extensions/ERC1155Pausable.test.js b/test/token/ERC1155/extensions/ERC1155Pausable.test.js index b0ac54bdb..248ea5684 100644 --- a/test/token/ERC1155/extensions/ERC1155Pausable.test.js +++ b/test/token/ERC1155/extensions/ERC1155Pausable.test.js @@ -16,21 +16,21 @@ contract('ERC1155Pausable', function (accounts) { context('when token is paused', function () { const firstTokenId = new BN('37'); - const firstTokenAmount = new BN('42'); + const firstTokenValue = new BN('42'); const secondTokenId = new BN('19842'); - const secondTokenAmount = new BN('23'); + const secondTokenValue = new BN('23'); beforeEach(async function () { await this.token.setApprovalForAll(operator, true, { from: holder }); - await this.token.$_mint(holder, firstTokenId, firstTokenAmount, '0x'); + await this.token.$_mint(holder, firstTokenId, firstTokenValue, '0x'); await this.token.$_pause(); }); it('reverts when trying to safeTransferFrom from holder', async function () { await expectRevertCustomError( - this.token.safeTransferFrom(holder, receiver, firstTokenId, firstTokenAmount, '0x', { from: holder }), + this.token.safeTransferFrom(holder, receiver, firstTokenId, firstTokenValue, '0x', { from: holder }), 'EnforcedPause', [], ); @@ -38,7 +38,7 @@ contract('ERC1155Pausable', function (accounts) { it('reverts when trying to safeTransferFrom from operator', async function () { await expectRevertCustomError( - this.token.safeTransferFrom(holder, receiver, firstTokenId, firstTokenAmount, '0x', { from: operator }), + this.token.safeTransferFrom(holder, receiver, firstTokenId, firstTokenValue, '0x', { from: operator }), 'EnforcedPause', [], ); @@ -46,7 +46,7 @@ contract('ERC1155Pausable', function (accounts) { it('reverts when trying to safeBatchTransferFrom from holder', async function () { await expectRevertCustomError( - this.token.safeBatchTransferFrom(holder, receiver, [firstTokenId], [firstTokenAmount], '0x', { from: holder }), + this.token.safeBatchTransferFrom(holder, receiver, [firstTokenId], [firstTokenValue], '0x', { from: holder }), 'EnforcedPause', [], ); @@ -54,7 +54,7 @@ contract('ERC1155Pausable', function (accounts) { it('reverts when trying to safeBatchTransferFrom from operator', async function () { await expectRevertCustomError( - this.token.safeBatchTransferFrom(holder, receiver, [firstTokenId], [firstTokenAmount], '0x', { + this.token.safeBatchTransferFrom(holder, receiver, [firstTokenId], [firstTokenValue], '0x', { from: operator, }), 'EnforcedPause', @@ -64,7 +64,7 @@ contract('ERC1155Pausable', function (accounts) { it('reverts when trying to mint', async function () { await expectRevertCustomError( - this.token.$_mint(holder, secondTokenId, secondTokenAmount, '0x'), + this.token.$_mint(holder, secondTokenId, secondTokenValue, '0x'), 'EnforcedPause', [], ); @@ -72,19 +72,19 @@ contract('ERC1155Pausable', function (accounts) { it('reverts when trying to mintBatch', async function () { await expectRevertCustomError( - this.token.$_mintBatch(holder, [secondTokenId], [secondTokenAmount], '0x'), + this.token.$_mintBatch(holder, [secondTokenId], [secondTokenValue], '0x'), 'EnforcedPause', [], ); }); it('reverts when trying to burn', async function () { - await expectRevertCustomError(this.token.$_burn(holder, firstTokenId, firstTokenAmount), 'EnforcedPause', []); + await expectRevertCustomError(this.token.$_burn(holder, firstTokenId, firstTokenValue), 'EnforcedPause', []); }); it('reverts when trying to burnBatch', async function () { await expectRevertCustomError( - this.token.$_burnBatch(holder, [firstTokenId], [firstTokenAmount]), + this.token.$_burnBatch(holder, [firstTokenId], [firstTokenValue]), 'EnforcedPause', [], ); @@ -98,9 +98,9 @@ contract('ERC1155Pausable', function (accounts) { }); describe('balanceOf', function () { - it('returns the amount of tokens owned by the given address', async function () { + it('returns the token value owned by the given address', async function () { const balance = await this.token.balanceOf(holder, firstTokenId); - expect(balance).to.be.bignumber.equal(firstTokenAmount); + expect(balance).to.be.bignumber.equal(firstTokenValue); }); }); diff --git a/test/token/ERC1155/extensions/ERC1155Supply.test.js b/test/token/ERC1155/extensions/ERC1155Supply.test.js index 22a75c84f..bf86920f6 100644 --- a/test/token/ERC1155/extensions/ERC1155Supply.test.js +++ b/test/token/ERC1155/extensions/ERC1155Supply.test.js @@ -12,10 +12,10 @@ contract('ERC1155Supply', function (accounts) { const uri = 'https://token.com'; const firstTokenId = new BN('37'); - const firstTokenAmount = new BN('42'); + const firstTokenValue = new BN('42'); const secondTokenId = new BN('19842'); - const secondTokenAmount = new BN('23'); + const secondTokenValue = new BN('23'); beforeEach(async function () { this.token = await ERC1155Supply.new(uri); @@ -35,7 +35,7 @@ contract('ERC1155Supply', function (accounts) { context('after mint', function () { context('single', function () { beforeEach(async function () { - await this.token.$_mint(holder, firstTokenId, firstTokenAmount, '0x'); + await this.token.$_mint(holder, firstTokenId, firstTokenValue, '0x'); }); it('exist', async function () { @@ -43,19 +43,14 @@ contract('ERC1155Supply', function (accounts) { }); it('totalSupply', async function () { - expect(await this.token.methods['totalSupply(uint256)'](firstTokenId)).to.be.bignumber.equal(firstTokenAmount); - expect(await this.token.methods['totalSupply()']()).to.be.bignumber.equal(firstTokenAmount); + expect(await this.token.methods['totalSupply(uint256)'](firstTokenId)).to.be.bignumber.equal(firstTokenValue); + expect(await this.token.methods['totalSupply()']()).to.be.bignumber.equal(firstTokenValue); }); }); context('batch', function () { beforeEach(async function () { - await this.token.$_mintBatch( - holder, - [firstTokenId, secondTokenId], - [firstTokenAmount, secondTokenAmount], - '0x', - ); + await this.token.$_mintBatch(holder, [firstTokenId, secondTokenId], [firstTokenValue, secondTokenValue], '0x'); }); it('exist', async function () { @@ -64,12 +59,10 @@ contract('ERC1155Supply', function (accounts) { }); it('totalSupply', async function () { - expect(await this.token.methods['totalSupply(uint256)'](firstTokenId)).to.be.bignumber.equal(firstTokenAmount); - expect(await this.token.methods['totalSupply(uint256)'](secondTokenId)).to.be.bignumber.equal( - secondTokenAmount, - ); + expect(await this.token.methods['totalSupply(uint256)'](firstTokenId)).to.be.bignumber.equal(firstTokenValue); + expect(await this.token.methods['totalSupply(uint256)'](secondTokenId)).to.be.bignumber.equal(secondTokenValue); expect(await this.token.methods['totalSupply()']()).to.be.bignumber.equal( - firstTokenAmount.add(secondTokenAmount), + firstTokenValue.add(secondTokenValue), ); }); }); @@ -78,8 +71,8 @@ contract('ERC1155Supply', function (accounts) { context('after burn', function () { context('single', function () { beforeEach(async function () { - await this.token.$_mint(holder, firstTokenId, firstTokenAmount, '0x'); - await this.token.$_burn(holder, firstTokenId, firstTokenAmount); + await this.token.$_mint(holder, firstTokenId, firstTokenValue, '0x'); + await this.token.$_burn(holder, firstTokenId, firstTokenValue); }); it('exist', async function () { @@ -94,13 +87,8 @@ contract('ERC1155Supply', function (accounts) { context('batch', function () { beforeEach(async function () { - await this.token.$_mintBatch( - holder, - [firstTokenId, secondTokenId], - [firstTokenAmount, secondTokenAmount], - '0x', - ); - await this.token.$_burnBatch(holder, [firstTokenId, secondTokenId], [firstTokenAmount, secondTokenAmount]); + await this.token.$_mintBatch(holder, [firstTokenId, secondTokenId], [firstTokenValue, secondTokenValue], '0x'); + await this.token.$_burnBatch(holder, [firstTokenId, secondTokenId], [firstTokenValue, secondTokenValue]); }); it('exist', async function () { @@ -118,7 +106,7 @@ contract('ERC1155Supply', function (accounts) { context('other', function () { it('supply unaffected by no-op', async function () { - this.token.safeTransferFrom(ZERO_ADDRESS, ZERO_ADDRESS, firstTokenId, firstTokenAmount, '0x', { + this.token.safeTransferFrom(ZERO_ADDRESS, ZERO_ADDRESS, firstTokenId, firstTokenValue, '0x', { from: ZERO_ADDRESS, }); expect(await this.token.methods['totalSupply(uint256)'](firstTokenId)).to.be.bignumber.equal('0'); diff --git a/test/token/ERC1155/extensions/ERC1155URIStorage.test.js b/test/token/ERC1155/extensions/ERC1155URIStorage.test.js index 95d9c18f7..58ac67bc6 100644 --- a/test/token/ERC1155/extensions/ERC1155URIStorage.test.js +++ b/test/token/ERC1155/extensions/ERC1155URIStorage.test.js @@ -12,14 +12,14 @@ contract(['ERC1155URIStorage'], function (accounts) { const baseUri = 'https://token.com/'; const tokenId = new BN('1'); - const amount = new BN('3000'); + const value = new BN('3000'); describe('with base uri set', function () { beforeEach(async function () { this.token = await ERC1155URIStorage.new(erc1155Uri); await this.token.$_setBaseURI(baseUri); - await this.token.$_mint(holder, tokenId, amount, '0x'); + await this.token.$_mint(holder, tokenId, value, '0x'); }); it('can request the token uri, returning the erc1155 uri if no token uri was set', async function () { @@ -44,7 +44,7 @@ contract(['ERC1155URIStorage'], function (accounts) { beforeEach(async function () { this.token = await ERC1155URIStorage.new(''); - await this.token.$_mint(holder, tokenId, amount, '0x'); + await this.token.$_mint(holder, tokenId, value, '0x'); }); it('can request the token uri, returning an empty string if no token uri was set', async function () { diff --git a/test/token/ERC1155/utils/ERC1155Holder.test.js b/test/token/ERC1155/utils/ERC1155Holder.test.js index 8d8541640..ee818eae8 100644 --- a/test/token/ERC1155/utils/ERC1155Holder.test.js +++ b/test/token/ERC1155/utils/ERC1155Holder.test.js @@ -11,13 +11,13 @@ contract('ERC1155Holder', function (accounts) { const [creator] = accounts; const uri = 'https://token-cdn-domain/{id}.json'; const multiTokenIds = [new BN(1), new BN(2), new BN(3)]; - const multiTokenAmounts = [new BN(1000), new BN(2000), new BN(3000)]; + const multiTokenValues = [new BN(1000), new BN(2000), new BN(3000)]; const transferData = '0x12345678'; beforeEach(async function () { this.multiToken = await ERC1155.new(uri); this.holder = await ERC1155Holder.new(); - await this.multiToken.$_mintBatch(creator, multiTokenIds, multiTokenAmounts, '0x'); + await this.multiToken.$_mintBatch(creator, multiTokenIds, multiTokenValues, '0x'); }); shouldSupportInterfaces(['ERC165', 'ERC1155Receiver']); @@ -27,13 +27,13 @@ contract('ERC1155Holder', function (accounts) { creator, this.holder.address, multiTokenIds[0], - multiTokenAmounts[0], + multiTokenValues[0], transferData, { from: creator }, ); expect(await this.multiToken.balanceOf(this.holder.address, multiTokenIds[0])).to.be.bignumber.equal( - multiTokenAmounts[0], + multiTokenValues[0], ); for (let i = 1; i < multiTokenIds.length; i++) { @@ -50,14 +50,14 @@ contract('ERC1155Holder', function (accounts) { creator, this.holder.address, multiTokenIds, - multiTokenAmounts, + multiTokenValues, transferData, { from: creator }, ); for (let i = 0; i < multiTokenIds.length; i++) { expect(await this.multiToken.balanceOf(this.holder.address, multiTokenIds[i])).to.be.bignumber.equal( - multiTokenAmounts[i], + multiTokenValues[i], ); } }); diff --git a/test/token/ERC20/ERC20.behavior.js b/test/token/ERC20/ERC20.behavior.js index bb2efda89..b6f8617b2 100644 --- a/test/token/ERC20/ERC20.behavior.js +++ b/test/token/ERC20/ERC20.behavior.js @@ -9,7 +9,7 @@ function shouldBehaveLikeERC20(initialSupply, accounts, opts = {}) { const { forcedApproval } = opts; describe('total supply', function () { - it('returns the total amount of tokens', async function () { + it('returns the total token value', async function () { expect(await this.token.totalSupply()).to.be.bignumber.equal(initialSupply); }); }); @@ -22,7 +22,7 @@ function shouldBehaveLikeERC20(initialSupply, accounts, opts = {}) { }); describe('when the requested account has some tokens', function () { - it('returns the total amount of tokens', async function () { + it('returns the total token value', async function () { expect(await this.token.balanceOf(initialHolder)).to.be.bignumber.equal(initialSupply); }); }); @@ -49,33 +49,33 @@ function shouldBehaveLikeERC20(initialSupply, accounts, opts = {}) { }); describe('when the token owner has enough balance', function () { - const amount = initialSupply; + const value = initialSupply; - it('transfers the requested amount', async function () { - await this.token.transferFrom(tokenOwner, to, amount, { from: spender }); + it('transfers the requested value', async function () { + await this.token.transferFrom(tokenOwner, to, value, { from: spender }); expect(await this.token.balanceOf(tokenOwner)).to.be.bignumber.equal('0'); - expect(await this.token.balanceOf(to)).to.be.bignumber.equal(amount); + expect(await this.token.balanceOf(to)).to.be.bignumber.equal(value); }); it('decreases the spender allowance', async function () { - await this.token.transferFrom(tokenOwner, to, amount, { from: spender }); + await this.token.transferFrom(tokenOwner, to, value, { from: spender }); expect(await this.token.allowance(tokenOwner, spender)).to.be.bignumber.equal('0'); }); it('emits a transfer event', async function () { - expectEvent(await this.token.transferFrom(tokenOwner, to, amount, { from: spender }), 'Transfer', { + expectEvent(await this.token.transferFrom(tokenOwner, to, value, { from: spender }), 'Transfer', { from: tokenOwner, to: to, - value: amount, + value: value, }); }); if (forcedApproval) { it('emits an approval event', async function () { - expectEvent(await this.token.transferFrom(tokenOwner, to, amount, { from: spender }), 'Approval', { + expectEvent(await this.token.transferFrom(tokenOwner, to, value, { from: spender }), 'Approval', { owner: tokenOwner, spender: spender, value: await this.token.allowance(tokenOwner, spender), @@ -84,7 +84,7 @@ function shouldBehaveLikeERC20(initialSupply, accounts, opts = {}) { } else { it('does not emit an approval event', async function () { expectEvent.notEmitted( - await this.token.transferFrom(tokenOwner, to, amount, { from: spender }), + await this.token.transferFrom(tokenOwner, to, value, { from: spender }), 'Approval', ); }); @@ -92,7 +92,7 @@ function shouldBehaveLikeERC20(initialSupply, accounts, opts = {}) { }); describe('when the token owner does not have enough balance', function () { - const amount = initialSupply; + const value = initialSupply; beforeEach('reducing balance', async function () { await this.token.transfer(to, 1, { from: tokenOwner }); @@ -100,9 +100,9 @@ function shouldBehaveLikeERC20(initialSupply, accounts, opts = {}) { it('reverts', async function () { await expectRevertCustomError( - this.token.transferFrom(tokenOwner, to, amount, { from: spender }), + this.token.transferFrom(tokenOwner, to, value, { from: spender }), 'ERC20InsufficientBalance', - [tokenOwner, amount - 1, amount], + [tokenOwner, value - 1, value], ); }); }); @@ -116,19 +116,19 @@ function shouldBehaveLikeERC20(initialSupply, accounts, opts = {}) { }); describe('when the token owner has enough balance', function () { - const amount = initialSupply; + const value = initialSupply; it('reverts', async function () { await expectRevertCustomError( - this.token.transferFrom(tokenOwner, to, amount, { from: spender }), + this.token.transferFrom(tokenOwner, to, value, { from: spender }), 'ERC20InsufficientAllowance', - [spender, allowance, amount], + [spender, allowance, value], ); }); }); describe('when the token owner does not have enough balance', function () { - const amount = allowance; + const value = allowance; beforeEach('reducing balance', async function () { await this.token.transfer(to, 2, { from: tokenOwner }); @@ -136,9 +136,9 @@ function shouldBehaveLikeERC20(initialSupply, accounts, opts = {}) { it('reverts', async function () { await expectRevertCustomError( - this.token.transferFrom(tokenOwner, to, amount, { from: spender }), + this.token.transferFrom(tokenOwner, to, value, { from: spender }), 'ERC20InsufficientBalance', - [tokenOwner, amount - 1, amount], + [tokenOwner, value - 1, value], ); }); }); @@ -162,16 +162,16 @@ function shouldBehaveLikeERC20(initialSupply, accounts, opts = {}) { }); describe('when the recipient is the zero address', function () { - const amount = initialSupply; + const value = initialSupply; const to = ZERO_ADDRESS; beforeEach(async function () { - await this.token.approve(spender, amount, { from: tokenOwner }); + await this.token.approve(spender, value, { from: tokenOwner }); }); it('reverts', async function () { await expectRevertCustomError( - this.token.transferFrom(tokenOwner, to, amount, { from: spender }), + this.token.transferFrom(tokenOwner, to, value, { from: spender }), 'ERC20InvalidReceiver', [ZERO_ADDRESS], ); @@ -180,13 +180,13 @@ function shouldBehaveLikeERC20(initialSupply, accounts, opts = {}) { }); describe('when the token owner is the zero address', function () { - const amount = 0; + const value = 0; const tokenOwner = ZERO_ADDRESS; const to = recipient; it('reverts', async function () { await expectRevertCustomError( - this.token.transferFrom(tokenOwner, to, amount, { from: spender }), + this.token.transferFrom(tokenOwner, to, value, { from: spender }), 'ERC20InvalidApprover', [ZERO_ADDRESS], ); @@ -195,8 +195,8 @@ function shouldBehaveLikeERC20(initialSupply, accounts, opts = {}) { }); describe('approve', function () { - shouldBehaveLikeERC20Approve(initialHolder, recipient, initialSupply, function (owner, spender, amount) { - return this.token.approve(spender, amount, { from: owner }); + shouldBehaveLikeERC20Approve(initialHolder, recipient, initialSupply, function (owner, spender, value) { + return this.token.approve(spender, value, { from: owner }); }); }); } @@ -204,38 +204,38 @@ function shouldBehaveLikeERC20(initialSupply, accounts, opts = {}) { function shouldBehaveLikeERC20Transfer(from, to, balance, transfer) { describe('when the recipient is not the zero address', function () { describe('when the sender does not have enough balance', function () { - const amount = balance.addn(1); + const value = balance.addn(1); it('reverts', async function () { - await expectRevertCustomError(transfer.call(this, from, to, amount), 'ERC20InsufficientBalance', [ + await expectRevertCustomError(transfer.call(this, from, to, value), 'ERC20InsufficientBalance', [ from, balance, - amount, + value, ]); }); }); describe('when the sender transfers all balance', function () { - const amount = balance; + const value = balance; - it('transfers the requested amount', async function () { - await transfer.call(this, from, to, amount); + it('transfers the requested value', async function () { + await transfer.call(this, from, to, value); expect(await this.token.balanceOf(from)).to.be.bignumber.equal('0'); - expect(await this.token.balanceOf(to)).to.be.bignumber.equal(amount); + expect(await this.token.balanceOf(to)).to.be.bignumber.equal(value); }); it('emits a transfer event', async function () { - expectEvent(await transfer.call(this, from, to, amount), 'Transfer', { from, to, value: amount }); + expectEvent(await transfer.call(this, from, to, value), 'Transfer', { from, to, value: value }); }); }); describe('when the sender transfers zero tokens', function () { - const amount = new BN('0'); + const value = new BN('0'); - it('transfers the requested amount', async function () { - await transfer.call(this, from, to, amount); + it('transfers the requested value', async function () { + await transfer.call(this, from, to, value); expect(await this.token.balanceOf(from)).to.be.bignumber.equal(balance); @@ -243,7 +243,7 @@ function shouldBehaveLikeERC20Transfer(from, to, balance, transfer) { }); it('emits a transfer event', async function () { - expectEvent(await transfer.call(this, from, to, amount), 'Transfer', { from, to, value: amount }); + expectEvent(await transfer.call(this, from, to, value), 'Transfer', { from, to, value: value }); }); }); }); @@ -260,65 +260,65 @@ function shouldBehaveLikeERC20Transfer(from, to, balance, transfer) { function shouldBehaveLikeERC20Approve(owner, spender, supply, approve) { describe('when the spender is not the zero address', function () { describe('when the sender has enough balance', function () { - const amount = supply; + const value = supply; it('emits an approval event', async function () { - expectEvent(await approve.call(this, owner, spender, amount), 'Approval', { + expectEvent(await approve.call(this, owner, spender, value), 'Approval', { owner: owner, spender: spender, - value: amount, + value: value, }); }); - describe('when there was no approved amount before', function () { - it('approves the requested amount', async function () { - await approve.call(this, owner, spender, amount); + describe('when there was no approved value before', function () { + it('approves the requested value', async function () { + await approve.call(this, owner, spender, value); - expect(await this.token.allowance(owner, spender)).to.be.bignumber.equal(amount); + expect(await this.token.allowance(owner, spender)).to.be.bignumber.equal(value); }); }); - describe('when the spender had an approved amount', function () { + describe('when the spender had an approved value', function () { beforeEach(async function () { await approve.call(this, owner, spender, new BN(1)); }); - it('approves the requested amount and replaces the previous one', async function () { - await approve.call(this, owner, spender, amount); + it('approves the requested value and replaces the previous one', async function () { + await approve.call(this, owner, spender, value); - expect(await this.token.allowance(owner, spender)).to.be.bignumber.equal(amount); + expect(await this.token.allowance(owner, spender)).to.be.bignumber.equal(value); }); }); }); describe('when the sender does not have enough balance', function () { - const amount = supply.addn(1); + const value = supply.addn(1); it('emits an approval event', async function () { - expectEvent(await approve.call(this, owner, spender, amount), 'Approval', { + expectEvent(await approve.call(this, owner, spender, value), 'Approval', { owner: owner, spender: spender, - value: amount, + value: value, }); }); - describe('when there was no approved amount before', function () { - it('approves the requested amount', async function () { - await approve.call(this, owner, spender, amount); + describe('when there was no approved value before', function () { + it('approves the requested value', async function () { + await approve.call(this, owner, spender, value); - expect(await this.token.allowance(owner, spender)).to.be.bignumber.equal(amount); + expect(await this.token.allowance(owner, spender)).to.be.bignumber.equal(value); }); }); - describe('when the spender had an approved amount', function () { + describe('when the spender had an approved value', function () { beforeEach(async function () { await approve.call(this, owner, spender, new BN(1)); }); - it('approves the requested amount and replaces the previous one', async function () { - await approve.call(this, owner, spender, amount); + it('approves the requested value and replaces the previous one', async function () { + await approve.call(this, owner, spender, value); - expect(await this.token.allowance(owner, spender)).to.be.bignumber.equal(amount); + expect(await this.token.allowance(owner, spender)).to.be.bignumber.equal(value); }); }); }); diff --git a/test/token/ERC20/ERC20.test.js b/test/token/ERC20/ERC20.test.js index ef6d82f2b..a63df5239 100644 --- a/test/token/ERC20/ERC20.test.js +++ b/test/token/ERC20/ERC20.test.js @@ -46,145 +46,145 @@ contract('ERC20', function (accounts) { describe('when the spender is not the zero address', function () { const spender = recipient; - function shouldDecreaseApproval(amount) { - describe('when there was no approved amount before', function () { + function shouldDecreaseApproval(value) { + describe('when there was no approved value before', function () { it('reverts', async function () { const allowance = await this.token.allowance(initialHolder, spender); await expectRevertCustomError( - this.token.decreaseAllowance(spender, amount, { from: initialHolder }), + this.token.decreaseAllowance(spender, value, { from: initialHolder }), 'ERC20FailedDecreaseAllowance', - [spender, allowance, amount], + [spender, allowance, value], ); }); }); - describe('when the spender had an approved amount', function () { - const approvedAmount = amount; + describe('when the spender had an approved value', function () { + const approvedValue = value; beforeEach(async function () { - await this.token.approve(spender, approvedAmount, { from: initialHolder }); + await this.token.approve(spender, approvedValue, { from: initialHolder }); }); it('emits an approval event', async function () { expectEvent( - await this.token.decreaseAllowance(spender, approvedAmount, { from: initialHolder }), + await this.token.decreaseAllowance(spender, approvedValue, { from: initialHolder }), 'Approval', { owner: initialHolder, spender: spender, value: new BN(0) }, ); }); - it('decreases the spender allowance subtracting the requested amount', async function () { - await this.token.decreaseAllowance(spender, approvedAmount.subn(1), { from: initialHolder }); + it('decreases the spender allowance subtracting the requested value', async function () { + await this.token.decreaseAllowance(spender, approvedValue.subn(1), { from: initialHolder }); expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal('1'); }); it('sets the allowance to zero when all allowance is removed', async function () { - await this.token.decreaseAllowance(spender, approvedAmount, { from: initialHolder }); + await this.token.decreaseAllowance(spender, approvedValue, { from: initialHolder }); expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal('0'); }); it('reverts when more than the full allowance is removed', async function () { await expectRevertCustomError( - this.token.decreaseAllowance(spender, approvedAmount.addn(1), { from: initialHolder }), + this.token.decreaseAllowance(spender, approvedValue.addn(1), { from: initialHolder }), 'ERC20FailedDecreaseAllowance', - [spender, approvedAmount, approvedAmount.addn(1)], + [spender, approvedValue, approvedValue.addn(1)], ); }); }); } describe('when the sender has enough balance', function () { - const amount = initialSupply; + const value = initialSupply; - shouldDecreaseApproval(amount); + shouldDecreaseApproval(value); }); describe('when the sender does not have enough balance', function () { - const amount = initialSupply.addn(1); + const value = initialSupply.addn(1); - shouldDecreaseApproval(amount); + shouldDecreaseApproval(value); }); }); describe('when the spender is the zero address', function () { - const amount = initialSupply; + const value = initialSupply; const spender = ZERO_ADDRESS; it('reverts', async function () { await expectRevertCustomError( - this.token.decreaseAllowance(spender, amount, { from: initialHolder }), + this.token.decreaseAllowance(spender, value, { from: initialHolder }), 'ERC20FailedDecreaseAllowance', - [spender, 0, amount], + [spender, 0, value], ); }); }); }); describe('increase allowance', function () { - const amount = initialSupply; + const value = initialSupply; describe('when the spender is not the zero address', function () { const spender = recipient; describe('when the sender has enough balance', function () { it('emits an approval event', async function () { - expectEvent(await this.token.increaseAllowance(spender, amount, { from: initialHolder }), 'Approval', { + expectEvent(await this.token.increaseAllowance(spender, value, { from: initialHolder }), 'Approval', { owner: initialHolder, spender: spender, - value: amount, + value: value, }); }); - describe('when there was no approved amount before', function () { - it('approves the requested amount', async function () { - await this.token.increaseAllowance(spender, amount, { from: initialHolder }); + describe('when there was no approved value before', function () { + it('approves the requested value', async function () { + await this.token.increaseAllowance(spender, value, { from: initialHolder }); - expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal(amount); + expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal(value); }); }); - describe('when the spender had an approved amount', function () { + describe('when the spender had an approved value', function () { beforeEach(async function () { await this.token.approve(spender, new BN(1), { from: initialHolder }); }); - it('increases the spender allowance adding the requested amount', async function () { - await this.token.increaseAllowance(spender, amount, { from: initialHolder }); + it('increases the spender allowance adding the requested value', async function () { + await this.token.increaseAllowance(spender, value, { from: initialHolder }); - expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal(amount.addn(1)); + expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal(value.addn(1)); }); }); }); describe('when the sender does not have enough balance', function () { - const amount = initialSupply.addn(1); + const value = initialSupply.addn(1); it('emits an approval event', async function () { - expectEvent(await this.token.increaseAllowance(spender, amount, { from: initialHolder }), 'Approval', { + expectEvent(await this.token.increaseAllowance(spender, value, { from: initialHolder }), 'Approval', { owner: initialHolder, spender: spender, - value: amount, + value: value, }); }); - describe('when there was no approved amount before', function () { - it('approves the requested amount', async function () { - await this.token.increaseAllowance(spender, amount, { from: initialHolder }); + describe('when there was no approved value before', function () { + it('approves the requested value', async function () { + await this.token.increaseAllowance(spender, value, { from: initialHolder }); - expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal(amount); + expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal(value); }); }); - describe('when the spender had an approved amount', function () { + describe('when the spender had an approved value', function () { beforeEach(async function () { await this.token.approve(spender, new BN(1), { from: initialHolder }); }); - it('increases the spender allowance adding the requested amount', async function () { - await this.token.increaseAllowance(spender, amount, { from: initialHolder }); + it('increases the spender allowance adding the requested value', async function () { + await this.token.increaseAllowance(spender, value, { from: initialHolder }); - expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal(amount.addn(1)); + expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal(value.addn(1)); }); }); }); @@ -195,7 +195,7 @@ contract('ERC20', function (accounts) { it('reverts', async function () { await expectRevertCustomError( - this.token.increaseAllowance(spender, amount, { from: initialHolder }), + this.token.increaseAllowance(spender, value, { from: initialHolder }), 'ERC20InvalidSpender', [ZERO_ADDRESS], ); @@ -204,11 +204,9 @@ contract('ERC20', function (accounts) { }); describe('_mint', function () { - const amount = new BN(50); + const value = new BN(50); it('rejects a null account', async function () { - await expectRevertCustomError(this.token.$_mint(ZERO_ADDRESS, amount), 'ERC20InvalidReceiver', [ - ZERO_ADDRESS, - ]); + await expectRevertCustomError(this.token.$_mint(ZERO_ADDRESS, value), 'ERC20InvalidReceiver', [ZERO_ADDRESS]); }); it('rejects overflow', async function () { @@ -221,22 +219,22 @@ contract('ERC20', function (accounts) { describe('for a non zero account', function () { beforeEach('minting', async function () { - this.receipt = await this.token.$_mint(recipient, amount); + this.receipt = await this.token.$_mint(recipient, value); }); it('increments totalSupply', async function () { - const expectedSupply = initialSupply.add(amount); + const expectedSupply = initialSupply.add(value); expect(await this.token.totalSupply()).to.be.bignumber.equal(expectedSupply); }); it('increments recipient balance', async function () { - expect(await this.token.balanceOf(recipient)).to.be.bignumber.equal(amount); + expect(await this.token.balanceOf(recipient)).to.be.bignumber.equal(value); }); it('emits Transfer event', async function () { const event = expectEvent(this.receipt, 'Transfer', { from: ZERO_ADDRESS, to: recipient }); - expect(event.args.value).to.be.bignumber.equal(amount); + expect(event.args.value).to.be.bignumber.equal(value); }); }); }); @@ -257,81 +255,81 @@ contract('ERC20', function (accounts) { ); }); - const describeBurn = function (description, amount) { + const describeBurn = function (description, value) { describe(description, function () { beforeEach('burning', async function () { - this.receipt = await this.token.$_burn(initialHolder, amount); + this.receipt = await this.token.$_burn(initialHolder, value); }); it('decrements totalSupply', async function () { - const expectedSupply = initialSupply.sub(amount); + const expectedSupply = initialSupply.sub(value); expect(await this.token.totalSupply()).to.be.bignumber.equal(expectedSupply); }); it('decrements initialHolder balance', async function () { - const expectedBalance = initialSupply.sub(amount); + const expectedBalance = initialSupply.sub(value); expect(await this.token.balanceOf(initialHolder)).to.be.bignumber.equal(expectedBalance); }); it('emits Transfer event', async function () { const event = expectEvent(this.receipt, 'Transfer', { from: initialHolder, to: ZERO_ADDRESS }); - expect(event.args.value).to.be.bignumber.equal(amount); + expect(event.args.value).to.be.bignumber.equal(value); }); }); }; describeBurn('for entire balance', initialSupply); - describeBurn('for less amount than balance', initialSupply.subn(1)); + describeBurn('for less value than balance', initialSupply.subn(1)); }); }); describe('_update', function () { - const amount = new BN(1); + const value = new BN(1); it('from is the zero address', async function () { const balanceBefore = await this.token.balanceOf(initialHolder); const totalSupply = await this.token.totalSupply(); - expectEvent(await this.token.$_update(ZERO_ADDRESS, initialHolder, amount), 'Transfer', { + expectEvent(await this.token.$_update(ZERO_ADDRESS, initialHolder, value), 'Transfer', { from: ZERO_ADDRESS, to: initialHolder, - value: amount, + value: value, }); - expect(await this.token.totalSupply()).to.be.bignumber.equal(totalSupply.add(amount)); - expect(await this.token.balanceOf(initialHolder)).to.be.bignumber.equal(balanceBefore.add(amount)); + expect(await this.token.totalSupply()).to.be.bignumber.equal(totalSupply.add(value)); + expect(await this.token.balanceOf(initialHolder)).to.be.bignumber.equal(balanceBefore.add(value)); }); it('to is the zero address', async function () { const balanceBefore = await this.token.balanceOf(initialHolder); const totalSupply = await this.token.totalSupply(); - expectEvent(await this.token.$_update(initialHolder, ZERO_ADDRESS, amount), 'Transfer', { + expectEvent(await this.token.$_update(initialHolder, ZERO_ADDRESS, value), 'Transfer', { from: initialHolder, to: ZERO_ADDRESS, - value: amount, + value: value, }); - expect(await this.token.totalSupply()).to.be.bignumber.equal(totalSupply.sub(amount)); - expect(await this.token.balanceOf(initialHolder)).to.be.bignumber.equal(balanceBefore.sub(amount)); + expect(await this.token.totalSupply()).to.be.bignumber.equal(totalSupply.sub(value)); + expect(await this.token.balanceOf(initialHolder)).to.be.bignumber.equal(balanceBefore.sub(value)); }); it('from and to are the zero address', async function () { const totalSupply = await this.token.totalSupply(); - await this.token.$_update(ZERO_ADDRESS, ZERO_ADDRESS, amount); + await this.token.$_update(ZERO_ADDRESS, ZERO_ADDRESS, value); expect(await this.token.totalSupply()).to.be.bignumber.equal(totalSupply); - expectEvent(await this.token.$_update(ZERO_ADDRESS, ZERO_ADDRESS, amount), 'Transfer', { + expectEvent(await this.token.$_update(ZERO_ADDRESS, ZERO_ADDRESS, value), 'Transfer', { from: ZERO_ADDRESS, to: ZERO_ADDRESS, - value: amount, + value: value, }); }); }); describe('_transfer', function () { - shouldBehaveLikeERC20Transfer(initialHolder, recipient, initialSupply, function (from, to, amount) { - return this.token.$_transfer(from, to, amount); + shouldBehaveLikeERC20Transfer(initialHolder, recipient, initialSupply, function (from, to, value) { + return this.token.$_transfer(from, to, value); }); describe('when the sender is the zero address', function () { @@ -346,8 +344,8 @@ contract('ERC20', function (accounts) { }); describe('_approve', function () { - shouldBehaveLikeERC20Approve(initialHolder, recipient, initialSupply, function (owner, spender, amount) { - return this.token.$_approve(owner, spender, amount); + shouldBehaveLikeERC20Approve(initialHolder, recipient, initialSupply, function (owner, spender, value) { + return this.token.$_approve(owner, spender, value); }); describe('when the owner is the zero address', function () { diff --git a/test/token/ERC20/extensions/ERC20Burnable.behavior.js b/test/token/ERC20/extensions/ERC20Burnable.behavior.js index 848e54b79..937491bdf 100644 --- a/test/token/ERC20/extensions/ERC20Burnable.behavior.js +++ b/test/token/ERC20/extensions/ERC20Burnable.behavior.js @@ -6,42 +6,42 @@ const { expectRevertCustomError } = require('../../../helpers/customError'); function shouldBehaveLikeERC20Burnable(owner, initialBalance, [burner]) { describe('burn', function () { - describe('when the given amount is not greater than balance of the sender', function () { - context('for a zero amount', function () { + describe('when the given value is not greater than balance of the sender', function () { + context('for a zero value', function () { shouldBurn(new BN(0)); }); - context('for a non-zero amount', function () { + context('for a non-zero value', function () { shouldBurn(new BN(100)); }); - function shouldBurn(amount) { + function shouldBurn(value) { beforeEach(async function () { - this.receipt = await this.token.burn(amount, { from: owner }); + this.receipt = await this.token.burn(value, { from: owner }); }); - it('burns the requested amount', async function () { - expect(await this.token.balanceOf(owner)).to.be.bignumber.equal(initialBalance.sub(amount)); + it('burns the requested value', async function () { + expect(await this.token.balanceOf(owner)).to.be.bignumber.equal(initialBalance.sub(value)); }); it('emits a transfer event', async function () { expectEvent(this.receipt, 'Transfer', { from: owner, to: ZERO_ADDRESS, - value: amount, + value: value, }); }); } }); - describe('when the given amount is greater than the balance of the sender', function () { - const amount = initialBalance.addn(1); + describe('when the given value is greater than the balance of the sender', function () { + const value = initialBalance.addn(1); it('reverts', async function () { - await expectRevertCustomError(this.token.burn(amount, { from: owner }), 'ERC20InsufficientBalance', [ + await expectRevertCustomError(this.token.burn(value, { from: owner }), 'ERC20InsufficientBalance', [ owner, initialBalance, - amount, + value, ]); }); }); @@ -49,54 +49,54 @@ function shouldBehaveLikeERC20Burnable(owner, initialBalance, [burner]) { describe('burnFrom', function () { describe('on success', function () { - context('for a zero amount', function () { + context('for a zero value', function () { shouldBurnFrom(new BN(0)); }); - context('for a non-zero amount', function () { + context('for a non-zero value', function () { shouldBurnFrom(new BN(100)); }); - function shouldBurnFrom(amount) { - const originalAllowance = amount.muln(3); + function shouldBurnFrom(value) { + const originalAllowance = value.muln(3); beforeEach(async function () { await this.token.approve(burner, originalAllowance, { from: owner }); - this.receipt = await this.token.burnFrom(owner, amount, { from: burner }); + this.receipt = await this.token.burnFrom(owner, value, { from: burner }); }); - it('burns the requested amount', async function () { - expect(await this.token.balanceOf(owner)).to.be.bignumber.equal(initialBalance.sub(amount)); + it('burns the requested value', async function () { + expect(await this.token.balanceOf(owner)).to.be.bignumber.equal(initialBalance.sub(value)); }); it('decrements allowance', async function () { - expect(await this.token.allowance(owner, burner)).to.be.bignumber.equal(originalAllowance.sub(amount)); + expect(await this.token.allowance(owner, burner)).to.be.bignumber.equal(originalAllowance.sub(value)); }); it('emits a transfer event', async function () { expectEvent(this.receipt, 'Transfer', { from: owner, to: ZERO_ADDRESS, - value: amount, + value: value, }); }); } }); - describe('when the given amount is greater than the balance of the sender', function () { - const amount = initialBalance.addn(1); + describe('when the given value is greater than the balance of the sender', function () { + const value = initialBalance.addn(1); it('reverts', async function () { - await this.token.approve(burner, amount, { from: owner }); - await expectRevertCustomError( - this.token.burnFrom(owner, amount, { from: burner }), - 'ERC20InsufficientBalance', - [owner, initialBalance, amount], - ); + await this.token.approve(burner, value, { from: owner }); + await expectRevertCustomError(this.token.burnFrom(owner, value, { from: burner }), 'ERC20InsufficientBalance', [ + owner, + initialBalance, + value, + ]); }); }); - describe('when the given amount is greater than the allowance', function () { + describe('when the given value is greater than the allowance', function () { const allowance = new BN(100); it('reverts', async function () { diff --git a/test/token/ERC20/extensions/ERC20Capped.behavior.js b/test/token/ERC20/extensions/ERC20Capped.behavior.js index c40e4fcc4..5af5c3ddc 100644 --- a/test/token/ERC20/extensions/ERC20Capped.behavior.js +++ b/test/token/ERC20/extensions/ERC20Capped.behavior.js @@ -9,12 +9,12 @@ function shouldBehaveLikeERC20Capped(accounts, cap) { expect(await this.token.cap()).to.be.bignumber.equal(cap); }); - it('mints when amount is less than cap', async function () { + it('mints when value is less than cap', async function () { await this.token.$_mint(user, cap.subn(1)); expect(await this.token.totalSupply()).to.be.bignumber.equal(cap.subn(1)); }); - it('fails to mint if the amount exceeds the cap', async function () { + it('fails to mint if the value exceeds the cap', async function () { await this.token.$_mint(user, cap.subn(1)); await expectRevertCustomError(this.token.$_mint(user, 2), 'ERC20ExceededCap', [cap.addn(1), cap]); }); diff --git a/test/token/ERC20/extensions/ERC20FlashMint.test.js b/test/token/ERC20/extensions/ERC20FlashMint.test.js index a646704e2..13d5b3ef4 100644 --- a/test/token/ERC20/extensions/ERC20FlashMint.test.js +++ b/test/token/ERC20/extensions/ERC20FlashMint.test.js @@ -15,7 +15,7 @@ contract('ERC20FlashMint', function (accounts) { const symbol = 'MTKN'; const initialSupply = new BN(100); - const loanAmount = new BN(10000000000000); + const loanValue = new BN(10000000000000); beforeEach(async function () { this.token = await ERC20FlashMintMock.new(name, symbol); @@ -34,11 +34,11 @@ contract('ERC20FlashMint', function (accounts) { describe('flashFee', function () { it('token match', async function () { - expect(await this.token.flashFee(this.token.address, loanAmount)).to.be.bignumber.equal('0'); + expect(await this.token.flashFee(this.token.address, loanValue)).to.be.bignumber.equal('0'); }); it('token mismatch', async function () { - await expectRevertCustomError(this.token.flashFee(ZERO_ADDRESS, loanAmount), 'ERC3156UnsupportedToken', [ + await expectRevertCustomError(this.token.flashFee(ZERO_ADDRESS, loanValue), 'ERC3156UnsupportedToken', [ ZERO_ADDRESS, ]); }); @@ -53,26 +53,26 @@ contract('ERC20FlashMint', function (accounts) { describe('flashLoan', function () { it('success', async function () { const receiver = await ERC3156FlashBorrowerMock.new(true, true); - const { tx } = await this.token.flashLoan(receiver.address, this.token.address, loanAmount, '0x'); + const { tx } = await this.token.flashLoan(receiver.address, this.token.address, loanValue, '0x'); await expectEvent.inTransaction(tx, this.token, 'Transfer', { from: ZERO_ADDRESS, to: receiver.address, - value: loanAmount, + value: loanValue, }); await expectEvent.inTransaction(tx, this.token, 'Transfer', { from: receiver.address, to: ZERO_ADDRESS, - value: loanAmount, + value: loanValue, }); await expectEvent.inTransaction(tx, receiver, 'BalanceOf', { token: this.token.address, account: receiver.address, - value: loanAmount, + value: loanValue, }); await expectEvent.inTransaction(tx, receiver, 'TotalSupply', { token: this.token.address, - value: initialSupply.add(loanAmount), + value: initialSupply.add(loanValue), }); expect(await this.token.totalSupply()).to.be.bignumber.equal(initialSupply); @@ -83,7 +83,7 @@ contract('ERC20FlashMint', function (accounts) { it('missing return value', async function () { const receiver = await ERC3156FlashBorrowerMock.new(false, true); await expectRevertCustomError( - this.token.flashLoan(receiver.address, this.token.address, loanAmount, '0x'), + this.token.flashLoan(receiver.address, this.token.address, loanValue, '0x'), 'ERC3156InvalidReceiver', [receiver.address], ); @@ -92,9 +92,9 @@ contract('ERC20FlashMint', function (accounts) { it('missing approval', async function () { const receiver = await ERC3156FlashBorrowerMock.new(true, false); await expectRevertCustomError( - this.token.flashLoan(receiver.address, this.token.address, loanAmount, '0x'), + this.token.flashLoan(receiver.address, this.token.address, loanValue, '0x'), 'ERC20InsufficientAllowance', - [this.token.address, 0, loanAmount], + [this.token.address, 0, loanValue], ); }); @@ -102,9 +102,9 @@ contract('ERC20FlashMint', function (accounts) { const receiver = await ERC3156FlashBorrowerMock.new(true, true); const data = this.token.contract.methods.transfer(other, 10).encodeABI(); await expectRevertCustomError( - this.token.flashLoan(receiver.address, this.token.address, loanAmount, data), + this.token.flashLoan(receiver.address, this.token.address, loanValue, data), 'ERC20InsufficientBalance', - [receiver.address, loanAmount - 10, loanAmount], + [receiver.address, loanValue - 10, loanValue], ); }); @@ -130,29 +130,29 @@ contract('ERC20FlashMint', function (accounts) { expect(await this.token.balanceOf(this.receiver.address)).to.be.bignumber.equal(receiverInitialBalance); await this.token.setFlashFee(flashFee); - expect(await this.token.flashFee(this.token.address, loanAmount)).to.be.bignumber.equal(flashFee); + expect(await this.token.flashFee(this.token.address, loanValue)).to.be.bignumber.equal(flashFee); }); it('default flash fee receiver', async function () { - const { tx } = await this.token.flashLoan(this.receiver.address, this.token.address, loanAmount, '0x'); + const { tx } = await this.token.flashLoan(this.receiver.address, this.token.address, loanValue, '0x'); await expectEvent.inTransaction(tx, this.token, 'Transfer', { from: ZERO_ADDRESS, to: this.receiver.address, - value: loanAmount, + value: loanValue, }); await expectEvent.inTransaction(tx, this.token, 'Transfer', { from: this.receiver.address, to: ZERO_ADDRESS, - value: loanAmount.add(flashFee), + value: loanValue.add(flashFee), }); await expectEvent.inTransaction(tx, this.receiver, 'BalanceOf', { token: this.token.address, account: this.receiver.address, - value: receiverInitialBalance.add(loanAmount), + value: receiverInitialBalance.add(loanValue), }); await expectEvent.inTransaction(tx, this.receiver, 'TotalSupply', { token: this.token.address, - value: initialSupply.add(receiverInitialBalance).add(loanAmount), + value: initialSupply.add(receiverInitialBalance).add(loanValue), }); expect(await this.token.totalSupply()).to.be.bignumber.equal( @@ -172,16 +172,16 @@ contract('ERC20FlashMint', function (accounts) { expect(await this.token.balanceOf(flashFeeReceiverAddress)).to.be.bignumber.equal('0'); - const { tx } = await this.token.flashLoan(this.receiver.address, this.token.address, loanAmount, '0x'); + const { tx } = await this.token.flashLoan(this.receiver.address, this.token.address, loanValue, '0x'); await expectEvent.inTransaction(tx, this.token, 'Transfer', { from: ZERO_ADDRESS, to: this.receiver.address, - value: loanAmount, + value: loanValue, }); await expectEvent.inTransaction(tx, this.token, 'Transfer', { from: this.receiver.address, to: ZERO_ADDRESS, - value: loanAmount, + value: loanValue, }); await expectEvent.inTransaction(tx, this.token, 'Transfer', { from: this.receiver.address, @@ -191,11 +191,11 @@ contract('ERC20FlashMint', function (accounts) { await expectEvent.inTransaction(tx, this.receiver, 'BalanceOf', { token: this.token.address, account: this.receiver.address, - value: receiverInitialBalance.add(loanAmount), + value: receiverInitialBalance.add(loanValue), }); await expectEvent.inTransaction(tx, this.receiver, 'TotalSupply', { token: this.token.address, - value: initialSupply.add(receiverInitialBalance).add(loanAmount), + value: initialSupply.add(receiverInitialBalance).add(loanValue), }); expect(await this.token.totalSupply()).to.be.bignumber.equal(initialSupply.add(receiverInitialBalance)); diff --git a/test/token/ERC20/extensions/ERC20Pausable.test.js b/test/token/ERC20/extensions/ERC20Pausable.test.js index 72bfc7769..92c90b9b8 100644 --- a/test/token/ERC20/extensions/ERC20Pausable.test.js +++ b/test/token/ERC20/extensions/ERC20Pausable.test.js @@ -84,52 +84,52 @@ contract('ERC20Pausable', function (accounts) { }); describe('mint', function () { - const amount = new BN('42'); + const value = new BN('42'); it('allows to mint when unpaused', async function () { - await this.token.$_mint(recipient, amount); + await this.token.$_mint(recipient, value); - expect(await this.token.balanceOf(recipient)).to.be.bignumber.equal(amount); + expect(await this.token.balanceOf(recipient)).to.be.bignumber.equal(value); }); it('allows to mint when paused and then unpaused', async function () { await this.token.$_pause(); await this.token.$_unpause(); - await this.token.$_mint(recipient, amount); + await this.token.$_mint(recipient, value); - expect(await this.token.balanceOf(recipient)).to.be.bignumber.equal(amount); + expect(await this.token.balanceOf(recipient)).to.be.bignumber.equal(value); }); it('reverts when trying to mint when paused', async function () { await this.token.$_pause(); - await expectRevertCustomError(this.token.$_mint(recipient, amount), 'EnforcedPause', []); + await expectRevertCustomError(this.token.$_mint(recipient, value), 'EnforcedPause', []); }); }); describe('burn', function () { - const amount = new BN('42'); + const value = new BN('42'); it('allows to burn when unpaused', async function () { - await this.token.$_burn(holder, amount); + await this.token.$_burn(holder, value); - expect(await this.token.balanceOf(holder)).to.be.bignumber.equal(initialSupply.sub(amount)); + expect(await this.token.balanceOf(holder)).to.be.bignumber.equal(initialSupply.sub(value)); }); it('allows to burn when paused and then unpaused', async function () { await this.token.$_pause(); await this.token.$_unpause(); - await this.token.$_burn(holder, amount); + await this.token.$_burn(holder, value); - expect(await this.token.balanceOf(holder)).to.be.bignumber.equal(initialSupply.sub(amount)); + expect(await this.token.balanceOf(holder)).to.be.bignumber.equal(initialSupply.sub(value)); }); it('reverts when trying to burn when paused', async function () { await this.token.$_pause(); - await expectRevertCustomError(this.token.$_burn(holder, amount), 'EnforcedPause', []); + await expectRevertCustomError(this.token.$_burn(holder, value), 'EnforcedPause', []); }); }); }); diff --git a/test/token/ERC20/extensions/ERC20Votes.test.js b/test/token/ERC20/extensions/ERC20Votes.test.js index 714a98adc..a6abb5f9f 100644 --- a/test/token/ERC20/extensions/ERC20Votes.test.js +++ b/test/token/ERC20/extensions/ERC20Votes.test.js @@ -10,7 +10,7 @@ const ethSigUtil = require('eth-sig-util'); const Wallet = require('ethereumjs-wallet').default; const { batchInBlock } = require('../../../helpers/txpool'); -const { getDomain, domainType, domainSeparator } = require('../../../helpers/eip712'); +const { getDomain, domainType } = require('../../../helpers/eip712'); const { clock, clockFromReceipt } = require('../../../helpers/time'); const { expectRevertCustomError } = require('../../../helpers/customError'); @@ -48,10 +48,10 @@ contract('ERC20Votes', function (accounts) { }); it('minting restriction', async function () { - const amount = new BN('2').pow(new BN('224')); - await expectRevertCustomError(this.token.$_mint(holder, amount), 'ERC20ExceededSafeSupply', [ - amount, - amount.subn(1), + const value = web3.utils.toBN(1).shln(224); + await expectRevertCustomError(this.token.$_mint(holder, value), 'ERC20ExceededSafeSupply', [ + value, + value.subn(1), ]); }); @@ -84,8 +84,8 @@ contract('ERC20Votes', function (accounts) { }); expectEvent(receipt, 'DelegateVotesChanged', { delegate: holder, - previousBalance: '0', - newBalance: supply, + previousVotes: '0', + newVotes: supply, }); expect(await this.token.delegates(holder)).to.be.equal(holder); @@ -147,8 +147,8 @@ contract('ERC20Votes', function (accounts) { }); expectEvent(receipt, 'DelegateVotesChanged', { delegate: delegatorAddress, - previousBalance: '0', - newBalance: supply, + previousVotes: '0', + newVotes: supply, }); expect(await this.token.delegates(delegatorAddress)).to.be.equal(delegatorAddress); @@ -248,13 +248,13 @@ contract('ERC20Votes', function (accounts) { }); expectEvent(receipt, 'DelegateVotesChanged', { delegate: holder, - previousBalance: supply, - newBalance: '0', + previousVotes: supply, + newVotes: '0', }); expectEvent(receipt, 'DelegateVotesChanged', { delegate: holderDelegatee, - previousBalance: '0', - newBalance: supply, + previousVotes: '0', + newVotes: supply, }); expect(await this.token.delegates(holder)).to.be.equal(holderDelegatee); @@ -290,8 +290,8 @@ contract('ERC20Votes', function (accounts) { expectEvent(receipt, 'Transfer', { from: holder, to: recipient, value: '1' }); expectEvent(receipt, 'DelegateVotesChanged', { delegate: holder, - previousBalance: supply, - newBalance: supply.subn(1), + previousVotes: supply, + newVotes: supply.subn(1), }); const { logIndex: transferLogIndex } = receipt.logs.find(({ event }) => event == 'Transfer'); @@ -310,7 +310,7 @@ contract('ERC20Votes', function (accounts) { const { receipt } = await this.token.transfer(recipient, 1, { from: holder }); expectEvent(receipt, 'Transfer', { from: holder, to: recipient, value: '1' }); - expectEvent(receipt, 'DelegateVotesChanged', { delegate: recipient, previousBalance: '0', newBalance: '1' }); + expectEvent(receipt, 'DelegateVotesChanged', { delegate: recipient, previousVotes: '0', newVotes: '1' }); const { logIndex: transferLogIndex } = receipt.logs.find(({ event }) => event == 'Transfer'); expect( @@ -331,10 +331,10 @@ contract('ERC20Votes', function (accounts) { expectEvent(receipt, 'Transfer', { from: holder, to: recipient, value: '1' }); expectEvent(receipt, 'DelegateVotesChanged', { delegate: holder, - previousBalance: supply, - newBalance: supply.subn(1), + previousVotes: supply, + newVotes: supply.subn(1), }); - expectEvent(receipt, 'DelegateVotesChanged', { delegate: recipient, previousBalance: '0', newBalance: '1' }); + expectEvent(receipt, 'DelegateVotesChanged', { delegate: recipient, previousVotes: '0', newVotes: '1' }); const { logIndex: transferLogIndex } = receipt.logs.find(({ event }) => event == 'Transfer'); expect( diff --git a/test/token/ERC20/extensions/ERC20Wrapper.test.js b/test/token/ERC20/extensions/ERC20Wrapper.test.js index 94415d088..c54a9e007 100644 --- a/test/token/ERC20/extensions/ERC20Wrapper.test.js +++ b/test/token/ERC20/extensions/ERC20Wrapper.test.js @@ -97,6 +97,15 @@ contract('ERC20Wrapper', function (accounts) { value: initialSupply, }); }); + + it('reverts minting to the wrapper contract', async function () { + await this.underlying.approve(this.token.address, MAX_UINT256, { from: initialHolder }); + await expectRevertCustomError( + this.token.depositFor(this.token.address, MAX_UINT256, { from: initialHolder }), + 'ERC20InvalidReceiver', + [this.token.address], + ); + }); }); describe('withdraw', function () { @@ -156,6 +165,14 @@ contract('ERC20Wrapper', function (accounts) { value: initialSupply, }); }); + + it('reverts withdrawing to the wrapper contract', async function () { + expectRevertCustomError( + this.token.withdrawTo(this.token.address, initialSupply, { from: initialHolder }), + 'ERC20InvalidReceiver', + [this.token.address], + ); + }); }); describe('recover', function () { diff --git a/test/token/ERC20/extensions/ERC4626.test.js b/test/token/ERC20/extensions/ERC4626.test.js index 99d6009e4..9dfc4c3b8 100644 --- a/test/token/ERC20/extensions/ERC4626.test.js +++ b/test/token/ERC20/extensions/ERC4626.test.js @@ -52,8 +52,8 @@ contract('ERC4626', function (accounts) { describe('reentrancy', async function () { const reenterType = Enum('No', 'Before', 'After'); - const amount = web3.utils.toBN(1000000000000000000); - const reenterAmount = web3.utils.toBN(1000000000); + const value = web3.utils.toBN(1000000000000000000); + const reenterValue = web3.utils.toBN(1000000000); let token; let vault; @@ -62,8 +62,8 @@ contract('ERC4626', function (accounts) { // Use offset 1 so the rate is not 1:1 and we can't possibly confuse assets and shares vault = await ERC4626OffsetMock.new('', '', token.address, 1); // Funds and approval for tests - await token.$_mint(holder, amount); - await token.$_mint(other, amount); + await token.$_mint(holder, value); + await token.$_mint(other, value); await token.$_approve(holder, vault.address, constants.MAX_UINT256); await token.$_approve(other, vault.address, constants.MAX_UINT256); await token.$_approve(token.address, vault.address, constants.MAX_UINT256); @@ -75,39 +75,39 @@ contract('ERC4626', function (accounts) { // intermediate state in which the ratio of assets/shares has been decreased (more shares than assets). it('correct share price is observed during reentrancy before deposit', async function () { // mint token for deposit - await token.$_mint(token.address, reenterAmount); + await token.$_mint(token.address, reenterValue); // Schedules a reentrancy from the token contract await token.scheduleReenter( reenterType.Before, vault.address, - vault.contract.methods.deposit(reenterAmount, holder).encodeABI(), + vault.contract.methods.deposit(reenterValue, holder).encodeABI(), ); // Initial share price - const sharesForDeposit = await vault.previewDeposit(amount, { from: holder }); - const sharesForReenter = await vault.previewDeposit(reenterAmount, { from: holder }); + const sharesForDeposit = await vault.previewDeposit(value, { from: holder }); + const sharesForReenter = await vault.previewDeposit(reenterValue, { from: holder }); // Do deposit normally, triggering the _beforeTokenTransfer hook - const receipt = await vault.deposit(amount, holder, { from: holder }); + const receipt = await vault.deposit(value, holder, { from: holder }); // Main deposit event await expectEvent(receipt, 'Deposit', { sender: holder, owner: holder, - assets: amount, + assets: value, shares: sharesForDeposit, }); // Reentrant deposit event → uses the same price await expectEvent(receipt, 'Deposit', { sender: token.address, owner: holder, - assets: reenterAmount, + assets: reenterValue, shares: sharesForReenter, }); // Assert prices is kept - const sharesAfter = await vault.previewDeposit(amount, { from: holder }); + const sharesAfter = await vault.previewDeposit(value, { from: holder }); expect(sharesForDeposit).to.be.bignumber.eq(sharesAfter); }); @@ -116,30 +116,30 @@ contract('ERC4626', function (accounts) { // If the order of burn -> transfer is changed to transfer -> burn, the reentrancy could be triggered on an // intermediate state in which the ratio of shares/assets has been decreased (more assets than shares). it('correct share price is observed during reentrancy after withdraw', async function () { - // Deposit into the vault: holder gets `amount` share, token.address gets `reenterAmount` shares - await vault.deposit(amount, holder, { from: holder }); - await vault.deposit(reenterAmount, token.address, { from: other }); + // Deposit into the vault: holder gets `value` share, token.address gets `reenterValue` shares + await vault.deposit(value, holder, { from: holder }); + await vault.deposit(reenterValue, token.address, { from: other }); // Schedules a reentrancy from the token contract await token.scheduleReenter( reenterType.After, vault.address, - vault.contract.methods.withdraw(reenterAmount, holder, token.address).encodeABI(), + vault.contract.methods.withdraw(reenterValue, holder, token.address).encodeABI(), ); // Initial share price - const sharesForWithdraw = await vault.previewWithdraw(amount, { from: holder }); - const sharesForReenter = await vault.previewWithdraw(reenterAmount, { from: holder }); + const sharesForWithdraw = await vault.previewWithdraw(value, { from: holder }); + const sharesForReenter = await vault.previewWithdraw(reenterValue, { from: holder }); // Do withdraw normally, triggering the _afterTokenTransfer hook - const receipt = await vault.withdraw(amount, holder, holder, { from: holder }); + const receipt = await vault.withdraw(value, holder, holder, { from: holder }); // Main withdraw event await expectEvent(receipt, 'Withdraw', { sender: holder, receiver: holder, owner: holder, - assets: amount, + assets: value, shares: sharesForWithdraw, }); // Reentrant withdraw event → uses the same price @@ -147,76 +147,76 @@ contract('ERC4626', function (accounts) { sender: token.address, receiver: holder, owner: token.address, - assets: reenterAmount, + assets: reenterValue, shares: sharesForReenter, }); // Assert price is kept - const sharesAfter = await vault.previewWithdraw(amount, { from: holder }); + const sharesAfter = await vault.previewWithdraw(value, { from: holder }); expect(sharesForWithdraw).to.be.bignumber.eq(sharesAfter); }); // Donate newly minted tokens to the vault during the reentracy causes the share price to increase. // Still, the deposit that trigger the reentracy is not affected and get the previewed price. - // Further deposits will get a different price (getting fewer shares for the same amount of assets) + // Further deposits will get a different price (getting fewer shares for the same value of assets) it('share price change during reentracy does not affect deposit', async function () { // Schedules a reentrancy from the token contract that mess up the share price await token.scheduleReenter( reenterType.Before, token.address, - token.contract.methods.$_mint(vault.address, reenterAmount).encodeABI(), + token.contract.methods.$_mint(vault.address, reenterValue).encodeABI(), ); // Price before - const sharesBefore = await vault.previewDeposit(amount); + const sharesBefore = await vault.previewDeposit(value); // Deposit, triggering the _beforeTokenTransfer hook - const receipt = await vault.deposit(amount, holder, { from: holder }); + const receipt = await vault.deposit(value, holder, { from: holder }); // Price is as previewed await expectEvent(receipt, 'Deposit', { sender: holder, owner: holder, - assets: amount, + assets: value, shares: sharesBefore, }); // Price was modified during reentrancy - const sharesAfter = await vault.previewDeposit(amount); + const sharesAfter = await vault.previewDeposit(value); expect(sharesAfter).to.be.bignumber.lt(sharesBefore); }); // Burn some tokens from the vault during the reentracy causes the share price to drop. // Still, the withdraw that trigger the reentracy is not affected and get the previewed price. - // Further withdraw will get a different price (needing more shares for the same amount of assets) + // Further withdraw will get a different price (needing more shares for the same value of assets) it('share price change during reentracy does not affect withdraw', async function () { - await vault.deposit(amount, other, { from: other }); - await vault.deposit(amount, holder, { from: holder }); + await vault.deposit(value, other, { from: other }); + await vault.deposit(value, holder, { from: holder }); // Schedules a reentrancy from the token contract that mess up the share price await token.scheduleReenter( reenterType.After, token.address, - token.contract.methods.$_burn(vault.address, reenterAmount).encodeABI(), + token.contract.methods.$_burn(vault.address, reenterValue).encodeABI(), ); // Price before - const sharesBefore = await vault.previewWithdraw(amount); + const sharesBefore = await vault.previewWithdraw(value); // Withdraw, triggering the _afterTokenTransfer hook - const receipt = await vault.withdraw(amount, holder, holder, { from: holder }); + const receipt = await vault.withdraw(value, holder, holder, { from: holder }); // Price is as previewed await expectEvent(receipt, 'Withdraw', { sender: holder, receiver: holder, owner: holder, - assets: amount, + assets: value, shares: sharesBefore, }); // Price was modified during reentrancy - const sharesAfter = await vault.previewWithdraw(amount); + const sharesAfter = await vault.previewWithdraw(value); expect(sharesAfter).to.be.bignumber.gt(sharesBefore); }); }); @@ -738,9 +738,9 @@ contract('ERC4626', function (accounts) { describe('ERC4626Fees', function () { const feeBasePoint = web3.utils.toBN(5e3); - const amountWithoutFees = web3.utils.toBN(10000); - const fees = amountWithoutFees.mul(feeBasePoint).divn(1e5); - const amountWithFees = amountWithoutFees.add(fees); + const valueWithoutFees = web3.utils.toBN(10000); + const fees = valueWithoutFees.mul(feeBasePoint).divn(1e5); + const valueWithFees = valueWithoutFees.add(fees); describe('input fees', function () { beforeEach(async function () { @@ -760,13 +760,13 @@ contract('ERC4626', function (accounts) { }); it('deposit', async function () { - expect(await this.vault.previewDeposit(amountWithFees)).to.be.bignumber.equal(amountWithoutFees); - ({ tx: this.tx } = await this.vault.deposit(amountWithFees, recipient, { from: holder })); + expect(await this.vault.previewDeposit(valueWithFees)).to.be.bignumber.equal(valueWithoutFees); + ({ tx: this.tx } = await this.vault.deposit(valueWithFees, recipient, { from: holder })); }); it('mint', async function () { - expect(await this.vault.previewMint(amountWithoutFees)).to.be.bignumber.equal(amountWithFees); - ({ tx: this.tx } = await this.vault.mint(amountWithoutFees, recipient, { from: holder })); + expect(await this.vault.previewMint(valueWithoutFees)).to.be.bignumber.equal(valueWithFees); + ({ tx: this.tx } = await this.vault.mint(valueWithoutFees, recipient, { from: holder })); }); afterEach(async function () { @@ -774,7 +774,7 @@ contract('ERC4626', function (accounts) { await expectEvent.inTransaction(this.tx, this.token, 'Transfer', { from: holder, to: this.vault.address, - value: amountWithFees, + value: valueWithFees, }); // redirect fees @@ -788,15 +788,15 @@ contract('ERC4626', function (accounts) { await expectEvent.inTransaction(this.tx, this.vault, 'Transfer', { from: constants.ZERO_ADDRESS, to: recipient, - value: amountWithoutFees, + value: valueWithoutFees, }); // deposit event await expectEvent.inTransaction(this.tx, this.vault, 'Deposit', { sender: holder, owner: recipient, - assets: amountWithFees, - shares: amountWithoutFees, + assets: valueWithFees, + shares: valueWithoutFees, }); }); }); @@ -819,13 +819,13 @@ contract('ERC4626', function (accounts) { }); it('redeem', async function () { - expect(await this.vault.previewRedeem(amountWithFees)).to.be.bignumber.equal(amountWithoutFees); - ({ tx: this.tx } = await this.vault.redeem(amountWithFees, recipient, holder, { from: holder })); + expect(await this.vault.previewRedeem(valueWithFees)).to.be.bignumber.equal(valueWithoutFees); + ({ tx: this.tx } = await this.vault.redeem(valueWithFees, recipient, holder, { from: holder })); }); it('withdraw', async function () { - expect(await this.vault.previewWithdraw(amountWithoutFees)).to.be.bignumber.equal(amountWithFees); - ({ tx: this.tx } = await this.vault.withdraw(amountWithoutFees, recipient, holder, { from: holder })); + expect(await this.vault.previewWithdraw(valueWithoutFees)).to.be.bignumber.equal(valueWithFees); + ({ tx: this.tx } = await this.vault.withdraw(valueWithoutFees, recipient, holder, { from: holder })); }); afterEach(async function () { @@ -833,7 +833,7 @@ contract('ERC4626', function (accounts) { await expectEvent.inTransaction(this.tx, this.token, 'Transfer', { from: this.vault.address, to: recipient, - value: amountWithoutFees, + value: valueWithoutFees, }); // redirect fees @@ -847,7 +847,7 @@ contract('ERC4626', function (accounts) { await expectEvent.inTransaction(this.tx, this.vault, 'Transfer', { from: holder, to: constants.ZERO_ADDRESS, - value: amountWithFees, + value: valueWithFees, }); // withdraw event @@ -855,8 +855,8 @@ contract('ERC4626', function (accounts) { sender: holder, receiver: recipient, owner: holder, - assets: amountWithoutFees, - shares: amountWithFees, + assets: valueWithoutFees, + shares: valueWithFees, }); }); }); diff --git a/test/token/ERC721/extensions/ERC721Votes.test.js b/test/token/ERC721/extensions/ERC721Votes.test.js index caa44ea8b..45020baf9 100644 --- a/test/token/ERC721/extensions/ERC721Votes.test.js +++ b/test/token/ERC721/extensions/ERC721Votes.test.js @@ -61,7 +61,7 @@ contract('ERC721Votes', function (accounts) { const { receipt } = await this.votes.transferFrom(account1, account2, tokens[0], { from: account1 }); expectEvent(receipt, 'Transfer', { from: account1, to: account2, tokenId: tokens[0] }); - expectEvent(receipt, 'DelegateVotesChanged', { delegate: account1, previousBalance: '1', newBalance: '0' }); + expectEvent(receipt, 'DelegateVotesChanged', { delegate: account1, previousVotes: '1', newVotes: '0' }); const { logIndex: transferLogIndex } = receipt.logs.find(({ event }) => event == 'Transfer'); expect( @@ -79,7 +79,7 @@ contract('ERC721Votes', function (accounts) { const { receipt } = await this.votes.transferFrom(account1, account2, tokens[0], { from: account1 }); expectEvent(receipt, 'Transfer', { from: account1, to: account2, tokenId: tokens[0] }); - expectEvent(receipt, 'DelegateVotesChanged', { delegate: account2, previousBalance: '0', newBalance: '1' }); + expectEvent(receipt, 'DelegateVotesChanged', { delegate: account2, previousVotes: '0', newVotes: '1' }); const { logIndex: transferLogIndex } = receipt.logs.find(({ event }) => event == 'Transfer'); expect( @@ -98,8 +98,8 @@ contract('ERC721Votes', function (accounts) { const { receipt } = await this.votes.transferFrom(account1, account2, tokens[0], { from: account1 }); expectEvent(receipt, 'Transfer', { from: account1, to: account2, tokenId: tokens[0] }); - expectEvent(receipt, 'DelegateVotesChanged', { delegate: account1, previousBalance: '1', newBalance: '0' }); - expectEvent(receipt, 'DelegateVotesChanged', { delegate: account2, previousBalance: '0', newBalance: '1' }); + expectEvent(receipt, 'DelegateVotesChanged', { delegate: account1, previousVotes: '1', newVotes: '0' }); + expectEvent(receipt, 'DelegateVotesChanged', { delegate: account2, previousVotes: '0', newVotes: '1' }); const { logIndex: transferLogIndex } = receipt.logs.find(({ event }) => event == 'Transfer'); expect(