ERC20-Token kann nicht von einem anderen Smart Contract an die Person übertragen werden, die Ether sendet

Ich habe zwei Smart Contracts erstellt und beide werden im Ropsten Test Network bereitgestellt. Ich verwende MetaMask für Transaktionen.

  1. ERC20-Token mit der folgenden Implementierung (bitte beachten Sie, dass ich meine in MetaMask verfügbaren Token sehen kann):

    contract AppleToken is ERC20Interface, Owned, SafeMath {
    string public symbol;
    string public  name;
    uint8 public decimals;
    uint public _totalSupply;
    
    mapping(address => uint) balances;
    mapping(address => mapping(address => uint)) allowed;
    
    
    // ------------------------------------------------------------------------
    // Constructor
    // ------------------------------------------------------------------------
    function AppleToken()  public {
        symbol = "AppleToken";
        name = "Apple Token";
        decimals = 18;
        _totalSupply = 100000000000000000000000000;
        balances[0x2cBccb25319231B921fCf02Ec3bc213FcdFAeA15] = _totalSupply;
        Transfer(address(0), 0x2cBccb25319231B921fCf02Ec3bc213FcdFAeA15, _totalSupply);
    }
    
    
    // ------------------------------------------------------------------------
    // Total supply
    // ------------------------------------------------------------------------
    function totalSupply() public constant returns (uint) {
        return _totalSupply  - balances[address(0)];
    }
    
    
    // ------------------------------------------------------------------------
    // Get the token balance for account tokenOwner
    // ------------------------------------------------------------------------
    function balanceOf(address tokenOwner) public constant returns (uint balance) {
        return balances[tokenOwner];
    }
    
    
    // ------------------------------------------------------------------------
    // Transfer the balance from token owner's account to to account
    // - Owner's account must have sufficient balance to transfer
    // - 0 value transfers are allowed
    // ------------------------------------------------------------------------
    function transfer(address to, uint tokens) public returns (bool success) {
        balances[msg.sender] = safeSub(balances[msg.sender], tokens);
        balances[to] = safeAdd(balances[to], tokens);
        Transfer(msg.sender, to, tokens);
        return true;
    }
    
    
    // ------------------------------------------------------------------------
    // Token owner can approve for spender to transferFrom(...) tokens
    // from the token owner's account
    //
    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
    // recommends that there are no checks for the approval double-spend attack
    // as this should be implemented in user interfaces 
    // ------------------------------------------------------------------------
    function approve(address spender, uint tokens) public returns (bool success) {
        allowed[msg.sender][spender] = tokens;
        Approval(msg.sender, spender, tokens);
        return true;
    }
    
    
    // ------------------------------------------------------------------------
    // Transfer tokens from the from account to the to account
    // 
    // The calling account must already have sufficient tokens approve(...)-d
    // for spending from the from account and
    // - From account must have sufficient balance to transfer
    // - Spender must have sufficient allowance to transfer
    // - 0 value transfers are allowed
    // ------------------------------------------------------------------------
    function transferFrom(address from, address to, uint tokens) public returns (bool success) {
        balances[from] = safeSub(balances[from], tokens);
        allowed[from][msg.sender] = safeSub(allowed[from][msg.sender], tokens);
        balances[to] = safeAdd(balances[to], tokens);
        Transfer(from, to, tokens);
        return true;
    }
    
    
    // ------------------------------------------------------------------------
    // Returns the amount of tokens approved by the owner that can be
    // transferred to the spender's account
    // ------------------------------------------------------------------------
    function allowance(address tokenOwner, address spender) public constant returns (uint remaining) {
        return allowed[tokenOwner][spender];
    }
    
    
    // ------------------------------------------------------------------------
    // Token owner can approve for spender to transferFrom(...) tokens
    // from the token owner's account. The spender contract function
    // receiveApproval(...) is then executed
    // ------------------------------------------------------------------------
    function approveAndCall(address spender, uint tokens, bytes data) public returns (bool success) {
        allowed[msg.sender][spender] = tokens;
        Approval(msg.sender, spender, tokens);
        ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);
        return true;
    }
    
    
    // ------------------------------------------------------------------------
    // Don't accept ETH
    // ------------------------------------------------------------------------
    function () public payable {
        revert();
    }
    
    
    // ------------------------------------------------------------------------
    // Owner can transfer out any accidentally sent ERC20 tokens
    // ------------------------------------------------------------------------
    function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) {
        return ERC20Interface(tokenAddress).transfer(owner, tokens);
    }
    

    }

  2. Ein weiterer Smart Contract, der Ether empfängt und mit dem oben angegebenen Smart Contract interagieren sollte, um meine Token an den Absender von Ether zu übertragen.

