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 migrate
zu 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 totalSupply
so implementiert ist:
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
Kann mir jemand erklären was los ist?
Das Problem ist, dass Sie in Ihrem Vertrag eine neue Speichervariable erstellen. FunnyToken
Der 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.
_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?
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 totalSupply
wird beim Aufrufen (definiert den Basisvertrag) auf die _totalSupply
aus 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 totalSupply
Methode 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
Maxpeinas
totalSupply
?