0

I'm learning solidity right now and making a dApp where users get paid to perform actions. Actions are paid based on certain criteria.

Since I can't schedule a cron job on ethereum, I can only pay users when the user trigger some function.

Therefore when the user triggers this 'claimPayment' function, he might have say an array of 10 unpaid actions, of which any number between 0-10 are payable. For our purposes let's say 4 are payable.

I'm wondering what is the most efficient way to replace the old array of 10 unpaid actions with the new array of 6 unpaid actions.

Is it more efficient to create 6 unpaid actions in memory and replace the prior variable? Or is it better to delete at specific indices and then move everything left?

Note by efficient i mean the way that will cost the least gas

Example of option 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;
    }

Example of option 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;
    }

Edit

enum ActionType { /* many action types here*/ }
struct UnpaidAction {
    ActionType actionType;
    string description;
    uint createdAt;
}
  • post UnpaidAction class – Karan Kurbur Jun 10 '18 at 2:25
  • @KaranKurbur added. It's just a struct – Terence Chow Jun 10 '18 at 4:31
0

Option 1 will raise an error:

UnimplementedFeatureError: Copying of type struct Test.stillUnpaid memory[] memory to storage not yet supported.

So I guess you'll have to stick to option 2.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.