I managed to resolve the issue, it was caused by the app setting the default GAS_PRICE and GAS_LIMIT as values that we're too high or too low.
For example, the web3j API had the GAS_LIMIT for the contract set at 4,300,000, but the GAS_PRICE at 22 GWEI (22,000,000,000 WEI), which was well bellow the network average gas price which was 450 GWEI (450,000,000,000 WEI).
First of all, I adjusted the GAS_PRICE to match the current average network GAS_PRICE, but still encountered the same "insufficient funds for gas * price + value" error, at which point I figured that the Transaction cost that the API was trying to reserve (the transaction is able to reserve more than it will spend) was greater than the balance I had
(450,000,000,000 * 4,300,000 = 1,935,000,000,000,000,000 WEI [1.935 ETH]).
So the next step was reducing the GAS_LIMIT, for regular ETH transactions it's usually set at 21,000, but token transactions are more expensive, so I set it at 30,000. Finally, my transaction went through and appeared on the network, but after about 10 minutes the transaction failed with the error OUT OF GAS. This meant the GAS_LIMIT I specified was too low, so I increased it to 100,000. This meant that at the current GAS_PRICE the max cost of the transaction was ~20$. The transaction went through again and got confirmed within a minute, costing me 9$.
Here's the updated code in case anyone is wondering how I updated the GAS_LIMIT and GAS_PRICE.
@Synchronized
fun TokenTransferFrom(TokenTransferFromDto: TokenTransferFromDto): ResultDto {
return try {
val sourceCredentials: Credentials = Util.generateCredentialsBip32(TokenTransferFromDto.sourceMnemonic)
return if (TokenTransferFromDto.sourcePrivateKey == sourceCredentials.ecKeyPair.privateKey.toString(16)) {
val fastRawTransactionManager = FastRawTransactionManager(web3j, sourceCredentials, NoOpProcessor(web3j))
// Load contract by source
val TokenSource = load(infuraTokenContractAddress, web3j, fastRawTransactionManager, DefaultGasProvider())
//
// NEW CODE STARTS HERE
//
// Generate a new gasProvider using the current network gasPrice and our own gasLimit
val gasProvider = StaticGasProvider(TokenSource.requestCurrentGasPrice(), BigInteger.valueOf(100000))
// Set our own gasProvider as the current gasProvider
TokenSource.setGasProvider(gasProvider)
//
// NEW CODE ENDS HERE
//
val transactionReceipt = TokenSource.transfer(TokenTransferFromDto.destination, TokenTransferFromDto.amount).send()
if (!transactionReceipt.isStatusOK) {
return wrapError("transactionReceipt.isStatusOK false", transactionReceipt.status)
}
logger.info(">>>>>>>>>> TokenTransferFrom txHash = ${transactionReceipt.transactionHash}")
ResultDto("success", null, "", transactionReceipt.transactionHash, null, null, null)
} else {
wrapError("", "Invalid mnemonic or private key")
}
} catch (e: Exception) {
logger.error(">>>>>>>>>> EXCEPTION: ${e.message}")
wrapError("", e.message.toString())
}
}
Best Answer
At a very high level, you can think of the current version of Ethereum as V2.1 of Ethereum and Metropolis as being another name for version 3. Byzantium is kind of like version 3 alpha (a feature-incomplete version of version 3, except not really in testing phase) -- it is the first half of the rollout of Byzantium. The rest of version 3 is being rolled out in Constantinople.
As an end-user, because version 3 adds backwards-incompatible changes to the current version of Ethereum, you will need to upgrade your Ethereum wallet to one that supports Byzantium. If you don't, in the best case, your transactions won't be recognized by people who have upgraded (and vice versa). So upgrade, unless you expect a majority of users will not be upgrading. I expect pretty much everyone will upgrade.
You will not lose any ether or tokens associated with your existing accounts (unless it's due to user error, like deleting your private keys while upgrading, or programmer error; back up your keys!).