Solidity

來自另一個合約的 ERC-20 合約

  • March 16, 2022

我正在嘗試創建可以訪問任何 ERC-20 標準代幣合約功能的合約。首先,我想獲得給定地址的餘額。

我使用 geth 執行私有測試網,我已經部署了以下令牌合約:

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();
}

}

一切正常,我在 geth 上成功測試了它。

然後我創建了以下契約:

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();
}
}

這個是使用這個 JavaScript 部署的:

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);
}
})

在 geth 中,getThis()並且沒問題,但是任何參數tokenAdrs()總是返回 0 :bal()

// geth console
> token.balanceOf(eth.accounts[0]) // instance of TokenERC20
2.0999984e+25
> tokenChecker.bal(eth.accounts[0])
0
> 

我的程式碼有什麼問題?為什麼 TokenChecker 不能與提供的 ERC-20 合約互動?通過給定這樣的合約地址,它甚至可以與隨機的 ERC-20 代幣進行通信嗎?先感謝您。

**編輯:**當我省略constantat 時bal(),送出新事務,沒有任何內容返回到控制台。當我開始挖礦時,沒有什麼特別的事情發生,只顯示關於挖礦的資訊。並且也view總是返回 0。

也許是因為 bal 設置為常數?https://solidity.readthedocs.io/en/v0.4.21/contracts.html?highlight=constant#constant-state-variables

function balanceOf(address _owner) constant returns (uint256 balance);是問題

我認為你必須使用如下: function balanceOf(address _owner) public view returns (uint256);

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