Assignment - Openzeppelin Reading

Read the attached PDF about the override and virtual keywords in solidity. Then answer the following questions in the forum.

  1. When should you put the virtual keyword on a function?

  2. When should you put the keyword override on a function?

  3. Why would a function have both virtual and override keywords on it?

4 Likes

When should you put the virtual keyword on a function?
When you what to allow another contract that is inheriting from the current contract to override its functionality

When should you put the keyword override on a function?
When you want to change the functionality of an inherited contract or implement its specification

Why would a function have both virtual and override keywords on it?
If the function is defined in an interface it must be marked with override, but if also it allows itself to be overridden it must also marked as virtual

1 Like

Question about the datatype used in the ReentrancyGuard utility.

How come a 2 constant uint256 values and a third uint256 status variable is used instead of just haveing one bool?

I am thinking something like this:

abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.

    bool private _status;

    constructor () internal {
        _status = false;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(!_status, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = true;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = false;
    }
}```
  1. When should you put the virtual keyword on a function?

When you wish to allow inherited to contracts to override that function.

  1. When should you put the keyword override on a function?

Override should be included in function where they are intended to replace the same function from a parent contract.

  1. Why would a function have both virtual and override keywords on it?

A function may include both virtual and override keywords if that function already replaces a parent function but also still allows itself to be replaced by an inherited contract function.

1 Like

Hey @Capplequoppe

The answer to your question is in the comments openezeppelin wrote :slight_smile:

  // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

Cheers,
Dani

:man_facepalming:
Sorry, should have read properly before posting…

1 Like

1. When should you put the virtual keyword on a function?

Whenever a function can be overridden by an inheriting contract. Good to know: all functions in Interface contracts are meant to be virtual !

2. When should you put the keyword override on a function?

Whenever a function shall override an already existing function in the base contract.

  1. Why would a function have both virtual and override keywords on it?

Whenever a function offers both, to override and be overridden.

3 Likes

1. When should you put the virtual keyword on a function?

When you want that function to be overridden by an inherited contract.

2. When should you put the keyword override on a function?

When you want that function to override a function in a parent contract.

3. Why would a function have both virtual and override keywords on it?

A function might have both the virtual and override keywords if it is necessary that it both overrides a function in a parent contract and can itself be overridden by another function if need be.

4 Likes

I am studying the utils contracts and the following question pops up:

Is there a good reason to not use SafeMath in the increment function in Counters.sol or is this a coding mishap? CountersIncrementSafeMath

1 Like

I think the reason here is that the counter usually starts with the initial value 0.
That means that we are VERY far from reaching an overflow and VERY close to reaching an underflow.
So safemath is used when decrementing the counter since the probability of reaching a theoretical -1 is pretty high.

On the other hand, since value is only increased by 1 at a time, you would have to call the increment function an insane amount of times before reaching an overflow, and by that point, the counter does no longer fulfill its purpose anyways since if fails to produce new unique numbers.

It is more probable that a possible attacker will run out of gas before reaching an overflow I think…

1 Like

If you are using solidity version 0.8, there is no need to use SafeMath any more. :nerd_face:

Carlos Z

3 Likes

Yes, I already found out :slight_smile: I was just looking through the openzeppelin contract Counters.sol and discovered an irregularity in the code, as they use SafeMath for the sub() but do not use it to increment the counter._value.

1 Like
  1. Virtual means the function can be overridden when the contract is inherited as a parent contract.
  2. Override keyword will be used in the child contract to indicate which functions, inherited from the parent contract, will be overridden
  3. A function with both virtual and override belongs in a contract that can be a parent contract, inherited from, and possibly overridden by a child contract’s function - as well as override functions that it inherits from other parent contracts.
3 Likes
  1. When should you put the virtual keyword on a function?
    If you would like to indicate that this function could be overridden.

  2. When should you put the keyword override on a function?
    To indicate this function is overriding a parent function.

  3. Why would a function have both virtual and override keywords on it?
    To indicate this function is overriding a function higher up the hierarchy but can also be overridden.

2 Likes
  1. When you want to override the function by an inherited contract.

  2. When you want to override the function in a parent contract.

  3. To override and to be overridden by another function.

2 Likes
  1. The virtual keyword should be used to mark that a function can be overridden in an inherited contract

  2. The override should be used when a function overrides a virtual function in the base contract

  3. A function can have both virtual and override keywords when it overrides the same function in the base contract, but can also be overridden in an inherited contract

1 Like

1. When should you put the virtual keyword on a function?
To allow an inherited contract to override a function.

2. When should you put the keyword override on a function?
To allow a function being override in a parent contract.

3. Why would a function have both virtual and override keywords on it?
To allow (if necessary) a function being override in a parent contract and also able to being override from an inherit contract.

Carlos Z

1 Like

The ReentrancyGuard reminds me a lot of the old Java days when one would use the synchronized keyword to prevent more than one clients/threads from entering a method at any one time. It works but was very limiting in a highly multithreaded/concurrent environment. Aren’t there similar concerns for a smart contract with functions that can be hit by thousands of clients at any one time ? doesn’t the ReentrancyGuard end up throttling requests quite a lot potentially ?

@filip

Hi @Emmett

The ReentrancyGuard only makes sure that a function is not called multiple times by the same user before the function actually completes.

Regards,
Dani

  1. When should you put the virtual keyword on a function?
    When we want to allow child contracts to be able override the function.

  2. When should you put the keyword override on a function?
    When we are overriding a virtual function defined in a parent contract.

  3. Why would a function have both virtual and override keywords on it?
    It needs override if it is overriding a virtual function from a parent contract and it also needs virtual if we want to allow child contracts to override it.

1 Like