¿Cómo estimar el costo del gas?

Tengo una función que itera a través de una matriz, lo que podría costar mucho combustible. Pero aún quiero probar el costo estimado del gas y luego decidir si debo mantener el diseño o no.

function giveAwayDividend(uint amount) onlyOwner payable {
for(uint i=0;i<size();i++){
    customerAddress[i].call.value((balances[customerAddress[i]] * amount * 100) / totalSupply)();
}}

Si pruebo en testnet, tengo que crear manualmente más de 1000 cuentas de usuario y enviarles un token a cada uno de ellos, lo que parece estúpido. ¿Hay una mejor manera de calcular el costo del gas? Por ejemplo, si el costo es lineal, podría calcular el costo de un cliente y luego multiplicarlo por la cantidad de clientes. La pregunta es, no creo que sea lineal, ¿alguien puede arrojar algo de luz sobre esto?

Respuestas (2)

Usando Trufa y testrpc . En realidad, es bastante fácil crear un entorno de desarrollo y probar diferentes casos de uso.

Para la estimación de gas, se basa principalmente en funciones nativas de Web3:

  1. Puede recuperar el precio del gas (en wei) usandoweb3.eth.getGasPrice

  2. La función estimateGasdará la estimación de gas para una función (con los parámetros pasados)

  3. Multiplique el número de gas por el precio del gas para obtener la estimación del costo del gas .

Por ejemplo

var TestContract = artifacts.require("./Test.sol");

// Run unit tests to populate my contract
// ...
// ...

// getGasPrice returns the gas price on the current network
TestContract.web3.eth.getGasPrice(function(error, result){ 
    var gasPrice = Number(result);
    console.log("Gas Price is " + gasPrice + " wei"); // "10000000000000"

    // Get Contract instance
    TestContract.deployed().then(function(instance) {

        // Use the keyword 'estimateGas' after the function name to get the gas estimation for this particular function 
        return instance.giveAwayDividend.estimateGas(1);

    }).then(function(result) {
        var gas = Number(result);

        console.log("gas estimation = " + gas + " units");
        console.log("gas cost estimation = " + (gas * gasPrice) + " wei");
        console.log("gas cost estimation = " + TestContract.web3.fromWei((gas * gasPrice), 'ether') + " ether");
    });
});

Resultado en mi caso (red privada):

> truffle test
Using network 'test'.

Compiling .\contracts\Migrations.sol...
Compiling .\contracts\Test.sol...

Gas Price is 20000000000 wei
gas estimation = 26794 units
gas cost estimation = 535880000000000 wei
gas cost estimation = 0.00053588 ether
O web3.eth.gasPriceen lugar deweb3.eth.getGasPrice
¿Cómo hacemos una transacción real con el gas?

La respuesta proporcionada por Greg Jeanmart explicó perfectamente cómo estimar el costo del gas para una función. Aquí quiero señalar que el diseño de su función giveAwayDividend()puede ser vulnerable a un ataque.

Dado que cada uno de los bucles for paga ether a un usuario, y solo ejecuta el siguiente bucle después de que este pago se envía con éxito, podría darse el caso de que el usuario customerAddress[0]rechace el pago (puede hacerlo al tener un contrato cuyo respaldo la función falla deliberadamente), entonces su función giveAwayDividend()también fallaría cada vez y, por lo tanto, se volvería inllamable.

Un mejor enfoque podría ser hacer que los usuarios llamen a una función de retiro (), de modo que el fondo solo vaya a su dirección cuando los usuarios lo soliciten. De esta manera, los atacantes solo pueden invalidar la función para su cuenta y no afectarán a nadie más.

También he pensado en su solución, es una solución técnicamente ideal, pero la situación es: quiero regalar dividendos automáticamente para que mis usuarios no tengan que llamar a retirar() ellos mismos, ya que la mayoría de ellos son inversores que no incluso saber algo sobre el contrato inteligente.