Solidity

使用虛擬和覆蓋的繼承問題(可能):找不到成員

  • October 27, 2022

我正在嘗試完成一門涵蓋虛擬和覆蓋的課程,並且似乎由於繼承而出現錯誤。下面是程式碼:

//SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.5.0 <0.9.0;

// -------------------------------------------------------------
// EIP-20: ERC-20 Token Standard
// https://eips.ethereum.org/EIPS/eip-20
// -------------------------------------------------------

interface ERC20Interface {

   // these three are only mandatory functions
   function totalSupply() external view returns (uint);
   function balanceOf(address tokenOwner) external view returns (uint balance);
   function transfer(address to, uint tokens) external returns (bool success);

   function allowance(address tokenOwner, address spender) external view returns (uint remaining);
   function approve(address spender, uint tokens) external returns (bool success);
   function transferFrom(address from, address to, uint tokens) external returns (bool success);

   event Transfer(address indexed from, address indexed to, uint tokens);
   event Approval(address indexed tokenOwner, address indexed spender, uint tokens);

}

// our contract will inherit from the standard token interface
contract Pennies is ERC20Interface {

   string public name = "Penny Pennies";
   string public symbol = "PENNY";
   uint public decimals = 0; // 18 is the most

   // need to override the inherited mandatory function
   uint public override totalSupply;

   // not part of standard
   address public founder;

   // this is how the contract stores the balance for each address
   mapping (address => uint) public balances;

   // this is a nested mapping (points to another mapping
   // shows how much one user allows the other user to spend
   // allower address is entered that points to mapping of addresses
   // and how much they are allowed to spend
   mapping(address => mapping(address => uint)) allowed;
   
   constructor(){

       // set initial supply
       totalSupply = 1000000;
       // set founder as person who deploys contract
       founder = msg.sender;
       // set the balance of the founder's address equal to the total supply
       balances[founder] = totalSupply;



   }

   // we need to override the balance function
   function balanceOf(address tokenOwner) public view override returns (uint balance){

       return balances[tokenOwner];

   }

   // we need to override the transfer function
   function transfer(address to, uint tokens) public virtual override returns (bool success){

       // the balance of the sender must be at least as much as they want to send
       require(balances[msg.sender] >= tokens);

       // the balance for the recipient's address increases
       balances[to] += tokens;
       // the balances for the sender's address decreases
       balances[msg.sender] -= tokens;
       // emit our event of the actual transfer 
       emit Transfer(msg.sender, to, tokens);

       // returns status
       return true;

   }

   // this overrides our allowed function and returns how much eash user is allowed to
   // spend by the token owner
   function allowance(address tokenOwner, address spender) public view override returns (uint){
       return allowed[tokenOwner][spender];
   }

   function approve(address spender, uint tokens) public override returns (bool success){

       // the sender has to have at least the amount of tokens they want to approve
       require(balances[msg.sender] >= tokens);
       // can't be an empty transaction
       require(tokens > 0);

       // updates allowed mapping so that the spender is allowed to spend a
       // certain amount of tokens
       allowed[msg.sender][spender] = tokens;

       // emit approval transaction
       emit Approval(msg.sender, spender, tokens);

       // return state
       return true;

   }

   function transferFrom(address from, address to, uint tokens) public virtual override returns (bool){

       // require that the user be allowed to send the amount of tokens desired
       require(allowed[from][msg.sender] >= tokens);

       // require they have the amount of tokens they want to transfer
       require(balances[from] >= tokens);

       // subtract token balance from user's balance
       balances[from] -= tokens;

       // subtract sent amount from total allowed amount
       allowed[from][msg.sender] -= tokens;

       // add tokens to balance of recipient
       balances[to] += tokens;

       // emit tranfer
       emit Transfer(from, to, tokens);

       // return status
       return true;

   }

}

