Contract-Deployment

錯誤:此合約對象尚未設置地址,請先設置地址

  • April 27, 2021

我應該點擊 HTML 中的按鈕,以便通過點擊必須部署智能合約並且必須執行其功能。但是當我在 Node-js 中編寫這兩個操作的程式碼時,會發生以下錯誤:

`Error: This contract object doesn't have address set yet, please set an address first.`

通過以下程式碼,我部署合約並執行其功能。合約的功能是fill

   app.post('/send-data', function(q,r){ 
       var source2='E:/Alireza/contracts/customer.sol';
       var customercompiled=solc.compile(source2)
       var customerJson="E:/Alireza/build/contracts/customer.json";
       var customerJs=JSON.parse(fs.readFileSync(customerJson));
       var ByteCode="...";
       var customer=new web3.eth.Contract(customerJs.abi, null, {data: ByteCode});
           web3.eth.personal.unlockAccount("0x83Ad536099658519ee6A40A3faCAf3dDcEf6178a","Alireza").then(()=>{console.log("Address unlocked");}).catch(console.error);
           customer.deploy().send({from: "0x6Db320B080b956c371c4bC5b00eF74e73bCE7798", gas:2100000, gasPrice:200}).then((instance)=>{console.log("Contract mined at "+instance.options.address);
           customerInstance=instance}//Here, the contract is deployed.           
           customer.methods.fill(Arg1,Arg2).send({from: "0x6Db320B080b956c371c4bC5b00eF74e73bCE7798", gas:2000000, gasPrice:200});
           //Above line is to interact with the contract and run its function called "fill".
   );

如何消除上述錯誤並改進上述程式碼?

提供的程式碼中有兩個問題: 1- customer.methods.fill(…).send(…)與還沒有地址的實例互動,因為:

var customer=new web3.eth.Contract(…);

定義一個尚未部署的合約,因此它沒有地址。因此,我們必須在部署合約後進行實例化。部署後,我們使用以下程式碼獲取一個實例:

var customerDeployed=new web3.eth.Contract(customerJs.abi,“address of the contract”);

instance.options.address我們可以通過inside訪問地址.then(…)

2- 與智能合約的互動必須在將其部署到網路後進行。在部署命令行之後編寫customer.methods.fill(…)並不能保證這些命令按照相同的順序執行,因為這兩個命令採用相同的實例。我們將互動程式碼寫入合約中,.then(…)以確保在部署後執行。

總而言之,實例化部署的合約和與之互動的命令應該用.then(…).

解決方案程式碼:

app.post('/send-data', function(q,r){ 
   var source2='E:/Alireza/contracts/customer.sol';
   var customercompiled=solc.compile(source2)
   var customerJson="E:/Alireza/build/contracts/customer.json";
   var customerJs=JSON.parse(fs.readFileSync(customerJson));
   var ByteCode="...";
   var customer=new web3.eth.Contract(customerJs.abi, null, {data: ByteCode});
       web3.eth.personal.unlockAccount("0x83Ad536099658519ee6A40A3faCAf3dDcEf6178a","Alireza").then(()=>{console.log("Address unlocked");}).catch(console.error);
       customer.deploy().send({from: "0x6Db320B080b956c371c4bC5b00eF74e73bCE7798", gas:2100000, gasPrice:200}).then((instance)=>{console.log("Contract mined at "+instance.options.address);
           customerInstance=instance; var deployedCustomer=new web3.eth.Contract(customer_abi, instance.options.address) ;deployedCustomer.methods.fill(q.body.firstname, q.body.lastname, q.body.id1, q.body.KYC, q.body.Level, q.body.hashValue, "BankA").send({from: "0xF25e4413a9bB7cEf81239Ab5eD2352Da472330b8", gas:3000000, gasPrice:200});
});

我猜您認為以下幾行定義了契約;

var customer=new web3.eth.Contract(customerJs.abi, null, {data: ByteCode});   web3.eth.personal.unlockAccount("0x83Ad536099658519ee6A40A3faCAf3dDcEf6178a","Alireza").then(()=>{console.log("Address unlocked");}).catch(console.error);
           customer.deploy().send({from: "0x6Db320B080b956c371c4bC5b00eF74e73bCE7798", gas:2100000, gasPrice:200}).then((instance)=>{console.log("Contract mined at "+instance.options.address);
           customerInstance=instance}

但是,這只是部署一個合約。要執行合約的功能,您需要將該合約定義為已部署的合約。通過問題中的程式碼,您正在呼叫平台中的合約,但web3.js無法理解它在哪裡。你應該理解web3.js這一點。在你部署了合約並且它有一個乙太坊地址之後,你應該使用這個命令:

let Customer=new web3.eth.Contract(customer_abi, <address>);

現在,web3.js可以找到合約,然後通過以下方式執行給定的函式:

Customer.methods.fill(arg1, arg2, arg3, arg4, arg5, arg6, arg7).send({from:<address>, gas:<value>, gasPrice:<value>});

正如@Alireza 所提到的:“必須在將智能合約部署到網路之後進行互動”並使用.then()保證。所以,你應該把答案的程式碼放在一個.then(). 因此,我們有以下問題,而不是問題提供的內容:

let customer=new web3.eth.Contract(customerJs.abi, null, {data: ByteCode});
web3.eth.personal.unlockAccount(<address>,<string>).then(()=>{console.log("Address unlocked");}).catch(console.error);
customer.deploy().send({from:<address>, gas:<value>, gasPrice:<value>}).then((instance)=>{console.log("Contract mined at "+instance.options.address);
customerInstance=instance; let Customer=new web3.eth.Contract(customer_abi, instance.options.address) ; Customer.methods.fill(arg1, q.body.lastname,..., arg7).send({from:<address>, gas:<value>, gasPrice:<value>});

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