diff --git a/contracts/UniswapV2.sol b/contracts/UniswapV2.sol index 1a73862..aaaf80a 100644 --- a/contracts/UniswapV2.sol +++ b/contracts/UniswapV2.sol @@ -88,8 +88,8 @@ contract UniswapV2 is IUniswapV2, ERC20("Uniswap V2", "UNI-V2", 18, 0), SafeTran uint128 blocksElapsed = (block.number - blockNumberLast).downcast128(); // get the prices according to the reserves as of the last official interaction with the contract - uint208 priceToken0 = UQ104x104.encode(reserves.token0).qdiv(UQ104x104.encode(reserves.token1)); - uint208 priceToken1 = UQ104x104.encode(reserves.token1).qdiv(UQ104x104.encode(reserves.token0)); + uint208 priceToken0 = UQ104x104.encode(reserves.token0).qdiv(reserves.token1); + uint208 priceToken1 = UQ104x104.encode(reserves.token1).qdiv(reserves.token0); return ( priceToken0Accumulated + (uint240(priceToken0) * blocksElapsed), @@ -126,8 +126,8 @@ contract UniswapV2 is IUniswapV2, ERC20("Uniswap V2", "UNI-V2", 18, 0), SafeTran uint32 blocksElapsed = blockNumber - blockNumberLast; // get the prices according to the reserves as of the last official interaction with the contract - uint208 priceToken0 = UQ104x104.encode(reserves.token0).qdiv(UQ104x104.encode(reserves.token1)); - uint208 priceToken1 = UQ104x104.encode(reserves.token1).qdiv(UQ104x104.encode(reserves.token0)); + uint208 priceToken0 = UQ104x104.encode(reserves.token0).qdiv(reserves.token1); + uint208 priceToken1 = UQ104x104.encode(reserves.token1).qdiv(reserves.token0); // multiply these prices by the number of elapsed blocks and add to the accumulators priceToken0Accumulated = priceToken0Accumulated + (uint240(priceToken0) * blocksElapsed); diff --git a/contracts/libraries/UQ104x104.sol b/contracts/libraries/UQ104x104.sol index bf21bd1..705cffe 100644 --- a/contracts/libraries/UQ104x104.sol +++ b/contracts/libraries/UQ104x104.sol @@ -17,14 +17,18 @@ library UQ104x104 { return uint232(y) * Q104; } - // we want to divide two modified-UQ104.104s (the outputs of encode), and return a traditional Q104. - // for our purposes, we'll do that by flooring the output of the division with `uint208(-1)`. - // (this corresponds to capping the relative prices of x and y at `1 / 2**104` and `uint208(-1) / 2**104`.) - // unfortunately, before we can compute `min(uint208(-1), output), we need to compute `output = x * 2**104 / y`, - // for which we need at least 416 bits (possibly 438 or 464? TODO think this through). - // for now, we just mock the function - function qdiv(uint232 x, uint232 y) internal pure returns (uint208 z) { - // TODO replace mock with real logic - z = uint208(x * Q104 / y); + // we want to divide a modified UQ104.104 (the output of encode) by an unencoded uint128, + // and return a traditional Q104. since we're using a modified UQ104.104, though, we need to handle overflows. + // for the moment, we simply truncate these to 1 and uint208(-1), though it's likely we'll handle this slightly + // differently in the future + function qdiv(uint232 x, uint128 y) internal pure returns (uint208 z) { + uint232 temp = x / y; + if (temp == 0) { + z = 1; + } else if (temp > uint208(-1)) { + z = uint208(-1); + } else { + z = uint208(temp); + } } }