0

I have created a simple savings contract, where users can withdraw back their deposit plus interest after a while. Interest rate is 12% only per hour for testing purposes. Unfortunately, when I try to withdraw it, the transaction gets reverted and I get this error : "The transaction has been reverted to the initial state. Note: The called function should be payable if you send value and the value you send should be less than your current balance." And I get this even when the balance of the contract as way higher than the requested amount, including the built up interest. Could you please tell me, why does it happen?

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract SavingsContract{

address owner;
uint8 interestPerMinute = 20; // 1200 basis points per hour == 20 basis points per minute
uint timeUploaded;

struct Savers{
    address saver;
    uint savedAmount;
    uint dateOfDeposit;
}
Savers[] public savers;

constructor(){
    owner = msg.sender;
    timeUploaded = block.timestamp;
}
modifier onlyOwner{
    owner == msg.sender;
    _;
}

function depositMoney() payable public {
    require(msg.value <= (msg.sender).balance,"Insufficient funds");
    require(msg.value >= 10000, "Need to send min 10 000 Wei");
    savers.push(Savers(msg.sender, msg.value, block.timestamp));
}

function calculateEarnedInterest() view public returns(uint){
    uint storedTime;
    uint interestEarned;
    uint storedAmount;
    for (uint i=0; i <= savers.length; ++i){
        Savers storage savingsAccount = savers[i];
        if (msg.sender == savingsAccount.saver){
            storedTime = (block.timestamp - savingsAccount.dateOfDeposit) / 1 minutes;
            interestEarned = storedTime * interestPerMinute;
            storedAmount = savingsAccount.savedAmount;
            storedAmount = storedAmount + storedAmount * interestEarned / 10000;
            return storedAmount;
        }
    }
    revert("User not found!");
}

function withdraw() payable public {
    uint storedTime;
    uint interestEarned;
    uint storedAmount;
    for (uint i=0; i <= savers.length; ++i){
        Savers storage savingsAccount = savers[i];
        if (msg.sender == savingsAccount.saver){
            storedTime = (block.timestamp - savingsAccount.dateOfDeposit) / 1 minutes;
            interestEarned = storedTime * interestPerMinute;
            storedAmount = savingsAccount.savedAmount;
            storedAmount = storedAmount + storedAmount * interestEarned / 10000;
            payable(savingsAccount.saver).transfer(storedAmount);
            savers[i] = savers[savers.length - 1];
            savers.pop();
        }
    }
    revert("User not found!");
}

function viewContractBalance() public view returns(uint){
    return address(this).balance;
}
function addCapital() payable public onlyOwner{}

}

1 Answer 1

1
  1. I don't know your use case but you don't need make withdraw method payable. becuse user don't need to pay while withdrawl.
  2. In loop condition, you just need to mention less than length, not less than and equal to length.
  3. Read "Revert" detail. because you're reverting the error in normal process.(https://docs.soliditylang.org/en/v0.8.17/control-structures.html)

there are other ways to revert error, rather than revert error in simple function scope.

function withdraw() public { uint storedTime; uint interestEarned; uint storedAmount; for ( uint i=0; i < savers.length;i++){ if (savers[i].saver == msg.sender){ Savers storage savingsAccount = savers[i]; storedTime = (block.timestamp - savingsAccount.dateOfDeposit) / 1 minutes; interestEarned = storedTime * interestPerMinute; storedAmount = savingsAccount.savedAmount; storedAmount = storedAmount + storedAmount * interestEarned / 10000; payable(savingsAccount.saver).transfer(storedAmount); savers[i] = savers[savers.length - 1]; savers.pop(); } } }

https://medium.com/@alishaheen93 this is my medium.

2
  • That worked. Thank you so much.
    – f22daniel
    Oct 23, 2022 at 12:08
  • Welcome dear. Any time.
    – faher ali
    Oct 23, 2022 at 18:47

Your Answer

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

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