Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- MojitoOracle
- Optimization enabled
- true
- Compiler version
- v0.6.12+commit.27d51765
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2021-11-10T14:12:08.666340Z
Constructor Arguments
00000000000000000000000079855a03426e15ad120df77efa623af87bd54ef3
Arg [0] (address) : 0x79855a03426e15ad120df77efa623af87bd54ef3
Contract source code
// File: @openzeppelin/contracts/math/SafeMath.sol // SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) return 0; uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a % b; } } // File: contracts/interfaces/IMojitoFactory.sol pragma solidity 0.6.12; interface IMojitoFactory { function getPair(address tokenA, address tokenB) external view returns (address pair); } // File: contracts/interfaces/IMojitoPair.sol pragma solidity 0.6.12; interface IMojitoPair { function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); function price0CumulativeLast() external view returns (uint); function price1CumulativeLast() external view returns (uint); } // File: contracts/MojitoOracle.sol pragma solidity =0.6.12; library FixedPoint { // range: [0, 2**112 - 1] // resolution: 1 / 2**112 struct uq112x112 { uint224 _x; } // range: [0, 2**144 - 1] // resolution: 1 / 2**112 struct uq144x112 { uint _x; } uint8 private constant RESOLUTION = 112; // encode a uint112 as a UQ112x112 function encode(uint112 x) internal pure returns (uq112x112 memory) { return uq112x112(uint224(x) << RESOLUTION); } // encodes a uint144 as a UQ144x112 function encode144(uint144 x) internal pure returns (uq144x112 memory) { return uq144x112(uint256(x) << RESOLUTION); } // divide a UQ112x112 by a uint112, returning a UQ112x112 function div(uq112x112 memory self, uint112 x) internal pure returns (uq112x112 memory) { require(x != 0, "FixedPoint: DIV_BY_ZERO"); return uq112x112(self._x / uint224(x)); } // multiply a UQ112x112 by a uint, returning a UQ144x112 // reverts on overflow function mul(uq112x112 memory self, uint y) internal pure returns (uq144x112 memory) { uint z; require(y == 0 || (z = uint(self._x) * y) / y == uint(self._x), "FixedPoint: MULTIPLICATION_OVERFLOW"); return uq144x112(z); } // returns a UQ112x112 which represents the ratio of the numerator to the denominator // equivalent to encode(numerator).div(denominator) function fraction(uint112 numerator, uint112 denominator) internal pure returns (uq112x112 memory) { require(denominator > 0, "FixedPoint: DIV_BY_ZERO"); return uq112x112((uint224(numerator) << RESOLUTION) / denominator); } // decode a UQ112x112 into a uint112 by truncating after the radix point function decode(uq112x112 memory self) internal pure returns (uint112) { return uint112(self._x >> RESOLUTION); } // decode a UQ144x112 into a uint144 by truncating after the radix point function decode144(uq144x112 memory self) internal pure returns (uint144) { return uint144(self._x >> RESOLUTION); } } library MojitoLibrary { using SafeMath for uint; // returns sorted token addresses, used to handle return values from pairs sorted in this order function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) { require(tokenA != tokenB, "MojitoLibrary: IDENTICAL_ADDRESSES"); (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); require(token0 != address(0), "MojitoLibrary: ZERO_ADDRESS"); } } library MojitoOracleLibrary { using FixedPoint for *; // helper function that returns the current block timestamp within the range of uint32, i.e. [0, 2**32 - 1] function currentBlockTimestamp() internal view returns (uint32) { return uint32(block.timestamp % 2 ** 32); } // produces the cumulative price using counterfactuals to save gas and avoid a call to sync. function currentCumulativePrices( address pair ) internal view returns (uint price0Cumulative, uint price1Cumulative, uint32 blockTimestamp) { blockTimestamp = currentBlockTimestamp(); price0Cumulative = IMojitoPair(pair).price0CumulativeLast(); price1Cumulative = IMojitoPair(pair).price1CumulativeLast(); // if time has elapsed since the last update on the pair, mock the accumulated price values (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast) = IMojitoPair(pair).getReserves(); if (blockTimestampLast != blockTimestamp) { // subtraction overflow is desired uint32 timeElapsed = blockTimestamp - blockTimestampLast; // addition overflow is desired // counterfactual price0Cumulative += uint(FixedPoint.fraction(reserve1, reserve0)._x) * timeElapsed; // counterfactual price1Cumulative += uint(FixedPoint.fraction(reserve0, reserve1)._x) * timeElapsed; } } } contract MojitoOracle { using FixedPoint for *; using SafeMath for uint; struct Observation { uint timestamp; uint price0Cumulative; uint price1Cumulative; } address public immutable factory; uint public constant PERIOD = 15 minutes; // mapping from pair address to a list of price observations of that pair mapping(address => Observation) public pairObservations; constructor(address factory_) public { factory = factory_; } function update(address tokenA, address tokenB) external { address pair = IMojitoFactory(factory).getPair(tokenA, tokenB); Observation storage observation = pairObservations[pair]; uint timeElapsed = block.timestamp - observation.timestamp; require(timeElapsed >= PERIOD, "MojitoOracle::update: PERIOD_NOT_ELAPSED"); (uint price0Cumulative, uint price1Cumulative,) = MojitoOracleLibrary.currentCumulativePrices(pair); observation.timestamp = block.timestamp; observation.price0Cumulative = price0Cumulative; observation.price1Cumulative = price1Cumulative; } function computeAmountOut(uint priceCumulativeStart, uint priceCumulativeEnd, uint timeElapsed, uint amountIn) private pure returns (uint amountOut) { // overflow is desired. FixedPoint.uq112x112 memory priceAverage = FixedPoint.uq112x112(uint224((priceCumulativeEnd - priceCumulativeStart) / timeElapsed)); amountOut = priceAverage.mul(amountIn).decode144(); } function consult(address tokenIn, uint amountIn, address tokenOut) external view returns (uint amountOut) { address pair = IMojitoFactory(factory).getPair(tokenIn, tokenOut); Observation storage observation = pairObservations[pair]; uint timeElapsed = block.timestamp - observation.timestamp; (uint price0Cumulative, uint price1Cumulative,) = MojitoOracleLibrary.currentCumulativePrices(pair); (address token0,) = MojitoLibrary.sortTokens(tokenIn, tokenOut); if (token0 == tokenIn) { return computeAmountOut(observation.price0Cumulative, price0Cumulative, timeElapsed, amountIn); } else { return computeAmountOut(observation.price1Cumulative, price1Cumulative, timeElapsed, amountIn); } } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"factory_","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"PERIOD","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amountOut","internalType":"uint256"}],"name":"consult","inputs":[{"type":"address","name":"tokenIn","internalType":"address"},{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"address","name":"tokenOut","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"factory","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"timestamp","internalType":"uint256"},{"type":"uint256","name":"price0Cumulative","internalType":"uint256"},{"type":"uint256","name":"price1Cumulative","internalType":"uint256"}],"name":"pairObservations","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"update","inputs":[{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"}]}]
Contract Creation Code
0x60a060405234801561001057600080fd5b506040516109823803806109828339818101604052602081101561003357600080fd5b5051606081901b6001600160601b0319166080526001600160a01b03166109116100716000398061016a52806102a752806102cd52506109116000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063402e1abf1461005c5780638c86f1e4146100a0578063b4d1d795146100e8578063c45a0155146100f0578063c640752d14610114575b600080fd5b6100826004803603602081101561007257600080fd5b50356001600160a01b0316610144565b60408051938452602084019290925282820152519081900360600190f35b6100d6600480360360608110156100b657600080fd5b506001600160a01b03813581169160208101359160409091013516610165565b60408051918252519081900360200190f35b6100d661029f565b6100f86102a5565b604080516001600160a01b039092168252519081900360200190f35b6101426004803603604081101561012a57600080fd5b506001600160a01b03813581169160200135166102c9565b005b60006020819052908152604090208054600182015460029092015490919083565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e6a4390586856040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b1580156101e657600080fd5b505afa1580156101fa573d6000803e3d6000fd5b505050506040513d602081101561021057600080fd5b50516001600160a01b03811660009081526020819052604081208054929350914203908061023d856103ff565b5091509150600061024e8a896105ce565b509050896001600160a01b0316816001600160a01b031614156102885761027b856001015484868c6106ac565b9650505050505050610298565b61027b856002015483868c6106ac565b9392505050565b61038481565b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e6a4390584846040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b15801561034957600080fd5b505afa15801561035d573d6000803e3d6000fd5b505050506040513d602081101561037357600080fd5b50516001600160a01b038116600090815260208190526040902080549192509042036103848110156103d65760405162461bcd60e51b815260040180806020018281038252602881526020018061086f6028913960400191505060405180910390fd5b6000806103e2856103ff565b504286556001860191909155600290940193909355505050505050565b600080600061040c61070a565b9050836001600160a01b0316635909c0d56040518163ffffffff1660e01b815260040160206040518083038186803b15801561044757600080fd5b505afa15801561045b573d6000803e3d6000fd5b505050506040513d602081101561047157600080fd5b505160408051635a3d549360e01b815290519194506001600160a01b03861691635a3d549391600480820192602092909190829003018186803b1580156104b757600080fd5b505afa1580156104cb573d6000803e3d6000fd5b505050506040513d60208110156104e157600080fd5b505160408051630240bc6b60e21b81529051919350600091829182916001600160a01b03891691630902f1ac916004808301926060929190829003018186803b15801561052d57600080fd5b505afa158015610541573d6000803e3d6000fd5b505050506040513d606081101561055757600080fd5b5080516020820151604090920151909450909250905063ffffffff808216908516146105c45780840363ffffffff81166105918486610714565b516001600160e01b031602969096019563ffffffff81166105b28585610714565b516001600160e01b0316029590950194505b5050509193909250565b600080826001600160a01b0316846001600160a01b031614156106225760405162461bcd60e51b81526004018080602001828103825260228152602001806108976022913960400191505060405180910390fd5b826001600160a01b0316846001600160a01b031610610642578284610645565b83835b90925090506001600160a01b0382166106a5576040805162461bcd60e51b815260206004820152601b60248201527f4d6f6a69746f4c6962726172793a205a45524f5f414444524553530000000000604482015290519081900360640190fd5b9250929050565b60006106b6610849565b604051806020016040528085888803816106cc57fe5b046001600160e01b0316905290506106ec6106e782856107c4565b610842565b71ffffffffffffffffffffffffffffffffffff169695505050505050565b63ffffffff421690565b61071c610849565b6000826001600160701b03161161077a576040805162461bcd60e51b815260206004820152601760248201527f4669786564506f696e743a204449565f42595f5a45524f000000000000000000604482015290519081900360640190fd5b6040805160208101909152806001600160701b0384166dffffffffffffffffffffffffffff60701b607087901b16816107af57fe5b046001600160e01b0316815250905092915050565b6107cc61085b565b60008215806107f257505082516001600160e01b0316828102908382816107ef57fe5b04145b61082d5760405162461bcd60e51b81526004018080602001828103825260238152602001806108b96023913960400191505060405180910390fd5b60408051602081019091529081529392505050565b5160701c90565b60408051602081019091526000815290565b604051806020016040528060008152509056fe4d6f6a69746f4f7261636c653a3a7570646174653a20504552494f445f4e4f545f454c41505345444d6f6a69746f4c6962726172793a204944454e544943414c5f4144445245535345534669786564506f696e743a204d554c5449504c49434154494f4e5f4f564552464c4f57a264697066735822122045d219d952d8e717e2290fef89c28ce75078324f8bc091a63a0a6e51f765ee2964736f6c634300060c003300000000000000000000000079855a03426e15ad120df77efa623af87bd54ef3
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063402e1abf1461005c5780638c86f1e4146100a0578063b4d1d795146100e8578063c45a0155146100f0578063c640752d14610114575b600080fd5b6100826004803603602081101561007257600080fd5b50356001600160a01b0316610144565b60408051938452602084019290925282820152519081900360600190f35b6100d6600480360360608110156100b657600080fd5b506001600160a01b03813581169160208101359160409091013516610165565b60408051918252519081900360200190f35b6100d661029f565b6100f86102a5565b604080516001600160a01b039092168252519081900360200190f35b6101426004803603604081101561012a57600080fd5b506001600160a01b03813581169160200135166102c9565b005b60006020819052908152604090208054600182015460029092015490919083565b6000807f00000000000000000000000079855a03426e15ad120df77efa623af87bd54ef36001600160a01b031663e6a4390586856040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b1580156101e657600080fd5b505afa1580156101fa573d6000803e3d6000fd5b505050506040513d602081101561021057600080fd5b50516001600160a01b03811660009081526020819052604081208054929350914203908061023d856103ff565b5091509150600061024e8a896105ce565b509050896001600160a01b0316816001600160a01b031614156102885761027b856001015484868c6106ac565b9650505050505050610298565b61027b856002015483868c6106ac565b9392505050565b61038481565b7f00000000000000000000000079855a03426e15ad120df77efa623af87bd54ef381565b60007f00000000000000000000000079855a03426e15ad120df77efa623af87bd54ef36001600160a01b031663e6a4390584846040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b15801561034957600080fd5b505afa15801561035d573d6000803e3d6000fd5b505050506040513d602081101561037357600080fd5b50516001600160a01b038116600090815260208190526040902080549192509042036103848110156103d65760405162461bcd60e51b815260040180806020018281038252602881526020018061086f6028913960400191505060405180910390fd5b6000806103e2856103ff565b504286556001860191909155600290940193909355505050505050565b600080600061040c61070a565b9050836001600160a01b0316635909c0d56040518163ffffffff1660e01b815260040160206040518083038186803b15801561044757600080fd5b505afa15801561045b573d6000803e3d6000fd5b505050506040513d602081101561047157600080fd5b505160408051635a3d549360e01b815290519194506001600160a01b03861691635a3d549391600480820192602092909190829003018186803b1580156104b757600080fd5b505afa1580156104cb573d6000803e3d6000fd5b505050506040513d60208110156104e157600080fd5b505160408051630240bc6b60e21b81529051919350600091829182916001600160a01b03891691630902f1ac916004808301926060929190829003018186803b15801561052d57600080fd5b505afa158015610541573d6000803e3d6000fd5b505050506040513d606081101561055757600080fd5b5080516020820151604090920151909450909250905063ffffffff808216908516146105c45780840363ffffffff81166105918486610714565b516001600160e01b031602969096019563ffffffff81166105b28585610714565b516001600160e01b0316029590950194505b5050509193909250565b600080826001600160a01b0316846001600160a01b031614156106225760405162461bcd60e51b81526004018080602001828103825260228152602001806108976022913960400191505060405180910390fd5b826001600160a01b0316846001600160a01b031610610642578284610645565b83835b90925090506001600160a01b0382166106a5576040805162461bcd60e51b815260206004820152601b60248201527f4d6f6a69746f4c6962726172793a205a45524f5f414444524553530000000000604482015290519081900360640190fd5b9250929050565b60006106b6610849565b604051806020016040528085888803816106cc57fe5b046001600160e01b0316905290506106ec6106e782856107c4565b610842565b71ffffffffffffffffffffffffffffffffffff169695505050505050565b63ffffffff421690565b61071c610849565b6000826001600160701b03161161077a576040805162461bcd60e51b815260206004820152601760248201527f4669786564506f696e743a204449565f42595f5a45524f000000000000000000604482015290519081900360640190fd5b6040805160208101909152806001600160701b0384166dffffffffffffffffffffffffffff60701b607087901b16816107af57fe5b046001600160e01b0316815250905092915050565b6107cc61085b565b60008215806107f257505082516001600160e01b0316828102908382816107ef57fe5b04145b61082d5760405162461bcd60e51b81526004018080602001828103825260238152602001806108b96023913960400191505060405180910390fd5b60408051602081019091529081529392505050565b5160701c90565b60408051602081019091526000815290565b604051806020016040528060008152509056fe4d6f6a69746f4f7261636c653a3a7570646174653a20504552494f445f4e4f545f454c41505345444d6f6a69746f4c6962726172793a204944454e544943414c5f4144445245535345534669786564506f696e743a204d554c5449504c49434154494f4e5f4f564552464c4f57a264697066735822122045d219d952d8e717e2290fef89c28ce75078324f8bc091a63a0a6e51f765ee2964736f6c634300060c0033