Teach you how to develop smart contracts nft in blockchain java (Part 4) – how to dynamically obtain gasPrice and gasLimit

Teach you how to develop smart contracts nft in [blockchain] java (Part 3) – how to dynamically obtain gasPrice and gasLimit?

Beginning to learn blockchain, it is really a pain and helpless. if no one takes you

This article written today is written on the basis of the previous article. Friends who are beginners in blockchain suggest to read the article I wrote earlier to teach you how to
develop smart contracts in blockchain java nft – the first article to
teach you blockchain java . Developing Smart Contract nft-Part 2 (Deploying the First NFT Smart Contract)

What is gas? What is gasPrice? What is gasLimit?

For these concepts, you can click to refer to the official description

How to input gasPrice and gasLimit during development?

For this problem, I was very complaining when I was just getting started. Any operation of EVM on the blockchain will consume a certain amount of gas. If the miners are missing, they will go on strike and report an error directly.

I really don’t understand these when I just started. I use web3j dependencies for java development. When deploying [smart contracts] , I use the default method to obtain gasPrice and gasLimit. The demo is as follows

Web3j web3j = Web3j.build(new HttpService("http://192.168.159.101:9545/"));
        BigInteger chainId = web3j.ethChainId().send().getChainId();
        RawTransactionManager transactionManager = new RawTransactionManager(web3j, getCredentials(),chainId.longValue());
        NFT721 nft721 = NFT721.deploy(web3j,transactionManager,new DefaultGasProvider()),

Then I tried my best to report the error, and I searched the wrong content on the Internet. I really couldn’t find any content. error, but can’t find the problem anywhere

Later, I went to a certain place on the official website. I saw a few configuration values, and I randomly configured the corresponding values. It was a magical success.

NFT721 nft721 = NFT721.deploy(web3j,transactionManager,new StaticGasProvider(BigInteger.valueOf(22_000_000_000l),BigInteger.valueOf(6_700_000l)),

Then I always use this value for development and testing, and report the situation to the leader after the event, saying that the current configuration of these two values ​​​​is dead, and the configuration of other values ​​​​is wrong. how to get

Get gasPrice dynamically

The dynamic acquisition of gasPrice is relatively simple, because you can directly call the api that web3j depends on, and you can get it

private static BigInteger getGasPrice(Web3j web3j){
    BigInteger gasPrice=null;
    try {
      EthGasPrice send = web3j.ethGasPrice().send();
      gasPrice=send.getGasPrice();
    } catch (IOException e) {
      log.error("can't get gasPrice from private chain ,load default gasPrice:[{}],exception log:{}",gasPrice,e);
    }
    return gasPrice;
  }

In this way, the dynamic gasPrice can be obtained. This value is the value corresponding to the gasPrice on the node, as viewed on geth attach:

> eth.gasPrice

Dynamically get gasLimit

Obtaining gasLimit is different from gasPrice and cannot be obtained directly. It is necessary to calculate the method to be operated by calling

EthEstimateGas send = web3j.ethEstimateGas(transaction).send();
      gasLimit=send.getAmountUsed();

Obtaining the gasLimit value, the difficulty is mainly in the transaction

I checked the Internet and found that there is very little information. Basically, no one has given how to obtain the estimated value of gasLimit.
So I followed the websocket sent by the front end to see it. Almost all the data sent by the smart contract is obtained. The gasLimit is roughly as follows:

{
    "id": 141,
    "jsonrpc": "2.0",
    "method": "eth_estimateGas",
    "params": [
        {
            "data": "0x42966c68000000000000000000000000000000000000000000000000000000000000050a",
            "from": "0x2dd277910fca14b15e5e086dbac6732d6f397ef7",
            "to": "0x0b6a1b596a3d5817f3d34322a0ec013ca5439842"
        }
    ]
}

So I started to study transaction, which mainly contains three data, from, to, data
from: is the address of the operating account
to: the address of the smart contract to be operated
data: is the encrypted string of parameters of the method to be operated (the encrypted string is my understanding, is actually encrypting the method)

How to do it?

Above code:

private static BigInteger getGasLimit(Web3j web3j,String from,String to,String data){
    BigInteger gasLimit=BigInteger.valueOf(GasConstant.GAS_LIMIT);;
    try {
      Transaction transaction = Transaction.createFunctionCallTransaction(from, null, null, null,to,data);
      EthEstimateGas send = web3j.ethEstimateGas(transaction).send();
      gasLimit=send.getAmountUsed();
      log.info("got gasLimit:[{}] from chain",gasLimit);
    } catch (IOException e) {
      log.error("can't get gasLimit from private chain,load default gasLimit:[{}],exception log :{}",gasLimit,e);
    }
    return gasLimit;
  }

This encapsulates the method of obtaining gasLimit, and the gasLimit can be obtained according to the incoming parameters

How to assemble data?
Here I take smart contract Token transfer as an example

public static void transfer(String address,String recipient,String tokenAddress,String amount){
        Function transferFunction = Token.getTransferFunction(recipient, new BigInteger(amount));
        Token token = getToken(address, tokenAddress, FunctionEncoder.encode(transferFunction));

        try {
            token.transfer(transferFunction).sendAsync();
        } catch (Exception e) {
            log.error("transfer failure:",e);
            throw new BusinessException(40502,"transfer failure:"+e.getMessage());
        }
    }
      private static Token getToken(String address,String contractAddress,String data){
        Token load = Token.load(contractAddress, web3j, Web3Util.getTransactionManager(web3j,address),                          getContractGasProvider(web3j,address,contractAddress,data));
        return load;
    }
  public static ContractGasProvider getContractGasProvider(Web3j web3j,String from,String to,String data){
    BigInteger gasPrice = getGasPrice(web3j);
    BigInteger gasLimit = getGasLimit(web3j, from,to,data);
    log.info("ContractGasProvider gasPrice:{},gasLimit:{}",gasPrice,gasLimit);
    StaticGasProvider staticGasProvider = new StaticGasProvider(gasPrice,gasLimit );
    return staticGasProvider;
  }

Among them, the getTransferFunction method and the transfer method are methods that I added manually, but in fact, I assembled it with reference to the method parameters of the Token transfer. The
original transfer method is as follows:

public RemoteFunctionCall<TransactionReceipt> transfer(String recipient, BigInteger amount) {
        final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(
                FUNC_TRANSFER, 
                Arrays.<Type>asList(new Address(recipient),
                new Uint256(amount)),
                Collections.<TypeReference<?>>emptyList());
        return executeRemoteCallTransaction(function);
    }

Now add the following method:

//This is the method of calling transfer 
    public RemoteFunctionCall<TransactionReceipt> transfer(org.web3j.abi.datatypes.Function function ) {
         return executeRemoteCallTransaction( function ) ;
    }

//Get the method function of the operation to be called, which will assemble the parameters and parameter values ​​into a Function object 
    public  static org.web3j.abi.datatypes.Function getTransferFunction(String recipient, BigInteger amount) {
         final org.web3j.abi. datatypes.Function function = new  org . web3j . abi . datatypes . Function (
                FUNC_TRANSFER,
                Arrays.<Type>asList(new Address(recipient),
                        new Uint256(amount)),
                Collections.<TypeReference<?>>emptyList());
        return function;
    }

In this way, the value of gasLimit can be estimated and the gasLimit can be obtained dynamically

If you operate other methods, you can modify the corresponding function methods and parameters by yourself. Of course, remember to change to your own corresponding methods when operating.

Leave a Comment

Your email address will not be published. Required fields are marked *