3

I should click on a button in HTML such that by the clicking a smart contract must be deployed and its function must be run. But when i write the codes of the both operations in Node-js the followed error occurs:

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

By the followed code i deploy the contract and run its function. the contract's function is 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".
    );

How can i eliminate the mentioned error and improve the above code?

2 Answers 2

1

I guess you thought the below lines define a contract;

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}

But, that just deploy a contract. To execute a contract's function you need to define that contract as a deployed contract. By the code in the question, you are calling a contract that there is in the platform but web3.js can't understand where it is. You should give to understand web3.js about that. After you deployed the contract and it has an Ethereum address you should use this command:

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

Now, web3.js can find the contract and, after that, run the given function by:

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

As @Alireza mentioned: "Interaction with a smart contract must occur after deploying it in the network" and using .then() guarantees that. So, you should put the answer's codes in a .then(). Thus, we have the below instead what the question provided:

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>});
0

There are two problems in the provided code: 1- customer.methods.fill(…).send(…) interacts to an instance that has no address yet, because:

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

Defines a contract that is not deployed yet hence it hasn’t an address. Thus, we have to take an instance after deploying the contract. We take an instance with the followed code after deploying:

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

We can access to the address with instance.options.address inside .then(…).

2- Interaction with a smart contract must occur after deploying it in the network. Writing customer.methods.fill(…) after deployment command line does not guarantee these commands run according to the same order, given that the both commands take a same instance. We write code of interaction to the contract in .then(…) to ensure that run after deployment.

In summary, commands of instantiate the deployed contract and interaction with it should be written in .then(…).

The solution code:

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});
});

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.