Why the gaslimit of the contract transaction be set much larger than the usage for executed? - solidity

Failed: gas:313,403 | 305,116 (97.36%)
https://goerli.etherscan.io/tx/0xa32a0df5fc02868fb2aab3b10d4a00596fec3a2a62122fdabd40d651b36ab847
Success: gas:415,841 | 287,893 (69.23%)
https://goerli.etherscan.io/tx/0xab7c8a675e0c421c855665743a32ca6fd636c7588aee0a03a750dc6dadaaf623
The same tx data. In the success tx gasused is 287,893,
I have try it by estimateGas is 287000~
But if I set the galimit 313,403, it's still failed.
Why?

Related

Etherscan status difference between pending and indexing

I've been checking block status and then I got wonder that I can't see pending in RinkebyScan but indexing.
The reason I check this is because I want to speed up my tx so I need to send new tx with higher gas when tx I sent is pending. But it always says it's indexing so my tx with higher gas make a new transaction not replacing the latest.
But in mainnet I could see pending status so I want to ask the difference and can't I see pending in Rinkeby?
This screenshot is from mainnet:
Indexing screenshot is from Rinkeby:

EVM(Solidity) "read" in "write" behavior

Let's see a Solidity pseudocode example:
function myFunction() external payable onlyOwner {
ExternalContract contract = ExternalContract(address);
uint result = contract.readFunction();
required(result > 0, 'might failed here') //if FALSE transaction not executing at all (works as **view**)
myCustomWriteLogic();
}
The gas fee will NOT be charged if required() will fail.
Is that mean I'm performing "READ" to the blockchain and then putting the transaction to txpool?
How to force push the transaction to txpool? In my case, I belive that result willl be >0 at the execution moment.
I'm executing a transaction via truffle and I want to push it EVEN it might failed:
const obj = await MyContract.deployed();
obj.myFunction({value: 1000});
The gas fee will NOT be charged if required() will fail.
This is correct only if the snippet is invoked using a (read-only) call. If it's invoked using a transaction, gas fees will be deducted for executing of the code until the point where the require() condition fails and produces a revert.
Calls do not go through the mempool, they are executed directly on the node that you're connected to.
How to force push transaction if your wallet recommends you to not send it (as it might fail)? That depends on the specific wallet or code that you're using to broadcast the transaction. For example the MetaMask UI shows a button to force sending the transaction - see the screenshot:

Coroutines "Asynchronous withTimeout" official tutorial strange behavior

In the official guide "Cancellation and timeouts" section "Asynchronous timeout and resources" there is an example that is supposed to... "If you run the above code you'll see that it does not always print zero, though it may depend on the timings of your machine you may need to tweak timeouts in this example to actually see non-zero values."
var acquired = 0
class Resource {
init { acquired++ } // Acquire the resource
fun close() { acquired-- } // Release the resource
}
fun main() {
runBlocking {
repeat(100_000) { // Launch 100K coroutines
launch {
val resource = withTimeout(60) { // Timeout of 60 ms
delay(50) // Delay for 50 ms
Resource() // Acquire a resource and return it from withTimeout block
}
resource.close() // Release the resource
}
}
}
// Outside of runBlocking all coroutines have completed
println(acquired) // Print the number of resources still acquired
}
I do not understand how that work.
If we let the timeout to 60, instances of Resource are never created. We had to go up to 120 to see instances been created.
However 60ms looks enough to let include a delay(50) + an instance creation. No?
Does someone could explain that?
Thanks in advance.
You should not assume these timings are accurate. delay(50) waits for about 50ms and withTimeout(60) timeouts after about 60ms. I believe both of them gives "at least" guarantee, but they may have to wait practically indefinitely. delay() may wait for a longer time than expected, because there are no free threads to resume. withTimeout() may timeout after a longer time, because coroutine does not cooperate for cancelling.
In your case it is possible that it takes more than 50ms for all 100_000 coroutines to get to delay() point. In that case they aren't resumed after 50ms, because they still wait for the thread to become free to handle them. But this is just a guess. Try to replace it with e.g. delay(150) and withTimeout(160).
The main point of this example is that if the timeout happens after the delay has resumed, but before the end of withTimeout() block then exiting from withTimeout() will throw CancellationException. As a result, Resource() will be invoked, but resource.close() won't.
The main reason why instance have no chance to be created is that execution of delay(50) and more generally the whole task take lot of time because 100_000 coroutines competing on the same thread don't let much time to execute in the delay.
So reducing the number of created coroutines to 10 or 100 (a more realistic situation), tasks look to complete quickly, respecting time and timeout.
Here's results
Number of | Created | Still |
coroutines | Resource | Opened |
| instances | Resources |
-----------+-----------+-----------+
100_000 | 0 | - |
10_000 | 8588 | 635 |
1_000 | 1000 | 0 |
100 | 100 | 0 |

Kusto memory status for an operation id

I executed the following control command
.set-or-append async XXXX<|fillXXXX()
This returned me an operation id
Now I want to check how much CPU/MEMORY usage (Query stats) happened for this operation id.
How can we do that?
When you run the command, you also get the ClientRequestId, and that's what you should use to get the resources used to run the command, :
.show commands
| where StartedOn > ago(1d)
| where ClientActivityId == "KE.RunCommand;9763ec24-910c-4e86-a823-339db440216e"
| where CommandType == "TableSetOrAppend"
| project ResourcesUtilization

