node icon indicating copy to clipboard operation
node copied to clipboard

Decimal for tokens

Open PresidentNavalny opened this issue 5 years ago • 1 comments

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

PresidentNavalny avatar Jul 05 '19 20:07 PresidentNavalny

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

tkoen93 avatar Jul 06 '19 06:07 tkoen93