Wie können die Kosten für die Änderung von 2 Zustandsvariablen und die Emission von 1 Ereignis 50.000 Gaseinheiten erreichen?

Ich habe diesen Vertrag:

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++;
    }
}

Und ich überprüfe die Benzinkosten von function addvia web3 v1.0.0-beta.34auf 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));
}

Beachten Sie, dass ich die Transaktion ausführe, nachdem ich die Gaskosten ausgedruckt habe, damit sie sich tatsächlich auf den Vertrag und anschließend auf die Gaskosten der nächsten Transaktion auswirkt.

Bei der ersten Iteration betragen die Benzinkosten 64827.

Bei jeder der folgenden Iterationen betragen die Benzinkosten 49827.

Dieser Unterschied an sich ist meiner Meinung nach sinnvoll, da die erste Transaktion wahrscheinlich viel mehr 0s in 1s ändert als jede der folgenden Transaktionen (ich würde vermuten, in der mapping (address => bool) public authorizedWalletsDatenstruktur).

Was für mich nicht viel Sinn macht, ist, warum jede dieser Transaktionen so kostspielig ist, da nur wenige Operationen ausgeführt werden:

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

Ich benutze Parity und Ropsten für alles, was wichtig ist (ich glaube, dass es keine Rolle spielen soll, aber vielleicht irre ich mich hier).

Kann bitte jemand erklären, warum die Kosten dieser wenigen Operationen 50.000 Gaseinheiten erreichen?

Danke schön!

Antworten (1)

  • 21.000 niedrige Transaktionsgaskosten.
  • authorizedWallets[_wallet] = true;ändert ein SSTORE eine Null in eine Nicht-Null, das sind also 20.000 Gas.
  • authorizedWalletCount++;ändert ein SSTORE eine Nicht-Null in eine Nicht-Null, das sind also 5.000 Gas.
  • emit Event(_wallet);macht ein LOG2, das 1.125 Gas kostet.

Das sind 47.125, was ziemlich nahe an Ihrer Gesamtzahl liegt. Fügen Sie ein SLOAD, etwas Hashing und etwas Overhead hinzu, um Dinge zu verschieben und Funktionen aufzurufen, und ich denke, 49.827 ist ziemlich vernünftig.

Ändern einer Null in eine Nicht-Null: hängen die Kosten dafür nicht von der Anzahl der geänderten Bits ab (in diesem Fall ein einzelnes Bit)? Dieselbe Frage in Bezug auf "Ändern einer Nicht-Null in eine Nicht-Null". Danke schön!
Nein, tut es nicht.