use uint240 for q104.104
This commit is contained in:
@ -12,7 +12,7 @@ import "./token/SafeTransfer.sol";
|
|||||||
contract UniswapV2 is IUniswapV2, ERC20("Uniswap V2", "UNI-V2", 18, 0), SafeTransfer {
|
contract UniswapV2 is IUniswapV2, ERC20("Uniswap V2", "UNI-V2", 18, 0), SafeTransfer {
|
||||||
using SafeMath128 for uint128;
|
using SafeMath128 for uint128;
|
||||||
using SafeMath256 for uint256;
|
using SafeMath256 for uint256;
|
||||||
using UQ104x104 for uint232;
|
using UQ104x104 for uint240;
|
||||||
|
|
||||||
struct TokenData {
|
struct TokenData {
|
||||||
uint128 token0;
|
uint128 token0;
|
||||||
@ -88,12 +88,12 @@ 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(reserves.token1);
|
uint240 priceToken0 = UQ104x104.encode(reserves.token0).qdiv(reserves.token1);
|
||||||
uint208 priceToken1 = UQ104x104.encode(reserves.token1).qdiv(reserves.token0);
|
uint240 priceToken1 = UQ104x104.encode(reserves.token1).qdiv(reserves.token0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
priceToken0Accumulated + (uint240(priceToken0) * blocksElapsed),
|
priceToken0Accumulated + priceToken0 * blocksElapsed,
|
||||||
priceToken1Accumulated + (uint240(priceToken1) * blocksElapsed)
|
priceToken1Accumulated + priceToken1 * blocksElapsed
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
@ -126,12 +126,12 @@ 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(reserves.token1);
|
uint240 priceToken0 = UQ104x104.encode(reserves.token0).qdiv(reserves.token1);
|
||||||
uint208 priceToken1 = UQ104x104.encode(reserves.token1).qdiv(reserves.token0);
|
uint240 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 + priceToken0 * blocksElapsed;
|
||||||
priceToken1Accumulated = priceToken1Accumulated + (uint240(priceToken1) * blocksElapsed);
|
priceToken1Accumulated = priceToken1Accumulated + priceToken1 * blocksElapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the last block number
|
// update the last block number
|
||||||
|
|||||||
@ -6,29 +6,28 @@ pragma solidity 0.5.12;
|
|||||||
// https://github.com/gnosis/solidity-arithmetic
|
// https://github.com/gnosis/solidity-arithmetic
|
||||||
|
|
||||||
library UQ104x104 {
|
library UQ104x104 {
|
||||||
uint232 constant Q104 = uint232(uint104(-1)) + 1;
|
uint240 constant Q104 = 2**104;
|
||||||
|
|
||||||
// we want to encode a uint128 `y` s.t. `y := y_encoded / 2**104` (i.e. with a Q104 denominator).
|
// we want to encode a uint128 `y` s.t. `y := y_encoded / 2**104` (i.e. with a Q104 denominator).
|
||||||
// in other words, to encode `y` we simply multiply by `2**104`, aka Q104.
|
// in other words, to encode `y` we simply multiply by `2**104`, aka Q104.
|
||||||
// however, in the case of a traditional UQ104.104, we'd store this output in a 208-bit slot,
|
// however, in the case of a traditional UQ104.104, we'd store this output in a 208-bit slot,
|
||||||
// which would overflow for values of `y` in (`uint104(-1)`, `uint128(-1)`], so instead we need to
|
// which would overflow for values of `y` in (`uint104(-1)`, `uint128(-1)`], so instead we need to
|
||||||
// store the output in 232 bits (TODO check this logic).
|
// store the output in 232 bits (TODO check this logic).
|
||||||
function encode(uint128 y) internal pure returns (uint232 z) {
|
function encode(uint128 y) internal pure returns (uint240 z) {
|
||||||
return uint232(y) * Q104;
|
return uint240(y) * Q104;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we want to divide a modified UQ104.104 (the output of encode) by an unencoded uint128,
|
// 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.
|
// 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
|
// 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
|
// differently in the future
|
||||||
function qdiv(uint232 x, uint128 y) internal pure returns (uint208 z) {
|
function qdiv(uint240 x, uint128 y) internal pure returns (uint240 z) {
|
||||||
uint232 temp = x / y;
|
z = x / y;
|
||||||
if (temp == 0) {
|
|
||||||
|
if (z == 0) {
|
||||||
z = 1;
|
z = 1;
|
||||||
} else if (temp > uint208(-1)) {
|
} else if (z > uint208(-1)) {
|
||||||
z = uint208(-1);
|
z = uint208(-1);
|
||||||
} else {
|
|
||||||
z = uint208(temp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user