I'm having a weird issue with the code below in that sometimes it works and sometimes it doesn't. It seems more apparent when TRANSACTIONS
is set to a larger number. I have had it fail AND pass with TRANSACTIONS
set to 20. What boggles my mind is that if i set from:
to always be accounts[0]
it seems to work every time, even when i set TRANSACTIONS
to 100. The error is thrown in executePromises()
and I show the error below but it's a Error: gas required exceeds allowance (8000029) or always failing transaction
-error. Further i have observed that, when it fails, it does send out some transactions that get picked up for example it sent out transactions for account 1-5 but not for the 6th or 7th etc.
Can someone shed some light on this?
async function multipleTx(
TRANSACTIONS,
GAS_PRICE,
) {
let accounts = await web3.eth.getAccounts()
let tripKey = 0
var sendBlockNumber = await web3.eth.getBlockNumber()
let bookingPromiseArr = []
let txStartTime = Date.now()
for (let i = 0; i < TRANSACTIONS; i++) {
let promise = ''
promise = instance.methods.bookTrip(tripKey).send({
from: accounts[i],
gasPrice: GAS_PRICE,
value: 1,
})
bookingPromiseArr.push(promise)
}
var receipts = await executePromises(bookingPromiseArr)
/* more code below ...*/
}
async function executePromises(promisesArr) {
let res = await Promise.all(promisesArr)
.then(async (receipts) => {
return receipts
})
.catch((error) => {
console.log('executePromises():', error)
process.exit(1)
})
return res
}
Smart Contract Function
function bookTrip(uint256 key) external payable requireTrip(key) {
Trip storage trip = trips[key];
trip.passengers[msg.sender] = trip.price;
trip.passengerCount++;
emit LogNewTripPassenger(msg.sender, key, trip.price);
}
Error Log:
executePromises(): Error: gas required exceeds allowance (8000029) or always fai
ling transaction
at C:\Users\Diddi\Documents\mjukvaruteknik\examensarbete\tqdt33\node_modules
\@truffle\hdwallet-provider\node_modules\web3-provider-engine\subproviders\provi
der.js:18:36
at XMLHttpRequest.request.onreadystatechange (C:\Users\Diddi\Documents\mjukv
aruteknik\examensarbete\tqdt33\node_modules\web3-providers-http\src\index.js:96:
13)
at XMLHttpRequestEventTarget.dispatchEvent (C:\Users\Diddi\Documents\mjukvar
uteknik\examensarbete\tqdt33\node_modules\xhr2-cookies\xml-http-request-event-ta
rget.ts:44:13)
at XMLHttpRequest._setReadyState (C:\Users\Diddi\Documents\mjukvaruteknik\ex
amensarbete\tqdt33\node_modules\xhr2-cookies\xml-http-request.ts:219:8)
at XMLHttpRequest._onHttpResponseEnd (C:\Users\Diddi\Documents\mjukvarutekni
k\examensarbete\tqdt33\node_modules\xhr2-cookies\xml-http-request.ts:345:8)
at IncomingMessage.<anonymous> (C:\Users\Diddi\Documents\mjukvaruteknik\exam
ensarbete\tqdt33\node_modules\xhr2-cookies\xml-http-request.ts:311:39)
at IncomingMessage.emit (events.js:228:7)
at endReadableNT (_stream_readable.js:1185:12)
at processTicksAndRejections (internal/process/task_queues.js:81:21)
Update
I took the advice that @LauriPeltonen gave and stripped everything down as much as I could and looked at what @goodvibration suggested regarding mixing synchronous and asynchronous execution in an incorrect manner. I still get the same error. The code below shows Transaction
set to 50. On etherscan I can see that my smart contract received 20 of those supposed 50 transactions. However on a second attempt it managed to send all 50.
const web3 = require('./web3.js')
const DeRail = require('../../build/contracts/DeRail.json')
const address = require('../../address.json')
const instance = new web3.eth.Contract(DeRail.abi, address.address, {
gasPrice: '20000000000',
})
async function multipleTx(TRANSACTIONS = 50, GAS_PRICE = 1000000000) {
let accounts = await web3.eth.getAccounts()
let tripKey = 19
console.log(accounts.length)
let bookingPromiseArr = []
for (let i = 0; i < TRANSACTIONS; i++) {
let promise = instance.methods.bookTrip(tripKey).send({
from: accounts[i],
gasPrice: GAS_PRICE,
value: 1,
})
bookingPromiseArr.push(promise)
}
var receipts = await executePromises(bookingPromiseArr)
process.exit(0)
}
async function executePromises(promisesArr) {
try {
let res = await Promise.all(promisesArr)
return res
} catch (error) {
console.log('executePromises():', error.message)
process.exit(1)
}
}
multipleTx()
accounts[0]
(probably the contract owner or something similar). Your transaction fails because the function reverts when called with any other account (not because of a gas-related issue, as might be inferred from the error-message).accounts[0]
. TherequireTrip
modifier doesn't restrict the function in any way regarding who is calling it. To clearify it is my smart contract as well.instance
? There is no sign of it in your code prior to using it. Is it possibly a different instance for each transaction (or for some of them)? Could there be different implementations of that function, where in some cases yourrequire(msg.sender == someSpecificAddress)
?executePromises
, you are mixing synchronous and asynchronous execution in an incorrect manner. Better just use one of them. For example:try {return await Promise.all(promisesArr);} catch (error) {...}
.