2

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`
}

}

1 Answer 1

0

Im pretty sure super refers to the contract right before the caller contract in the inheritance tree. Not sure what would happen in the case you're describing. Id suggest testing to find out what happens. If it doesnt check for both maybe make TimedCrowdsale inherits CappedCrowdsale?

1
  • Sure, it would be my default solution but I think that it doe not keep the code pretty. Sep 29, 2021 at 9:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.