// ICO Contract
contract PennyICO is Pennies {

   // declare admin
   address public admin;

   // declare deposit vault
   address payable public deposit;

   // set token price
   uint tokenPrice = 0.000001 ether;

   // hard cap of total ether that can be invested
   uint public hardCap = 300 ether;

   // value in wei of raised amount
   uint public raisedAmount;

   // start time
   uint public saleStart = block.timestamp + 10;

   // set ICO close time (1 week)
   uint public saleEnd = block.timestamp + 3600 * 24 * 7;

   // tokens will be transferred to investor wallets 
   // one week after the ICO ends
   uint public tokenTradeStart = saleEnd + 604800;

   // set max and min investment per address
   uint public maxInvestment = 5 ether;
   uint public minInvestment = 0.00001 ether;

   // create an enum to hold the state of our ICO
   enum State {beforeStart, running, afterEnd, halted}

   // declare a state variable of type state to hold the ICO state
   State public ICOstate;

   // declare constructor of contract
   constructor(address payable _deposit){
       deposit = _deposit;
       admin = msg.sender;
       ICOstate = State.beforeStart;
   }

   // admin should be able to halt ICO in emrgency

   // first make admin modifier
   modifier onlyAdmin(){
       require(msg.sender == admin);
       _;
   }

   // admin can halt ICO
   function halt() public onlyAdmin{
       ICOstate = State.halted;
   }

   // admin can resume ICO
   function resume() public onlyAdmin{
       ICOstate = State.running;
   }

   // function to allow the admin to change the deposit contract
   function changeDepositAddress(address payable newDeposit) public onlyAdmin{

       deposit = newDeposit;

   }

   // a getter function to return the state of the ICO
   function getCurrentState() public view returns(State){
       if (ICOstate == State.halted){
           return State.halted;
           } else if (block.timestamp < saleStart){
               return State.beforeStart;
           } else if (block.timestamp >= saleStart && block.timestamp <= saleEnd){
               return State.running;
           } else {
               return State.afterEnd;
           }
   
   }

   // to make the below function interact with front end we create an event
   event Invest(address investor, uint value, uint tokens);

   // main function for ICO
   function invest() payable public returns(bool){

       // first we need to establish that ICO is currently running
       ICOstate = getCurrentState();

       // test if ICO is running
       require(ICOstate == State.running);

       // must invest in the limits for per address investment range
       require(msg.value >= minInvestment && msg.value <= maxInvestment);

       // increment raised amount
       raisedAmount += msg.value;

       // make sure ICO hardcape won't already be breached
       require(raisedAmount <= hardCap);

       // calculate number of tokens the user has bought
       uint tokens = msg.value / tokenPrice;

       // exchange tokens between founder and investor
       balances[msg.sender] += tokens;
       balances[founder] -= tokens;

       // send investor's wei to deposit vault
       deposit.transfer(msg.value);

       // emit event for frontend
       emit Invest(msg.sender, msg.value, tokens);

       // return transaction state
       return true;

   }

   // create template receivable function that calls the invest function
   // above if the user sends money directly to the address
   receive() payable external{
       invest();
   }



    // we need to override the transfer function again to let the user be able
    // to trade it a week after receiving it
   function transfer(address to, uint tokens) public override returns (bool success){

       // require the trading holding persiod has passed
       require(block.timestamp > tokenTradeStart);

       // transfer the tokens to the recipient
       Pennies.tranfer(to, tokens);

       // return function status
       return true;

   }

   function transferFrom(address from, address to, uint tokens) public override returns (bool){

       require(block.timestamp > tokenTradeStart);
       Pennies.transferFrom(from, tokens);
       return true;

   }

}

Pennies.transfer當我嘗試或時似乎找不到“便士” Pennies.transferFrom

我注意到第 277 行有一個錯字,應該是:(Pennies.transfer(to, tokens);缺少 s)。

同樣在第 287 行,Pennies.transferFrom缺少to參數,應替換為:Pennies.transferFrom(from, to, tokens);

除此之外,程式碼工作正常。我建議您使用 IDE 輕鬆調試此類錯誤。無需設置即可使用的最簡單的方法是https://remix.ethereum.org

引用自:https://ethereum.stackexchange.com/questions/138294