0

Since web3 apparently doesn't require functions with uint parameters to have positive values for those parameters, I thought I'd try it in Solidity. I'm posting this to see if I'm overthinking it, if there is any unnecessary code, or if there's still a way it could break. For the contract I'm working on, this would be infrequently used but important so it would be worth making sure that negative or irregular amounts would never be set.

modifier validateUintFromInt(int _value) {
    require(_value > 0); // check positive value
    require(_value <= 2**128 - 1); // assumes nothing more than uint128 is needed - not sure if this is necessary with the statement below
    require(_value == int(uint(_value))); // uint and int overflow at different points so this would provide some assurance that massive numbers would not be allowed
    _;
}

This could be used like this:

function updateValue(int _newInt) external validateUintFromInt(_newInt) {
    uint _newUint = uint(_newInt);
    globalUint = _newUint;
}
4
  • I don't understand your goal. Why not just take a uint256 as a parameter?
    – user19510
    Sep 6, 2019 at 8:11
  • Accidentally passing -1, for example, wouldn’t be prevented by web3 and would result in a massive number. It’s an unlikely scenario, but I was mainly surprised that I couldn’t find much on the topic. Sep 6, 2019 at 14:24
  • 1
    Accidentally passing -1 would be the same as accidentally passing 2**256-1. If 2**256-1 is out of bounds, just accept a uint256 and do require(value <= MAX_VALUE, "Number out of range.");
    – user19510
    Sep 6, 2019 at 16:28
  • Assuming you're the one writing the UI, you should also make that layer be helpful (e.g. don't allow the user to type a number starting with a negative sign).
    – user19510
    Sep 6, 2019 at 16:30

1 Answer 1

2

Since web3 apparently doesn't require functions with uint parameters to have positive values

Not true. uint is always a positive number, by definition.

I suspect the issue is about how the contract interprets incoming data.

int, uint and bytes32 are all 32-byte words. So, any of those choices means the contract expects 256-bits. The casting of variable governs interpretation and available methods.

If you want the input to be positive, just cast the argument as uint. As smarx points out, a front end should discourage sending negative numbers. In the case that a negative number is sent to a uint, the bit reserved for sign will be interpreted as another digit of precision resulting in a massive number.

On the contract side, all that should be required is a test for the maximum allowable input.

require(x < limit, "too big");

In case it helps, those types are convertible. This little fiddle might clarify what's going on.

pragma solidity 0.5.11;

contract UintInt {

    function asBytes32(int i, uint u) public pure returns(bytes32 _i, bytes32 _u) {
        return(bytes32(i), bytes32(u));
    }

    function asUint(int i) public pure returns(uint u) {
        return(uint(i));
    }

    function underflow() public pure returns(int i, uint u, bytes32 bi, bytes32 bu) {
        i = int(0)-int(1);
        u = uint(0)-uint(1);
        bi = bytes32(i);
        bu = bytes32(u);
    }
}

enter image description here

Hope it helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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