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