Wie ersetzt man ein Array in einem Mapping?

Ich lerne gerade Solidität und erstelle eine dApp, bei der Benutzer dafür bezahlt werden, Aktionen auszuführen. Aktionen werden nach bestimmten Kriterien bezahlt.

Da ich keinen Cron-Job auf Ethereum planen kann, kann ich Benutzer nur bezahlen, wenn der Benutzer eine Funktion auslöst.

Wenn der Benutzer diese 'claimPayment'-Funktion auslöst, könnte er daher eine Reihe von 10 unbezahlten Aktionen sagen, von denen eine beliebige Zahl zwischen 0 und 10 zu zahlen ist. Nehmen wir für unsere Zwecke an, dass 4 zahlbar sind.

Ich frage mich, was der effizienteste Weg ist, um das alte Array von 10 unbezahlten Aktionen durch das neue Array von 6 unbezahlten Aktionen zu ersetzen.

Ist es effizienter, 6 unbezahlte Aktionen im Speicher zu erstellen und die vorherige Variable zu ersetzen? Oder ist es besser, an bestimmten Indizes zu löschen und dann alles nach links zu verschieben?

Beachten Sie, dass ich mit effizient den Weg meine, der am wenigsten Benzin kostet

Beispiel für Möglichkeit 1:

mapping(address => UnpaidAction[]) unpaidActions;

function claimPayment() public returns (bool){
        uint arrayLength = unpaidActions[msg.sender].length;
        if (arrayLength != 0) {

            UnpaidAction[] memory stillUnpaid;
            uint offset = 0;
            for (uint i = 0; i < arrayLength; i++) {

                if (/*some criteria is met then we pay user*/) {
                    ...
                } else {
                    // criteria not met add it to our temporary array
                    stillUnpaid[offset] = unpaidActions[msg.sender][i];
                    offset += 1;
                }
            }

            // done everything let's replace our storage variable
            unpaidActions[msg.sender] = stillUnpaid
        }

        return true;
    }

Beispiel für Variante 2

function claimPayment() public returns (bool){
        uint arrayLength = unpaidActions[msg.sender].length;
        if (arrayLength != 0) {

            for (uint i = 0; i < arrayLength; i++) {

                if (/*some criteria is met we pay user and delete index*/) {

                    balances[msg.sender] += 100 

                    // delete
                    delete unpaidActions[msg.sender][i]

                } 
            }

            // now run a second for loop and move everything left

            uint offset = 0;
            for (uint i = 0; i < arrayLength; i++) {
                if (offset > 0) {
                    unpaidActions[msg.sender][i - offset] = unpaidActions[msg.sender][i]
                }

                // check if this element has been deleted
                if (unpaidActions[msg.sender][i].someIntVar == 0) {
                    offset +=1;
                } 
            }
            unpaidActions[msg.sender][i].length -= offset
        }

        return true;
    }

Bearbeiten

enum ActionType { /* many action types here*/ }
struct UnpaidAction {
    ActionType actionType;
    string description;
    uint createdAt;
}
post UnpaidAction-Klasse
@KaranKurbur hinzugefügt. Es ist nur einstruct

Antworten (1)

Option 1 löst einen Fehler aus:

UnimplementedFeatureError: Das Kopieren von Speicher vom Typ struct Test.stillUnpaid memory[] in Speicher wird noch nicht unterstützt.

Also musst du wohl bei Option 2 bleiben.