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.
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
}
}
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);
}
}
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`
}
}