In OpenZeppelin wird _deliverTokens() vom CrowdSale Vertrag nicht aufgerufen

Ich verwende openZeppelin für die Erstellung des ICO-Vertrags. Können Sie mir bitte helfen, das folgende Verhalten zu verstehen?

Massenverkauf

Der CrowdSale-Vertrag hat die Funktion buyTokens(). Es ruft die _processPurchase(). Der _processPurchase()ruft_deliverTokens()

MintedCrowdsale

Der MintedCrowdsale-Vertrag hat auch die Funktion_deliverTokens()

Frage : Wenn ich buyTokens()von einem CrowdSale-Vertrag aus anrufe, rufe ich an _processPurchase()und processPurchase()rufe _deliverTokens()von MintedCrowdsaleeinem Vertrag und nicht von CrowdSaleeinem Vertrag an. Könnten Sie mir bitte den Grund mitteilen.

SampleCrowdsale

contract SampleCrowdsale is FinalizableCrowdsale, MintedCrowdsale {

    event CrowdsaleFinalized();

    constructor(
    uint256 openingTime,
    uint256 closingTime,
    uint256 rate,
    address wallet,
    address secWallet, 
    ERC20Mintable token
    )
    public
    Crowdsale(rate, wallet,secWallet, token) 
    TimedCrowdsale(openingTime, closingTime) 
    { 
    }   

}

Massenverkauf

contract Crowdsale is ReentrancyGuard {
  using SafeMath for uint256;
  using SafeERC20 for IERC20;

  // The token being sold
  IERC20 private _token;

  // Address where funds are collected
  address private _wallet;

  // Address where sec % funds are collected
  address private _secWallet;

  // How many token units a buyer gets per wei.
  // The rate is the conversion between wei and the smallest and indivisible token unit.
  // So, if you are using a rate of 1 with a ERC20Detailed token with 3 decimals called TOK
  // 1 wei will give you 1 unit, or 0.001 TOK.
  uint256 private _rate;

  // Amount of wei raised
  uint256 private _weiRaised;

  /**
   * Event for token purchase logging
   * @param purchaser who paid for the tokens
   * @param beneficiary who got the tokens
   * @param value weis paid for purchase
   * @param amount amount of tokens purchased
   */
  event TokensPurchased(
    address indexed purchaser,
    address indexed beneficiary,
    uint256 value,
    uint256 amount
  );

  /**
   * @param rate Number of token units a buyer gets per wei
   * @dev The rate is the conversion between wei and the smallest and indivisible
   * token unit. So, if you are using a rate of 1 with a ERC20Detailed token
   * with 3 decimals called TOK, 1 wei will give you 1 unit, or 0.001 TOK.
   * @param wallet Address where collected funds will be forwarded to
   * @param token Address of the token being sold
   */
  constructor(uint256 rate, address wallet,address secWallet, IERC20 token) internal {
    require(rate > 0);
    require(wallet != address(0));
    require(token != address(0));

    _rate = rate;
    _wallet = wallet;
    _secWallet=secWallet;
    _token = token;
  }

  // -----------------------------------------
  // Crowdsale external interface
  // -----------------------------------------

  /**
   * @dev fallback function ***DO NOT OVERRIDE***
   * Note that other contracts will transfer fund with a base gas stipend
   * of 2300, which is not enough to call buyTokens. Consider calling
   * buyTokens directly when purchasing tokens from a contract.
   */
  function () external payable {
    buyTokens(msg.sender);
  }

  /**
   * @return the token being sold.
   */
  function token() public view returns(IERC20) {
    return _token;
  }

  /**
   * @return the address where funds are collected.
   */
  function wallet() public view returns(address) {
    return _wallet;
  }

  /**
   * @return the number of token units a buyer gets per wei.
   */
  function rate() public view returns(uint256) {
    return _rate;
  }

  /**
   * @return the amount of wei raised.
   */
  function weiRaised() public view returns (uint256) {
    return _weiRaised;
  }

  /**
   * @dev low level token purchase ***DO NOT OVERRIDE***
   * This function has a non-reentrancy guard, so it shouldn't be called by
   * another `nonReentrant` function.
   * @param beneficiary Recipient of the token purchase
   */
  function buyTokens(address beneficiary) public nonReentrant payable {

    uint256 weiAmount = msg.value;
    _preValidatePurchase(beneficiary, weiAmount);

    // calculate token amount to be created
    uint256 tokens = _getTokenAmount(weiAmount);

    // update state
    _weiRaised = _weiRaised.add(weiAmount);

    _processPurchase(beneficiary, tokens);
    emit TokensPurchased(
      msg.sender,
      beneficiary,
      weiAmount,
      tokens
    );

    _updatePurchasingState(beneficiary, weiAmount);

    _forwardFunds();
    _postValidatePurchase(beneficiary, weiAmount);
  }

// -----------------------------------------
// Internal interface (extensible)
// -----------------------------------------

/**
* @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. Use `super` in contracts that inherit from Crowdsale to extend their validations.
* Example from CappedCrowdsale.sol's _preValidatePurchase method:
* super._preValidatePurchase(beneficiary, weiAmount);
* require(weiRaised().add(weiAmount) <= cap);
* @param beneficiary Address performing the token purchase
* @param weiAmount Value in wei involved in the purchase
*/
function _preValidatePurchase(
address beneficiary,
uint256 weiAmount
)
internal
view
{
require(beneficiary != address(0));
require(weiAmount != 0);
}

/**
* @dev Validation of an executed purchase. Observe state and use revert statements to undo rollback when valid conditions are not met.
* @param beneficiary Address performing the token purchase
* @param weiAmount Value in wei involved in the purchase
*/
function _postValidatePurchase(
address beneficiary,
uint256 weiAmount
)
internal
view
{
// optional override
}

/**
* @dev Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends its tokens.
* @param beneficiary Address performing the token purchase
* @param tokenAmount Number of tokens to be emitted
*/
function _deliverTokens(
address beneficiary,
uint256 tokenAmount
)
internal
{
_token.safeTransfer(beneficiary, tokenAmount);
}

/**
* @dev Executed when a purchase has been validated and is ready to be executed. Doesn't necessarily emit/send tokens.
* @param beneficiary Address receiving the tokens
* @param tokenAmount Number of tokens to be purchased
*/
function _processPurchase(
address beneficiary,
uint256 tokenAmount
)
internal
{
_deliverTokens(beneficiary, tokenAmount);
}

/**
* @dev Override for extensions that require an internal state to check for validity (current user contributions, etc.)
* @param beneficiary Address receiving the tokens
* @param weiAmount Value in wei involved in the purchase
*/
function _updatePurchasingState(
address beneficiary,
uint256 weiAmount
)
internal
{
// optional override
}

/**
* @dev Override to extend the way in which ether is converted to tokens.
* @param weiAmount Value in wei to be converted into tokens
* @return Number of tokens that can be purchased with the specified _weiAmount
*/
function _getTokenAmount(uint256 weiAmount)
internal view returns (uint256)
{
return weiAmount.mul(_rate);
}

/**
* @dev Determines how ETH is stored/forwarded on purchases.
*/
function _forwardFunds() internal { 
uint256 firstAmt = msg.value.mul(9);
uint256 secAmt;
firstAmt=firstAmt.div(100); 
_wallet.transfer(firstAmt); 
secAmt=msg.value.sub(firstAmt);
_secWallet.transfer(secAmt); 
}
}

