1

I have an array of struct, where I'm storing two uint variables. The user can keep adding values to the array and I'm simply deleting the elements/deposits which are withdrawn completely. The question is that this array (lockData[msg.sender]) can potentially be huge, almost never ending if the user wants to keep adding funds. Hence, I want to know how good does the delete keyword does to the time and gas cost preservation because I can't skip the number of iterations in any case.
Any suggestion for a new approach is welcome.

Here is the code for reference
    function checkDepositData(address _user) public view returns(uint, uint, uint){
    uint sum=0;
    uint i;
    uint start;
    uint end;
    
    // checking for first non zero index
    for(i=0;i<lockData[_user].length; i++){
        if(lockData[_user][i]._releaseTime < block.timestamp && lockData[_user][i]._amount>0) {
            start=i;
            break;
        }
        else{
            i++;
            if(lockData[_user][i]._releaseTime < block.timestamp && lockData[_user][i]._amount>0 && lockData[_user][i-1]._amount==0){
                start=i;
                break;
            }
        }
    }
    
    // start= the element where released deposition starts from
    for(i=start;i<lockData[_user].length; i++){
        if(lockData[_user][i]._releaseTime < block.timestamp){
            sum+=lockData[_user][i]._amount;
            end=i;
        }
    }
    return (sum, start, end);
}
    
/* 
    _amount: Amount to lock
    _releaseTime: Entered by the user
    _start: The index in lockData[msg.sender] array till the point deposits are released
*/
function enterLOCK(uint256 _amount,uint _releaseTime, uint _start) public {
    require((lockData[msg.sender].length - _start) <200, "Number of active depositions exceeded");
    
    uint releaseTime = (_releaseTime * 1 days) + block.timestamp;
    uint256 totalToken= token.balanceOf(address(this));
    uint256 totalShares = totalSupply();
    lockData[msg.sender].push(TimeLock(_amount, releaseTime));
    if (totalShares == 0 || totalToken== 0) {
        _mint(msg.sender, _amount);
    } else {
        uint256 what = _amount.mul(totalShares).div(totalToken);
        _mint(msg.sender, what);
    }
    token.transferFrom(msg.sender, address(this), _amount);
}

function leavelock(uint256 _share) public {
    uint256 totalShares = totalSupply();
    uint256 what = _share.mul(token.balanceOf(address(this))).div(totalShares);
    // temp vars
    uint claimableAmt;
    uint claimableIndexStart;
    uint claimableIndexEnd;
    (claimableAmt, claimableIndexStart, claimableIndexEnd)= checkDepositData(msg.sender);
    require(claimableAmt< _share, "Cannot claim more than unlocked amount");
    uint i;
    uint withdrawalAmt= _share;
    for(i=claimableIndexStart; i<= claimableIndexEnd;i++){
        /* 
            E.g. [200, 400, 200, 500, 300], _share=700
            i) _share= _share-deposit[0]= 700-200= 500
            ii) _share= _share (500) - deposit[1]= 500-400= 100
            iii) (first if condn.) deposit[2]= deposit[2] - _share= 200-100= 100
            END
        */
        if(lockData[msg.sender][i]._amount > withdrawalAmt){
            lockData[msg.sender][i]._amount-= withdrawalAmt;
            break;
        }else{
            withdrawalAmt-= lockData[msg.sender][i]._amount;
            delete lockData[msg.sender][i]; // sets the values to 0, null, false etc. 
        }
    }
    // Actual transfer
    _burn(msg.sender, _share);
    token.transfer(msg.sender, what);

}
2
  • Deleting an array item doesn't remove it from the array, it just resets its value to 0. The array will have the same length after the deletion. Iterating an unbounded array is bad for gas consumption. Try rearranging your data or designing a new algorithm that doesn't use arrays.
    – Ismael
    Commented Nov 28, 2021 at 3:11
  • Yes, I am aware of that. But my question is your answer itself, how can I change my approach. Just a hint of the direction, I need to look at. Solutions can be: 1. User deposit in the start position, which isn't possible. But then I could just pop off the last elements. 2. I pop elements in order, by using two loops. That will be very costly then. So, I cannot seem to think of a proper solution.
    – cyberhawk
    Commented Nov 29, 2021 at 4:34

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.