1

I was getting a "EVM error", so I commented out some code and backtracked to find the issue. I added my _feeAmount to an Emit, and getting a what seems to be a bizarre math answer on a simple math problem.

results displayed from Truffle Unit Test with console.log statements. Everything converted from WeiToEth.

event.feePercent =10
event.FeeAmount  =-18
event.amountGet  =2
event.amountGive =1

FeeAmount should be 2 / 100 * 10 which should be .2 but I'm getting -18. No idea why it's negative.

import "openzeppelin-solidity/contracts/math/SafeMath.sol";
...

 function _trade(uint _orderId, address _user, address _tokenGet, 
                uint _amountGet, address _tokenGive, uint _amountGive) internal {
     // Fee paid by the user that fills the order, a.k.a. msg.sender.
     // charge fees - paid by msg.sender - user filling the order 
     // taken from the amount he gets 
     uint _feeAmount = _amountGet.div(100).mul(feePercent); 


     // do the trade, _user created the order, msg.sender is filling the order 
     //tokens[_tokenGet][msg.sender] = tokens[_tokenGet][msg.sender].sub(_amountGet.add(_feeAmount)); 
     /*
     tokens[_tokenGet][_user] = tokens[_tokenGet][_user].add(_amountGet); 

     // send the fees to the feeAccount 
     tokens[_tokenGet][feeAccount] = tokens[_tokenGet][feeAccount].add(_feeAmount); 

     tokens[_tokenGive][_user] = tokens[_tokenGive][_user].sub(_amountGive); 
     tokens[_tokenGive][msg.sender] = tokens[_tokenGive][msg.sender].add(_amountGive); 
     */ 

     // emit trade event 
     emit Trade(_orderId, _user, _tokenGet, _amountGet, _tokenGive, _amountGive, _feeAmount, 
                feePercent, msg.sender, now); 
 }

Truffle test code:

it('emits a "Trade" event', async () => { // this is why we needed the "result=" above; // "result" is what a subscriber would get subscribing to this event //console.log(result); console.log("Number of logs=" + result.logs.length)

const log = result.logs[0];
let event; 
// get event from logs 
event = log.args

console.log("event.feePercent =" + event.feePercent); 
console.log("event.FeeAmount  ="  + WeiToEth(event.feeAmount))  
console.log("event.amountGet  ="  + WeiToEth(event.amountGet))  
console.log("event.amountGive ="  + WeiToEth(event.amountGive))  

Definition of Trade event:

  event Trade(
      uint id, 
      address user, 
      address tokenGet, 
      uint amountGet, 
      address tokenGive, 
      uint amountGive, 
      uint feeAmount, 
      uint feePercent,
      address userFill, 
      uint timestamp
      );

Helper function:

export const WeiToEth = (n) => {
    return new web3.utils.BN(
      web3.utils.fromWei(n.toString(),'ether')
    )
  }

Definition of feePercent:

uint public feePercent;  // Fee percentage  

Everything in WEI:

event.feePercent =10
event.FeeAmount  =200000000000000000
event.amountGet  =2000000000000000000
event.amountGive =1000000000000000000
12
  • 1
    What is .2??? What variable type do you use for storing this value? Commented Nov 6, 2019 at 20:35
  • And how could you possibly be getting -18 when all your variables are unsigned??? What off-chain tool are you using in order to call this transaction and parse the returned value? If it's a programmatic tool (for example, web3.js), then what does your code look like? Commented Nov 6, 2019 at 20:37
  • What is your declaration of event Trade? Are we suppose to assume that you are passing _feeAmount in the correct place? Commented Nov 6, 2019 at 20:39
  • 3
    BTW, just so you know, 2 / 100 * 10 == (2 / 100) * 10 == 0 * 10 == 0. Commented Nov 6, 2019 at 20:40
  • Added part of my truffle/js test code. In the contract, everything is in WEI, displaying in ETH to keep it simple. Commented Nov 6, 2019 at 20:56

2 Answers 2

0

The immediate issue appears to be that you are expecting non-integer results from your equation when using integers in Solidity.

As other people have commented, in Solidity when dealing with integers, 2/100 = 0

https://solidity.readthedocs.io/en/latest/types.html#division
In Solidity, division rounds towards zero.


Remix is great to quickly test contracts.

The following Test contract can be used in Remix (you can import from GitHub in Remix).

Note: You should only use code published in an official release of OpenZeppelin Contracts, the latest release is 2.4. When importing via GitHub on Remix you can specify the release tag, (otherwise you will get the latest code in the master branch).

pragma solidity ^0.5.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.4.0/contracts/math/SafeMath.sol";

contract Test {

    using SafeMath for uint256;

    function divide(uint256 a, uint256 b) public pure returns(uint256) {
        return a / b;   
    }

    function safeDivide(uint256 a, uint256 b) public pure returns(uint256) {
        return a.div(b);   
    }
}

If you have questions on using OpenZeppelin you can also ask in the Community Forum: https://forum.openzeppelin.com/

Disclosure: I am the Community Manager at OpenZeppelin

1
  • 1
    Sorry, had nothing to do with OpenZeppelin, just had a big mistake in my WeiToEth helper function that made it look like the math was wrong. Commented Nov 7, 2019 at 20:50
0

The actual problem had nothing to do with OpenZepllin, but I must admit that I didn't know about the know decimal limitations.

@GoodVibrations noted that if I displayed everything WEI, the math was correct (and I updated the question with those numbers). So it was converting WEI to a decimal that was the problem.

I had two helper routines in JavaScript that were messing up the result. Had the new web3.utils.BN() wrapper on both, but it should NOT be on the WeiToEth routine.

In my mind, I need the BigNumber when sending a value to the contract, but going from WeiToEth I don't need a big number at all.

export const EthToWei = (n) => {
    return new web3.utils.BN(
      web3.utils.toWei(n.toString(),'ether')
    )
  }

export const WeiToEth = (n) => {
     return web3.utils.fromWei(n.toString(),'ether')
  }

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.