¿Cómo puede el costo de cambiar 2 variables de estado y emitir 1 evento llegar a 50K unidades de gas?

tengo este contrato:

pragma solidity ^0.4.23;
contract Test {
    event Event(address indexed wallet);

    mapping (address => bool) public authorizedWallets;

    uint256 public authorizedWalletCount;

    function add(address _wallet) external {
        _add(_wallet);
        emit Event(_wallet);
    }

    function _add(address _wallet) private {
        require(!authorizedWallets[_wallet]);
        authorizedWallets[_wallet] = true;
        authorizedWalletCount++;
    }
}

Y estoy comprobando el costo del gas de function addvía web3 v1.0.0-beta.34en NodeJS:

async function send(transaction) {
    let success = await web3.eth.personal.unlockAccount(OWNER_ADDRESS, OWNER_PASSWORD);
    let gas = await transaction.estimateGas({from: OWNER_ADDRESS, gasPrice: GAS_PRICE});
    console.log(`gas = ${gas}`);
    return await transaction.send({from: OWNER_ADDRESS, gasPrice: GAS_PRICE, gas: gas});
}

for (let i = 1; i < 10; i++) {
    let wallet = `0x5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5${i}`;
    let hash = await send(contract.methods.add(wallet));
}

Tenga en cuenta que después de imprimir el costo del gas, ejecuto la transacción para que tenga un efecto real en el contrato y, posteriormente, en el costo del gas de la siguiente transacción.

En la primera iteración, el costo del gas es 64827.

En cada una de las siguientes iteraciones, el costo del gas es 49827.

Supongo que esta diferencia en sí misma tiene sentido, ya que la primera transacción probablemente cambia muchos más 0 en 1 que cada una de las siguientes transacciones (supongo, en la mapping (address => bool) public authorizedWalletsestructura de datos).

Lo que no tiene mucho sentido para mí es por qué cada una de estas transacciones es tan costosa, ya que solo se ejecutan unas pocas operaciones:

  • _add(_wallet);
    • require(!authorizedWallets[_wallet]);
    • authorizedWallets[_wallet] = true;
    • authorizedWalletCount++;
  • emit WalletAccepted(_wallet);

Estoy usando Parity y Ropsten para todo lo que importa (creo que no debería importar, pero tal vez me equivoque aquí).

¿Alguien puede explicar por qué el costo de estas pocas operaciones alcanza las 50,000 unidades de gas?

¡Gracias!

Respuestas (1)

  • 21,000 costo base de gas de transacción.
  • authorizedWallets[_wallet] = true;hace un SSTORE cambiando un cero a un distinto de cero, por lo que es 20.000 de gas.
  • authorizedWalletCount++;hace un SSTORE cambiando un distinto de cero a otro distinto de cero, por lo que es 5000 de gas.
  • emit Event(_wallet);hace un LOG2, que cuesta 1.125 de gasolina.

Eso es 47,125, que es bastante cercano a su total. Agregue un SLOAD, algo de hashing y algo de sobrecarga para mover las cosas y llamar a las funciones, y creo que 49,827 es bastante razonable.

Cambiar un cero a otro distinto de cero: ¿el costo de eso no depende de la cantidad de bits cambiados (en este caso, un solo bit)? La misma pregunta con respecto a 'cambiar un valor distinto de cero a otro distinto de cero'. ¡Gracias!
No, no lo hace.