ERC20 totalSupply gibt nicht den richtigen Wert zurück

Ich teste einen ERC20-Vertrag basierend auf der Openzeppelin-Solidity-Vorlage. Aber ich beobachte ein merkwürdiges Verhalten beim Lesen einer globalen Variablen. Hier ist der Vertrag:

pragma solidity ^0.4.24;

import "../node_modules/openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";


contract FunnyToken is ERC20 {
    string public constant name = "FunnyToken";
    string public constant symbol = "FYT";
    uint8 public constant decimals = 18;
    uint256 private _totalSupply = 10000 * (10 ** uint256(decimals));
    address private owner;

    constructor() public {
        owner = msg.sender;
    }
}

dann gehe ich truffle migratezu ganache-cli und führe die folgenden Befehle auf der Truffle-Konsole aus:

FunnyToken.deployed().then(inst=> tok=inst);
tok.totalSupply();

Der zurückgegebene Wert ist: BigNumber { s: 1, e: 0, c: [ 0 ] }. Daraus schließe ich, dass die globale Variable _totalSupply nicht richtig initialisiert wird, weil die Funktion totalSupplyso implementiert ist:

function totalSupply() public view returns (uint256) {
    return _totalSupply;
  }

Kann mir jemand erklären was los ist?

Sind Sie sicher, dass der Vertrag aktiviert ist, wenn Sie anrufen totalSupply?

Antworten (4)

Das Problem ist, dass Sie in Ihrem Vertrag eine neue Speichervariable erstellen. FunnyTokenDer Basisvertrag greift weiterhin auf die alte Speichervariable zu.

Eine Lösung besteht darin, den Wert im Konstruktor zuzuweisen.

pragma solidity ^0.4.0;

contract TokenBase {
    uint _totalSupply;
    function totalSupply() public view returns (uint) {
        return _totalSupply;
    }
}

contract Token is TokenBase {
    // uint _totalSupply = 4321; // <-- this creates a new storage variable
    constructor() public {
        _totalSupply = 1234; // It is better to initialize the old variable
    }
}

Eine andere mögliche Lösung besteht darin, die Funktion totalSupply()in Ihrem Vertrag außer Kraft zu setzen, aber Sie verschwenden einen zusätzlichen Speicherplatz.

Ich glaube, ich habe versucht, den Wert von _totalSupply auch im Konstruktor zuzuweisen, aber das Problem wurde dadurch nicht gelöst. Ich habe das Erbe vorerst aufgegeben.
Ich denke, das liegt daran, dass die neue Version von OpenZeppelin diese Variable privat ist und Sie keinen Zugriff von untergeordneten Verträgen haben. Aber ihr Beispiel github.com/OpenZeppelin/openzeppelin-solidity/blob/master/… zeigt, wie man interne Funktionen aufruft _mint.

Alles, was Sie tun müssen, ist, die große Zahl in eine tatsächliche Zahl umzuwandeln. Darüber hinaus scheint dies ziemlich ungewöhnlich zu sein, wenn man bedenkt, wie viele Menschen offene Zeppeline verwenden. Versuchen Sie, die große Zahl als Zahl darzustellen.

const number = tok.totalSupply()
number.toNumber()

Siehe Wie konvertiere ich BigNumber in Number im Truffle-Framework?

Das gibt eine Fehlermeldung, dass toNumber keine Funktion ist. Wenn Sie versuchen, darauf als Attribut zuzugreifen, gibt es undefiniert zurück.
Ich habe die Trüffelkonsole nie wirklich verwendet, ich werde den Code aktualisieren.
In jedem Fall ist der im BigNumber-Typ zurückgegebene Fehler falsch, er entspricht 0

Ich habe die Antwort auf meine eigene Frage gefunden: Bei der Vererbung können abgeleitete Verträge nicht auf private Variablen aus dem Basisvertrag zugreifen (witzig, aber wahr), daher totalSupplywird beim Aufrufen (definiert den Basisvertrag) auf die _totalSupplyaus dem Basisvertrag zugegriffen diejenige, die ich im abgeleiteten Vertrag definiert habe, und gibt somit 0 zurück.

Ich denke, um dies zu umgehen, müsste ich die totalSupplyMethode für den abgeleiteten Vertrag überladen. Ich habe das aber nicht getestet.

Sie haben _totalSupply als deklariert

uint256 private _totalSupply = 10000 * (10 ** uint256(decimals));

Da es sich um eine private Variable in Ihrem Basisvertrag handelt, können Sie sie von keinem Ihrer abgeleiteten Verträge ( Reason ) aufrufen.

Jetzt ist es noch einfacher, dasselbe in Solidity ^0.5.0 zu umgehen:

pragma solidity ^0.5.0;

import 'openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol';
import 'openzeppelin-solidity/contracts/token/ERC721/ERC721Mintable.sol';

contract FunnyToken is ERC20 {
    string public constant name = "FunnyToken";
    string public constant symbol = "FYT";
    uint8 public constant decimals = 18;
    uint256 public _totalSupply = 10000;
    address private owner;

    constructor() public {
        owner = msg.sender;
    }
}

Hoffe bin klar auf dem oben. Danke