【问题标题】:Cannot call function within deployed contract无法在已部署的合约中调用函数
【发布时间】:2017-12-21 00:49:06
【问题描述】:

我正在尝试让已部署的 HelloWorld 合同在节点应用程序中运行。我想像这样运行call() 函数来检查它:

const deployed = helloWorldContract.new({
  from: acct1,
  data: compiled.contracts[':HelloWorld'].bytecode,
  gas: 151972,
  gasPrice: 5
}, (error, contract) => {
    if(!error){
      console.log(contract.displayMessage.call());
    } else {
      console.log(error);
    }
});

以下是合同供参考:

contract HelloWorld {
  function displayMessage() public constant returns (string){
    return "hello from smart contract - {name}";
  }
}

当我在回调中尝试 console.log(contract.displayMessage.call()) 时,返回:TypeError: Cannot read property 'call' of undefined,但是,当我登录 console.log(contract.displayMessage) 时,它返回:

{ [Function: bound ]
   request: [Function: bound ],
   call: [Function: bound ],
   sendTransaction: [Function: bound ],
   estimateGas: [Function: bound ],
   getData: [Function: bound ],
   '': [Circular] }

我在这里做错了什么?如何在已部署的合约中运行 call 函数?

【问题讨论】:

  • 它不是一个函数而不是一个属性吗?
  • 正确。如果它是一个属性,我不会使用 contract.displayMessage.call 访问吗?如果它是一个函数,我不能用 contract.displayMessage.call() 访问它吗?为了清楚起见,将合同代码添加到问题中
  • 我的意思是 displayMessage?
  • 是的,它是一个函数,在我的合同中定义,尽管console.log(contract.displayMessage) 将返回上面发布的对象。如果我自己运行console.log(contract.displayMessage());,我会得到:contract.displayMessage is not a function 如果我运行console.log(contract.displayMessage().call());,我会得到:contract.displayMessage is not a function 你有什么建议?

标签: ethereum web3js


【解决方案1】:

我认为您的问题可能是由.new 构造函数引起的。我个人不推荐使用它,因为它很奇怪。相反,您应该将字节码部署为标准事务。

无论如何,如果您查看.newsource code,您会发现回调实际上被调用了两次。这是完全非标准的,据我所知,没有记录。

事务发送后第一次调用回调,contract对象会设置transactionHash

第二次调用回调时,contract 对象应该设置了address 属性。这就是你想要的,因为没有地址属性,你不能调用合约方法。

简而言之,试试这个

const deployed = helloWorldContract.new({
  from: acct1,
  data: compiled.contracts[':HelloWorld'].bytecode,
  gas: 151972,
  gasPrice: 5
}, (error, contract) => {
    if (error){
      console.error(error);
    } else {
      console.log(contract);
      if (contract.address) {
        console.log(contract.displayMessage());
      }
    }
});

不使用.new方法部署合约,首先需要生成合约字节码和ABI。您可以使用solc 或在线solidity 编译器或任何其他方式获得它。

然后部署您使用web3.eth.sendTransaction 并将data 参数设置为字节码和一个空的to 地址的合约。 sendTransaction会给你一个transactionHash,你需要等待被挖掘和确认。最简单的方法是通过轮询——我写的这个方法是一个很好的起点——https://gist.github.com/gaiazov/17c9fc7fdedf297e82386b74b34c61cd

如果您的合约采用构造函数参数,它们会附加到字节码中,例如data: bytecode + encodedConstructorArguments.

【讨论】:

  • 非常感谢!你是对的,它被调用了两次,我没有任何线索(因为我什至没有走那么远)。您能否提供一个关于如何将字节码部署为标准事务的建议?
  • 我添加了关于如何在没有“新”方法的情况下部署合约的简短描述。它有点高级,但我希望它有所帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-07
  • 2020-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-10
相关资源
最近更新 更多