文件 1 的 1:FRTRebaser.sol
pragma solidity ^0.5.16;
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, 'SafeMath: addition overflow');
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, 'SafeMath: subtraction overflow');
}
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
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;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, 'SafeMath: division by zero');
}
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
}
interface IUniswapV2Pair {
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
event Transfer(address indexed from, address indexed to, uint256 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 (uint256);
function balanceOf(address owner) external view returns (uint256);
function allowance(address owner, address spender)
external
view
returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transfer(address to, uint256 value) external returns (bool);
function transferFrom(
address from,
address to,
uint256 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 (uint256);
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
event Mint(address indexed sender, uint256 amount0, uint256 amount1);
event Burn(
address indexed sender,
uint256 amount0,
uint256 amount1,
address indexed to
);
event Swap(
address indexed sender,
uint256 amount0In,
uint256 amount1In,
uint256 amount0Out,
uint256 amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint256);
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 (uint256);
function price1CumulativeLast() external view returns (uint256);
function kLast() external view returns (uint256);
function mint(address to) external returns (uint256 liquidity);
function burn(address to)
external
returns (uint256 amount0, uint256 amount1);
function swap(
uint256 amount0Out,
uint256 amount1Out,
address to,
bytes calldata data
) external;
function skim(address to) external;
function sync() external;
function initialize(address, address) external;
}
interface FRT {
function allowance(address owner, address spender)
external
view
returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function balanceOf(address account) external view returns (uint256);
function decimals() external view returns (uint8);
function decreaseAllowance(address spender, uint256 subtractedValue)
external
returns (bool);
function governance() external view returns (address);
function increaseAllowance(address spender, uint256 addedValue)
external
returns (bool);
function monetaryPolicy() external view returns (address);
function name() external view returns (string memory);
function rebase(uint256 epoch, int256 supplyDelta)
external
returns (uint256);
function setGovernance(address _governance) external;
function setMonetaryPolicy(address monetaryPolicy_) external;
function symbol() external view returns (string memory);
function totalSupply() external view returns (uint256);
function transfer(address recipient, uint256 amount)
external
returns (bool);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
}
interface FRTTreasury {
function sendReward(uint256 rate, address account) external;
}
contract FRTRebaser {
using SafeMath for uint256;
uint256 public constant PERIOD = 10 minutes;
IUniswapV2Pair public pair;
FRT public token;
FRTTreasury public treasury;
uint256 public starttime = 1606266000;
uint256 public price0CumulativeLast = 0;
uint32 public blockTimestampLast = 0;
uint224 public price0RawAverage = 0;
address public lastRebaser = 0x0000000000000000000000000000000000000000;
uint256 public epoch = 0;
constructor(address _pair, address _treasury) public {
pair = IUniswapV2Pair(_pair);
treasury = FRTTreasury(_treasury);
token = FRT(pair.token0());
price0CumulativeLast = pair.price0CumulativeLast();
uint112 reserve0;
uint112 reserve1;
(reserve0, reserve1, blockTimestampLast) = pair.getReserves();
require(reserve0 != 0 && reserve1 != 0, 'NO_RESERVES');
}
event LogRebase(uint indexed epoch, uint totalSupply, uint256 rand, address account);
uint256 private constant MAX_INT256 = ~(uint256(1) << 255);
function rebaseTime() public view returns (bool) {
return block.timestamp % 3600 < 3 * 60;
}
function toInt256Safe(uint256 a) internal pure returns (int256) {
require(a <= MAX_INT256);
return int256(a);
}
function hasFRT() private view returns (bool) {
if (token.balanceOf(msg.sender) > 0) {
return true;
} else {
return false;
}
}
function rand() private view returns (uint256) {
uint256 seed = uint256(
keccak256(
abi.encodePacked(
block.timestamp +
block.difficulty +
((
uint256(keccak256(abi.encodePacked(block.coinbase)))
) / (now)) +
block.gaslimit +
((uint256(keccak256(abi.encodePacked(msg.sender)))) /
(now)) +
block.number
)
)
);
if ((seed - ((seed / 10) * 10)) == 0 || (seed - ((seed / 10) * 10)) > 9 ) {
return 1;
} else {
return (seed - ((seed / 10) * 10));
}
}
function rebase() external {
require(block.timestamp > starttime, 'REBASE IS NOT ACTIVE YET');
require(lastRebaser != msg.sender, 'YOU_ALREADY_REBASED');
require(rebaseTime(), 'IS_NOT_TIME_TO_REBASE');
require(hasFRT(), 'YOU_DO_NOT_HOLD_FRT');
uint256 price0Cumulative = pair.price0CumulativeLast();
uint112 reserve0;
uint112 reserve1;
uint32 blockTimestamp;
(reserve0, reserve1, blockTimestamp) = pair.getReserves();
require(reserve0 != 0 && reserve1 != 0, 'NO_RESERVES');
uint32 timeElapsed = blockTimestamp - blockTimestampLast;
require(timeElapsed >= PERIOD, 'PERIOD_NOT_ELAPSED');
price0RawAverage = uint224(
(price0Cumulative - price0CumulativeLast) / timeElapsed
);
price0CumulativeLast = price0Cumulative;
blockTimestampLast = blockTimestamp;
uint256 price = price0RawAverage;
uint256 priceComp = 0;
price = price.mul(10**5).div(2**112);
priceComp = price.mul(10**3).div(2**112);
require(priceComp != 1000 || priceComp != 999, 'NO_NEED_TO_REBASE');
uint256 random = rand();
if (price > 100000) {
uint256 delta = price.sub(100000);
token.rebase(
epoch,
toInt256Safe(token.totalSupply().mul(delta).div(100000 * 10))
);
treasury.sendReward(random, msg.sender);
} else {
uint256 delta = 100000;
delta = delta.sub(price);
token.rebase(
epoch,
-toInt256Safe(token.totalSupply().mul(delta).div(100000 * 2))
);
treasury.sendReward(random, msg.sender);
}
pair.sync();
epoch = epoch.add(1);
lastRebaser = msg.sender;
emit LogRebase(epoch, token.totalSupply(), random, msg.sender);
}
}