Ich versuche zu implementieren, was in Punkt Nummer 2 erwähnt wird, aber wenn ich versuche, auf die „Transfer“-Funktion der ERC20-Token-Instanz zuzugreifen, erhalte ich einen Fehler, dass die Gasschätzung überschritten wird (ich habe versucht, das Gaslimit zu erhöhen, tut es nicht arbeiten). Wenn ich versuche, die Transaktion über MetaMask zu erzwingen, werden mir die Ausführungskosten mit 60001 Eth angezeigt, selbst wenn ich versuche, nur 1 Ether zu senden.

Hier ist die Implementierung meiner Funktion

IM JETZT BIN ICH DER SENDER VON ETHER UND ICH BIN DER EMPFÄNGER DER ERC20-TOKEN

function sendTokens () public payable returns (uint)
    {
       //tokenAddress is the address of the ERC20 token deployed on Ropsten
        AppleToken appleToken;
        appleToken = AppleToken(tokenAddress);
        appleToken.transfer(msg.sender, 10);
        return appleToken.balanceOf(msg.sender);
    }

Ich sende im Moment zu Testzwecken fest codierte 10 Token. Beachten Sie, dass ich AppleToken mit import „browser/AppleToken.sol“ eingeschlossen habe;

Wenn ich NUR die Funktion appleToken.balanceOf ausführe, gibt sie nichts zurück. Zusammenfassend lässt sich sagen, dass die Funktion "Transfer" aufgrund der übermäßig berechneten Ausführungskosten problematisch ist und für "BalanceOf" nichts zurückgibt, nicht einmal eine 0.

Initiiere ich die Instanz von AppleToken korrekt? Oder mache ich noch etwas falsch?

Jede Hilfe wäre willkommen.

Danke schön.

AKTUALISIEREN

Öffentliche Kontoadresse auf Ropsten: 0x2cBccb25319231B921fCf02Ec3bc213FcdFAeA15

ERC20-Token-Adresse auf Ropsten: 0x580156edb25D3c3deD584F1075CcCC5dA4861883

Es folgt der gesamte Code des EquityInvestments-Vertrags:

Ich habe unnötige Dinge im Code entfernt, da ich diese Funktionen nicht aufrufe oder einige Variablen verwende, die für das Problem definiert sind, mit dem ich konfrontiert bin

pragma solidity ^0.4.16;
import "browser/AppleToken.sol";

contract EquityInvestments 
{
    AppleToken appleToken;
    Group [] _Groups;
    uint PriceEth = 1;
    address tokenAddress = 0x580156edb25D3c3deD584F1075CcCC5dA4861883;
    mapping (address => mapping(uint=>UserInvestment)) private _UserInvestments;

    function EquityInvestments () public
    {
        _Groups.push(Group({
            GroupID: 1,
            GroupName: "Google",
            TotalInvestment: 0,
            GroupPriceDollars: 200,
            GroupPriceEth: 1
        }));
         _Groups.push(Group({
            GroupID: 2,
            GroupName: "Tesla",
             TotalInvestment: 0,
             GroupPriceDollars: 200,
             GroupPriceEth: 1
        }));
         _Groups.push(Group({
            GroupID: 3,
            GroupName: "Apple",
             TotalInvestment: 0,
             GroupPriceDollars: 200,
             GroupPriceEth: 1
        }));
    }

    struct Group
    {
     uint GroupID;
     string GroupName;
     uint TotalInvestment;
     uint GroupPriceDollars;
     uint GroupPriceEth;
    }

    function sendTokens () public payable returns (uint)
    {
        appleToken = AppleToken(tokenAddress);
        // return appleToken.balanceOf(msg.sender);
        // appleToken.approve(this, 10);
        require(appleToken.transfer(msg.sender, 10));
        return appleToken.balanceOf(msg.sender);
    }



}

