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