浏览代码

Make view and pure functions virtual (#2473)

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

+ 1 - 0
CHANGELOG.md

@@ -15,6 +15,7 @@
  * `EnumerableMap`: fix a memory allocation issue by adding new `EnumerableMap.tryGet(uint)→(bool,address)` functions. `EnumerableMap.get(uint)→string` is now deprecated. ([#2462](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2462))
  * `EnumerableMap`: fix a memory allocation issue by adding new `EnumerableMap.tryGet(uint)→(bool,address)` functions. `EnumerableMap.get(uint)→string` is now deprecated. ([#2462](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2462))
  * `ERC165Checker`: added batch `getSupportedInterfaces`. ([#2469](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2469))
  * `ERC165Checker`: added batch `getSupportedInterfaces`. ([#2469](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2469))
  * `RefundEscrow`: `beneficiaryWithdraw` will forward all available gas to the beneficiary. ([#2480](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2480))
  * `RefundEscrow`: `beneficiaryWithdraw` will forward all available gas to the beneficiary. ([#2480](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2480))
+ * Many view and pure 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.
 
 
 ### Security Fixes
 ### Security Fixes
 
 

+ 9 - 9
contracts/GSN/GSNRecipient.sol

@@ -35,7 +35,7 @@ abstract contract GSNRecipient is IRelayRecipient, Context {
     /**
     /**
      * @dev Returns the address of the {IRelayHub} contract for this recipient.
      * @dev Returns the address of the {IRelayHub} contract for this recipient.
      */
      */
-    function getHubAddr() public view override returns (address) {
+    function getHubAddr() public view virtual override returns (address) {
         return _relayHub;
         return _relayHub;
     }
     }
 
 
@@ -62,7 +62,7 @@ abstract contract GSNRecipient is IRelayRecipient, Context {
      */
      */
     // This function is view for future-proofing, it may require reading from
     // This function is view for future-proofing, it may require reading from
     // storage in the future.
     // storage in the future.
-    function relayHubVersion() public view returns (string memory) {
+    function relayHubVersion() public view virtual returns (string memory) {
         this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
         this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
         return "1.0.0";
         return "1.0.0";
     }
     }
@@ -73,7 +73,7 @@ abstract contract GSNRecipient is IRelayRecipient, Context {
      * Derived contracts should expose this in an external interface with proper access control.
      * Derived contracts should expose this in an external interface with proper access control.
      */
      */
     function _withdrawDeposits(uint256 amount, address payable payee) internal virtual {
     function _withdrawDeposits(uint256 amount, address payable payee) internal virtual {
-        IRelayHub(_relayHub).withdraw(amount, payee);
+        IRelayHub(getHubAddr()).withdraw(amount, payee);
     }
     }
 
 
     // Overrides for Context's functions: when called from RelayHub, sender and
     // Overrides for Context's functions: when called from RelayHub, sender and
@@ -88,7 +88,7 @@ abstract contract GSNRecipient is IRelayRecipient, Context {
      * IMPORTANT: Contracts derived from {GSNRecipient} should never use `msg.sender`, and use {_msgSender} instead.
      * IMPORTANT: Contracts derived from {GSNRecipient} should never use `msg.sender`, and use {_msgSender} instead.
      */
      */
     function _msgSender() internal view virtual override returns (address payable) {
     function _msgSender() internal view virtual override returns (address payable) {
-        if (msg.sender != _relayHub) {
+        if (msg.sender != getHubAddr()) {
             return msg.sender;
             return msg.sender;
         } else {
         } else {
             return _getRelayedCallSender();
             return _getRelayedCallSender();
@@ -102,7 +102,7 @@ abstract contract GSNRecipient is IRelayRecipient, Context {
      * IMPORTANT: Contracts derived from {GSNRecipient} should never use `msg.data`, and use {_msgData} instead.
      * IMPORTANT: Contracts derived from {GSNRecipient} should never use `msg.data`, and use {_msgData} instead.
      */
      */
     function _msgData() internal view virtual override returns (bytes memory) {
     function _msgData() internal view virtual override returns (bytes memory) {
-        if (msg.sender != _relayHub) {
+        if (msg.sender != getHubAddr()) {
             return msg.data;
             return msg.data;
         } else {
         } else {
             return _getRelayedCallData();
             return _getRelayedCallData();
@@ -162,7 +162,7 @@ abstract contract GSNRecipient is IRelayRecipient, Context {
      * @dev Return this in acceptRelayedCall to proceed with the execution of a relayed call. Note that this contract
      * @dev Return this in acceptRelayedCall to proceed with the execution of a relayed call. Note that this contract
      * will be charged a fee by RelayHub
      * will be charged a fee by RelayHub
      */
      */
-    function _approveRelayedCall() internal pure returns (uint256, bytes memory) {
+    function _approveRelayedCall() internal pure virtual returns (uint256, bytes memory) {
         return _approveRelayedCall("");
         return _approveRelayedCall("");
     }
     }
 
 
@@ -171,14 +171,14 @@ abstract contract GSNRecipient is IRelayRecipient, Context {
      *
      *
      * This overload forwards `context` to _preRelayedCall and _postRelayedCall.
      * This overload forwards `context` to _preRelayedCall and _postRelayedCall.
      */
      */
-    function _approveRelayedCall(bytes memory context) internal pure returns (uint256, bytes memory) {
+    function _approveRelayedCall(bytes memory context) internal pure virtual returns (uint256, bytes memory) {
         return (_RELAYED_CALL_ACCEPTED, context);
         return (_RELAYED_CALL_ACCEPTED, context);
     }
     }
 
 
     /**
     /**
      * @dev Return this in acceptRelayedCall to impede execution of a relayed call. No fees will be charged.
      * @dev Return this in acceptRelayedCall to impede execution of a relayed call. No fees will be charged.
      */
      */
-    function _rejectRelayedCall(uint256 errorCode) internal pure returns (uint256, bytes memory) {
+    function _rejectRelayedCall(uint256 errorCode) internal pure virtual returns (uint256, bytes memory) {
         return (_RELAYED_CALL_REJECTED + errorCode, "");
         return (_RELAYED_CALL_REJECTED + errorCode, "");
     }
     }
 
 
@@ -186,7 +186,7 @@ abstract contract GSNRecipient is IRelayRecipient, Context {
      * @dev Calculates how much RelayHub will charge a recipient for using `gas` at a `gasPrice`, given a relayer's
      * @dev Calculates how much RelayHub will charge a recipient for using `gas` at a `gasPrice`, given a relayer's
      * `serviceFee`.
      * `serviceFee`.
      */
      */
-    function _computeCharge(uint256 gas, uint256 gasPrice, uint256 serviceFee) internal pure returns (uint256) {
+    function _computeCharge(uint256 gas, uint256 gasPrice, uint256 serviceFee) internal pure virtual returns (uint256) {
         // The fee is expressed as a percentage. E.g. a value of 40 stands for a 40% fee, so the recipient will be
         // The fee is expressed as a percentage. E.g. a value of 40 stands for a 40% fee, so the recipient will be
         // charged for 1.4 times the spent amount.
         // charged for 1.4 times the spent amount.
         return (gas * gasPrice * (100 + serviceFee)) / 100;
         return (gas * gasPrice * (100 + serviceFee)) / 100;

+ 10 - 10
contracts/GSN/GSNRecipientERC20Fee.sol

@@ -37,15 +37,15 @@ contract GSNRecipientERC20Fee is GSNRecipient {
     /**
     /**
      * @dev Returns the gas payment token.
      * @dev Returns the gas payment token.
      */
      */
-    function token() public view returns (IERC20) {
-        return IERC20(_token);
+    function token() public view virtual returns (__unstable__ERC20Owned) {
+        return _token;
     }
     }
 
 
     /**
     /**
      * @dev Internal function that mints the gas payment token. Derived contracts should expose this function in their public API, with proper access control mechanisms.
      * @dev Internal function that mints the gas payment token. Derived contracts should expose this function in their public API, with proper access control mechanisms.
      */
      */
     function _mint(address account, uint256 amount) internal virtual {
     function _mint(address account, uint256 amount) internal virtual {
-        _token.mint(account, amount);
+        token().mint(account, amount);
     }
     }
 
 
     /**
     /**
@@ -68,7 +68,7 @@ contract GSNRecipientERC20Fee is GSNRecipient {
         override
         override
         returns (uint256, bytes memory)
         returns (uint256, bytes memory)
     {
     {
-        if (_token.balanceOf(from) < maxPossibleCharge) {
+        if (token().balanceOf(from) < maxPossibleCharge) {
             return _rejectRelayedCall(uint256(GSNRecipientERC20FeeErrorCodes.INSUFFICIENT_BALANCE));
             return _rejectRelayedCall(uint256(GSNRecipientERC20FeeErrorCodes.INSUFFICIENT_BALANCE));
         }
         }
 
 
@@ -85,7 +85,7 @@ contract GSNRecipientERC20Fee is GSNRecipient {
         (address from, uint256 maxPossibleCharge) = abi.decode(context, (address, uint256));
         (address from, uint256 maxPossibleCharge) = abi.decode(context, (address, uint256));
 
 
         // The maximum token charge is pre-charged from the user
         // The maximum token charge is pre-charged from the user
-        _token.safeTransferFrom(from, address(this), maxPossibleCharge);
+        token().safeTransferFrom(from, address(this), maxPossibleCharge);
 
 
         return 0;
         return 0;
     }
     }
@@ -104,7 +104,7 @@ contract GSNRecipientERC20Fee is GSNRecipient {
         actualCharge = actualCharge.sub(overestimation);
         actualCharge = actualCharge.sub(overestimation);
 
 
         // After the relayed call has been executed and the actual charge estimated, the excess pre-charge is returned
         // After the relayed call has been executed and the actual charge estimated, the excess pre-charge is returned
-        _token.safeTransfer(from, maxPossibleCharge.sub(actualCharge));
+        token().safeTransfer(from, maxPossibleCharge.sub(actualCharge));
     }
     }
 }
 }
 
 
@@ -121,12 +121,12 @@ contract __unstable__ERC20Owned is ERC20, Ownable {
     constructor(string memory name, string memory symbol) public ERC20(name, symbol) { }
     constructor(string memory name, string memory symbol) public ERC20(name, symbol) { }
 
 
     // The owner (GSNRecipientERC20Fee) can mint tokens
     // The owner (GSNRecipientERC20Fee) can mint tokens
-    function mint(address account, uint256 amount) public onlyOwner {
+    function mint(address account, uint256 amount) public virtual onlyOwner {
         _mint(account, amount);
         _mint(account, amount);
     }
     }
 
 
     // The owner has 'infinite' allowance for all token holders
     // The owner has 'infinite' allowance for all token holders
-    function allowance(address tokenOwner, address spender) public view override returns (uint256) {
+    function allowance(address tokenOwner, address spender) public view virtual override returns (uint256) {
         if (spender == owner()) {
         if (spender == owner()) {
             return _UINT256_MAX;
             return _UINT256_MAX;
         } else {
         } else {
@@ -135,7 +135,7 @@ contract __unstable__ERC20Owned is ERC20, Ownable {
     }
     }
 
 
     // Allowance for the owner cannot be changed (it is always 'infinite')
     // Allowance for the owner cannot be changed (it is always 'infinite')
-    function _approve(address tokenOwner, address spender, uint256 value) internal override {
+    function _approve(address tokenOwner, address spender, uint256 value) internal virtual override {
         if (spender == owner()) {
         if (spender == owner()) {
             return;
             return;
         } else {
         } else {
@@ -143,7 +143,7 @@ contract __unstable__ERC20Owned is ERC20, Ownable {
         }
         }
     }
     }
 
 
-    function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
+    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
         if (recipient == owner()) {
         if (recipient == owner()) {
             _transfer(sender, recipient, amount);
             _transfer(sender, recipient, amount);
             return true;
             return true;

+ 2 - 2
contracts/access/Ownable.sol

@@ -32,7 +32,7 @@ abstract contract Ownable is Context {
     /**
     /**
      * @dev Returns the address of the current owner.
      * @dev Returns the address of the current owner.
      */
      */
-    function owner() public view returns (address) {
+    function owner() public view virtual returns (address) {
         return _owner;
         return _owner;
     }
     }
 
 
@@ -40,7 +40,7 @@ abstract contract Ownable is Context {
      * @dev Throws if called by any account other than the owner.
      * @dev Throws if called by any account other than the owner.
      */
      */
     modifier onlyOwner() {
     modifier onlyOwner() {
-        require(_owner == _msgSender(), "Ownable: caller is not the owner");
+        require(owner() == _msgSender(), "Ownable: caller is not the owner");
         _;
         _;
     }
     }
 
 

+ 21 - 12
contracts/access/TimelockController.sol

@@ -93,33 +93,42 @@ contract TimelockController is AccessControl {
      */
      */
     receive() external payable {}
     receive() external payable {}
 
 
+    /**
+     * @dev Returns whether an id correspond to a registered operation. This
+     * includes both Pending, Ready and Done operations.
+     */
+    function isOperation(bytes32 id) public view virtual returns (bool pending) {
+        return getTimestamp(id) > 0;
+    }
+
     /**
     /**
      * @dev Returns whether an operation is pending or not.
      * @dev Returns whether an operation is pending or not.
      */
      */
-    function isOperationPending(bytes32 id) public view returns (bool pending) {
-        return _timestamps[id] > _DONE_TIMESTAMP;
+    function isOperationPending(bytes32 id) public view virtual returns (bool pending) {
+        return getTimestamp(id) > _DONE_TIMESTAMP;
     }
     }
 
 
     /**
     /**
      * @dev Returns whether an operation is ready or not.
      * @dev Returns whether an operation is ready or not.
      */
      */
-    function isOperationReady(bytes32 id) public view returns (bool ready) {
+    function isOperationReady(bytes32 id) public view virtual returns (bool ready) {
+        uint256 timestamp = getTimestamp(id);
         // solhint-disable-next-line not-rely-on-time
         // solhint-disable-next-line not-rely-on-time
-        return _timestamps[id] > _DONE_TIMESTAMP && _timestamps[id] <= block.timestamp;
+        return timestamp > _DONE_TIMESTAMP && timestamp <= block.timestamp;
     }
     }
 
 
     /**
     /**
      * @dev Returns whether an operation is done or not.
      * @dev Returns whether an operation is done or not.
      */
      */
-    function isOperationDone(bytes32 id) public view returns (bool done) {
-        return _timestamps[id] == _DONE_TIMESTAMP;
+    function isOperationDone(bytes32 id) public view virtual returns (bool done) {
+        return getTimestamp(id) == _DONE_TIMESTAMP;
     }
     }
 
 
     /**
     /**
      * @dev Returns the timestamp at with an operation becomes ready (0 for
      * @dev Returns the timestamp at with an operation becomes ready (0 for
      * unset operations, 1 for done operations).
      * unset operations, 1 for done operations).
      */
      */
-    function getTimestamp(bytes32 id) public view returns (uint256 timestamp) {
+    function getTimestamp(bytes32 id) public view virtual returns (uint256 timestamp) {
         return _timestamps[id];
         return _timestamps[id];
     }
     }
 
 
@@ -128,7 +137,7 @@ contract TimelockController is AccessControl {
      *
      *
      * This value can be changed by executing an operation that calls `updateDelay`.
      * This value can be changed by executing an operation that calls `updateDelay`.
      */
      */
-    function getMinDelay() public view returns (uint256 duration) {
+    function getMinDelay() public view virtual returns (uint256 duration) {
         return _minDelay;
         return _minDelay;
     }
     }
 
 
@@ -136,7 +145,7 @@ contract TimelockController is AccessControl {
      * @dev Returns the identifier of an operation containing a single
      * @dev Returns the identifier of an operation containing a single
      * transaction.
      * transaction.
      */
      */
-    function hashOperation(address target, uint256 value, bytes calldata data, bytes32 predecessor, bytes32 salt) public pure returns (bytes32 hash) {
+    function hashOperation(address target, uint256 value, bytes calldata data, bytes32 predecessor, bytes32 salt) public pure virtual returns (bytes32 hash) {
         return keccak256(abi.encode(target, value, data, predecessor, salt));
         return keccak256(abi.encode(target, value, data, predecessor, salt));
     }
     }
 
 
@@ -144,7 +153,7 @@ contract TimelockController is AccessControl {
      * @dev Returns the identifier of an operation containing a batch of
      * @dev Returns the identifier of an operation containing a batch of
      * transactions.
      * transactions.
      */
      */
-    function hashOperationBatch(address[] calldata targets, uint256[] calldata values, bytes[] calldata datas, bytes32 predecessor, bytes32 salt) public pure returns (bytes32 hash) {
+    function hashOperationBatch(address[] calldata targets, uint256[] calldata values, bytes[] calldata datas, bytes32 predecessor, bytes32 salt) public pure virtual returns (bytes32 hash) {
         return keccak256(abi.encode(targets, values, datas, predecessor, salt));
         return keccak256(abi.encode(targets, values, datas, predecessor, salt));
     }
     }
 
 
@@ -187,8 +196,8 @@ contract TimelockController is AccessControl {
      * @dev Schedule an operation that is to becomes valid after a given delay.
      * @dev Schedule an operation that is to becomes valid after a given delay.
      */
      */
     function _schedule(bytes32 id, uint256 delay) private {
     function _schedule(bytes32 id, uint256 delay) private {
-        require(_timestamps[id] == 0, "TimelockController: operation already scheduled");
-        require(delay >= _minDelay, "TimelockController: insufficient delay");
+        require(!isOperation(id), "TimelockController: operation already scheduled");
+        require(delay >= getMinDelay(), "TimelockController: insufficient delay");
         // solhint-disable-next-line not-rely-on-time
         // solhint-disable-next-line not-rely-on-time
         _timestamps[id] = SafeMath.add(block.timestamp, delay);
         _timestamps[id] = SafeMath.add(block.timestamp, delay);
     }
     }

+ 3 - 3
contracts/drafts/EIP712.sol

@@ -46,7 +46,7 @@ abstract contract EIP712 {
     constructor(string memory name, string memory version) internal {
     constructor(string memory name, string memory version) internal {
         bytes32 hashedName = keccak256(bytes(name));
         bytes32 hashedName = keccak256(bytes(name));
         bytes32 hashedVersion = keccak256(bytes(version));
         bytes32 hashedVersion = keccak256(bytes(version));
-        bytes32 typeHash = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); 
+        bytes32 typeHash = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
         _HASHED_NAME = hashedName;
         _HASHED_NAME = hashedName;
         _HASHED_VERSION = hashedVersion;
         _HASHED_VERSION = hashedVersion;
         _CACHED_CHAIN_ID = _getChainId();
         _CACHED_CHAIN_ID = _getChainId();
@@ -57,7 +57,7 @@ abstract contract EIP712 {
     /**
     /**
      * @dev Returns the domain separator for the current chain.
      * @dev Returns the domain separator for the current chain.
      */
      */
-    function _domainSeparatorV4() internal view returns (bytes32) {
+    function _domainSeparatorV4() internal view virtual returns (bytes32) {
         if (_getChainId() == _CACHED_CHAIN_ID) {
         if (_getChainId() == _CACHED_CHAIN_ID) {
             return _CACHED_DOMAIN_SEPARATOR;
             return _CACHED_DOMAIN_SEPARATOR;
         } else {
         } else {
@@ -92,7 +92,7 @@ abstract contract EIP712 {
      * address signer = ECDSA.recover(digest, signature);
      * address signer = ECDSA.recover(digest, signature);
      * ```
      * ```
      */
      */
-    function _hashTypedDataV4(bytes32 structHash) internal view returns (bytes32) {
+    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
         return keccak256(abi.encodePacked("\x19\x01", _domainSeparatorV4(), structHash));
         return keccak256(abi.encodePacked("\x19\x01", _domainSeparatorV4(), structHash));
     }
     }
 
 

+ 1 - 1
contracts/introspection/ERC165.sol

@@ -32,7 +32,7 @@ abstract contract ERC165 is IERC165 {
      *
      *
      * Time complexity O(1), guaranteed to always use less than 30 000 gas.
      * Time complexity O(1), guaranteed to always use less than 30 000 gas.
      */
      */
-    function supportsInterface(bytes4 interfaceId) public view override returns (bool) {
+    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
         return _supportedInterfaces[interfaceId];
         return _supportedInterfaces[interfaceId];
     }
     }
 
 

+ 1 - 1
contracts/introspection/ERC1820Implementer.sol

@@ -20,7 +20,7 @@ contract ERC1820Implementer is IERC1820Implementer {
     /**
     /**
      * See {IERC1820Implementer-canImplementInterfaceForAddress}.
      * See {IERC1820Implementer-canImplementInterfaceForAddress}.
      */
      */
-    function canImplementInterfaceForAddress(bytes32 interfaceHash, address account) public view override returns (bytes32) {
+    function canImplementInterfaceForAddress(bytes32 interfaceHash, address account) public view virtual override returns (bytes32) {
         return _supportedInterfaces[interfaceHash][account] ? _ERC1820_ACCEPT_MAGIC : bytes32(0x00);
         return _supportedInterfaces[interfaceHash][account] ? _ERC1820_ACCEPT_MAGIC : bytes32(0x00);
     }
     }
 
 

+ 9 - 9
contracts/payment/escrow/RefundEscrow.sol

@@ -36,14 +36,14 @@ contract RefundEscrow is ConditionalEscrow {
     /**
     /**
      * @return The current state of the escrow.
      * @return The current state of the escrow.
      */
      */
-    function state() public view returns (State) {
+    function state() public view virtual returns (State) {
         return _state;
         return _state;
     }
     }
 
 
     /**
     /**
      * @return The beneficiary of the escrow.
      * @return The beneficiary of the escrow.
      */
      */
-    function beneficiary() public view returns (address) {
+    function beneficiary() public view virtual returns (address payable) {
         return _beneficiary;
         return _beneficiary;
     }
     }
 
 
@@ -52,7 +52,7 @@ contract RefundEscrow is ConditionalEscrow {
      * @param refundee The address funds will be sent to if a refund occurs.
      * @param refundee The address funds will be sent to if a refund occurs.
      */
      */
     function deposit(address refundee) public payable virtual override {
     function deposit(address refundee) public payable virtual override {
-        require(_state == State.Active, "RefundEscrow: can only deposit while active");
+        require(state() == State.Active, "RefundEscrow: can only deposit while active");
         super.deposit(refundee);
         super.deposit(refundee);
     }
     }
 
 
@@ -60,8 +60,8 @@ contract RefundEscrow is ConditionalEscrow {
      * @dev Allows for the beneficiary to withdraw their funds, rejecting
      * @dev Allows for the beneficiary to withdraw their funds, rejecting
      * further deposits.
      * further deposits.
      */
      */
-    function close() public onlyOwner virtual {
-        require(_state == State.Active, "RefundEscrow: can only close while active");
+    function close() public virtual onlyOwner {
+        require(state() == State.Active, "RefundEscrow: can only close while active");
         _state = State.Closed;
         _state = State.Closed;
         emit RefundsClosed();
         emit RefundsClosed();
     }
     }
@@ -70,7 +70,7 @@ contract RefundEscrow is ConditionalEscrow {
      * @dev Allows for refunds to take place, rejecting further deposits.
      * @dev Allows for refunds to take place, rejecting further deposits.
      */
      */
     function enableRefunds() public onlyOwner virtual {
     function enableRefunds() public onlyOwner virtual {
-        require(_state == State.Active, "RefundEscrow: can only enable refunds while active");
+        require(state() == State.Active, "RefundEscrow: can only enable refunds while active");
         _state = State.Refunding;
         _state = State.Refunding;
         emit RefundsEnabled();
         emit RefundsEnabled();
     }
     }
@@ -79,8 +79,8 @@ contract RefundEscrow is ConditionalEscrow {
      * @dev Withdraws the beneficiary's funds.
      * @dev Withdraws the beneficiary's funds.
      */
      */
     function beneficiaryWithdraw() public virtual {
     function beneficiaryWithdraw() public virtual {
-        require(_state == State.Closed, "RefundEscrow: beneficiary can only withdraw while closed");
-        _beneficiary.sendValue(address(this).balance);
+        require(state() == State.Closed, "RefundEscrow: beneficiary can only withdraw while closed");
+        beneficiary().sendValue(address(this).balance);
     }
     }
 
 
     /**
     /**
@@ -88,6 +88,6 @@ contract RefundEscrow is ConditionalEscrow {
      * 'payee' argument, but we ignore it here since the condition is global, not per-payee.
      * 'payee' argument, but we ignore it here since the condition is global, not per-payee.
      */
      */
     function withdrawalAllowed(address) public view override returns (bool) {
     function withdrawalAllowed(address) public view override returns (bool) {
-        return _state == State.Refunding;
+        return state() == State.Refunding;
     }
     }
 }
 }

+ 2 - 2
contracts/proxy/BeaconProxy.sol

@@ -38,7 +38,7 @@ contract BeaconProxy is Proxy {
     /**
     /**
      * @dev Returns the current beacon address.
      * @dev Returns the current beacon address.
      */
      */
-    function _beacon() internal view returns (address beacon) {
+    function _beacon() internal view virtual returns (address beacon) {
         bytes32 slot = _BEACON_SLOT;
         bytes32 slot = _BEACON_SLOT;
         // solhint-disable-next-line no-inline-assembly
         // solhint-disable-next-line no-inline-assembly
         assembly {
         assembly {
@@ -49,7 +49,7 @@ contract BeaconProxy is Proxy {
     /**
     /**
      * @dev Returns the current implementation address of the associated beacon.
      * @dev Returns the current implementation address of the associated beacon.
      */
      */
-    function _implementation() internal view override returns (address) {
+    function _implementation() internal view virtual override returns (address) {
         return IBeacon(_beacon()).implementation();
         return IBeacon(_beacon()).implementation();
     }
     }
 
 

+ 1 - 1
contracts/proxy/Proxy.sol

@@ -44,7 +44,7 @@ abstract contract Proxy {
      * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
      * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
      * and {_fallback} should delegate.
      * and {_fallback} should delegate.
      */
      */
-    function _implementation() internal virtual view returns (address);
+    function _implementation() internal view virtual returns (address);
 
 
     /**
     /**
      * @dev Delegates the current call to the address returned by `_implementation()`.
      * @dev Delegates the current call to the address returned by `_implementation()`.

+ 2 - 2
contracts/proxy/ProxyAdmin.sol

@@ -18,7 +18,7 @@ contract ProxyAdmin is Ownable {
      *
      *
      * - This contract must be the admin of `proxy`.
      * - This contract must be the admin of `proxy`.
      */
      */
-    function getProxyImplementation(TransparentUpgradeableProxy proxy) public view returns (address) {
+    function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {
         // We need to manually run the static call since the getter cannot be flagged as view
         // We need to manually run the static call since the getter cannot be flagged as view
         // bytes4(keccak256("implementation()")) == 0x5c60da1b
         // bytes4(keccak256("implementation()")) == 0x5c60da1b
         (bool success, bytes memory returndata) = address(proxy).staticcall(hex"5c60da1b");
         (bool success, bytes memory returndata) = address(proxy).staticcall(hex"5c60da1b");
@@ -33,7 +33,7 @@ contract ProxyAdmin is Ownable {
      *
      *
      * - This contract must be the admin of `proxy`.
      * - This contract must be the admin of `proxy`.
      */
      */
-    function getProxyAdmin(TransparentUpgradeableProxy proxy) public view returns (address) {
+    function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {
         // We need to manually run the static call since the getter cannot be flagged as view
         // We need to manually run the static call since the getter cannot be flagged as view
         // bytes4(keccak256("admin()")) == 0xf851a440
         // bytes4(keccak256("admin()")) == 0xf851a440
         (bool success, bytes memory returndata) = address(proxy).staticcall(hex"f851a440");
         (bool success, bytes memory returndata) = address(proxy).staticcall(hex"f851a440");

+ 1 - 1
contracts/proxy/TransparentUpgradeableProxy.sol

@@ -121,7 +121,7 @@ contract TransparentUpgradeableProxy is UpgradeableProxy {
     /**
     /**
      * @dev Returns the current admin.
      * @dev Returns the current admin.
      */
      */
-    function _admin() internal view returns (address adm) {
+    function _admin() internal view virtual returns (address adm) {
         bytes32 slot = _ADMIN_SLOT;
         bytes32 slot = _ADMIN_SLOT;
         // solhint-disable-next-line no-inline-assembly
         // solhint-disable-next-line no-inline-assembly
         assembly {
         assembly {

+ 1 - 1
contracts/proxy/UpgradeableBeacon.sol

@@ -31,7 +31,7 @@ contract UpgradeableBeacon is IBeacon, Ownable {
     /**
     /**
      * @dev Returns the current implementation address.
      * @dev Returns the current implementation address.
      */
      */
-    function implementation() public view override returns (address) {
+    function implementation() public view virtual override returns (address) {
         return _implementation;
         return _implementation;
     }
     }
 
 

+ 1 - 1
contracts/proxy/UpgradeableProxy.sol

@@ -44,7 +44,7 @@ contract UpgradeableProxy is Proxy {
     /**
     /**
      * @dev Returns the current implementation address.
      * @dev Returns the current implementation address.
      */
      */
-    function _implementation() internal view override returns (address impl) {
+    function _implementation() internal view virtual override returns (address impl) {
         bytes32 slot = _IMPLEMENTATION_SLOT;
         bytes32 slot = _IMPLEMENTATION_SLOT;
         // solhint-disable-next-line no-inline-assembly
         // solhint-disable-next-line no-inline-assembly
         assembly {
         assembly {

+ 5 - 5
contracts/token/ERC1155/ERC1155.sol

@@ -72,7 +72,7 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
      * Clients calling this function must replace the `\{id\}` substring with the
      * Clients calling this function must replace the `\{id\}` substring with the
      * actual token type ID.
      * actual token type ID.
      */
      */
-    function uri(uint256) external view override returns (string memory) {
+    function uri(uint256) external view virtual override returns (string memory) {
         return _uri;
         return _uri;
     }
     }
 
 
@@ -83,7 +83,7 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
      *
      *
      * - `account` cannot be the zero address.
      * - `account` cannot be the zero address.
      */
      */
-    function balanceOf(address account, uint256 id) public view override returns (uint256) {
+    function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {
         require(account != address(0), "ERC1155: balance query for the zero address");
         require(account != address(0), "ERC1155: balance query for the zero address");
         return _balances[id][account];
         return _balances[id][account];
     }
     }
@@ -101,6 +101,7 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
     )
     )
         public
         public
         view
         view
+        virtual
         override
         override
         returns (uint256[] memory)
         returns (uint256[] memory)
     {
     {
@@ -109,8 +110,7 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
         uint256[] memory batchBalances = new uint256[](accounts.length);
         uint256[] memory batchBalances = new uint256[](accounts.length);
 
 
         for (uint256 i = 0; i < accounts.length; ++i) {
         for (uint256 i = 0; i < accounts.length; ++i) {
-            require(accounts[i] != address(0), "ERC1155: batch balance query for the zero address");
-            batchBalances[i] = _balances[ids[i]][accounts[i]];
+            batchBalances[i] = balanceOf(accounts[i], ids[i]);
         }
         }
 
 
         return batchBalances;
         return batchBalances;
@@ -129,7 +129,7 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
     /**
     /**
      * @dev See {IERC1155-isApprovedForAll}.
      * @dev See {IERC1155-isApprovedForAll}.
      */
      */
-    function isApprovedForAll(address account, address operator) public view override returns (bool) {
+    function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {
         return _operatorApprovals[account][operator];
         return _operatorApprovals[account][operator];
     }
     }
 
 

+ 5 - 5
contracts/token/ERC20/ERC20.sol

@@ -61,7 +61,7 @@ contract ERC20 is Context, IERC20 {
     /**
     /**
      * @dev Returns the name of the token.
      * @dev Returns the name of the token.
      */
      */
-    function name() public view returns (string memory) {
+    function name() public view virtual returns (string memory) {
         return _name;
         return _name;
     }
     }
 
 
@@ -69,7 +69,7 @@ contract ERC20 is Context, IERC20 {
      * @dev Returns the symbol of the token, usually a shorter version of the
      * @dev Returns the symbol of the token, usually a shorter version of the
      * name.
      * name.
      */
      */
-    function symbol() public view returns (string memory) {
+    function symbol() public view virtual returns (string memory) {
         return _symbol;
         return _symbol;
     }
     }
 
 
@@ -86,21 +86,21 @@ contract ERC20 is Context, IERC20 {
      * no way affects any of the arithmetic of the contract, including
      * no way affects any of the arithmetic of the contract, including
      * {IERC20-balanceOf} and {IERC20-transfer}.
      * {IERC20-balanceOf} and {IERC20-transfer}.
      */
      */
-    function decimals() public view returns (uint8) {
+    function decimals() public view virtual returns (uint8) {
         return _decimals;
         return _decimals;
     }
     }
 
 
     /**
     /**
      * @dev See {IERC20-totalSupply}.
      * @dev See {IERC20-totalSupply}.
      */
      */
-    function totalSupply() public view override returns (uint256) {
+    function totalSupply() public view virtual override returns (uint256) {
         return _totalSupply;
         return _totalSupply;
     }
     }
 
 
     /**
     /**
      * @dev See {IERC20-balanceOf}.
      * @dev See {IERC20-balanceOf}.
      */
      */
-    function balanceOf(address account) public view override returns (uint256) {
+    function balanceOf(address account) public view virtual override returns (uint256) {
         return _balances[account];
         return _balances[account];
     }
     }
 
 

+ 2 - 2
contracts/token/ERC20/ERC20Capped.sol

@@ -24,7 +24,7 @@ abstract contract ERC20Capped is ERC20 {
     /**
     /**
      * @dev Returns the cap on the token's total supply.
      * @dev Returns the cap on the token's total supply.
      */
      */
-    function cap() public view returns (uint256) {
+    function cap() public view virtual returns (uint256) {
         return _cap;
         return _cap;
     }
     }
 
 
@@ -39,7 +39,7 @@ abstract contract ERC20Capped is ERC20 {
         super._beforeTokenTransfer(from, to, amount);
         super._beforeTokenTransfer(from, to, amount);
 
 
         if (from == address(0)) { // When minting tokens
         if (from == address(0)) { // When minting tokens
-            require(totalSupply().add(amount) <= _cap, "ERC20Capped: cap exceeded");
+            require(totalSupply().add(amount) <= cap(), "ERC20Capped: cap exceeded");
         }
         }
     }
     }
 }
 }

+ 2 - 2
contracts/token/ERC20/ERC20Snapshot.sol

@@ -89,7 +89,7 @@ abstract contract ERC20Snapshot is ERC20 {
     /**
     /**
      * @dev Retrieves the balance of `account` at the time `snapshotId` was created.
      * @dev Retrieves the balance of `account` at the time `snapshotId` was created.
      */
      */
-    function balanceOfAt(address account, uint256 snapshotId) public view returns (uint256) {
+    function balanceOfAt(address account, uint256 snapshotId) public view virtual returns (uint256) {
         (bool snapshotted, uint256 value) = _valueAt(snapshotId, _accountBalanceSnapshots[account]);
         (bool snapshotted, uint256 value) = _valueAt(snapshotId, _accountBalanceSnapshots[account]);
 
 
         return snapshotted ? value : balanceOf(account);
         return snapshotted ? value : balanceOf(account);
@@ -98,7 +98,7 @@ abstract contract ERC20Snapshot is ERC20 {
     /**
     /**
      * @dev Retrieves the total supply at the time `snapshotId` was created.
      * @dev Retrieves the total supply at the time `snapshotId` was created.
      */
      */
-    function totalSupplyAt(uint256 snapshotId) public view returns(uint256) {
+    function totalSupplyAt(uint256 snapshotId) public view virtual returns(uint256) {
         (bool snapshotted, uint256 value) = _valueAt(snapshotId, _totalSupplySnapshots);
         (bool snapshotted, uint256 value) = _valueAt(snapshotId, _totalSupplySnapshots);
 
 
         return snapshotted ? value : totalSupply();
         return snapshotted ? value : totalSupply();

+ 6 - 6
contracts/token/ERC20/TokenTimelock.sol

@@ -34,21 +34,21 @@ contract TokenTimelock {
     /**
     /**
      * @return the token being held.
      * @return the token being held.
      */
      */
-    function token() public view returns (IERC20) {
+    function token() public view virtual returns (IERC20) {
         return _token;
         return _token;
     }
     }
 
 
     /**
     /**
      * @return the beneficiary of the tokens.
      * @return the beneficiary of the tokens.
      */
      */
-    function beneficiary() public view returns (address) {
+    function beneficiary() public view virtual returns (address) {
         return _beneficiary;
         return _beneficiary;
     }
     }
 
 
     /**
     /**
      * @return the time when the tokens are released.
      * @return the time when the tokens are released.
      */
      */
-    function releaseTime() public view returns (uint256) {
+    function releaseTime() public view virtual returns (uint256) {
         return _releaseTime;
         return _releaseTime;
     }
     }
 
 
@@ -57,11 +57,11 @@ contract TokenTimelock {
      */
      */
     function release() public virtual {
     function release() public virtual {
         // solhint-disable-next-line not-rely-on-time
         // solhint-disable-next-line not-rely-on-time
-        require(block.timestamp >= _releaseTime, "TokenTimelock: current time is before release time");
+        require(block.timestamp >= releaseTime(), "TokenTimelock: current time is before release time");
 
 
-        uint256 amount = _token.balanceOf(address(this));
+        uint256 amount = token().balanceOf(address(this));
         require(amount > 0, "TokenTimelock: no tokens to release");
         require(amount > 0, "TokenTimelock: no tokens to release");
 
 
-        _token.safeTransfer(_beneficiary, amount);
+        token().safeTransfer(beneficiary(), amount);
     }
     }
 }
 }

+ 24 - 24
contracts/token/ERC721/ERC721.sol

@@ -103,51 +103,51 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable
     /**
     /**
      * @dev See {IERC721-balanceOf}.
      * @dev See {IERC721-balanceOf}.
      */
      */
-    function balanceOf(address owner) public view override returns (uint256) {
+    function balanceOf(address owner) public view virtual override returns (uint256) {
         require(owner != address(0), "ERC721: balance query for the zero address");
         require(owner != address(0), "ERC721: balance query for the zero address");
-
         return _holderTokens[owner].length();
         return _holderTokens[owner].length();
     }
     }
 
 
     /**
     /**
      * @dev See {IERC721-ownerOf}.
      * @dev See {IERC721-ownerOf}.
      */
      */
-    function ownerOf(uint256 tokenId) public view override returns (address) {
+    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
         return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token");
         return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token");
     }
     }
 
 
     /**
     /**
      * @dev See {IERC721Metadata-name}.
      * @dev See {IERC721Metadata-name}.
      */
      */
-    function name() public view override returns (string memory) {
+    function name() public view virtual override returns (string memory) {
         return _name;
         return _name;
     }
     }
 
 
     /**
     /**
      * @dev See {IERC721Metadata-symbol}.
      * @dev See {IERC721Metadata-symbol}.
      */
      */
-    function symbol() public view override returns (string memory) {
+    function symbol() public view virtual override returns (string memory) {
         return _symbol;
         return _symbol;
     }
     }
 
 
     /**
     /**
      * @dev See {IERC721Metadata-tokenURI}.
      * @dev See {IERC721Metadata-tokenURI}.
      */
      */
-    function tokenURI(uint256 tokenId) public view override returns (string memory) {
+    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
         require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
         require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
 
 
         string memory _tokenURI = _tokenURIs[tokenId];
         string memory _tokenURI = _tokenURIs[tokenId];
+        string memory base = baseURI();
 
 
         // If there is no base URI, return the token URI.
         // If there is no base URI, return the token URI.
-        if (bytes(_baseURI).length == 0) {
+        if (bytes(base).length == 0) {
             return _tokenURI;
             return _tokenURI;
         }
         }
         // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
         // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
         if (bytes(_tokenURI).length > 0) {
         if (bytes(_tokenURI).length > 0) {
-            return string(abi.encodePacked(_baseURI, _tokenURI));
+            return string(abi.encodePacked(base, _tokenURI));
         }
         }
         // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
         // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
-        return string(abi.encodePacked(_baseURI, tokenId.toString()));
+        return string(abi.encodePacked(base, tokenId.toString()));
     }
     }
 
 
     /**
     /**
@@ -155,21 +155,21 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable
     * automatically added as a prefix in {tokenURI} to each token's URI, or
     * automatically added as a prefix in {tokenURI} to each token's URI, or
     * to the token ID if no specific URI is set for that token ID.
     * to the token ID if no specific URI is set for that token ID.
     */
     */
-    function baseURI() public view returns (string memory) {
+    function baseURI() public view virtual returns (string memory) {
         return _baseURI;
         return _baseURI;
     }
     }
 
 
     /**
     /**
      * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
      * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
      */
      */
-    function tokenOfOwnerByIndex(address owner, uint256 index) public view override returns (uint256) {
+    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
         return _holderTokens[owner].at(index);
         return _holderTokens[owner].at(index);
     }
     }
 
 
     /**
     /**
      * @dev See {IERC721Enumerable-totalSupply}.
      * @dev See {IERC721Enumerable-totalSupply}.
      */
      */
-    function totalSupply() public view override returns (uint256) {
+    function totalSupply() public view virtual override returns (uint256) {
         // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds
         // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds
         return _tokenOwners.length();
         return _tokenOwners.length();
     }
     }
@@ -177,7 +177,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable
     /**
     /**
      * @dev See {IERC721Enumerable-tokenByIndex}.
      * @dev See {IERC721Enumerable-tokenByIndex}.
      */
      */
-    function tokenByIndex(uint256 index) public view override returns (uint256) {
+    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
         (uint256 tokenId, ) = _tokenOwners.at(index);
         (uint256 tokenId, ) = _tokenOwners.at(index);
         return tokenId;
         return tokenId;
     }
     }
@@ -186,10 +186,10 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable
      * @dev See {IERC721-approve}.
      * @dev See {IERC721-approve}.
      */
      */
     function approve(address to, uint256 tokenId) public virtual override {
     function approve(address to, uint256 tokenId) public virtual override {
-        address owner = ownerOf(tokenId);
+        address owner = ERC721.ownerOf(tokenId);
         require(to != owner, "ERC721: approval to current owner");
         require(to != owner, "ERC721: approval to current owner");
 
 
-        require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
+        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),
             "ERC721: approve caller is not owner nor approved for all"
             "ERC721: approve caller is not owner nor approved for all"
         );
         );
 
 
@@ -199,7 +199,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable
     /**
     /**
      * @dev See {IERC721-getApproved}.
      * @dev See {IERC721-getApproved}.
      */
      */
-    function getApproved(uint256 tokenId) public view override returns (address) {
+    function getApproved(uint256 tokenId) public view virtual override returns (address) {
         require(_exists(tokenId), "ERC721: approved query for nonexistent token");
         require(_exists(tokenId), "ERC721: approved query for nonexistent token");
 
 
         return _tokenApprovals[tokenId];
         return _tokenApprovals[tokenId];
@@ -218,7 +218,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable
     /**
     /**
      * @dev See {IERC721-isApprovedForAll}.
      * @dev See {IERC721-isApprovedForAll}.
      */
      */
-    function isApprovedForAll(address owner, address operator) public view override returns (bool) {
+    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
         return _operatorApprovals[owner][operator];
         return _operatorApprovals[owner][operator];
     }
     }
 
 
@@ -278,7 +278,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable
      * Tokens start existing when they are minted (`_mint`),
      * Tokens start existing when they are minted (`_mint`),
      * and stop existing when they are burned (`_burn`).
      * and stop existing when they are burned (`_burn`).
      */
      */
-    function _exists(uint256 tokenId) internal view returns (bool) {
+    function _exists(uint256 tokenId) internal view virtual returns (bool) {
         return _tokenOwners.contains(tokenId);
         return _tokenOwners.contains(tokenId);
     }
     }
 
 
@@ -289,10 +289,10 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable
      *
      *
      * - `tokenId` must exist.
      * - `tokenId` must exist.
      */
      */
-    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {
+    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
         require(_exists(tokenId), "ERC721: operator query for nonexistent token");
         require(_exists(tokenId), "ERC721: operator query for nonexistent token");
-        address owner = ownerOf(tokenId);
-        return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
+        address owner = ERC721.ownerOf(tokenId);
+        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));
     }
     }
 
 
     /**
     /**
@@ -354,7 +354,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable
      * Emits a {Transfer} event.
      * Emits a {Transfer} event.
      */
      */
     function _burn(uint256 tokenId) internal virtual {
     function _burn(uint256 tokenId) internal virtual {
-        address owner = ownerOf(tokenId);
+        address owner = ERC721.ownerOf(tokenId); // internal owner
 
 
         _beforeTokenTransfer(owner, address(0), tokenId);
         _beforeTokenTransfer(owner, address(0), tokenId);
 
 
@@ -385,7 +385,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable
      * Emits a {Transfer} event.
      * Emits a {Transfer} event.
      */
      */
     function _transfer(address from, address to, uint256 tokenId) internal virtual {
     function _transfer(address from, address to, uint256 tokenId) internal virtual {
-        require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
+        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); // internal owner
         require(to != address(0), "ERC721: transfer to the zero address");
         require(to != address(0), "ERC721: transfer to the zero address");
 
 
         _beforeTokenTransfer(from, to, tokenId);
         _beforeTokenTransfer(from, to, tokenId);
@@ -451,7 +451,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable
 
 
     function _approve(address to, uint256 tokenId) private {
     function _approve(address to, uint256 tokenId) private {
         _tokenApprovals[tokenId] = to;
         _tokenApprovals[tokenId] = to;
-        emit Approval(ownerOf(tokenId), to, tokenId);
+        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner
     }
     }
 
 
     /**
     /**

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

@@ -89,14 +89,14 @@ contract ERC777 is Context, IERC777, IERC20 {
     /**
     /**
      * @dev See {IERC777-name}.
      * @dev See {IERC777-name}.
      */
      */
-    function name() public view override returns (string memory) {
+    function name() public view virtual override returns (string memory) {
         return _name;
         return _name;
     }
     }
 
 
     /**
     /**
      * @dev See {IERC777-symbol}.
      * @dev See {IERC777-symbol}.
      */
      */
-    function symbol() public view override returns (string memory) {
+    function symbol() public view virtual override returns (string memory) {
         return _symbol;
         return _symbol;
     }
     }
 
 
@@ -106,7 +106,7 @@ contract ERC777 is Context, IERC777, IERC20 {
      * Always returns 18, as per the
      * Always returns 18, as per the
      * [ERC777 EIP](https://eips.ethereum.org/EIPS/eip-777#backward-compatibility).
      * [ERC777 EIP](https://eips.ethereum.org/EIPS/eip-777#backward-compatibility).
      */
      */
-    function decimals() public pure returns (uint8) {
+    function decimals() public pure virtual returns (uint8) {
         return 18;
         return 18;
     }
     }
 
 
@@ -115,21 +115,21 @@ contract ERC777 is Context, IERC777, IERC20 {
      *
      *
      * This implementation always returns `1`.
      * This implementation always returns `1`.
      */
      */
-    function granularity() public view override returns (uint256) {
+    function granularity() public view virtual override returns (uint256) {
         return 1;
         return 1;
     }
     }
 
 
     /**
     /**
      * @dev See {IERC777-totalSupply}.
      * @dev See {IERC777-totalSupply}.
      */
      */
-    function totalSupply() public view override(IERC20, IERC777) returns (uint256) {
+    function totalSupply() public view virtual override(IERC20, IERC777) returns (uint256) {
         return _totalSupply;
         return _totalSupply;
     }
     }
 
 
     /**
     /**
      * @dev Returns the amount of tokens owned by an account (`tokenHolder`).
      * @dev Returns the amount of tokens owned by an account (`tokenHolder`).
      */
      */
-    function balanceOf(address tokenHolder) public view override(IERC20, IERC777) returns (uint256) {
+    function balanceOf(address tokenHolder) public view virtual override(IERC20, IERC777) returns (uint256) {
         return _balances[tokenHolder];
         return _balances[tokenHolder];
     }
     }
 
 
@@ -176,7 +176,7 @@ contract ERC777 is Context, IERC777, IERC20 {
     /**
     /**
      * @dev See {IERC777-isOperatorFor}.
      * @dev See {IERC777-isOperatorFor}.
      */
      */
-    function isOperatorFor(address operator, address tokenHolder) public view override returns (bool) {
+    function isOperatorFor(address operator, address tokenHolder) public view virtual override returns (bool) {
         return operator == tokenHolder ||
         return operator == tokenHolder ||
             (_defaultOperators[operator] && !_revokedDefaultOperators[tokenHolder][operator]) ||
             (_defaultOperators[operator] && !_revokedDefaultOperators[tokenHolder][operator]) ||
             _operators[tokenHolder][operator];
             _operators[tokenHolder][operator];
@@ -215,7 +215,7 @@ contract ERC777 is Context, IERC777, IERC20 {
     /**
     /**
      * @dev See {IERC777-defaultOperators}.
      * @dev See {IERC777-defaultOperators}.
      */
      */
-    function defaultOperators() public view override returns (address[] memory) {
+    function defaultOperators() public view virtual override returns (address[] memory) {
         return _defaultOperatorsArray;
         return _defaultOperatorsArray;
     }
     }
 
 
@@ -256,7 +256,7 @@ contract ERC777 is Context, IERC777, IERC20 {
      * not have allowance, and accounts with allowance may not be operators
      * not have allowance, and accounts with allowance may not be operators
      * themselves.
      * themselves.
      */
      */
-    function allowance(address holder, address spender) public view override returns (uint256) {
+    function allowance(address holder, address spender) public view virtual override returns (uint256) {
         return _allowances[holder][spender];
         return _allowances[holder][spender];
     }
     }
 
 

+ 3 - 3
contracts/utils/Pausable.sol

@@ -36,7 +36,7 @@ abstract contract Pausable is Context {
     /**
     /**
      * @dev Returns true if the contract is paused, and false otherwise.
      * @dev Returns true if the contract is paused, and false otherwise.
      */
      */
-    function paused() public view returns (bool) {
+    function paused() public view virtual returns (bool) {
         return _paused;
         return _paused;
     }
     }
 
 
@@ -48,7 +48,7 @@ abstract contract Pausable is Context {
      * - The contract must not be paused.
      * - The contract must not be paused.
      */
      */
     modifier whenNotPaused() {
     modifier whenNotPaused() {
-        require(!_paused, "Pausable: paused");
+        require(!paused(), "Pausable: paused");
         _;
         _;
     }
     }
 
 
@@ -60,7 +60,7 @@ abstract contract Pausable is Context {
      * - The contract must be paused.
      * - The contract must be paused.
      */
      */
     modifier whenPaused() {
     modifier whenPaused() {
-        require(_paused, "Pausable: not paused");
+        require(paused(), "Pausable: not paused");
         _;
         _;
     }
     }
 
 

+ 1 - 1
test/token/ERC1155/ERC1155.behavior.js

@@ -106,7 +106,7 @@ function shouldBehaveLikeERC1155 ([minter, firstTokenHolder, secondTokenHolder,
             [firstTokenHolder, secondTokenHolder, ZERO_ADDRESS],
             [firstTokenHolder, secondTokenHolder, ZERO_ADDRESS],
             [firstTokenId, secondTokenId, unknownTokenId],
             [firstTokenId, secondTokenId, unknownTokenId],
           ),
           ),
-          'ERC1155: batch balance query for the zero address',
+          'ERC1155: balance query for the zero address',
         );
         );
       });
       });