Ich versuche, einen Vertrag zu erstellen, der auf Funktionen jedes ERC-20-Standard-Token-Vertrags zugreifen kann. Zuerst möchte ich das Gleichgewicht der angegebenen Adresse erhalten.
Ich betreibe ein privates Testnetz mit Geth und habe folgenden Token-Vertrag bereitgestellt:
pragma solidity ^0.4.16;
interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) external; }
contract TokenERC20 {
string public name;
string public symbol;
uint8 public decimals = 18;
uint256 public totalSupply;
mapping (address => uint256) public balanceOf;
mapping (address => mapping (address => uint256)) public allowance;
event Transfer(address indexed from, address indexed to, uint256 value);
event Burn(address indexed from, uint256 value);
constructor(uint256 initialSupply, string tokenName, string tokenSymbol) public {
totalSupply = initialSupply;
balanceOf[msg.sender] = totalSupply;
name = tokenName;
symbol = tokenSymbol;
}
function _transfer(address _from, address _to, uint _value) internal {
require(_to != 0x0);
require(balanceOf[_from] >= _value);
require(balanceOf[_to] + _value >= balanceOf[_to]);
uint previousBalances = balanceOf[_from] + balanceOf[_to];
balanceOf[_from] -= _value;
balanceOf[_to] += _value;
emit Transfer(_from, _to, _value);
assert(balanceOf[_from] + balanceOf[_to] == previousBalances);
}
function transfer(address _to, uint256 _value) public {
_transfer(msg.sender, _to, _value);
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
require(_value <= allowance[_from][msg.sender]);
allowance[_from][msg.sender] -= _value;
_transfer(_from, _to, _value);
return true;
}
function approve(address _spender, uint256 _value) public returns (bool success) {
allowance[msg.sender][_spender] = _value;
return true;
}
function approveAndCall(address _spender, uint256 _value, bytes _extraData) public returns (bool success) {
tokenRecipient spender = tokenRecipient(_spender);
if (approve(_spender, _value)) {
spender.receiveApproval(msg.sender, _value, this, _extraData);
return true;
}
}
function burn(uint256 _value) public returns (bool success) {
require(balanceOf[msg.sender] >= _value);
balanceOf[msg.sender] -= _value;
totalSupply -= _value;
emit Burn(msg.sender, _value);
return true;
}
function burnFrom(address _from, uint256 _value) public returns (bool success) {
require(_value <= allowance[_from][msg.sender]);
require(balanceOf[_from] >= _value);
balanceOf[_from] -= _value;
allowance[_from][msg.sender] -= _value;
totalSupply -= _value;
emit Burn(_from, _value);
return true;
}
function () public payable {
revert();
}
}
Alles funktioniert gut, ich habe es auf geth erfolgreich getestet.
Dann habe ich folgenden Vertrag erstellt:
pragma solidity ^0.4.16;
contract ERC20 {
function totalSupply() constant returns (uint256 totalSupply);
function balanceOf(address _owner) constant returns (uint256 balance);
function transfer(address _to, uint _value);
event Transfer(address indexed _from, address indexed _to, uint _value);
}
contract TokenChecker {
address private senderAddress;
address private tokenAddress;
constructor(address _tokenAddress) public {
senderAddress = msg.sender;
tokenAddress = _tokenAddress;
}
function bal(address _address) public constant returns (uint256 balance) {
ERC20 token = ERC20(tokenAddress);
return token.balanceOf(_address);
}
function getThis() public constant returns (address thisAddress) {
return address(this);
}
function tokenAdrs() public constant returns (address adrs) {
return tokenAddress;
}
function () public payable {
revert();
}
}
Dieser wurde mit diesem JavaScript bereitgestellt:
var tokenCheckerFactory = eth.contract(COMPILED_WITH_SOLC_ABI)
var tokenCheckerCompiled = "0xCOMPILED_WITH_SOLC_BIN"
var _tokenAddress = "DEPLOYED_TokenERC20_ADDRESS"
var tokenChecker = tokenCheckerFactory.new(_tokenAddress, {from:eth.accounts[0],data:tokenCheckerCompiled,gas:2000000}, function(e, contract){
if(e) {
console.error(e); // If something goes wrong, at least we'll know.
return;
}
if(!contract.address) {
console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined...");
} else {
console.log("Contract mined! Address: " + contract.address);
console.log(contract);
}
})
In Geth getThis()
und tokenAdrs()
sind OK, aber es wird immer 0 bal()
mit jedem Argument zurückgegeben:
// geth console
> token.balanceOf(eth.accounts[0]) // instance of TokenERC20
2.0999984e+25
> tokenChecker.bal(eth.accounts[0])
0
>
Was ist falsch an meinem Code? Warum kann TokenChecker nicht mit dem bereitgestellten ERC-20-Vertrag interagieren? Könnte es sogar mit einem zufälligen ERC-20-Token kommunizieren, indem es seine Vertragsadresse wie folgt angibt? Vielen Dank im Voraus.
Bearbeiten: Wenn ich constant
bei weglasse bal()
, wird eine neue Transaktion übermittelt, nichts wird an die Konsole zurückgegeben. Wenn ich mit dem Mining beginne, passiert nichts Besonderes, es werden nur Informationen zum Mining angezeigt. Und view
gibt auch immer 0 zurück.
Vielleicht, weil bal als konstant eingestellt ist? https://solidity.readthedocs.io/en/v0.4.21/contracts.html?highlight=constant#constant-state-variables
constant
, wird eine neue Transaktion übermittelt, nichts wird an die Konsole zurückgegeben. Wenn ich mit dem Mining beginne, passiert nichts Besonderes, es werden nur Informationen zum Mining angezeigt.view
gibt auch immer 0 zurück.function balanceOf(address _owner) constant returns (uint256 balance);
ist das Problem
Ich denke, Sie müssen wie folgt verwenden:function balanceOf(address _owner) public view returns (uint256);
Matt Swezy
^0.4.16;
Sie verwenden jedoch Funktionen, die nach dieser Version eingeführt wurden. Sagen Sie nicht, dass dies Ihre Lösung ist, sondern notieren Sie es als Referenz. Das Schlüsselwortconstructor
wurde in 0.4.22 (2018-04-16) github.com/ethereum/solidity/blob/develop/Changelog.md eingeführtMatt Swezy
bal()
haben gearbeitet und den richtigen Wert zurückgegeben. Ich würde annehmen, dass das Problem bei Ihrem JS-Code liegt, nicht bei Solidity. .MichalVales
function tokenSupply() public constant returns (uint256 totalSupply) { return token.totalSupply(); }
und es wird auch 0 zurückgegeben, als ob die Instanz von ERC20 nicht existierte.