3

I'm trying to transfer to send some ether from one account to another in a smart contract written in Solidity. The transfer is successful but the amount received is not exactly matching up with the amount transferred. There is a very minute difference, sometimes it is increasing and sometimes decreasing.

For Example -

received amount: 0.04999999999999716
Transferred amount: 0.05

Another example -

Received amount - 0.05000000000001137
Transferred amount -0.05

Is there anything I'm missing?

Solidity function which does the transfer -

function borrowBook(uint id) onlyMember payable{
    // Can't borrow book if passed value is not sufficient
    if (msg.value < 100){
        throw;
    }
    // Can't borrow a non-existent book
    if (id > numBooks || catalog[id].state != State.Available) {
        throw;
    }
    catalog[id].borrower = msg.sender;
    catalog[id].dateIssued = now;
    catalog[id].state = State.Borrowed;
    // 50% value is shared with the owner
    var owner_share = msg.value/2; 
    if (!catalog[id].owner.send(owner_share)){
        throw;
    }
    Borrow(id, msg.sender, catalog[id].dateIssued);
}

Test case where I'm checking the balances of sender and receiver -

    it.only('should borrow book and transfer 50% weis to owner account', async function(){
        await lms.addBook('a', 'b', 'c');
        await lms.addMember('Michael Scofield', accounts[2]);
        // balance of owner and borrower's account before book borrow
        let ownerBal1 = web3.fromWei(web3.eth.getBalance(accounts[0]).valueOf());
        let borrowBal1 = web3.fromWei(web3.eth.getBalance(accounts[2]).valueOf());
        await lms.borrowBook(1, {from: accounts[2], value: web3.toWei(0.1)});
        // balance of owner and borrower's account after book borrow
        let ownerBal2 = web3.fromWei(web3.eth.getBalance(accounts[0]).valueOf());
        let borrowBal2 = web3.fromWei(web3.eth.getBalance(accounts[2]).valueOf());
        let contractBal = web3.fromWei(web3.eth.getBalance(lms.address).valueOf());
        // contract account get's 50% of the value
        assert.equal(contractBal, 0.05);
        // owner's account should get increased by approx 50% of sent value
        console.log(ownerBal2 - ownerBal1);
        console.log(0.05);
        console.log(borrowBal1-borrowBal2);
        assert.isAtMost(ownerBal2 - ownerBal1, 0.05);
        // borrower's account shoul d get decreased by atleat total sent value
        assert.isAtLeast(borrowBal1 - borrowBal2, 0.1);
    });
  • Probably due to JS floating point precision and a suggestion is to keep values in BigNumber (rather than converting to strings and doing computations on them). – eth Apr 25 '17 at 8:06
  • 1
    Yes, you are right. I was taking valueOf every time. With removing valueOf at variable declaration fixed this issue. Thanks! – Sanchit Apr 25 '17 at 9:01
1

When possible, keep values in BigNumber to avoid Javascript precision and number limits. Try to avoid using valueOf(), and prefer to operate using BigNumber methods when needed.

So more precise code is like:

let ownerBal1 = web3.fromWei(web3.eth.getBalance(accounts[0]));

and

ownerBal2.sub(ownerBal1);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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