Antworten (2)

Ich kann nicht sehen, was mit dem Token-Vertrag nicht stimmt.

Was die zweite betrifft, sollten Sie Folgendes tun:

function sendTokens () public payable returns (uint)
    {
        AppleToken appleToken = AppleToken(tokenAddress);
        require(appleToken.transfer(msg.sender, 10));
        return appleToken.balanceOf(msg.sender);
    }
  1. Sie müssen die appleToken-Variable nicht deklarieren und dann festlegen, Sie können beides kombinieren.
  2. Stellen Sie sicher, dass tokenAddressdies die richtige ist.
  3. requireVerwenden Sie beim Token-Transfer immer a ! Denken Sie nicht, dass es wie die transferMethode für funktioniert ether, die Fehler behandelt und für Sie wirft.

BEARBEITEN :

Ich habe die Verträge getestet und es funktioniert gut. Ich denke, Sie haben einfach vergessen, Token an den EquityInvestmentsVertrag zu senden, daher Token-Guthaben für den msg.senderAufenthalt bei 0.

Immer noch kein Glück. Dies ist der Fehler, den ich sehe, habe ihn auch schon einmal gesehen. "Die Gasschätzung ist mit der folgenden Meldung fehlerhaft (siehe unten). Die Transaktionsausführung wird wahrscheinlich fehlschlagen. Möchten Sie das Senden erzwingen? Fehler: Gas erforderlich überschreitet die Zulässigkeit oder die Transaktion schlägt immer fehl bei chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js: 18062:326 bei chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:17305:855 bei chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:400:2363 bei u (chrome- ...."
Kannst du den ganzen Code + die Adressen der Verträge auf ropsten geben?
Vielen Dank, dass Sie sich mit dieser @Elisha befasst haben. Ich habe meine Frage aktualisiert. Bitte überprüfen Sie sie.
@MuradHasan Haben Sie dem EquityInvestments-Vertrag tatsächlich Token gutgeschrieben?
@ ElishaDion könntest du das bitte näher erläutern? Weil ich nicht versuche, Token an den EquityInvestments-Vertrag zu senden. Dieser Vertrag dient nur dazu, Ether zu akzeptieren und sollte die Übertragungsfunktion des AppleToken-Vertrags aufrufen, um Token an die Adresse von msg.sender zu senden (die im EquityInvestments-Vertrag empfangen wurde).
Sie sollten lesen, wie transferfunktioniert. Es "gibt" eine bestimmte Menge des msg.sender, der die Funktion aufruft, an eine andere Adresse. Wenn Ihr Vertrag keine Token enthält, kann er nichts an Personen senden , die etheran ihn senden. In Ihrem Fall kann es nicht auf magische Weise neue Token prägen.
Sie, Miss, haben meinen Tag gerettet! Ich verstand das Konzept jetzt VIEL besser. Es funktionierte. Danke schön! @ ElishaDrion

Um auf einen Kommentar von @elidrion näher einzugehen, die .transferMethode, die an Verträge angehängt ist, WIRD ETHER NOT TOKENS aus dem Nachrichtenvertrag an den Besitzer SENDEN.

Um beispielsweise Token aus einem Vertrag herauszuziehen, verwenden Sie nicht die von Solidity bereitgestellte globale Transfermethode, sondern tun Sie Folgendes:

function transferTokensOutOfTokenContract(uint tokens) public onlyOwner returns (bool success) {
        require(tokens <= balances[address(this)]);
        balances[address(this)] = balances[address(this)].sub(tokens);
        balances[msg.sender] = balances[msg.sender].add(tokens);
        emit Transfer(address(this), msg.sender, tokens);
        return true;
    }