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");
);
【问题讨论】:
nextTokenIdToAssign
是 constant
函数吗?发布您的合同代码也可能会有所帮助。
我已经添加了 setInitialOwner 方法和 nextTokenFunc 函数的合约代码。基本上我将构造函数中的下一个令牌 ID 设置为 1。分配的其余令牌 ID 由函数确定。
Ok...nextTokenIdToAssign
是一个公共状态变量,所以你没问题。你console.log
是回调里面的值吗?您正在向call
提供回调并在那里设置变量,但也试图将其分配为返回值。坚持一种方法(最好是回调。然后将 rawTransaction
中的所有内容放入回调中。)。
我可以进行一笔交易。但我无法设法使用 tokenIdToAssignHexin 更新 nextTokenToAssign 以更新下一个令牌 ID。所以我最终得到了令牌 1,它将恢复任何进一步的交易。我添加了 tokenIdToAssignHex,但它会产生错误。
因此,为了更新我的nextTokenIdToAssign
,我不得不再次向nextTokenIdToAssign
发送rawTransaction
,因为infura 不支持sendTransaction
。此时的问题它仍然没有更新。考虑到nextTokenIdToAssign
在setInitialOwner
期间使用nextTokenIdToAssign
之类的内部函数本质上发生了变化,是否可能是setter 函数nextTokenFunc(uint256 _tokenId)
引起的。
【参考方案1】:
由于其他人可能会遇到此问题,因此我将发布我得出的解决方案。这里的问题是我的nextTokenToAssign
变量没有正确更新。
我使用myetherwallet.com 来部署合约并检查其价值。部署合约时,如果之后没有调用构造函数,将nextTokenToAssign
的初始值设置为1,在后续调用setInitialOwner
函数的过程中不会更新。所以解决方案只是简单地调用该函数。
【讨论】:
以上是关于ERC20 代币。无法获取变量,也无法使用已部署合约的方法的主要内容,如果未能解决你的问题,请参考以下文章