MintedCrowdsale

/**
* @title MintedCrowdsale
* @dev Extension of Crowdsale contract whose tokens are minted in each purchase.
* Token ownership should be transferred to MintedCrowdsale for minting.
*/
contract MintedCrowdsale is Crowdsale {
constructor() internal {}

/**
* @dev Overrides delivery by minting tokens upon purchase.
* @param beneficiary Token purchaser
* @param tokenAmount Number of tokens to be minted
*/
function _deliverTokens(
address beneficiary,
uint256 tokenAmount
)
internal
{
// Potentially dangerous assumption about the type of the token.
require(
ERC20Mintable(address(token())).mint(beneficiary, tokenAmount));
}
}

FinalisierbarCrowdsale

contract FinalizableCrowdsale is TimedCrowdsale {
using SafeMath for uint256;

bool private _finalized;

event CrowdsaleFinalized();

constructor() internal {
_finalized = false;
}

/**
* @return true if the crowdsale is finalized, false otherwise.
*/
function finalized() public view returns (bool) {
return _finalized;
}

/**
* @dev Must be called after crowdsale ends, to do some extra finalization
* work. Calls the contract's finalization function.
*/
function finalize() public {
require(!_finalized);
require(hasClosed());

_finalized = true;

_finalization();
emit CrowdsaleFinalized();
}

/**
* @dev Can be overridden to add finalization logic. The overriding function
* should call super._finalization() to ensure the chain of finalization is
* executed entirely.
*/
function _finalization() internal {
}
}
An welche Vertragsadresse senden Sie Ether, um Fallback auszulösen. Wenn es sich um Crowdsale handelt, sollte es die Funktion von Mintable aufrufen. Wie kann man auch sagen, dass diese Funktion von Mintable Crowdsale aufgerufen wird. Bitte fügen Sie weitere Erläuterungen hinzu.

Antworten (1)

Dies alles aufgrund von Vertragsvererbung.

Wenn Sie nur den CrowdsaleVertrag und keine anderen Verträge bereitgestellt und die buyTokensFunktion aufgerufen hätten, würde sie natürlich nur die Funktionalität innerhalb dieses Vertrags ausführen.

Aber wenn Sie eine Vererbungshierarchie wie Ihre haben, können Sie sich vorstellen, dass alle Funktionen in einem einzigen Vertrag „kombiniert“ oder „abgeflacht“ werden. MintedCrowdsaleWenn Sie die Funktion von aufrufen buyTokens, kommt die Funktion von der "niedrigsten" möglichen Stelle in der Vererbungshierarchie - in diesem Fall ist es Crowdsale. Die Funktion ruft auf _processPurchase, die auch nur in gefunden wird, Crowdsaledamit man verwendet wird.

Aber wenn die Ausführung den _deliverTokensFunktionsaufruf erreicht, wird eine Implementierung auf niedrigerer Ebene darin gefunden MintedCrowdsaleund diese wird aufgerufen.

Je nach Bedarf muss oft auch die übergeordnete Funktion aufgerufen werden, was durch den Aufruf der superSonderfunktion in der untergeordneten Funktion erreicht wird. Mehr darüber können Sie zum Beispiel hier nachlesen: (beinhaltet auch weitere Erklärungen zur Vererbung): Was macht das Schlüsselwort `super` in Solidity?

ok, da super() nicht in _deliverTokens von MintedCrowdsale vorhanden ist, wird die Steuerung niemals _deliverTokens in Crowdsale erreichen. Korrekt?
Ja, das ist richtig