2

I would like to define a function like this:

function convert(ufixed x) external pure returns (uint256 result) {
    result = x * 1e18;
}

Unfortunately, the code above does not compile:

TypeError: type ufixed128x18 is not implicitly convertible to expected type uint256.

I went ahead and casted x to uint256:

result = uint256(x) * 1e18;

But this didn't work either:

UnimplementedFeatureError: Fixed point types not implemented.

I have read the docs, and I understand that fixed-point types cannot be assigned to or from. However, all I want is to multiply them by a pre-factor.

Is this still not possible to do in Solidity just yet?

1 Answer 1

1

At the moment we cannot do practically anything with the ufixed type.

You could implement your own UFixed type or use a library that handles "fix point" number arithmetics.

Take a look at the following UFixed custom type and FixedMath library to abstract the details of the arithmetics operations for this type:

// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;

type UserId is uint256;
type UFixed is uint256;

/// A minimal library to do fixed point operations on UFixed.
library FixedMath {
    uint constant multiplier = 10**18;

    /// Adds two UFixed numbers. Reverts on overflow, 
    /// relying on checked arithmetic on uint256.
    function add(UFixed a, UFixed b) internal pure returns (UFixed) {
        return UFixed.wrap(UFixed.unwrap(a) + UFixed.unwrap(b));
    }
    /// Multiplies UFixed and uint256. Reverts on overflow,
    /// relying on checked arithmetic on uint256.
    function mul(UFixed a, uint256 b) internal pure returns (UFixed) {
        return UFixed.wrap(UFixed.unwrap(a) * b);
    }
    /// Take the floor of a UFixed number.
    /// @return the largest integer that does not exceed `a`.
    function floor(UFixed a) internal pure returns (uint256) {
        return UFixed.unwrap(a) / multiplier;
    }
    /// Turns a uint256 into a UFixed of the same value.
    /// Reverts if the integer is too large.
    function toUFixed(uint256 a) internal pure returns (UFixed) {
        return UFixed.wrap(a * multiplier);
    }
}

contract Contract {
    using FixedMath for UFixed;

    mapping(UserId => User) public users;

    struct User {
        UserId id;
        string name;
    }

    function getUser(UserId userId) public view returns(User memory) {
        return users[userId];
    }

    function add(UFixed a, UFixed b) public pure returns(UFixed) {
        return a.add(b);
    }

}
2
  • 1
    Thanks for your answer! Ironically, I've actually built my own fixed-point math library. I needed this convertor function as an internal utility for the library tests. Commented Sep 25, 2022 at 16:29
  • Oh wow! That's awesome! I've seen this library being mentioned in multiple places. Good job! Commented Sep 25, 2022 at 16:43

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.