Warum fordert Solidity mich auf, die Zustandsmodifikatorfunktion auf die Anzeige zu beschränken?

Version 0.8.7

Solidity beschwert sich darüber, dass mehrere Zustandsmodifikatorfunktionen auf die Anzeige beschränkt werden können, wie zum Beispiel:

function updateStruct(
    uint256 dummyParam
) public onlyOwner {
    DummyStruct memory dummy = dummyStructArray[dummyParam];
    dummy.something = 1;
}

Grundsätzlich weist jede Funktion, die eine Struktur ändert, eine Warnung auf, dass die Änderung des Funktionszustands auf die Anzeige beschränkt werden kann.

Antworten (1)

In der Dokumentation zum Ansichtsmodifikator heißt es:

Funktionen können als Ansicht deklariert werden, in diesem Fall versprechen sie, den Zustand nicht zu ändern.

Zusätzlich gelten die Zuordnungsregeln zwischen Speicher- und Gedächtniszuständen:

Zuordnungen zwischen Storage und Memory (oder aus Calldata) erzeugen immer eine eigenständige Kopie.

So :

function updateStruct(uint256 dummyParam) public onlyOwner {
    // Creates a memory COPY of dummyStructArray[dummyParam]
    DummyStruct memory dummy = dummyStructArray[dummyParam];
    // Modified the memory COPY
    dummy.something = 1;
}

Sie haben den Zustand beim Zugriff gelesen dummyStructArray[dummyParam], aber Sie ändern nur eine Speicherkopie, nicht die Zustandsvariable. Daher entspricht Ihre Funktion den Ansichtsanforderungen, da sie den Status nicht ändert.

Die function state mutability can be restricted to viewWarnung ist vollkommen berechtigt.

Das gleiche Verhalten ist bei diesem Code zu sehen, Sie können es bei Remix ausprobieren :

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract Example {
    uint256 public stateVariable = 0;

    function modifiesInMemory() public {
        uint256 memoryCopy = stateVariable;
        memoryCopy = 10;
    }
}

BEARBEITEN : Hinzufügen eines einfachen Beispiels gemäß dem Kommentar von OP.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;
    
contract Example {
    struct DummyStruct {
        uint256 something;
    }

    DummyStruct[1] public dummyStructArray;


    // Creates a memory copy and operates on it
    // "Assignments between storage and memory (or from calldata) always create an independent copy."
    function modifiesInMemory() public {
        DummyStruct memory memoryCopy = dummyStructArray[0];
        memoryCopy.something = 10;

        // ASSIGN THE MEMORY COPY BACK TO THE STATE VARIABLE
        dummyStructArray[0] = memoryCopy;
    }

    // Creates a local storage reference to the state variable
    // "Assignments from storage to a local storage variable also only assign a reference."
    function modifiedInLocalStorage() public {
         DummyStruct storage localStorageReference = dummyStructArray[0];
         localStorageReference.something = 10;
    }

    // Directly modifies the state variable
    function modifiesInState() public {
        // MODIFIES THE STATE VARIABLE IN PLACE
        dummyStructArray[0].something = 10;
    }
}
Also wird es irgendwann die ursprüngliche Struktur aktualisieren, oder?
Nein. Sie aktualisieren nur mit diesem Code eine unabhängige Kopie. Sie müssen die Zustandsvariable entweder direkt ändern oder ihr Ihre Speicherkopie zuweisen, nachdem Ihre Änderungen vorgenommen wurden.
Können Sie bitte näher erläutern (oder eine Codereferenz, einen Link usw.), wie Sie Änderungen an der Speicherkopie dem Original zuweisen?
Ich habe ein Beispiel hinzugefügt, das die 3 Möglichkeiten zeigt, dies zu tun. Speicherkopie / lokale Speicherreferenz / vorhanden.
Ja, jetzt macht es Sinn, vielen Dank