ERC20 代币。无法获取变量,也无法使用已部署合约的方法

Posted

技术标签:

【中文标题】ERC20 代币。无法获取变量,也无法使用已部署合约的方法【英文标题】:ERC20 token. Cannot get variable nor use methods with deployed contract 【发布时间】:2018-09-10 10:17:32 【问题描述】:

我已经通过 Metamask 在 Ropsten 网络上部署了 ERC20 代币合约。问题是我正在尝试通过 web3 与它进行交互。我已按照 SO 和 SE 中提供的有关令牌传输和方法调用的答案进行操作。

正如你将看到的,我不是在这里转移代币,而是使用我的 Solidity 合约方法来设置代币的初始所有者。合约中的方法接收 2 个参数,一个地址和一个 tokenId。

当我使用代码将令牌转移到测试 Metamask 帐户时,它失败了,也就是说,如果我进入这个测试帐户并导入令牌,它没有。

作为参考,这个 tokenId 基本上是由我的变量 nextTokenIdToAssign 提供的,我这样称呼它:

const tokenIdToAssign = contract.nextTokenIdToAssign.call(function(err, res)
    if(!err)  tokenIdToAssign = res; 
    else  console.log("Error"); 
  ); 

奇怪的是,当我尝试 console.log 时,它返回为未定义。另外,在this question的问题cmets之后,我使用了

const test = web3.eth.getCode(contractAddress);

它只是返回一个空值。 cmets 表明我的构造函数或父构造函数中存在崩溃。

我在这里遗漏了一些重要的细节吗?

完整代码如下:

const config = require('../config');
var Web3 = require('web3');
var web3 = new Web3();
const infuraApi = (config.infura.infuraApiKey);

//Set a provider (HttpProvider)
if (typeof web3 !== 'undefined') 
  web3 = new Web3(web3.currentProvider);
 else 
  // set the provider you want from Web3.providers
  web3 = new Web3(new Web3.providers.HttpProvider('https://ropsten.infura.io/'+infuraApi));


const EthereumTx = require('ethereumjs-tx');
var accountAddressHex = (config.metamaskAccount.metamaskAddressHex);
var accountAddressPrivateKey  = (config.metamaskAccount.metamaskAddressPrivateKey);
var privateKey = new Buffer(accountAddressPrivateKey, 'hex');

var count = web3.eth.getTransactionCount(accountAddressHex);
var contractAddress = (config.solidityContract.contractAddress);
var contractAbiArray = (config.solidityContract.contractABI);
var contract = web3.eth.contract(contractAbiArray).at(contractAddress);

const testSendAccount= "0x...";

const gasPrice = web3.eth.gasPrice;
const gasPriceHex = web3.toHex(gasPrice);
const gasLimitHex = web3.toHex(30000000);
//const tokenTransferAmount = 1;
var tokenIdToAssignHex = contract.nextTokenIdToAssign.sendTransaction( from: accountAddressHex, function(err, hash)
        if(!err)  tokenIdToAssignHex = hash;
        console.log(tokenIdToAssignHex); 
        else  console.log("Error"); 
      );


var tokenIdToAssign = contract.nextTokenIdToAssign.call(function(err, res)
        if(!err)  tokenIdToAssign = res; 
        else  console.log("Error"); 
      );
    const test = web3.eth.getCode(contractAddress);

var rawTransaction = 
          "from": accountAddressHex,
          "nonce": web3.toHex(count),
          "gasPrice": gasPriceHex,
          "gasLimit": gasLimitHex,
          "to": contractAddress,
          "value": "0x0",
          "data": contract.setInitialOwner.getData(testSendAccount, tokenIdToAssign, from: accountAddressHex), //contract.transfer.getData("0xCb...", 10, from: "0x26..."),
          "chainId": 0x03 //Ropsten id is 3, replace with 1 for main
      ;

      var tx = new EthereumTx(rawTransaction);
      tx.sign(privateKey);
      var serializedTx = tx.serialize();

      web3.eth.sendRawTransaction('0x' + serializedTx.toString('hex'), function(err, hash) 
          if (!err)  console.log( 'contract creation tx: ' + hash); 
          else 
              console.log(err);
              return;
            
      );

编辑 1

这里是 setInitialOwner 的合约代码:

function setInitialOwner(address _to, uint256 _tokenId) public
    onlyOwner
    tokensRemainingToAssign
    tenKLimit (_tokenId)
    yesZeroAddressOwner (_tokenId) 
    notSelfSend (_to, _tokenId) 

        tokenIdToOwner[_tokenId] = _to;
        balanceOfAddress[_to] = balanceOfAddress[_to].add(1);
        emit Assign(_to, _tokenId);

        tokenIndexArray.push(_tokenId);

        uint256 length = balanceOf(msg.sender);
        ownedTokensIndexMapping[_tokenId] = length;
        addressToTokenIdByIndex[msg.sender][length] = _tokenId;

        nextTokenIdToAssign = nextTokenFunc(nextTokenIdToAssign);
       hypeKillsTokensRemainingToAssign = tokensRemainingToAssign.sub(1);
        

编辑 2 我已经更改了 tokenToAssign 并添加了

var tokenIdToAssignHex = contract.nextTokenIdToAssign.sendTransaction( from: accountAddressHex, function(err, hash)
    if(!err)  tokenIdToAssignHex = hash;
    console.log(tokenIdToAssignHex); 
    else  console.log("Error"); 
  );

【问题讨论】:

nextTokenIdToAssignconstant 函数吗?发布您的合同代码也可能会有所帮助。 我已经添加了 setInitialOwner 方法和 nextTokenFunc 函数的合约代码。基本上我将构造函数中的下一个令牌 ID 设置为 1。分配的其余令牌 ID 由函数确定。 Ok...nextTokenIdToAssign 是一个公共状态变量,所以你没问题。你console.log 是回调里面的值吗?您正在向call 提供回调并在那里设置变量,但也试图将其分配为返回值。坚持一种方法(最好是回调。然后将 rawTransaction 中的所有内容放入回调中。)。 我可以进行一笔交易。但我无法设法使用 tokenIdToAssignHexin 更新 nextTokenToAssign 以更新下一个令牌 ID。所以我最终得到了令牌 1,它将恢复任何进一步的交易。我添加了 tokenIdToAssignHex,但它会产生错误。 因此,为了更新我的nextTokenIdToAssign,我不得不再次向nextTokenIdToAssign 发送rawTransaction,因为infura 不支持sendTransaction。此时的问题它仍然没有更新。考虑到nextTokenIdToAssignsetInitialOwner 期间使用nextTokenIdToAssign 之类的内部函数本质上发生了变化,是否可能是setter 函数nextTokenFunc(uint256 _tokenId) 引起的。 【参考方案1】:

由于其他人可能会遇到此问题,因此我将发布我得出的解决方案。这里的问题是我的nextTokenToAssign 变量没有正确更新。

我使用myetherwallet.com 来部署合约并检查其价值。部署合约时,如果之后没有调用构造函数,将nextTokenToAssign的初始值设置为1,在后续调用setInitialOwner函数的过程中不会更新。所以解决方案只是简单地调用该函数。

【讨论】:

以上是关于ERC20 代币。无法获取变量,也无法使用已部署合约的方法的主要内容,如果未能解决你的问题,请参考以下文章

ERC20 合约无法转移大额代币

手把手教你发行代币

以太坊私链部署erc20_usdt代币

ERC20 代币在没有所有者的情况下成功部署

为部署在 RinkeBy 测试网上的智能合约执行 ERC20 代币“传输函数”的原始交易

我们可以在不同的区块链上部署相同的 ERC20 代币吗?