Search code examples
ethereumsolidity

Dividing contract value (actually it is token contract) between holders


this is part of my code (a part of token contracts):

contract SpeadTheGainContract{
    uint public _totalSupply;
    mapping(address => uint) public balances;
    uint public indexedAddressesCounter = 0;
    mapping(address=>bool) ifAdressExisted;
    mapping(uint=>address) ownersAddresses;
    uint requiredAmount = 1 wei;
    
    function spreadTheGain() external{
        for (uint i = 0; i < indexedAddressesCounter; i++){
            payable(ownersAddresses[i]).transfer(address(this).balance*(balances[ownersAddresses[i]]/_totalSupply));
        }
    }
    
    function increaseValue() external payable{
        require(msg.value >= requiredAmount, "Can't send 0 value!");
    }
}

By each transfer of token, new receivers' address will be added to ownersAddresses.

With increaseValue(), contract receives an amount of ETH and stores it.

With spreadTheGain(), contract's stored ETH will be spread among holders of token.

Problem is it works fine when there is 1 holder of token (the owner) but if there is another one, it does not work and executes the function without any sending ETH.

In the transaction details it shows to the amount of holders internal transaction with send ETH to the holders but sending value is 0 ETH.

What is the problem?!


Solution

  • There are two problemes:

    1. After each transfer the contract balance is updated address(this).balance. So if you want to split 10 wei between 10 addresses, the first will see 10 wei/10, but the second one will see 9 wei /10.

    2. The integer division in solidity truncates the result, so 9/10 is returns 0. The calculations does EtherBalance * (TokenBalance / TotalSupply). When there are more than 1 holder TokenBalance < TotalSupply and TokenBalance / TotalSupply = 0.

    To solve the first problem save the balance in a variable before entering the loop. The second problem can be solved by reordering the operatins doing the product first and then the division (EtherBalance * TokenBalance) / TotalSupply.

    function spreadTheGain() external {
        uint256 totalBalance = address(this).balance;
        for (uint i = 0; i < indexedAddressesCounter; i++) {
            uint256 amount = (totalBalance * balances[ownersAddresses[i]]) / _totalSupply;
            payable(ownersAddresses[i]).transfer(amount);
        }
    }