Skip to main content
2 of 2
added 2937 characters in body

"Super" keyword with same function in multiple inheritance contracts?

I'm having some doubts when extending the same contract function in different classes, with super keyword.

Would function _preValidate (in Contract B) check both conditions of contracts A1 & A2, before executing the initial behavior of A parent's _preValidate function?

Imagine I have a Contract A with validate function:

contract A {
function _preValidate(address beneficiary) internal view {
        require(beneficiary != address(0), "Beneficiary is the zero address");
        this; 
 }
}

contract A1 is A {

uint256 = closeTime;
 modifier onlyWhileOpen {
        require(block.timestamp < closeTime, "Operation is closed");
        _;
    }

function _preValidate(address beneficiary) internal onlyWhileOpen view {
        super._preValidate(beneficiary);
 }
}

contract A2 is A {

uint256 = openTime;
 modifier onlyAfterOpen {
        require(block.timestamp > openTime, "Operation is not open");
        _;
    }

function _preValidate(address beneficiary) internal onlyAfterOpen view {
        super._preValidate(beneficiary);
 }
}


contract B is A, A1, A2 {
    
    //[...] 
    }
    

Real world example:

A real example can be found with OpenZeppelin's Crowdsale contracts in 2.5.1 version.

Crowdsale

contract Crowdsale is Context, ReentrancyGuard {x

 function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
        require(beneficiary != address(0), "Crowdsale: beneficiary is the zero address");
        require(weiAmount != 0, "Crowdsale: weiAmount is 0");
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
    }


}

TimedCrowdsale

contract TimedCrowdsale is Crowdsale {     

uint256 private _openingTime;
    uint256 private _closingTime;

modifier onlyWhileOpen {
        require(isOpen(), "TimedCrowdsale: not open");
        _;
    }

function isOpen() public view returns (bool) {
        // solhint-disable-next-line not-rely-on-time
        return block.timestamp >= _openingTime && block.timestamp <= _closingTime;
    }

 function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal onlyWhileOpen view {
        super._preValidatePurchase(beneficiary, weiAmount);
    }

}

CappedCrowdsale

contract CappedCrowdsale is Crowdsale {
uint256 private _cap;
    function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
        super._preValidatePurchase(beneficiary, weiAmount);
        require(weiRaised().add(weiAmount) <= _cap, "CappedCrowdsale: cap exceeded");
    }
}

MyCrowdsale: (Timed and capped) contract MyCrowdsale is Crowdsale, CappedCrowdsale, TimedCrowdsale {

constructor(
    uint256 rate,            // rate, in TKNbits
    address payable wallet,  // wallet to send Ether
    IERC20 token,            // the token
    uint256 cap,             // total cap, in wei
    uint256 openingTime,     // opening time in unix epoch seconds
    uint256 closingTime      // closing time in unix epoch seconds
)
    CappedCrowdsale(cap)
    TimedCrowdsale(openingTime, closingTime)
    Crowdsale(rate, wallet, token)
    public
{
    // nice, we just created a crowdsale that's only open
    // for a certain amount of time
    // and stops accepting contributions once it reaches `cap`
}

}