CREDITSCOM / node

Credits Node is the main module that provide an opportunity to run a node and participate in CREDITS blockchain network.
https://developers.credits.com/
GNU Affero General Public License v3.0
151 stars 16 forks source link

Decimal for tokens #39

Open PresidentNavalny opened 5 years ago

PresidentNavalny commented 5 years ago

Describe the bug When you create a token, if you specify a value in the decimal parameter for example 5, and then when the token is created, send 0.000001 of this token or less, the tokens will not be sent, but there will be 2 transactions where it will be written that the sending was successful

To Reproduce Created a SWAP token(SWP) here is his smart contract "C2e5NyvG4cLaZYN5uqPmuVNuZLbgcdgapknmfzifvjiyj". in graph decimal pointed out 5. After that, sent 0.000001 SWP to address "7qk4vxgdqQGZJGVPk746X135DGTXTBrk52aadzmrskxk" The sending did not pass, the tokens were not debited from the balance, but the wallet and the monitor reported that the tokens were sent 2 2,2 2,3 2,4

tkoen93 commented 5 years ago

Contract bug, and therefore your own responsibility as a contract deployer.

Yes, it does look weird that your transaction is a success, but that is because the contract returns true for your transfer.

So, how did that happen?

@Override
    public boolean transfer(String to, String amount) {
        contractIsNotFrozen();
        if (!to.equals(initiator)) {
            BigDecimal decimalAmount = toBigDecimal(amount);
            BigDecimal sourceBalance = getTokensBalance(initiator);
            BigDecimal targetTokensBalance = getTokensBalance(to);
            if (sourceBalance.compareTo(decimalAmount) < 0) {
                throw new RuntimeException("the wallet " + initiator + " doesn't have enough tokens to transfer");
            }
            balances.put(initiator, sourceBalance.subtract(decimalAmount));
            balances.put(to, targetTokensBalance.add(decimalAmount));
        }
        return true;
    }

private BigDecimal toBigDecimal(String stringValue) {
        return new BigDecimal(stringValue).setScale(decimal, ROUND_DOWN);
    }

Copied both transfer function and the toBigDecimal function from your contract.

The only thing it does is converting the amount that is entered as a string to bigdecimal, with the correct amount of decimals, causing no change as it will be converted to 0.00000 -> no change in balances. It does not check how many decimals you enter. If you want to be able to send 0.000001 you should make sure you allow more decimals, or simply send an amount within the limitations.

As mentioned in #11 I wouldn't recommend using the current token contract as there are more minor bugs in it. To fix your issue, simply make a change to the toBigDecimal function:

private BigDecimal toBigDecimal(String stringValue) {
 if(stringValue.contains(".")) {
 int decimalLength = stringValue.split("\\.")[1].length();
 if(decimalLength > decimal)
 throw new RuntimeException(decimalLength + " decimals not allowed"); 
 }

 return new BigDecimal(stringValue).setScale(decimal, ROUND_DOWN);
 }

Result on monitor: image