浏览代码

Make more functions virtual (#3078)

Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
Hadrien Croubois 3 年之前
父节点
当前提交
ecae978cb5

+ 1 - 0
CHANGELOG.md

@@ -19,6 +19,7 @@
  * `SignedMath`: a new signed version of the Math library with `max`, `min`,  and `average`. ([#2686](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2686))
  * `SignedMath`: a new signed version of the Math library with `max`, `min`,  and `average`. ([#2686](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2686))
  * `ERC1967Upgrade`: Refactor the secure upgrade to use `ERC1822` instead of the previous rollback mechanism. This reduces code complexity and attack surface with similar security guarantees. ([#3021](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3021))
  * `ERC1967Upgrade`: Refactor the secure upgrade to use `ERC1822` instead of the previous rollback mechanism. This reduces code complexity and attack surface with similar security guarantees. ([#3021](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3021))
  * `UUPSUpgradeable`: Add `ERC1822` compliance to support the updated secure upgrade mechanism. ([#3021](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3021))
  * `UUPSUpgradeable`: Add `ERC1822` compliance to support the updated secure upgrade mechanism. ([#3021](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3021))
+ * Some more functions have been made virtual to customize them via overrides. In many cases this will not imply that other functions in the contract will automatically adapt to the overridden definitions. People who wish to override should consult the source code to understand the impact and if they need to override any additional functions to achieve the desired behavior.
 
 
 ### Breaking changes
 ### Breaking changes
 
 

+ 3 - 3
contracts/access/AccessControl.sol

@@ -81,7 +81,7 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
     /**
     /**
      * @dev Returns `true` if `account` has been granted `role`.
      * @dev Returns `true` if `account` has been granted `role`.
      */
      */
-    function hasRole(bytes32 role, address account) public view override returns (bool) {
+    function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
         return _roles[role].members[account];
         return _roles[role].members[account];
     }
     }
 
 
@@ -92,7 +92,7 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
      *
      *
      *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
      *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
      */
      */
-    function _checkRole(bytes32 role, address account) internal view {
+    function _checkRole(bytes32 role, address account) internal view virtual {
         if (!hasRole(role, account)) {
         if (!hasRole(role, account)) {
             revert(
             revert(
                 string(
                 string(
@@ -113,7 +113,7 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
      *
      *
      * To change a role's admin, use {_setRoleAdmin}.
      * To change a role's admin, use {_setRoleAdmin}.
      */
      */
-    function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
+    function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
         return _roles[role].adminRole;
         return _roles[role].adminRole;
     }
     }
 
 

+ 2 - 2
contracts/access/AccessControlEnumerable.sol

@@ -34,7 +34,7 @@ abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessCon
      * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
      * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
      * for more information.
      * for more information.
      */
      */
-    function getRoleMember(bytes32 role, uint256 index) public view override returns (address) {
+    function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) {
         return _roleMembers[role].at(index);
         return _roleMembers[role].at(index);
     }
     }
 
 
@@ -42,7 +42,7 @@ abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessCon
      * @dev Returns the number of accounts that have `role`. Can be used
      * @dev Returns the number of accounts that have `role`. Can be used
      * together with {getRoleMember} to enumerate all bearers of a role.
      * together with {getRoleMember} to enumerate all bearers of a role.
      */
      */
-    function getRoleMemberCount(bytes32 role) public view override returns (uint256) {
+    function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) {
         return _roleMembers[role].length();
         return _roleMembers[role].length();
     }
     }
 
 

+ 1 - 1
contracts/governance/Governor.sol

@@ -370,7 +370,7 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
         address target,
         address target,
         uint256 value,
         uint256 value,
         bytes calldata data
         bytes calldata data
-    ) external onlyGovernance {
+    ) external virtual onlyGovernance {
         Address.functionCallWithValue(target, data, value);
         Address.functionCallWithValue(target, data, value);
     }
     }
 
 

+ 2 - 1
contracts/token/ERC20/extensions/ERC20FlashMint.sol

@@ -23,7 +23,7 @@ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender {
      * @param token The address of the token that is requested.
      * @param token The address of the token that is requested.
      * @return The amont of token that can be loaned.
      * @return The amont of token that can be loaned.
      */
      */
-    function maxFlashLoan(address token) public view override returns (uint256) {
+    function maxFlashLoan(address token) public view virtual override returns (uint256) {
         return token == address(this) ? type(uint256).max - ERC20.totalSupply() : 0;
         return token == address(this) ? type(uint256).max - ERC20.totalSupply() : 0;
     }
     }
 
 
@@ -62,6 +62,7 @@ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender {
         uint256 amount,
         uint256 amount,
         bytes calldata data
         bytes calldata data
     ) public virtual override returns (bool) {
     ) public virtual override returns (bool) {
+        require(amount <= maxFlashLoan(token), "ERC20FlashMint: amount exceeds maxFlashLoan");
         uint256 fee = flashFee(token, amount);
         uint256 fee = flashFee(token, amount);
         _mint(address(receiver), amount);
         _mint(address(receiver), amount);
         require(
         require(

+ 3 - 3
contracts/token/ERC20/extensions/ERC20Votes.sol

@@ -61,7 +61,7 @@ abstract contract ERC20Votes is IVotes, ERC20Permit {
     /**
     /**
      * @dev Gets the current votes balance for `account`
      * @dev Gets the current votes balance for `account`
      */
      */
-    function getVotes(address account) public view override returns (uint256) {
+    function getVotes(address account) public view virtual override returns (uint256) {
         uint256 pos = _checkpoints[account].length;
         uint256 pos = _checkpoints[account].length;
         return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes;
         return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes;
     }
     }
@@ -73,7 +73,7 @@ abstract contract ERC20Votes is IVotes, ERC20Permit {
      *
      *
      * - `blockNumber` must have been already mined
      * - `blockNumber` must have been already mined
      */
      */
-    function getPastVotes(address account, uint256 blockNumber) public view override returns (uint256) {
+    function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) {
         require(blockNumber < block.number, "ERC20Votes: block not yet mined");
         require(blockNumber < block.number, "ERC20Votes: block not yet mined");
         return _checkpointsLookup(_checkpoints[account], blockNumber);
         return _checkpointsLookup(_checkpoints[account], blockNumber);
     }
     }
@@ -86,7 +86,7 @@ abstract contract ERC20Votes is IVotes, ERC20Permit {
      *
      *
      * - `blockNumber` must have been already mined
      * - `blockNumber` must have been already mined
      */
      */
-    function getPastTotalSupply(uint256 blockNumber) public view override returns (uint256) {
+    function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) {
         require(blockNumber < block.number, "ERC20Votes: block not yet mined");
         require(blockNumber < block.number, "ERC20Votes: block not yet mined");
         return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber);
         return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber);
     }
     }

+ 2 - 2
contracts/token/ERC20/extensions/ERC20VotesComp.sol

@@ -26,14 +26,14 @@ abstract contract ERC20VotesComp is ERC20Votes {
     /**
     /**
      * @dev Comp version of the {getVotes} accessor, with `uint96` return type.
      * @dev Comp version of the {getVotes} accessor, with `uint96` return type.
      */
      */
-    function getCurrentVotes(address account) external view returns (uint96) {
+    function getCurrentVotes(address account) external view virtual returns (uint96) {
         return SafeCast.toUint96(getVotes(account));
         return SafeCast.toUint96(getVotes(account));
     }
     }
 
 
     /**
     /**
      * @dev Comp version of the {getPastVotes} accessor, with `uint96` return type.
      * @dev Comp version of the {getPastVotes} accessor, with `uint96` return type.
      */
      */
-    function getPriorVotes(address account, uint256 blockNumber) external view returns (uint96) {
+    function getPriorVotes(address account, uint256 blockNumber) external view virtual returns (uint96) {
         return SafeCast.toUint96(getPastVotes(account, blockNumber));
         return SafeCast.toUint96(getPastVotes(account, blockNumber));
     }
     }
 
 

+ 1 - 1
contracts/token/ERC777/ERC777.sol

@@ -467,7 +467,7 @@ contract ERC777 is Context, IERC777, IERC20 {
         address holder,
         address holder,
         address spender,
         address spender,
         uint256 value
         uint256 value
-    ) internal {
+    ) internal virtual {
         require(holder != address(0), "ERC777: approve from the zero address");
         require(holder != address(0), "ERC777: approve from the zero address");
         require(spender != address(0), "ERC777: approve to the zero address");
         require(spender != address(0), "ERC777: approve to the zero address");
 
 

+ 1 - 1
contracts/utils/Multicall.sol

@@ -14,7 +14,7 @@ abstract contract Multicall {
     /**
     /**
      * @dev Receives and executes a batch of function calls on this contract.
      * @dev Receives and executes a batch of function calls on this contract.
      */
      */
-    function multicall(bytes[] calldata data) external returns (bytes[] memory results) {
+    function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) {
         results = new bytes[](data.length);
         results = new bytes[](data.length);
         for (uint256 i = 0; i < data.length; i++) {
         for (uint256 i = 0; i < data.length; i++) {
             results[i] = Address.functionDelegateCall(address(this), data[i]);
             results[i] = Address.functionDelegateCall(address(this), data[i]);