I am having an issue with ethereum based project.
I made web3 API to communicate to the blockchain. I did this two ways. both call the same function on same address:
METHOD 1 (Using Unlocked accounts provided by testrpc):
This is Js code which calls the contract:
lottery.generate = function (req, res) {
var lotteryUsers = helper.getLotteryUsers();
var biddingTime = req.body.bidding_time; //seconds
var pricePerEntry = web3.utils.toWei(req.body.price_in_ether, 'ether'); //ether
var minEntries = req.body.min_entries; //min entries per lottery
var id = req.body.id; //id of lottery
lotteryUsers
.methods
.createLottery(biddingTime, pricePerEntry, minEntries, id)
.estimateGas()
.then(function(gasAmount) {
lotteryUsers
.methods
.createLottery(biddingTime, pricePerEntry, minEntries, id)
.send({gas: gasAmount, from: config.account}) //config.account is test account
.then(function(receipt) {
console.log("receipt", receipt);
res.send(receipt);
})
.catch(function(error) {
console.log("error", error);
res.status(500).send(error.toString());
});
})
.catch(function(error) {
res.send(error);
});
};
It works perfectly. Creates an entry on blockchain. and returns me :
{
"transactionHash": "0x79e459c35e6125b63a3c15bf18868bb79397fc2355ac08716fa5b5609a112579",
"transactionIndex": 0,
"blockHash": "0x0000ce5d0ca7699c6757678833b0d1fe0b506eb55a6a99fdffd4e188c7750a55",
"blockNumber": 9,
"gasUsed": 589396,
"cumulativeGasUsed": 589396,
"contractAddress": null,
"status": true,
"events": {
"NewLottery": {
"logIndex": 0,
"transactionIndex": 0,
"transactionHash": "0x79e459c35e6125b63a3c15bf18868bb79397fc2355ac08716fa5b5609a112579",
"blockHash": "0x0000ce5d0ca7699c6757678833b0d1fe0b506eb55a6a99fdffd4e188c7750a55",
"blockNumber": 9,
"address": "0xEb6ca4A45F9F71ce55Eb8B821188ac27D1d92Fe7",
"type": "mined",
"id": "log_599f5c6f",
"returnValues": {
"0": "0x972877c35198A8dB560371cb558fE36aceBCF753",
"1": "0xa2eF5c45f25b3b2E9559542f499402B535d89bc8",
"2": "1524403958",
"3": "1524404022",
"4": "100000",
"5": "9",
"6": "25",
"7": "10",
"owner": "0x972877c35198A8dB560371cb558fE36aceBCF753",
"usersContractAddress": "0xa2eF5c45f25b3b2E9559542f499402B535d89bc8",
"entryTime": "1524403958",
"lotteryEnd": "1524404022",
"pricePerEntry": "100000",
"startBlock": "9",
"id": "25",
"minEntries": "10"
},
"event": "NewLottery",
"signature": "0x637e63e954826293e14c38de613bec8b58c00ec77125234b9aa753f78626732d",
"raw": {
"data": "0x000000000000000000000000972877c35198a8db560371cb558fe36acebcf753000000000000000000000000a2ef5c45f25b3b2e9559542f499402b535d89bc8000000000000000000000000000000000000000000000000000000005adc8ef6000000000000000000000000000000000000000000000000000000005adc8f3600000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000000a",
"topics": [
"0x637e63e954826293e14c38de613bec8b58c00ec77125234b9aa753f78626732d"
]
}
}
}
}
Notice the gas used : "gasUsed": 589396
METHOD 2 (Using users private key to manually sign the tx):
Js code which calls the same contract instance and function:
lottery.generate = function (req, res) {
var lotteryUsers = helper.getLotteryUsers();
var biddingTime = req.body.bidding_time; //seconds
var pricePerEntry = web3.utils.toWei(req.body.price_in_ether, 'ether'); //ether
var minEntries = req.body.min_entries; //min entries per lottery
var id = req.body.id; //id of lottery
var privateKey = req.body.private_key; //private key of the account
var publicKey = req.body.public_key;
var createLottery = lotteryUsers.methods.createLottery(biddingTime, pricePerEntry, minEntries, id);
var encodedABI = createLottery.encodeABI();
var tx = {
gas: 4712388,
gasPrice: 2,
data: encodedABI
}
console.log("tx "+tx);
console.log("privateKey "+privateKey);
var successEvent = function (receipt) {
res.status(200).send(receipt);
}
var failureEvent = function (error) {
res.status(500).send({message: errorMessage});
}
web3.eth.accounts.signTransaction(tx, privateKey)
.then(signed => {
console.log("signed "+signed.toString());
var tran = web3.eth.sendSignedTransaction(rawTx)
tran.on('confirmation', (confirmationNumber, receipt) => {
console.log('confirmation: ' + confirmationNumber);
});
tran.on('transactionHash', hash => {
console.log('hash');
console.log(hash);
});
tran.on('receipt', receipt => {
console.log('reciept');
console.log(receipt);
successEvent(receipt);
});
tran.on('error', error => {
console.log(error.toString());
failureEvent(error);
});
});
};
Notice how I have created an ABI. then a tx object, with sufficient
gas. Then used web3 apis to sign and broadcast the tx. Also getting
events back.
Response of the api is:
{
"transactionHash": "0x54569155c5af3744d17031787c6a5fee4c7ea468b947d76ddc7d525c5623ca2f",
"transactionIndex": 0,
"blockHash": "0xbaf67b7ff8449425d3ee175cb63eb078c18e4309ace58f558d7b45766d085cda",
"blockNumber": 10,
"gasUsed": 54171,
"cumulativeGasUsed": 54171,
"contractAddress": "0x6945a93653b36aCA660F230Fd2E84a0c7b394882",
"logs": [],
"status": true
}
The API does not error our, but somehow it executes partially on blockchain. I say partially, because of two reasons:
1) No entry is created like being created by Method 1 on the blockchain
2) Gas used in Method 2 is 1/10th of gas used in Method 1
I need your help to figure out what is the problem with method 2.
I have spent hours debugging and narrowed it down to this much , that problem is with the way i create tx object or broadcast the object. Any help would be really appreciated, thanks in advance.
Best Answer
I figured it out, Finally! :
the tx object in Method 2 does not have a "to" address.
I think without the to address, EVM was clueless where to send the tx. I had assumed lotteryUsers object would have taken care of this (since i made abi from it), but alas! i was wrong.
So remember to put in all transaction parameters in the object you plan to send with your transactions!
Note: i tried sending with and without from, both worked. I am assuming EVM figures out the "from" address from the private key. On this one i am sure.