文件 1 的 1:MostERC20.sol
pragma solidity >=0.6.2;
interface IMostERC20 {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
event LogRebase(uint indexed epoch, uint totalSupply);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function epoch() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function PERIOD() external pure returns (uint);
function pair() external view returns (address);
function rebaseSetter() external view returns (address);
function creator() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function price0CumulativeLast() external view returns (uint);
function price1CumulativeLast() external view returns (uint);
function blockTimestampLast() external view returns (uint32);
function initialize(address, address) external;
function rebase() external returns (uint);
function setRebaseSetter(address) external;
function setCreator(address) external;
function consult(address token, uint amountIn) external view returns (uint amountOut);
}
pragma solidity >=0.5.0;
interface IERC20 {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
}
pragma solidity >=0.5.0;
interface IUniswapV2Pair {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
event Mint(address indexed sender, uint amount0, uint amount1);
event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
event Swap(
address indexed sender,
uint amount0In,
uint amount1In,
uint amount0Out,
uint amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint);
function price1CumulativeLast() external view returns (uint);
function kLast() external view returns (uint);
function mint(address to) external returns (uint liquidity);
function burn(address to) external returns (uint amount0, uint amount1);
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
function skim(address to) external;
function sync() external;
function initialize(address, address) external;
}
pragma solidity >=0.4.0;
library FixedPoint {
struct uq112x112 {
uint224 _x;
}
struct uq144x112 {
uint _x;
}
uint8 private constant RESOLUTION = 112;
function encode(uint112 x) internal pure returns (uq112x112 memory) {
return uq112x112(uint224(x) << RESOLUTION);
}
function encode144(uint144 x) internal pure returns (uq144x112 memory) {
return uq144x112(uint256(x) << RESOLUTION);
}
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));
}
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);
}
function fraction(uint112 numerator, uint112 denominator) internal pure returns (uq112x112 memory) {
require(denominator > 0, "FixedPoint: DIV_BY_ZERO");
return uq112x112((uint224(numerator) << RESOLUTION) / denominator);
}
function decode(uq112x112 memory self) internal pure returns (uint112) {
return uint112(self._x >> RESOLUTION);
}
function decode144(uq144x112 memory self) internal pure returns (uint144) {
return uint144(self._x >> RESOLUTION);
}
}
pragma solidity >=0.5.0;
library UniswapV2OracleLibrary {
using FixedPoint for *;
function currentBlockTimestamp() internal view returns (uint32) {
return uint32(block.timestamp % 2 ** 32);
}
function currentCumulativePrices(
address pair
) internal view returns (uint price0Cumulative, uint price1Cumulative, uint32 blockTimestamp) {
blockTimestamp = currentBlockTimestamp();
price0Cumulative = IUniswapV2Pair(pair).price0CumulativeLast();
price1Cumulative = IUniswapV2Pair(pair).price1CumulativeLast();
(uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast) = IUniswapV2Pair(pair).getReserves();
if (blockTimestampLast != blockTimestamp) {
uint32 timeElapsed = blockTimestamp - blockTimestampLast;
price0Cumulative += uint(FixedPoint.fraction(reserve1, reserve0)._x) * timeElapsed;
price1Cumulative += uint(FixedPoint.fraction(reserve0, reserve1)._x) * timeElapsed;
}
}
}
pragma solidity =0.6.6;
library SafeMath {
function add(uint x, uint y) internal pure returns (uint z) {
require((z = x + y) >= x, 'ds-math-add-overflow');
}
function sub(uint x, uint y) internal pure returns (uint z) {
require((z = x - y) <= x, 'ds-math-sub-underflow');
}
function mul(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
}
function abs(int a) internal pure returns (int) {
require(a != int256(1) << 255, 'ds-math-mul-overflow');
return a < 0 ? -a : a;
}
}
pragma solidity >=0.5.0;
library UniswapV2Library {
using SafeMath for uint;
function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {
require(tokenA != tokenB, 'UniswapV2Library: IDENTICAL_ADDRESSES');
(token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
require(token0 != address(0), 'UniswapV2Library: ZERO_ADDRESS');
}
function pairFor(address factory, address tokenA, address tokenB) internal pure returns (address pair) {
(address token0, address token1) = sortTokens(tokenA, tokenB);
pair = address(uint(keccak256(abi.encodePacked(
hex'ff',
factory,
keccak256(abi.encodePacked(token0, token1)),
hex'96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f'
))));
}
function getReserves(address factory, address tokenA, address tokenB) internal view returns (uint reserveA, uint reserveB) {
(address token0,) = sortTokens(tokenA, tokenB);
(uint reserve0, uint reserve1,) = IUniswapV2Pair(pairFor(factory, tokenA, tokenB)).getReserves();
(reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
}
function quote(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint amountB) {
require(amountA > 0, 'UniswapV2Library: INSUFFICIENT_AMOUNT');
require(reserveA > 0 && reserveB > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
amountB = amountA.mul(reserveB) / reserveA;
}
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) {
require(amountIn > 0, 'UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT');
require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
uint amountInWithFee = amountIn.mul(997);
uint numerator = amountInWithFee.mul(reserveOut);
uint denominator = reserveIn.mul(1000).add(amountInWithFee);
amountOut = numerator / denominator;
}
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) internal pure returns (uint amountIn) {
require(amountOut > 0, 'UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT');
require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
uint numerator = reserveIn.mul(amountOut).mul(1000);
uint denominator = reserveOut.sub(amountOut).mul(997);
amountIn = (numerator / denominator).add(1);
}
function getAmountsOut(address factory, uint amountIn, address[] memory path) internal view returns (uint[] memory amounts) {
require(path.length >= 2, 'UniswapV2Library: INVALID_PATH');
amounts = new uint[](path.length);
amounts[0] = amountIn;
for (uint i; i < path.length - 1; i++) {
(uint reserveIn, uint reserveOut) = getReserves(factory, path[i], path[i + 1]);
amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);
}
}
function getAmountsIn(address factory, uint amountOut, address[] memory path) internal view returns (uint[] memory amounts) {
require(path.length >= 2, 'UniswapV2Library: INVALID_PATH');
amounts = new uint[](path.length);
amounts[amounts.length - 1] = amountOut;
for (uint i = path.length - 1; i > 0; i--) {
(uint reserveIn, uint reserveOut) = getReserves(factory, path[i - 1], path[i]);
amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);
}
}
}
pragma solidity =0.6.6;
contract MostERC20 is IMostERC20 {
using FixedPoint for *;
using SafeMath for uint;
using SafeMath for int;
string public constant override name = 'MOST';
string public constant override symbol = 'MOST';
uint8 public constant override decimals = 9;
uint public override totalSupply;
uint public override epoch;
mapping(address => uint) private gonBalanceOf;
mapping(address => mapping(address => uint)) public override allowance;
uint public constant override PERIOD = 24 hours;
uint private constant MAX_UINT256 = ~uint256(0);
uint private constant INITIAL_FRAGMENTS_SUPPLY = 1 * 10**6 * 10**uint(decimals);
uint8 private constant RATE_BASE = 100;
uint8 private constant UPPER_BOUND = 106;
uint8 private constant LOWER_BOUND = 96;
uint private constant TOTAL_GONS = MAX_UINT256 - (MAX_UINT256 % INITIAL_FRAGMENTS_SUPPLY);
uint private constant MAX_SUPPLY = ~uint128(0);
uint private gonsPerFragment;
address public override pair;
address public override rebaseSetter;
address public override creator;
address public override token0;
address public override token1;
uint public override price0CumulativeLast;
uint public override price1CumulativeLast;
uint32 public override blockTimestampLast;
FixedPoint.uq112x112 private price0Average;
FixedPoint.uq112x112 private price1Average;
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
event LogRebase(uint indexed epoch, uint totalSupply);
constructor() public {
creator = msg.sender;
totalSupply = INITIAL_FRAGMENTS_SUPPLY;
gonBalanceOf[msg.sender] = TOTAL_GONS;
gonsPerFragment = TOTAL_GONS / totalSupply;
emit Transfer(address(0), msg.sender, totalSupply);
}
function initialize(address factory, address tokenB) external override {
require(msg.sender == creator, 'MOST: FORBIDDEN');
IUniswapV2Pair _pair = IUniswapV2Pair(UniswapV2Library.pairFor(factory, address(this), tokenB));
pair = address(_pair);
token0 = _pair.token0();
token1 = _pair.token1();
price0CumulativeLast = _pair.price0CumulativeLast();
price1CumulativeLast = _pair.price1CumulativeLast();
uint112 reserve0;
uint112 reserve1;
(reserve0, reserve1, blockTimestampLast) = _pair.getReserves();
require(reserve0 != 0 && reserve1 != 0, 'MOST: NO_RESERVES');
}
function _approve(address owner, address spender, uint value) private {
allowance[owner][spender] = value;
emit Approval(owner, spender, value);
}
function _transfer(address from, address to, uint value) private {
uint gonValue = value.mul(gonsPerFragment);
gonBalanceOf[from] = gonBalanceOf[from].sub(gonValue);
gonBalanceOf[to] = gonBalanceOf[to].add(gonValue);
emit Transfer(from, to, value);
}
function balanceOf(address owner) external view override returns (uint) {
return gonBalanceOf[owner] / gonsPerFragment;
}
function approve(address spender, uint value) external override returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
function transfer(address to, uint value) external override returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
function transferFrom(address from, address to, uint value) external override returns (bool) {
if (allowance[from][msg.sender] != uint(-1)) {
allowance[from][msg.sender] = allowance[from][msg.sender].sub(value);
}
_transfer(from, to, value);
return true;
}
function rebase() external override returns (uint) {
require(msg.sender == rebaseSetter, 'MOST: FORBIDDEN');
(uint price0Cumulative, uint price1Cumulative, uint32 blockTimestamp) =
UniswapV2OracleLibrary.currentCumulativePrices(pair);
uint32 timeElapsed = blockTimestamp - blockTimestampLast;
require(timeElapsed >= PERIOD, 'MOST: PERIOD_NOT_ELAPSED');
epoch = epoch.add(1);
price0Average = FixedPoint.uq112x112(uint224((price0Cumulative - price0CumulativeLast) / timeElapsed));
price1Average = FixedPoint.uq112x112(uint224((price1Cumulative - price1CumulativeLast) / timeElapsed));
price0CumulativeLast = price0Cumulative;
price1CumulativeLast = price1Cumulative;
blockTimestampLast = blockTimestamp;
uint priceAverage = consult(address(this), 10**uint(decimals));
uint tokenBRemaining;
if (address(this) == token0) {
tokenBRemaining = 10 ** uint(IERC20(token1).decimals() - 2);
} else {
tokenBRemaining = 10 ** uint(IERC20(token0).decimals() - 2);
}
uint unitBase = RATE_BASE * tokenBRemaining;
int256 supplyDelta;
if (priceAverage > UPPER_BOUND * tokenBRemaining) {
supplyDelta = 0 - int(totalSupply.mul(priceAverage.sub(unitBase)) / priceAverage);
} else if (priceAverage < LOWER_BOUND * tokenBRemaining) {
supplyDelta = int(totalSupply.mul(unitBase.sub(priceAverage)) / unitBase);
} else {
supplyDelta = 0;
}
supplyDelta = supplyDelta / 10;
if (supplyDelta == 0) {
emit LogRebase(epoch, totalSupply);
return totalSupply;
}
if (supplyDelta < 0) {
totalSupply = totalSupply.sub(uint256(supplyDelta.abs()));
} else {
totalSupply = totalSupply.add(uint256(supplyDelta));
}
if (totalSupply > MAX_SUPPLY) {
totalSupply = MAX_SUPPLY;
}
gonsPerFragment = TOTAL_GONS / totalSupply;
emit LogRebase(epoch, totalSupply);
return totalSupply;
}
function setRebaseSetter(address _rebaseSetter) external override {
require(msg.sender == creator, 'MOST: FORBIDDEN');
rebaseSetter = _rebaseSetter;
}
function setCreator(address _creator) external override {
require(msg.sender == creator, 'MOST: FORBIDDEN');
creator = _creator;
}
function consult(address token, uint amountIn) public view override returns (uint amountOut) {
if (token == token0) {
amountOut = price0Average.mul(amountIn).decode144();
} else {
require(token == token1, 'MOST: INVALID_TOKEN');
amountOut = price1Average.mul(amountIn).decode144();
}
}
}