Create a new opcode for muldiv

In Uniswap V3, we make heavy use of a FullMath#mulDiv, which allows you to multiply two numbers x and y then divide by a third number d, when x * y > type(uint256).max but x * y / d <= type(uint256).max

This function is extremely useful to smart contract developers working with fixed point math. Hari (@_hrkrshnn) suggested that we write an EIP to add a muldiv opcode.

Is there any reason this shouldn’t be built into the EVM? Should it be a precompile since the result can overflow?


What about signed int256?

So this suppose to work like MULMOD except it should return quotient instead of remainder? You also need to specify what happens when divisor is zero and when quotient is bigger than type(uint256).max.

But fundamentally, I don’t see technical reasons not to have it if useful. The division algorithm in MULMOD and other instructions computes both quotient and remainder in general case.

Yes. It should be the quotient for from the mulmod algorithm. If the quotient is bigger, I was thinking maybe it should truncate to 256 bits. Just and(2**256 - 1, 512-bit-quotient). The zero divisor case can be the same as that for mulmod.

Maybe this is obvious, but how do you detect the calculation overflowed if it just returns the lower 256 bits on overflow?

This would indeed be very useful. I use this ALL THE TIME!

Truncating to 256-bit is straight-forward from implementation perspective. But this probably should be checked with formal verification. IIRC returning 0 for division by 0 causes some troubles in verification.

To be clear, this very much make sense as an EIP draft. Someone should start writing it.

Seconded. A native muldiv opcode would allow me to do away with my monster implementation in PRBMath.

And I guess a precompile would be faster than any implementation available today?

@hrkrshnn et al started an EIP here! MULDIV instruction by hrkrshnn · Pull Request #5000 · ethereum/EIPs · GitHub

1 Like

@hrkrshnn Why did you opt for special casing z = 0 instead of returning two stack items, from the EIP?

  • Returning two stack items, higher and lower order bits