¿Cómo puedo establecer el precio del gas al implementar un contrato con web3.js?

Configuré un nodo Geth en la red Rinkeby recientemente. Y si bien puedo enviar transacciones ordinarias en segundos sin problemas, parece que no puedo lograr que se cree un contrato en menos de una hora. Cuando compilo un contrato simple en Remix y luego pego el código de implementación web3.js que genera en la consola Geth, envía la transacción a la red, pero luego permanece allí durante más de una hora sin ninguno de los nodos autorizados. aceptándolo en un bloque. Aunque finalmente se acepta.

Me pregunto si el problema aquí puede ser el precio del gas. Según etherscan, parece que web3.js decidió establecer el precio del gas para la transacción en 4 gwei. He verificado que el promedio de la red actualmente es de solo 2 gwei, pero aún así, me gustaría eliminar esto como una posibilidad. (El límite de gas definitivamente no es un problema: establecido en 4700000 y el gas estimado para el código de creación del contrato según Remix es solo 80924).

Si alguien lee esto y sospecha que lo que estoy viendo se debe a algo más que a que el precio del combustible es demasiado bajo, no dude en ver la transacción aquí y hacer sugerencias:

https://rinkeby.etherscan.io/tx/0xe134c193cead33031e3348ebb1db42115fdf156cb5e1a1d43d5c4ecfdf026413

De todos modos, mi pregunta específica es: ¿de dónde viene este precio de gasolina predeterminado de 4gwei y cómo puedo anularlo con algo más alto?

Por alguna razón, en la documentación de web3.js no se menciona ninguna forma de especificar el precio del gas para la creación de un contrato, aunque proporciona una forma de especificarlo para una transacción ordinaria:

https://github.com/ethereum/wiki/wiki/JavaScript-API

¿Puedo simplemente pasar una opción adicional a web3.eth.contract() de gasPrice= , o quizás a myContract.new()?

La transacción a la que se vinculó parece haber tenido éxito hace más de una hora.
Sí, lo siento, pensé que se suponía que mi navegador se actualizaba automáticamente, pero aparentemente no fue así por alguna razón. De todos modos, tardó más de una hora en completarse, lo que todavía es demasiado tiempo; lo he editado ahora para reflejar eso.
No estoy seguro, pero la demora puede deberse al límite de gas muy alto. Los bloques tienen un límite de gas, por lo que es más difícil incluir transacciones muy pesadas en un bloque. (Su transacción en realidad no usó tanto gas, pero un minero que prepara un bloque presumiblemente no lo sabe hasta que intenta incluir su transacción). Intente especificar un límite de gas más bajo la próxima vez.
¡Oh, vaya! No me había dado cuenta de que eso podría marcar la diferencia. Una cosa extraña que noto ahora es que el gas estimado por remix fue solo 80924. Pero el gas consumido real fue 908733. Aunque todavía no es mucho, es mucho más de lo esperado y no estoy seguro de por qué. Parece que la transacción estuvo pendiente durante más de una hora, pero se extrajo en menos de 15 segundos una vez que finalmente se aceptó.
¿Qué campo exacto viste en Remix que decía 80924? El "costo de transacción" es el que desea. Por supuesto, el costo puede variar entre redes, dependiendo de lo que haga la transacción. Por ejemplo, podría funcionar proporcionalmente al número de bloque o un valor en otro contrato, etc. Tendría que compartir su código para que alguien especule sobre ese tipo de cosas.
También extraño: el límite de gas de 4700000 fue autogenerado por remix en la misma compilación que la estimación de gas de 80924. No tengo idea de por qué lo configuraron mucho más alto, solo copié el código de implementación sin darme cuenta.
Lo obtuve de "totalCost" en GASESTIMATES: "Creation": { "codeDepositCost": "80800", "executionCost": "124", "totalCost": "80924" }
Ah, ¿en los "detalles" de la pestaña "compilar"? Veo 4700000 allí también para cualquier código. Creo que solo está codificado. Para los "GASESTIMATES", no tengo explicación. Tendría que ver el código.

Respuestas (3)

De la documentación:

var contractInstance = MyContract.new([constructorParam1] [, constructorParam2],
  {data: '0x12345...', from: myAccount, gas: 1000000});

Sí, puedes simplemente agregar un gasPricea ese objeto:

var contractInstance = MyContract.new([constructorParam1] [, constructorParam2],
 {data: '0x12345...', from: myAccount, gas: 1000000, gasPrice: web3.toWei(2, 'gwei')});
Gracias. ¿Sabe si hay documentación para web3.js en algún lugar que enumere todos los parámetros que cada método puede aceptar? ¿Quizás es mejor simplemente mirar el código fuente en caso de duda?
No veo ninguna documentación para .new(), pero estoy bastante seguro de que ese parámetro es el mismo que en sendTransactiony similares: github.com/ethereum/wiki/wiki/… .

web3 también tiene una función para estimar el gas necesario, podrías hacer algo como:

var gasEstimate = web3.eth.estimateGas({data: bytecode});
var contract = web3.eth.contract(abi);
var instance = contract.new({data: bytecode, from: from, gas: gasEstimate});
var receipt = web3.eth.getTransactionReceipt(instance.transactionHash);

Puede anular el precio del gas en su código, como se muestra a continuación.

    const tx = {
      from: walletAddress,
      to: contractAddress,
      gas: 4700000,
      gasPrice: 20000000000,
      data: encodedABI,
    };

Donde puede usar la variable tx como se muestra a continuación (me salté la parte donde necesita crear una instancia de su HttpProvider)

....
...
smartContract = new web3.eth.Contract(abi, contractAddress);

const privateKey = '0x' + '12714D.....A3D8CC53';
const walletAddress = '0x77.....60';

// change this to whatever contract method you are trying to call, e.g. buyToken(type, title, desc)
const query = smartContract.methods.buyToken(type, title, desc);
const encodedABI = query.encodeABI();
const tx = {
  from: walletAddress,
  to: contractAddress,
  gas: 4700000,
  gasPrice: 10,
  data: encodedABI,
};

const account = web3.eth.accounts.privateKeyToAccount(privateKey);
console.log(account);
web3.eth.getBalance(walletAddress).then(console.log);

web3.eth.accounts.signTransaction(tx, privateKey).then(signed => {
  const tran = web3.eth
    .sendSignedTransaction(signed.rawTransaction)
    .on('confirmation', (confirmationNumber, receipt) => {
      console.log('=> confirmation: ' + confirmationNumber);
    })
    .on('transactionHash', hash => {
      console.log('=> hash');
      console.log(hash);

    })
    .on('receipt', receipt => {
      console.log('=> reciept');
      console.log(receipt);
    })
    .on('error', console.error);
});

Su tarifa de transacción sería gas usado x gasPrice. ¿Cómo saber el gas utilizado? Solo puede saberlo después de que se haya utilizado, como ver su recibo de transacción, vea la imagen a continuación (en el elemento de costo de transacción en Remix donde muestra 206993 gas).

ingrese la descripción de la imagen aquí

P/D: TODAVÍA SOY UN NUEVO EN ETHEREUM Y SOLO QUERÍA AYUDAR. SI HE COMETIDO ALGÚN ERROR POR FAVOR NO DEJEN VOTAR PERO DEJEN COMENTARIOS Y EDITARÉ MI RESPUESTA