web3j Error processing transaction request: insufficient funds for gas * price + value

Following this tutorial
https://github.com/web3j/web3j
Started the geth client as a private network.
Here is the contract code
pragma solidity ^0.4.10;
contract Counter {
uint256 counter =0;
function increase() public {
counter++;
}
function decrease() public{
counter--;
}
function getCounter() public constant returns (uint256) {
return counter;
}
}
Compiled the contract and genetaed the wrapper code for the contract.
Java code for Counter.sol was generated, then I tried to deploy the contract
Web3j web3 = Web3j.build(new org.web3j.protocol.http.HttpService("http://localhost:8080"));
Web3ClientVersion web3ClientVersion = web3.web3ClientVersion().send();
String clientVersion = web3ClientVersion.getWeb3ClientVersion();
Counter contract = Counter.deploy(web3, credentials,Counter.GAS_PRICE;,Counter.GAS_LIMIT).send(); // constructor params
System.out.println("before increase counter "+contract.getCounter());
contract.increase();
System.out.println("after increase counter "+contract.getCounter());
contract.decrease();
System.out.println("after decrease counter "+contract.getCounter());
Getting exception
ontract gas limit 4300000
[info] counter gas price 22000000000
[error] java.lang.RuntimeException: java.lang.RuntimeException: Error processing transaction request: insufficient funds for gas * price + value
[error] at org.web3j.tx.Contract.deploy(Contract.java:350)
[error] at org.web3j.tx.Contract.lambda$deployRemoteCall$5(Contract.java:384)
[error] at org.web3j.protocol.core.RemoteCall.send(RemoteCall.java:30)
[error] at models.smartcontract.FirstContractJava.main(FirstContractJava.java:33)
[error] Caused by: java.lang.RuntimeException: Error processing transaction request: insufficient funds for gas * price + value
[error] at org.web3j.tx.TransactionManager.processResponse(TransactionManager.java:67)
[error] at org.web3j.tx.TransactionManager.executeTransaction(TransactionManager.java:51)
[error] at org.web3j.tx.ManagedTransaction.send(ManagedTransaction.java:87)
[error] at org.web3j.tx.Contract.executeTransaction(Contract.java:275)
[error] at org.web3j.tx.Contract.create(Contract.java:317)
[error] at org.web3j.tx.Contract.deploy(Contract.java:346)
[error] ... 3 more
Then I deployed the contract using ethereum wallet because it estimates the gas limit and gas price for us.
It estimated
gas price 86440
gas limit 186440
So I changed the code like this
BigInteger gp = BigInteger.valueOf(86440);
BigInteger gl = BigInteger.valueOf(186440);
Counter contract = Counter.deploy(web3, credentials,gp,gl).send(); // constructor params
But the exception remained same.
Please guide me how to resolve this exception also how to estimate gas price and gas limit for a contract.
Web3j doesn't give very good default gas price/limit values. I believe they are hardcoded regardless of the contract you develop or the action you try to take. That being said, their default values SHOULD be ok (most of the time) if you have enough ether in your account.
Gas Price
Gas prices fluctuate depending on how much activity is on the network. The more you pay, the more likely (and faster) your transaction will be picked up. Gas prices are measured in Gwei (1 Gwei = 1000000000 Wei). You can see recent gas prices being in MainNet at https://ethgasstation.info/. Usually, you'll see most transactions paying 1-10 Gwei. For higher priority transactions (usually coin/ether transfers as those transactions don't consume a lot of gas), you may see gas prices at 100 or even 1000 Gwei. If you're running a private network, you can use whatever gas price you want (even 0), but you have to set up your miners to accept work at that low of a price. For example, with geth, you can set the minimal gas price with the --gasprice option.
MINER OPTIONS:
--mine Enable mining
--minerthreads value Number of CPU threads to use for mining (default: 8)
--etherbase value Public address for block mining rewards (default = first account created) (default: "0")
--targetgaslimit value Target gas limit sets the artificial target gas floor for the blocks to mine (default: 4712388)
--gasprice "18000000000" --> Minimal gas price to accept for mining a transactions <--
--extradata value Block extra data set by the miner (default = client version)
In your case, the default 22 Gwei is ok, but you can probably lower that to 1-5. However, the 86440 Wei when you deployed through Ethereum Wallet almost certainly won't work.
Gas Limit
Web3j just uses an old default block gas limit as its default value. It has changed over time and is currently around 8 million. Ropsten is fixed and is about 4.7 million. Web3j's default of 4.3 million is just to make sure you don't hit block size limits in test environments. However, if you start a transaction specifying 4.3 million gas at 22 Gwei, you have to have ~0.1 ether in your account. You should be able to lower you gas limit to 200,000 (based off your debug output from deployment, but you would need to post the contract code to confirm).
Balance
Finally, make sure you have ether in your account! Run a simple web3.eth.getBalance() in your geth console to confirm your balance. You can initialize an account balance in your private network in the genesis.json
{
...
"alloc": {
"<ACCT_ID>": {
"balance": "30000000000000000000000000000"
}
}
}