Go-Ethereum

從 web3.js 呼叫部署的智能合約

  • January 19, 2022

我有一個小型測試智能合約,它部署到我的測試網路。我想使用伺服器來呼叫合約中的函式。這是程式碼:payontime.sol

pragma solidity ^0.4.0;

contract payontime{
 address public remitter;
 address private remittee;
 uint value;
 bool public start;

 /*Only owner can use these function*/
 modifier onlyOwner(){
   if(msg.sender != remitter) throw;
   _;
 }

 /*Initialize the owner*/
 function payontime(address receiver) payable{
   remitter = msg.sender;
   value = msg.value;
   remittee = receiver;
   start = true;
   if(!remittee.send(value)){
       throw;
   }
 }

 function wakeUp() public returns (string){
   return "success" ; 
 }

 function getContractAddr() public returns(address){
   return this;
 }

 /*Get the remittee*/
 function getRemitee() public returns(address){
   return remittee;
 }
}

我使用truffle serve和一個網頁來新契約。

應用程序.js

import { default as Web3} from 'web3';
import { default as contract } from 'truffle-contract'
import payontime_artifacts from '../../build/contracts/payontime.json'
var payontime = contract(payontime_artifacts);

window.App = {
   sendCoin : function(){

       var sender = web3.eth.accounts[0];
       var receiver = document.getElementById('receiver').value;
       var amount =         parseInt(document.getElementById('amount').value);
   web3.eth.getBalance(receiver,function(error,result){
       if(!error){
           consol.log("Before transfer: " + result );
       }else{
           console.log("Error: " + error);
       }
   });

   var newContract = payontime.new(receiver,{from:sender, value:amount}).then(
       function(myPay){
           console.log(myPay.getContractAddr.call());
       }).then(
       function(){
           web3.eth.getBalance(receiver,function(error,result){
               if(!error){
                   console.log("After transfer: " + result );
               }else{
                   console.log("Error: " + error);
               }
           });
       });
   }
}

window.addEventListener('load', function() {
 // Checking if Web3 has been injected by the browser (Mist/MetaMask)
 if (typeof web3 !== 'undefined') {
   console.warn("Using web3 detected from external source. If you find that your accounts don't appear or you have 0 MetaCoin, ensure you've configured that source properly. If using MetaMask, see the following link. Feel free to delete this warning. :) http://truffleframework.com/tutorials/truffle-and-metamask")
   // Use Mist/MetaMask's provider
   window.web3 = new Web3(web3.currentProvider);
 } else {
   console.warn("No web3 detected. Falling back to http://localhost:8545. You should remove this fallback when you deploy live, as it's inherently insecure. Consider switching to Metamask for development. More info here: http://truffleframework.com/tutorials/truffle-and-metamask");
   // fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
   window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
 }
 payontime.setProvider(web3.currentProvider);
});

app.js記錄地址0x1d379f2ab48ad20319e9f81cb45af415aa6f2966,我想用這個地址wakeUp()通過payontime.sol另一個應用程序呼叫index.js

const Web3 = require('web3');

/* Connect to ethereum node */
const etherUrl = "http://localhost:8545";
const abi = [{"constant":false,"inputs":[],"name":"wakeUp","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"getContractAddr","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"remitter","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"start","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"getRemitee","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"inputs":[{"name":"receiver","type":"address"}],"payable":true,"type":"constructor"}];

let web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider(etherUrl));


/*Call the function which already deployed on ethereum network
 Notice: ABI have to modifeid when the smart contract code change*/
var contractInstance = web3.eth.contract(abi).at('0x1d379f2ab48ad20319e9f81cb45af415aa6f2966');
var reply = "false";
reply = contractInstance.wakeUp.call(function(error,result){
   if(error){
       console.log("Error");
       throw error;
   }else{
       return result;
   }
});
console.log(reply);

但是有一個錯誤資訊: BigNumber Error: new BigNumber() not a base 16 number 我發現它可能是由於 not fully synced引起的。我認為在部署的契約中呼叫該函式時會出現一些問題。那麼如何從 web.js 呼叫已部署的合約呢?

BigNumber() is not a base 16 number 錯誤在許多情況下可能發生,但原因不一定相同。我相信原始文章的問題是使用索引“字元串”類型的事件,我也遇到了。如果我的契約事件將“字元串”類型標記為“索引”,我會得到同樣的錯誤。但是,如果我將“索引”關鍵字限制為“地址”類型,我很好。我正在嘗試查找有關可以在契約事件中“索引”哪些數據類型的文件,但無濟於事。我的直覺是任何可以解析為數字(地址、整數等)的東西都可以。我不認為區塊鏈同步是這裡的問題。所以現在嘗試刪除事件定義中字元串欄位的任何索引,直到他們修復錯誤。

ref:- Web3“BigNumber not a base 16 number Error”是什麼意思

web3.js 1.0的文件中, 我們可以從 web3js 呼叫方法:

myContract.methods.myMethod(

$$ param1[, param2[, … $$]])

讓我們看看例子

var Web3 = require('web3')
var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
const abi = abi_of_contract
const Contract = web3.eth.contract(abi)
var contractaddress = address_of_deployed_contract
const contractInstance = Contract.at(contractaddress)

//here I am using default account as first account from the list of addresses in the rpc enabled node
web3.eth.defaultAccount = web3.eth.accounts[0]

//calling contract function wakeUp()  

contractInstance.wakeUp(   
       {
           from:   web3.eth.defaultAccount,
           to:     contractaddress           
   });

您得到的錯誤 Error: new BigNumber() not a base 16 number 可能是由於您傳遞的地址。請先將您使用的帳戶設為預設帳戶。它可能會解決您的問題。

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