add skeleton Q104.104 implementation
This commit is contained in:
@ -4,7 +4,7 @@ import "./interfaces/IUniswapV2.sol";
|
||||
|
||||
import "./libraries/Math.sol";
|
||||
import "./libraries/SafeMath128.sol";
|
||||
import "./libraries/MOCK_Decimal.sol";
|
||||
import "./libraries/UQ104x104.sol";
|
||||
|
||||
import "./token/ERC20.sol";
|
||||
import "./token/SafeTransfer.sol";
|
||||
@ -12,6 +12,7 @@ import "./token/SafeTransfer.sol";
|
||||
contract UniswapV2 is IUniswapV2, ERC20("Uniswap V2", "UNI-V2", 18, 0), SafeTransfer {
|
||||
using SafeMath128 for uint128;
|
||||
using SafeMath256 for uint256;
|
||||
using UQ104x104 for uint208;
|
||||
|
||||
struct TokenData {
|
||||
uint128 token0;
|
||||
@ -24,9 +25,9 @@ contract UniswapV2 is IUniswapV2, ERC20("Uniswap V2", "UNI-V2", 18, 0), SafeTran
|
||||
|
||||
TokenData private reserves;
|
||||
|
||||
MOCK_Decimal.Decimal private accumulatedPriceToken0; // mocked accumulated price of token0 / token1
|
||||
MOCK_Decimal.Decimal private accumulatedPriceToken1; // mocked accumulated price of token1 / token0
|
||||
uint256 private blockNumberLast;
|
||||
uint240 private priceToken0Accumulated;
|
||||
uint240 private priceToken1Accumulated;
|
||||
uint32 private blockNumberLast;
|
||||
|
||||
bool private notEntered = true;
|
||||
modifier lock() {
|
||||
@ -87,22 +88,18 @@ 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
|
||||
MOCK_Decimal.Decimal memory priceToken0 = MOCK_Decimal.div(reserves.token0, reserves.token1);
|
||||
MOCK_Decimal.Decimal memory priceToken1 = MOCK_Decimal.div(reserves.token1, reserves.token0);
|
||||
uint208 priceToken0 = UQ104x104.encode(reserves.token0).qdiv(UQ104x104.encode(reserves.token1));
|
||||
uint208 priceToken1 = UQ104x104.encode(reserves.token1).qdiv(UQ104x104.encode(reserves.token0));
|
||||
|
||||
// multiply these prices by the number of elapsed blocks
|
||||
MOCK_Decimal.Decimal memory priceToken0Accumulated = MOCK_Decimal.mul(priceToken0, blocksElapsed);
|
||||
MOCK_Decimal.Decimal memory priceToken1Accumulated = MOCK_Decimal.mul(priceToken1, blocksElapsed);
|
||||
|
||||
// add the accumulated prices to the global accumulators
|
||||
// multiply these prices by the number of elapsed blocks and add to the accumulators
|
||||
return (
|
||||
MOCK_Decimal.add(accumulatedPriceToken0, priceToken0Accumulated).data,
|
||||
MOCK_Decimal.add(accumulatedPriceToken1, priceToken1Accumulated).data
|
||||
priceToken0Accumulated + (uint240(priceToken0) * blocksElapsed),
|
||||
priceToken1Accumulated + (uint240(priceToken1) * blocksElapsed)
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
accumulatedPriceToken0.data,
|
||||
accumulatedPriceToken1.data
|
||||
priceToken0Accumulated,
|
||||
priceToken1Accumulated
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -125,24 +122,21 @@ contract UniswapV2 is IUniswapV2, ERC20("Uniswap V2", "UNI-V2", 18, 0), SafeTran
|
||||
// if any blocks have gone by since the last time this function was called, we have to update
|
||||
if (block.number > blockNumberLast) {
|
||||
// make sure that this isn't the first time this function is being called
|
||||
uint32 blockNumber = block.number.downcast32();
|
||||
if (blockNumberLast > 0) {
|
||||
uint128 blocksElapsed = (block.number - blockNumberLast).downcast128();
|
||||
uint32 blocksElapsed = blockNumber - blockNumberLast;
|
||||
|
||||
// get the prices according to the reserves as of the last official interaction with the contract
|
||||
MOCK_Decimal.Decimal memory priceToken0 = MOCK_Decimal.div(reserves.token0, reserves.token1);
|
||||
MOCK_Decimal.Decimal memory priceToken1 = MOCK_Decimal.div(reserves.token1, reserves.token0);
|
||||
uint208 priceToken0 = UQ104x104.encode(reserves.token0).qdiv(UQ104x104.encode(reserves.token1));
|
||||
uint208 priceToken1 = UQ104x104.encode(reserves.token1).qdiv(UQ104x104.encode(reserves.token0));
|
||||
|
||||
// multiply these prices by the number of elapsed blocks
|
||||
MOCK_Decimal.Decimal memory priceToken0Accumulated = MOCK_Decimal.mul(priceToken0, blocksElapsed);
|
||||
MOCK_Decimal.Decimal memory priceToken1Accumulated = MOCK_Decimal.mul(priceToken1, blocksElapsed);
|
||||
|
||||
// add these incremental accumulated prices to the global accumulators
|
||||
accumulatedPriceToken0 = MOCK_Decimal.add(accumulatedPriceToken0, priceToken0Accumulated);
|
||||
accumulatedPriceToken1 = MOCK_Decimal.add(accumulatedPriceToken1, priceToken1Accumulated);
|
||||
// multiply these prices by the number of elapsed blocks and add to the accumulators
|
||||
priceToken0Accumulated = priceToken0Accumulated + (uint240(priceToken0) * blocksElapsed);
|
||||
priceToken1Accumulated = priceToken1Accumulated + (uint240(priceToken1) * blocksElapsed);
|
||||
}
|
||||
|
||||
// update the last block number
|
||||
blockNumberLast = block.number;
|
||||
blockNumberLast = blockNumber;
|
||||
}
|
||||
|
||||
// update reserves
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
pragma solidity 0.5.12;
|
||||
|
||||
// mock fixed- or floating-point math
|
||||
library MOCK_Decimal {
|
||||
struct Decimal {
|
||||
uint256 data;
|
||||
}
|
||||
|
||||
function div(uint128 numerator, uint128 denominator) internal pure returns (Decimal memory) {
|
||||
return Decimal(numerator / denominator);
|
||||
}
|
||||
|
||||
function mul(Decimal memory a, uint128 b) internal pure returns (Decimal memory) {
|
||||
return Decimal(a.data * b);
|
||||
}
|
||||
|
||||
function add(Decimal memory a, Decimal memory b) internal pure returns (Decimal memory) {
|
||||
return Decimal(a.data + b.data);
|
||||
}
|
||||
}
|
||||
@ -15,4 +15,9 @@ library SafeMath256 {
|
||||
require(y <= uint128(-1), "downcast-128-overflow");
|
||||
z = uint128(y);
|
||||
}
|
||||
|
||||
function downcast32(uint256 y) internal pure returns (uint32 z) {
|
||||
require(y <= uint32(-1), "downcast-32-overflow");
|
||||
z = uint32(y);
|
||||
}
|
||||
}
|
||||
|
||||
17
contracts/libraries/UQ104x104.sol
Normal file
17
contracts/libraries/UQ104x104.sol
Normal file
@ -0,0 +1,17 @@
|
||||
pragma solidity 0.5.12;
|
||||
|
||||
// TODO this whole library is basically just a mock at the moment
|
||||
library UQ104x104 {
|
||||
uint208 constant Q104 = uint104(-1);
|
||||
|
||||
function encode(uint128 y) internal pure returns (uint208 z) {
|
||||
// require(y <= Q104, "encode-overflow");
|
||||
z = y * Q104;
|
||||
}
|
||||
function qmul(uint208 x, uint208 y) internal pure returns (uint208 z) {
|
||||
z = x * y / Q104;
|
||||
}
|
||||
function qdiv(uint208 x, uint208 y) internal pure returns (uint208 z) {
|
||||
z = x / y;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user