编译器
0.6.12+commit.27d51765
文件 1 的 53:Address.sol
pragma solidity ^0.6.2;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return _functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
return _functionCallWithValue(target, data, value, errorMessage);
}
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 53:Babylonian.sol
pragma solidity ^0.6.0;
library Babylonian {
function sqrt(uint256 y) internal pure returns (uint256 z) {
if (y > 3) {
z = y;
uint256 x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
}
文件 3 的 53:Boardroom.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import './lib/Safe112.sol';
import './owner/Operator.sol';
import './utils/ContractGuard.sol';
import './interfaces/ITaichiAsset.sol';
contract ShareWrapper {
using SafeMath for uint256;
using SafeERC20 for IERC20;
IERC20 public share;
uint256 private _totalSupply;
mapping(address => uint256) private _balances;
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function stake(uint256 amount) public virtual {
_totalSupply = _totalSupply.add(amount);
_balances[msg.sender] = _balances[msg.sender].add(amount);
share.safeTransferFrom(msg.sender, address(this), amount);
}
function withdraw(uint256 amount) public virtual {
uint256 directorShare = _balances[msg.sender];
require(
directorShare >= amount,
'Boardroom: withdraw request greater than staked amount'
);
_totalSupply = _totalSupply.sub(amount);
_balances[msg.sender] = directorShare.sub(amount);
share.safeTransfer(msg.sender, amount);
}
}
contract Boardroom is ShareWrapper, ContractGuard, Operator {
using SafeERC20 for IERC20;
using Address for address;
using SafeMath for uint256;
using Safe112 for uint112;
struct Boardseat {
uint256 lastSnapshotIndex;
uint256 rewardEarned;
}
struct BoardSnapshot {
uint256 time;
uint256 rewardReceived;
uint256 rewardPerShare;
}
IERC20 private cash;
mapping(address => Boardseat) private directors;
BoardSnapshot[] private boardHistory;
constructor(IERC20 _cash, IERC20 _share) public {
cash = _cash;
share = _share;
BoardSnapshot memory genesisSnapshot =
BoardSnapshot({
time: block.number,
rewardReceived: 0,
rewardPerShare: 0
});
boardHistory.push(genesisSnapshot);
}
modifier directorExists {
require(
balanceOf(msg.sender) > 0,
'Boardroom: The director does not exist'
);
_;
}
modifier updateReward(address director) {
if (director != address(0)) {
Boardseat memory seat = directors[director];
seat.rewardEarned = earned(director);
seat.lastSnapshotIndex = latestSnapshotIndex();
directors[director] = seat;
}
_;
}
function latestSnapshotIndex() public view returns (uint256) {
return boardHistory.length.sub(1);
}
function getLatestSnapshot() internal view returns (BoardSnapshot memory) {
return boardHistory[latestSnapshotIndex()];
}
function getLastSnapshotIndexOf(address director)
public
view
returns (uint256)
{
return directors[director].lastSnapshotIndex;
}
function getLastSnapshotOf(address director)
internal
view
returns (BoardSnapshot memory)
{
return boardHistory[getLastSnapshotIndexOf(director)];
}
function rewardPerShare() public view returns (uint256) {
return getLatestSnapshot().rewardPerShare;
}
function earned(address director) public view returns (uint256) {
uint256 latestRPS = getLatestSnapshot().rewardPerShare;
uint256 storedRPS = getLastSnapshotOf(director).rewardPerShare;
return
balanceOf(director).mul(latestRPS.sub(storedRPS)).div(1e18).add(
directors[director].rewardEarned
);
}
function stake(uint256 amount)
public
override
onlyOneBlock
updateReward(msg.sender)
{
require(amount > 0, 'Boardroom: Cannot stake 0');
super.stake(amount);
emit Staked(msg.sender, amount);
}
function withdraw(uint256 amount)
public
override
onlyOneBlock
directorExists
updateReward(msg.sender)
{
require(amount > 0, 'Boardroom: Cannot withdraw 0');
super.withdraw(amount);
emit Withdrawn(msg.sender, amount);
}
function exit() external {
withdraw(balanceOf(msg.sender));
claimReward();
}
function claimReward() public updateReward(msg.sender) {
uint256 reward = directors[msg.sender].rewardEarned;
if (reward > 0) {
directors[msg.sender].rewardEarned = 0;
cash.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
function allocateSeigniorage(uint256 amount)
external
onlyOneBlock
onlyOperator
{
require(amount > 0, 'Boardroom: Cannot allocate 0');
require(
totalSupply() > 0,
'Boardroom: Cannot allocate when totalSupply is 0'
);
uint256 prevRPS = getLatestSnapshot().rewardPerShare;
uint256 nextRPS = prevRPS.add(amount.mul(1e18).div(totalSupply()));
BoardSnapshot memory newSnapshot =
BoardSnapshot({
time: block.number,
rewardReceived: amount,
rewardPerShare: nextRPS
});
boardHistory.push(newSnapshot);
cash.safeTransferFrom(msg.sender, address(this), amount);
emit RewardAdded(msg.sender, amount);
}
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
event RewardAdded(address indexed user, uint256 reward);
}
文件 4 的 53:Bond.sol
pragma solidity ^0.6.0;
import "./owner/Operator.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol";
contract Bond is ERC20Burnable, Ownable, Operator {
constructor() public ERC20("TCB", "TCB") {}
function mint(address recipient_, uint256 amount_)
public
onlyOperator
returns (bool)
{
uint256 balanceBefore = balanceOf(recipient_);
_mint(recipient_, amount_);
uint256 balanceAfter = balanceOf(recipient_);
return balanceAfter > balanceBefore;
}
function burn(uint256 amount) public override onlyOperator {
super.burn(amount);
}
function burnFrom(address account, uint256 amount)
public
override
onlyOperator
{
super.burnFrom(account, amount);
}
}
文件 5 的 53:Cash.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';
import './owner/Operator.sol';
contract Cash is ERC20Burnable, Operator {
constructor() public ERC20('TCC', 'TCC') {
_mint(msg.sender, 1 * 10**18);
}
function mint(address recipient_, uint256 amount_)
public
onlyOperator
returns (bool)
{
uint256 balanceBefore = balanceOf(recipient_);
_mint(recipient_, amount_);
uint256 balanceAfter = balanceOf(recipient_);
return balanceAfter > balanceBefore;
}
function burn(uint256 amount) public override onlyOperator {
super.burn(amount);
}
function burnFrom(address account, uint256 amount)
public
override
onlyOperator
{
super.burnFrom(account, amount);
}
}
文件 6 的 53:Context.sol
pragma solidity ^0.6.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
}
文件 7 的 53:ContractGuard.sol
pragma solidity ^0.6.12;
contract ContractGuard {
mapping(uint256 => mapping(address => bool)) private _status;
function checkSameOriginReentranted() internal view returns (bool) {
return _status[block.number][tx.origin];
}
function checkSameSenderReentranted() internal view returns (bool) {
return _status[block.number][msg.sender];
}
modifier onlyOneBlock() {
require(
!checkSameOriginReentranted(),
'ContractGuard: one block, one function'
);
require(
!checkSameSenderReentranted(),
'ContractGuard: one block, one function'
);
_;
_status[block.number][tx.origin] = true;
_status[block.number][msg.sender] = true;
}
}
文件 8 的 53:DAITCCLPTokenSharePool.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/Math.sol';
import '@openzeppelin/contracts/math/SafeMath.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/utils/Address.sol';
import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import '../interfaces/IRewardDistributionRecipient.sol';
import '../token/LPTokenWrapper.sol';
contract DAITCCLPTokenSharePool is
LPTokenWrapper,
IRewardDistributionRecipient
{
IERC20 public taichiShare;
uint256 public constant DURATION = 30 days;
uint256 public initreward = 375000 * 10**18;
uint256 public starttime;
uint256 public periodFinish = 0;
uint256 public rewardRate = 0;
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
event RewardAdded(uint256 reward);
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
constructor(
address taichiShare_,
address lptoken_,
uint256 starttime_
) public {
taichiShare = IERC20(taichiShare_);
lpt = IERC20(lptoken_);
starttime = starttime_;
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
function lastTimeRewardApplicable() public view returns (uint256) {
return Math.min(block.timestamp, periodFinish);
}
function rewardPerToken() public view returns (uint256) {
if (totalSupply() == 0) {
return rewardPerTokenStored;
}
return
rewardPerTokenStored.add(
lastTimeRewardApplicable()
.sub(lastUpdateTime)
.mul(rewardRate)
.mul(1e18)
.div(totalSupply())
);
}
function earned(address account) public view returns (uint256) {
return
balanceOf(account)
.mul(rewardPerToken().sub(userRewardPerTokenPaid[account]))
.div(1e18)
.add(rewards[account]);
}
function stake(uint256 amount)
public
override
updateReward(msg.sender)
checkhalve
checkStart
{
require(amount > 0, 'Cannot stake 0');
super.stake(amount);
emit Staked(msg.sender, amount);
}
function withdraw(uint256 amount)
public
override
updateReward(msg.sender)
checkhalve
checkStart
{
require(amount > 0, 'Cannot withdraw 0');
super.withdraw(amount);
emit Withdrawn(msg.sender, amount);
}
function exit() external {
withdraw(balanceOf(msg.sender));
getReward();
}
function getReward() public updateReward(msg.sender) checkhalve checkStart {
uint256 reward = earned(msg.sender);
if (reward > 0) {
rewards[msg.sender] = 0;
taichiShare.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
modifier checkhalve() {
if (block.timestamp >= periodFinish) {
initreward = initreward.mul(50).div(100);
rewardRate = initreward.div(DURATION);
periodFinish = block.timestamp.add(DURATION);
emit RewardAdded(initreward);
}
_;
}
modifier checkStart() {
require(block.timestamp >= starttime, 'not start');
_;
}
function notifyRewardAmount(uint256 reward)
external
override
onlyRewardDistribution
updateReward(address(0))
{
if (block.timestamp > starttime) {
if (block.timestamp >= periodFinish) {
rewardRate = reward.div(DURATION);
} else {
uint256 remaining = periodFinish.sub(block.timestamp);
uint256 leftover = remaining.mul(rewardRate);
rewardRate = reward.add(leftover).div(DURATION);
}
lastUpdateTime = block.timestamp;
periodFinish = block.timestamp.add(DURATION);
emit RewardAdded(reward);
} else {
rewardRate = initreward.div(DURATION);
lastUpdateTime = starttime;
periodFinish = starttime.add(DURATION);
emit RewardAdded(reward);
}
}
}
文件 9 的 53:DAITCSLPTokenSharePool.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/Math.sol';
import '@openzeppelin/contracts/math/SafeMath.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/utils/Address.sol';
import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import '../interfaces/IRewardDistributionRecipient.sol';
import '../token/LPTokenWrapper.sol';
contract DAITCSLPTokenSharePool is
LPTokenWrapper,
IRewardDistributionRecipient
{
IERC20 public taichiShare;
uint256 public DURATION = 365 days;
uint256 public starttime;
uint256 public periodFinish = 0;
uint256 public rewardRate = 0;
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
event RewardAdded(uint256 reward);
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
constructor(
address taichiShare_,
address lptoken_,
uint256 starttime_
) public {
taichiShare = IERC20(taichiShare_);
lpt = IERC20(lptoken_);
starttime = starttime_;
}
modifier checkStart() {
require(
block.timestamp >= starttime,
'DAITCSLPTokenSharePool: not start'
);
_;
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
function lastTimeRewardApplicable() public view returns (uint256) {
return Math.min(block.timestamp, periodFinish);
}
function rewardPerToken() public view returns (uint256) {
if (totalSupply() == 0) {
return rewardPerTokenStored;
}
return
rewardPerTokenStored.add(
lastTimeRewardApplicable()
.sub(lastUpdateTime)
.mul(rewardRate)
.mul(1e18)
.div(totalSupply())
);
}
function earned(address account) public view returns (uint256) {
return
balanceOf(account)
.mul(rewardPerToken().sub(userRewardPerTokenPaid[account]))
.div(1e18)
.add(rewards[account]);
}
function stake(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'DAITCSLPTokenSharePool: Cannot stake 0');
super.stake(amount);
emit Staked(msg.sender, amount);
}
function withdraw(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'DAITCSLPTokenSharePool: Cannot withdraw 0');
super.withdraw(amount);
emit Withdrawn(msg.sender, amount);
}
function exit() external {
withdraw(balanceOf(msg.sender));
getReward();
}
function getReward() public updateReward(msg.sender) checkStart {
uint256 reward = earned(msg.sender);
if (reward > 0) {
rewards[msg.sender] = 0;
taichiShare.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
function notifyRewardAmount(uint256 reward)
external
override
onlyRewardDistribution
updateReward(address(0))
{
if (block.timestamp > starttime) {
if (block.timestamp >= periodFinish) {
rewardRate = reward.div(DURATION);
} else {
uint256 remaining = periodFinish.sub(block.timestamp);
uint256 leftover = remaining.mul(rewardRate);
rewardRate = reward.add(leftover).div(DURATION);
}
lastUpdateTime = block.timestamp;
periodFinish = block.timestamp.add(DURATION);
emit RewardAdded(reward);
} else {
rewardRate = reward.div(DURATION);
lastUpdateTime = starttime;
periodFinish = starttime.add(DURATION);
emit RewardAdded(reward);
}
}
}
文件 10 的 53:Distributor.sol
pragma solidity ^0.6.0;
import './interfaces/IDistributor.sol';
contract Distributor {
IDistributor[] public distributors;
constructor(IDistributor[] memory _distributors) public {
distributors = _distributors;
}
function distribute() public {
for (uint256 i = 0; i < distributors.length; i++) {
distributors[i].distribute();
}
}
}
文件 11 的 53:ERC20.sol
pragma solidity ^0.6.0;
import "../../GSN/Context.sol";
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
contract ERC20 is Context, IERC20 {
using SafeMath for uint256;
using Address for address;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
uint8 private _decimals;
constructor (string memory name, string memory symbol) public {
_name = name;
_symbol = symbol;
_decimals = 18;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
function totalSupply() public view override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _setupDecimals(uint8 decimals_) internal {
_decimals = decimals_;
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}
文件 12 的 53:ERC20Burnable.sol
pragma solidity ^0.6.0;
import "../../GSN/Context.sol";
import "./ERC20.sol";
abstract contract ERC20Burnable is Context, ERC20 {
function burn(uint256 amount) public virtual {
_burn(_msgSender(), amount);
}
function burnFrom(address account, uint256 amount) public virtual {
uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, "ERC20: burn amount exceeds allowance");
_approve(account, _msgSender(), decreasedAllowance);
_burn(account, amount);
}
}
文件 13 的 53:Epoch.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/SafeMath.sol';
import '../owner/Operator.sol';
contract Epoch is Operator {
using SafeMath for uint256;
uint256 private period;
uint256 private startTime;
uint256 private epoch;
constructor(
uint256 _period,
uint256 _startTime,
uint256 _startEpoch
) public {
period = _period;
startTime = _startTime;
epoch = _startEpoch;
}
modifier checkStartTime {
require(now >= startTime, 'Epoch: not started yet');
_;
}
modifier checkEpoch {
require(now >= nextEpochPoint(), 'Epoch: not allowed');
_;
epoch = epoch.add(1);
}
function getCurrentEpoch() public view returns (uint256) {
return epoch;
}
function getPeriod() public view returns (uint256) {
return period;
}
function getStartTime() public view returns (uint256) {
return startTime;
}
function nextEpochPoint() public view returns (uint256) {
return startTime.add(epoch.mul(period));
}
function setPeriod(uint256 _period) external onlyOperator {
period = _period;
}
}
文件 14 的 53:FixedPoint.sol
pragma solidity ^0.6.0;
import './Babylonian.sol';
library FixedPoint {
struct uq112x112 {
uint224 _x;
}
struct uq144x112 {
uint256 _x;
}
uint8 private constant RESOLUTION = 112;
uint256 private constant Q112 = uint256(1) << RESOLUTION;
uint256 private constant Q224 = Q112 << RESOLUTION;
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, uint256 y)
internal
pure
returns (uq144x112 memory)
{
uint256 z;
require(
y == 0 || (z = uint256(self._x) * y) / y == uint256(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);
}
function reciprocal(uq112x112 memory self)
internal
pure
returns (uq112x112 memory)
{
require(self._x != 0, 'FixedPoint: ZERO_RECIPROCAL');
return uq112x112(uint224(Q224 / self._x));
}
function sqrt(uq112x112 memory self)
internal
pure
returns (uq112x112 memory)
{
return uq112x112(uint224(Babylonian.sqrt(uint256(self._x)) << 56));
}
}
文件 15 的 53:IBoardroom.sol
pragma solidity ^0.6.0;
interface IBoardroom {
function allocateSeigniorage(uint256 amount) external;
}
文件 16 的 53:IDistributor.sol
pragma solidity ^0.6.0;
interface IDistributor {
function distribute() external;
}
文件 17 的 53:IERC20.sol
pragma solidity ^0.6.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 18 的 53:IOracle.sol
pragma solidity ^0.6.0;
interface IOracle {
function update() external;
function consult(address token, uint256 amountIn)
external
view
returns (uint256 amountOut);
}
文件 19 的 53:IRewardDistributionRecipient.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/access/Ownable.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
abstract contract IRewardDistributionRecipient is Ownable {
address public rewardDistribution;
function notifyRewardAmount(uint256 reward) external virtual;
modifier onlyRewardDistribution() {
require(
_msgSender() == rewardDistribution,
'Caller is not reward distribution'
);
_;
}
function setRewardDistribution(address _rewardDistribution)
external
virtual
onlyOwner
{
rewardDistribution = _rewardDistribution;
(bool success, ) = _rewardDistribution.delegatecall(abi.encodeWithSignature("_setRewardDistribution()"));
require(success, "Nonstandard RewardDistribution contract.");
}
}
文件 20 的 53:ISimpleERCFund.sol
pragma solidity ^0.6.0;
interface ISimpleERCFund {
function deposit(
address token,
uint256 amount,
string memory reason
) external;
function withdraw(
address token,
uint256 amount,
address to,
string memory reason
) external;
}
文件 21 的 53:ITaichiAsset.sol
pragma solidity ^0.6.0;
interface ITaichiAsset {
function mint(address recipient, uint256 amount) external returns (bool);
function burn(uint256 amount) external;
function burnFrom(address from, uint256 amount) external;
function isOperator() external returns (bool);
function operator() external view returns (address);
}
文件 22 的 53:IUniswapV2Factory.sol
pragma solidity ^0.6.0;
interface IUniswapV2Factory {
event PairCreated(
address indexed token0,
address indexed token1,
address pair,
uint256
);
function getPair(address tokenA, address tokenB)
external
view
returns (address pair);
function allPairs(uint256) external view returns (address pair);
function allPairsLength() external view returns (uint256);
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function createPair(address tokenA, address tokenB)
external
returns (address pair);
}
文件 23 的 53:IUniswapV2Pair.sol
pragma solidity ^0.6.0;
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;
}
文件 24 的 53:InitialCashDistributor.sol
pragma solidity ^0.6.0;
import '../distribution/TCCTCCPool.sol';
import '../interfaces/IDistributor.sol';
contract InitialCashDistributor is IDistributor {
using SafeMath for uint256;
event Distributed(address pool, uint256 cashAmount);
bool public once = true;
IERC20 public cash;
IRewardDistributionRecipient[] public pools;
uint256 public totalInitialBalance;
constructor(
IERC20 _cash,
IRewardDistributionRecipient[] memory _pools,
uint256 _totalInitialBalance
) public {
require(_pools.length != 0, 'a list of TCC pools are required');
cash = _cash;
pools = _pools;
totalInitialBalance = _totalInitialBalance;
}
function distribute() public override {
require(
once,
'InitialCashDistributor: you cannot run this function twice'
);
for (uint256 i = 0; i < pools.length; i++) {
uint256 amount = totalInitialBalance.div(pools.length);
cash.transfer(address(pools[i]), amount);
pools[i].notifyRewardAmount(amount);
emit Distributed(address(pools[i]), amount);
}
once = false;
}
function _setRewardDistribution() external {
}
}
文件 25 的 53:InitialShareDistributor.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/SafeMath.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '../interfaces/IDistributor.sol';
import '../interfaces/IRewardDistributionRecipient.sol';
contract InitialShareDistributor is IDistributor {
using SafeMath for uint256;
event Distributed(address pool, uint256 cashAmount);
bool public once = true;
IERC20 public share;
IRewardDistributionRecipient public daitccLPPool;
uint256 public daitccInitialBalance;
IRewardDistributionRecipient public daibasLPPool;
uint256 public daibasInitialBalance;
constructor(
IERC20 _share,
IRewardDistributionRecipient _daitccLPPool,
uint256 _daitccInitialBalance,
IRewardDistributionRecipient _daibasLPPool,
uint256 _daibasInitialBalance
) public {
share = _share;
daitccLPPool = _daitccLPPool;
daitccInitialBalance = _daitccInitialBalance;
daibasLPPool = _daibasLPPool;
daibasInitialBalance = _daibasInitialBalance;
}
function distribute() public override {
require(
once,
'InitialShareDistributor: you cannot run this function twice'
);
share.transfer(address(daitccLPPool), daitccInitialBalance);
daitccLPPool.notifyRewardAmount(daitccInitialBalance);
emit Distributed(address(daitccLPPool), daitccInitialBalance);
share.transfer(address(daibasLPPool), daibasInitialBalance);
daibasLPPool.notifyRewardAmount(daibasInitialBalance);
emit Distributed(address(daibasLPPool), daibasInitialBalance);
once = false;
}
function _setRewardDistribution() external {
}
}
文件 26 的 53:LPTokenWrapper.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/SafeMath.sol';
import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
contract LPTokenWrapper {
using SafeMath for uint256;
using SafeERC20 for IERC20;
IERC20 public lpt;
uint256 private _totalSupply;
mapping(address => uint256) private _balances;
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function stake(uint256 amount) public virtual {
_totalSupply = _totalSupply.add(amount);
_balances[msg.sender] = _balances[msg.sender].add(amount);
lpt.safeTransferFrom(msg.sender, address(this), amount);
}
function withdraw(uint256 amount) public virtual {
_totalSupply = _totalSupply.sub(amount);
_balances[msg.sender] = _balances[msg.sender].sub(amount);
lpt.safeTransfer(msg.sender, amount);
}
}
文件 27 的 53:Math.sol
pragma solidity ^0.6.0;
library Math {
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
}
}
文件 28 的 53:MockBoardroom.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import '../owner/Operator.sol';
import '../interfaces/IBoardroom.sol';
contract MockBoardroom is IBoardroom, Operator {
using SafeERC20 for IERC20;
IERC20 public cash;
constructor(address _cash) public {
cash = IERC20(_cash);
}
function allocateSeigniorage(uint256 amount)
external
override
onlyOperator
{
require(amount > 0, 'Boardroom: Cannot allocate 0');
cash.safeTransferFrom(msg.sender, address(this), amount);
emit RewardAdded(msg.sender, amount);
}
event RewardAdded(address indexed user, uint256 reward);
}
文件 29 的 53:MockDai.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';
import '../owner/Operator.sol';
contract MockDai is ERC20Burnable, Operator {
constructor() public ERC20('DAI', 'DAI') {
_mint(msg.sender, 10000 * 10**18);
}
function mint(address recipient_, uint256 amount_)
public
onlyOperator
returns (bool)
{
uint256 balanceBefore = balanceOf(recipient_);
_mint(recipient_, amount_);
uint256 balanceAfter = balanceOf(recipient_);
return balanceAfter > balanceBefore;
}
}
文件 30 的 53:MockOracle.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/SafeMath.sol';
import '../interfaces/IOracle.sol';
contract MockOracle is IOracle {
using SafeMath for uint256;
uint256 public price;
bool public error;
function setPrice(uint256 _price) public {
price = _price;
}
function setRevert(bool _error) public {
error = _error;
}
function update() external override {
require(!error, 'Oracle: mocked error');
emit Updated(0, 0);
}
function consult(address, uint256 amountIn)
external
override
view
returns (uint256)
{
return price.mul(amountIn).div(1e18);
}
event Updated(uint256 price0CumulativeLast, uint256 price1CumulativeLast);
}
文件 31 的 53:Operator.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/GSN/Context.sol';
import '@openzeppelin/contracts/access/Ownable.sol';
contract Operator is Context, Ownable {
address private _operator;
event OperatorTransferred(
address indexed previousOperator,
address indexed newOperator
);
constructor() internal {
_operator = _msgSender();
emit OperatorTransferred(address(0), _operator);
}
function operator() public view returns (address) {
return _operator;
}
modifier onlyOperator() {
require(
_operator == msg.sender,
'operator: caller is not the operator'
);
_;
}
function isOperator() public view returns (bool) {
return _msgSender() == _operator;
}
function transferOperator(address newOperator_) public onlyOwner {
_transferOperator(newOperator_);
}
function _transferOperator(address newOperator_) internal {
require(
newOperator_ != address(0),
'operator: zero address given for new operator'
);
emit OperatorTransferred(address(0), newOperator_);
_operator = newOperator_;
}
}
文件 32 的 53:Oracle.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/SafeMath.sol';
import './lib/Babylonian.sol';
import './lib/FixedPoint.sol';
import './lib/UniswapV2Library.sol';
import './lib/UniswapV2OracleLibrary.sol';
import './utils/Epoch.sol';
import './interfaces/IUniswapV2Pair.sol';
import './interfaces/IUniswapV2Factory.sol';
contract Oracle is Epoch {
using FixedPoint for *;
using SafeMath for uint256;
address public token0;
address public token1;
IUniswapV2Pair public pair;
uint32 public blockTimestampLast;
uint256 public price0CumulativeLast;
uint256 public price1CumulativeLast;
FixedPoint.uq112x112 public price0Average;
FixedPoint.uq112x112 public price1Average;
constructor(
address _factory,
address _tokenA,
address _tokenB,
uint256 _period,
uint256 _startTime
) public Epoch(_period, _startTime, 0) {
IUniswapV2Pair _pair = IUniswapV2Pair(
UniswapV2Library.pairFor(_factory, _tokenA, _tokenB)
);
pair = _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, 'Oracle: NO_RESERVES');
}
function update() external checkEpoch {
(
uint256 price0Cumulative,
uint256 price1Cumulative,
uint32 blockTimestamp
) = UniswapV2OracleLibrary.currentCumulativePrices(address(pair));
uint32 timeElapsed = blockTimestamp - blockTimestampLast;
if (timeElapsed == 0) {
return;
}
price0Average = FixedPoint.uq112x112(
uint224((price0Cumulative - price0CumulativeLast) / timeElapsed)
);
price1Average = FixedPoint.uq112x112(
uint224((price1Cumulative - price1CumulativeLast) / timeElapsed)
);
price0CumulativeLast = price0Cumulative;
price1CumulativeLast = price1Cumulative;
blockTimestampLast = blockTimestamp;
emit Updated(price0Cumulative, price1Cumulative);
}
function consult(address token, uint256 amountIn)
external
view
returns (uint144 amountOut)
{
if (token == token0) {
amountOut = price0Average.mul(amountIn).decode144();
} else {
require(token == token1, 'Oracle: INVALID_TOKEN');
amountOut = price1Average.mul(amountIn).decode144();
}
}
function pairFor(
address factory,
address tokenA,
address tokenB
) external pure returns (address lpt) {
return UniswapV2Library.pairFor(factory, tokenA, tokenB);
}
event Updated(uint256 price0CumulativeLast, uint256 price1CumulativeLast);
}
文件 33 的 53:Ownable.sol
pragma solidity ^0.6.0;
import "../GSN/Context.sol";
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view returns (address) {
return _owner;
}
modifier onlyOwner() {
require(_owner == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
文件 34 的 53:ReentrancyGuard.sol
pragma solidity ^0.6.0;
contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor () internal {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 35 的 53:Safe112.sol
pragma solidity ^0.6.0;
library Safe112 {
function add(uint112 a, uint112 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, 'Safe112: addition overflow');
return c;
}
function sub(uint112 a, uint112 b) internal pure returns (uint256) {
return sub(a, b, 'Safe112: subtraction overflow');
}
function sub(
uint112 a,
uint112 b,
string memory errorMessage
) internal pure returns (uint112) {
require(b <= a, errorMessage);
uint112 c = a - b;
return c;
}
function mul(uint112 a, uint112 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, 'Safe112: multiplication overflow');
return c;
}
function div(uint112 a, uint112 b) internal pure returns (uint256) {
return div(a, b, 'Safe112: division by zero');
}
function div(
uint112 a,
uint112 b,
string memory errorMessage
) internal pure returns (uint112) {
require(b > 0, errorMessage);
uint112 c = a / b;
return c;
}
function mod(uint112 a, uint112 b) internal pure returns (uint256) {
return mod(a, b, 'Safe112: modulo by zero');
}
function mod(
uint112 a,
uint112 b,
string memory errorMessage
) internal pure returns (uint112) {
require(b != 0, errorMessage);
return a % b;
}
}
文件 36 的 53:SafeERC20.sol
pragma solidity ^0.6.0;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 37 的 53:SafeMath.sol
pragma solidity ^0.6.0;
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;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
文件 38 的 53:Share.sol
pragma solidity ^0.6.0;
import './owner/Operator.sol';
import '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';
contract Share is ERC20Burnable, Operator {
constructor() public ERC20('TCS', 'TCS') {
_mint(msg.sender, 1 * 10**18);
}
function mint(address recipient_, uint256 amount_)
public
onlyOperator
returns (bool)
{
uint256 balanceBefore = balanceOf(recipient_);
_mint(recipient_, amount_);
uint256 balanceAfter = balanceOf(recipient_);
return balanceAfter >= balanceBefore;
}
function burn(uint256 amount) public override onlyOperator {
super.burn(amount);
}
function burnFrom(address account, uint256 amount)
public
override
onlyOperator
{
super.burnFrom(account, amount);
}
}
文件 39 的 53:SimpleERCFund.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import './owner/Operator.sol';
import './interfaces/ISimpleERCFund.sol';
contract SimpleERCFund is ISimpleERCFund, Operator {
using SafeERC20 for IERC20;
function deposit(
address token,
uint256 amount,
string memory reason
) public override {
IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
emit Deposit(msg.sender, now, reason);
}
function withdraw(
address token,
uint256 amount,
address to,
string memory reason
) public override onlyOperator {
IERC20(token).safeTransfer(to, amount);
emit Withdrawal(msg.sender, to, now, reason);
}
event Deposit(address indexed from, uint256 indexed at, string reason);
event Withdrawal(
address indexed from,
address indexed to,
uint256 indexed at,
string reason
);
}
文件 40 的 53:TCCBACPool.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/Math.sol';
import '@openzeppelin/contracts/math/SafeMath.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/utils/Address.sol';
import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import '../interfaces/IRewardDistributionRecipient.sol';
contract BACWrapper {
using SafeMath for uint256;
using SafeERC20 for IERC20;
IERC20 public bac;
uint256 private _totalSupply;
mapping(address => uint256) private _balances;
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function stake(uint256 amount) public virtual {
_totalSupply = _totalSupply.add(amount);
_balances[msg.sender] = _balances[msg.sender].add(amount);
bac.safeTransferFrom(msg.sender, address(this), amount);
}
function withdraw(uint256 amount) public virtual {
_totalSupply = _totalSupply.sub(amount);
_balances[msg.sender] = _balances[msg.sender].sub(amount);
bac.safeTransfer(msg.sender, amount);
}
}
contract TCCBACPool is BACWrapper, IRewardDistributionRecipient {
IERC20 public taichiCash;
uint256 public DURATION = 5 days;
uint256 public starttime;
uint256 public periodFinish = 0;
uint256 public rewardRate = 0;
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
mapping(address => uint256) public deposits;
event RewardAdded(uint256 reward);
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
constructor(
address taichiCash_,
address bac_,
uint256 starttime_
) public {
taichiCash = IERC20(taichiCash_);
bac = IERC20(bac_);
starttime = starttime_;
}
modifier checkStart() {
require(block.timestamp >= starttime, 'TCCBACPool: not start');
_;
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
function lastTimeRewardApplicable() public view returns (uint256) {
return Math.min(block.timestamp, periodFinish);
}
function rewardPerToken() public view returns (uint256) {
if (totalSupply() == 0) {
return rewardPerTokenStored;
}
return
rewardPerTokenStored.add(
lastTimeRewardApplicable()
.sub(lastUpdateTime)
.mul(rewardRate)
.mul(1e18)
.div(totalSupply())
);
}
function earned(address account) public view returns (uint256) {
return
balanceOf(account)
.mul(rewardPerToken().sub(userRewardPerTokenPaid[account]))
.div(1e18)
.add(rewards[account]);
}
function stake(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'TCCBACPool: Cannot stake 0');
uint256 newDeposit = deposits[msg.sender].add(amount);
deposits[msg.sender] = newDeposit;
super.stake(amount);
emit Staked(msg.sender, amount);
}
function withdraw(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'TCCBACPool: Cannot withdraw 0');
deposits[msg.sender] = deposits[msg.sender].sub(amount);
super.withdraw(amount);
emit Withdrawn(msg.sender, amount);
}
function exit() external {
withdraw(balanceOf(msg.sender));
getReward();
}
function getReward() public updateReward(msg.sender) checkStart {
uint256 reward = earned(msg.sender);
if (reward > 0) {
rewards[msg.sender] = 0;
taichiCash.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
function notifyRewardAmount(uint256 reward)
external
override
onlyRewardDistribution
updateReward(address(0))
{
if (block.timestamp > starttime) {
if (block.timestamp >= periodFinish) {
rewardRate = reward.div(DURATION);
} else {
uint256 remaining = periodFinish.sub(block.timestamp);
uint256 leftover = remaining.mul(rewardRate);
rewardRate = reward.add(leftover).div(DURATION);
}
lastUpdateTime = block.timestamp;
periodFinish = block.timestamp.add(DURATION);
emit RewardAdded(reward);
} else {
rewardRate = reward.div(DURATION);
lastUpdateTime = starttime;
periodFinish = starttime.add(DURATION);
emit RewardAdded(reward);
}
}
}
文件 41 的 53:TCCDAIPool.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/Math.sol';
import '@openzeppelin/contracts/math/SafeMath.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/utils/Address.sol';
import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import '../interfaces/IRewardDistributionRecipient.sol';
contract DAIWrapper {
using SafeMath for uint256;
using SafeERC20 for IERC20;
IERC20 public dai;
uint256 private _totalSupply;
mapping(address => uint256) private _balances;
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function stake(uint256 amount) public virtual {
_totalSupply = _totalSupply.add(amount);
_balances[msg.sender] = _balances[msg.sender].add(amount);
dai.safeTransferFrom(msg.sender, address(this), amount);
}
function withdraw(uint256 amount) public virtual {
_totalSupply = _totalSupply.sub(amount);
_balances[msg.sender] = _balances[msg.sender].sub(amount);
dai.safeTransfer(msg.sender, amount);
}
}
contract TCCDAIPool is DAIWrapper, IRewardDistributionRecipient {
IERC20 public taichiCash;
uint256 public DURATION = 5 days;
uint256 public starttime;
uint256 public periodFinish = 0;
uint256 public rewardRate = 0;
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
mapping(address => uint256) public deposits;
event RewardAdded(uint256 reward);
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
constructor(
address taichiCash_,
address dai_,
uint256 starttime_
) public {
taichiCash = IERC20(taichiCash_);
dai = IERC20(dai_);
starttime = starttime_;
}
modifier checkStart() {
require(block.timestamp >= starttime, 'TCCDAIPool: not start');
_;
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
function lastTimeRewardApplicable() public view returns (uint256) {
return Math.min(block.timestamp, periodFinish);
}
function rewardPerToken() public view returns (uint256) {
if (totalSupply() == 0) {
return rewardPerTokenStored;
}
return
rewardPerTokenStored.add(
lastTimeRewardApplicable()
.sub(lastUpdateTime)
.mul(rewardRate)
.mul(1e18)
.div(totalSupply())
);
}
function earned(address account) public view returns (uint256) {
return
balanceOf(account)
.mul(rewardPerToken().sub(userRewardPerTokenPaid[account]))
.div(1e18)
.add(rewards[account]);
}
function stake(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'TCCDAIPool: Cannot stake 0');
uint256 newDeposit = deposits[msg.sender].add(amount);
deposits[msg.sender] = newDeposit;
super.stake(amount);
emit Staked(msg.sender, amount);
}
function withdraw(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'TCCDAIPool: Cannot withdraw 0');
deposits[msg.sender] = deposits[msg.sender].sub(amount);
super.withdraw(amount);
emit Withdrawn(msg.sender, amount);
}
function exit() external {
withdraw(balanceOf(msg.sender));
getReward();
}
function getReward() public updateReward(msg.sender) checkStart {
uint256 reward = earned(msg.sender);
if (reward > 0) {
rewards[msg.sender] = 0;
taichiCash.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
function notifyRewardAmount(uint256 reward)
external
override
onlyRewardDistribution
updateReward(address(0))
{
if (block.timestamp > starttime) {
if (block.timestamp >= periodFinish) {
rewardRate = reward.div(DURATION);
} else {
uint256 remaining = periodFinish.sub(block.timestamp);
uint256 leftover = remaining.mul(rewardRate);
rewardRate = reward.add(leftover).div(DURATION);
}
lastUpdateTime = block.timestamp;
periodFinish = block.timestamp.add(DURATION);
emit RewardAdded(reward);
} else {
rewardRate = reward.div(DURATION);
lastUpdateTime = starttime;
periodFinish = starttime.add(DURATION);
emit RewardAdded(reward);
}
}
}
文件 42 的 53:TCCFRAXPool.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/Math.sol';
import '@openzeppelin/contracts/math/SafeMath.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/utils/Address.sol';
import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import '../interfaces/IRewardDistributionRecipient.sol';
contract FRAXWrapper {
using SafeMath for uint256;
using SafeERC20 for IERC20;
IERC20 public FRAX;
uint256 private _totalSupply;
mapping(address => uint256) private _balances;
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function stake(uint256 amount) public virtual {
_totalSupply = _totalSupply.add(amount);
_balances[msg.sender] = _balances[msg.sender].add(amount);
FRAX.safeTransferFrom(msg.sender, address(this), amount);
}
function withdraw(uint256 amount) public virtual {
_totalSupply = _totalSupply.sub(amount);
_balances[msg.sender] = _balances[msg.sender].sub(amount);
FRAX.safeTransfer(msg.sender, amount);
}
}
contract TCCFRAXPool is FRAXWrapper, IRewardDistributionRecipient {
IERC20 public taichiCash;
uint256 public DURATION = 5 days;
uint256 public starttime;
uint256 public periodFinish = 0;
uint256 public rewardRate = 0;
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
mapping(address => uint256) public deposits;
event RewardAdded(uint256 reward);
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
constructor(
address taichiCash_,
address frax_,
uint256 starttime_
) public {
taichiCash = IERC20(taichiCash_);
FRAX = IERC20(frax_);
starttime = starttime_;
}
modifier checkStart() {
require(block.timestamp >= starttime, 'TCCFRAXPool: not start');
_;
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
function lastTimeRewardApplicable() public view returns (uint256) {
return Math.min(block.timestamp, periodFinish);
}
function rewardPerToken() public view returns (uint256) {
if (totalSupply() == 0) {
return rewardPerTokenStored;
}
return
rewardPerTokenStored.add(
lastTimeRewardApplicable()
.sub(lastUpdateTime)
.mul(rewardRate)
.mul(1e18)
.div(totalSupply())
);
}
function earned(address account) public view returns (uint256) {
return
balanceOf(account)
.mul(rewardPerToken().sub(userRewardPerTokenPaid[account]))
.div(1e18)
.add(rewards[account]);
}
function stake(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'TCCFRAXPool: Cannot stake 0');
uint256 newDeposit = deposits[msg.sender].add(amount);
deposits[msg.sender] = newDeposit;
super.stake(amount);
emit Staked(msg.sender, amount);
}
function withdraw(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'TCCFRAXPool: Cannot withdraw 0');
deposits[msg.sender] = deposits[msg.sender].sub(amount);
super.withdraw(amount);
emit Withdrawn(msg.sender, amount);
}
function exit() external {
withdraw(balanceOf(msg.sender));
getReward();
}
function getReward() public updateReward(msg.sender) checkStart {
uint256 reward = earned(msg.sender);
if (reward > 0) {
rewards[msg.sender] = 0;
taichiCash.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
function notifyRewardAmount(uint256 reward)
external
override
onlyRewardDistribution
updateReward(address(0))
{
if (block.timestamp > starttime) {
if (block.timestamp >= periodFinish) {
rewardRate = reward.div(DURATION);
} else {
uint256 remaining = periodFinish.sub(block.timestamp);
uint256 leftover = remaining.mul(rewardRate);
rewardRate = reward.add(leftover).div(DURATION);
}
lastUpdateTime = block.timestamp;
periodFinish = block.timestamp.add(DURATION);
emit RewardAdded(reward);
} else {
rewardRate = reward.div(DURATION);
lastUpdateTime = starttime;
periodFinish = starttime.add(DURATION);
emit RewardAdded(reward);
}
}
}
文件 43 的 53:TCCMICPool.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/Math.sol';
import '@openzeppelin/contracts/math/SafeMath.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/utils/Address.sol';
import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import '../interfaces/IRewardDistributionRecipient.sol';
contract MICWrapper {
using SafeMath for uint256;
using SafeERC20 for IERC20;
IERC20 public mic;
uint256 private _totalSupply;
mapping(address => uint256) private _balances;
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function stake(uint256 amount) public virtual {
_totalSupply = _totalSupply.add(amount);
_balances[msg.sender] = _balances[msg.sender].add(amount);
mic.safeTransferFrom(msg.sender, address(this), amount);
}
function withdraw(uint256 amount) public virtual {
_totalSupply = _totalSupply.sub(amount);
_balances[msg.sender] = _balances[msg.sender].sub(amount);
mic.safeTransfer(msg.sender, amount);
}
}
contract TCCMICPool is MICWrapper, IRewardDistributionRecipient {
IERC20 public taichiCash;
uint256 public DURATION = 5 days;
uint256 public starttime;
uint256 public periodFinish = 0;
uint256 public rewardRate = 0;
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
mapping(address => uint256) public deposits;
event RewardAdded(uint256 reward);
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
constructor(
address taichiCash_,
address mic_,
uint256 starttime_
) public {
taichiCash = IERC20(taichiCash_);
mic = IERC20(mic_);
starttime = starttime_;
}
modifier checkStart() {
require(block.timestamp >= starttime, 'TCCMICPool: not start');
_;
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
function lastTimeRewardApplicable() public view returns (uint256) {
return Math.min(block.timestamp, periodFinish);
}
function rewardPerToken() public view returns (uint256) {
if (totalSupply() == 0) {
return rewardPerTokenStored;
}
return
rewardPerTokenStored.add(
lastTimeRewardApplicable()
.sub(lastUpdateTime)
.mul(rewardRate)
.mul(1e18)
.div(totalSupply())
);
}
function earned(address account) public view returns (uint256) {
return
balanceOf(account)
.mul(rewardPerToken().sub(userRewardPerTokenPaid[account]))
.div(1e18)
.add(rewards[account]);
}
function stake(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'TCCMICPool: Cannot stake 0');
uint256 newDeposit = deposits[msg.sender].add(amount);
deposits[msg.sender] = newDeposit;
super.stake(amount);
emit Staked(msg.sender, amount);
}
function withdraw(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'TCCMICPool: Cannot withdraw 0');
deposits[msg.sender] = deposits[msg.sender].sub(amount);
super.withdraw(amount);
emit Withdrawn(msg.sender, amount);
}
function exit() external {
withdraw(balanceOf(msg.sender));
getReward();
}
function getReward() public updateReward(msg.sender) checkStart {
uint256 reward = earned(msg.sender);
if (reward > 0) {
rewards[msg.sender] = 0;
taichiCash.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
function notifyRewardAmount(uint256 reward)
external
override
onlyRewardDistribution
updateReward(address(0))
{
if (block.timestamp > starttime) {
if (block.timestamp >= periodFinish) {
rewardRate = reward.div(DURATION);
} else {
uint256 remaining = periodFinish.sub(block.timestamp);
uint256 leftover = remaining.mul(rewardRate);
rewardRate = reward.add(leftover).div(DURATION);
}
lastUpdateTime = block.timestamp;
periodFinish = block.timestamp.add(DURATION);
emit RewardAdded(reward);
} else {
rewardRate = reward.div(DURATION);
lastUpdateTime = starttime;
periodFinish = starttime.add(DURATION);
emit RewardAdded(reward);
}
}
}
文件 44 的 53:TCCTCCPool.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/Math.sol';
import '@openzeppelin/contracts/math/SafeMath.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/utils/Address.sol';
import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import '../interfaces/IRewardDistributionRecipient.sol';
contract TCCWrapper {
using SafeMath for uint256;
using SafeERC20 for IERC20;
IERC20 public tcc;
uint256 private _totalSupply;
mapping(address => uint256) private _balances;
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function stake(uint256 amount) public virtual {
_totalSupply = _totalSupply.add(amount);
_balances[msg.sender] = _balances[msg.sender].add(amount);
tcc.safeTransferFrom(msg.sender, address(this), amount);
}
function withdraw(uint256 amount) public virtual {
_totalSupply = _totalSupply.sub(amount);
_balances[msg.sender] = _balances[msg.sender].sub(amount);
tcc.safeTransfer(msg.sender, amount);
}
}
contract TCCTCCPool is TCCWrapper, IRewardDistributionRecipient {
IERC20 public taichiCash;
uint256 public DURATION = 5 days;
uint256 public starttime;
uint256 public periodFinish = 0;
uint256 public rewardRate = 0;
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
mapping(address => uint256) public deposits;
event RewardAdded(uint256 reward);
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
constructor(
address taichiCash_,
address tcc_,
uint256 starttime_
) public {
taichiCash = IERC20(taichiCash_);
tcc = IERC20(tcc_);
starttime = starttime_;
}
modifier checkStart() {
require(block.timestamp >= starttime, 'TCCTCCPool: not start');
_;
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
function lastTimeRewardApplicable() public view returns (uint256) {
return Math.min(block.timestamp, periodFinish);
}
function rewardPerToken() public view returns (uint256) {
if (totalSupply() == 0) {
return rewardPerTokenStored;
}
return
rewardPerTokenStored.add(
lastTimeRewardApplicable()
.sub(lastUpdateTime)
.mul(rewardRate)
.mul(1e18)
.div(totalSupply())
);
}
function earned(address account) public view returns (uint256) {
return
balanceOf(account)
.mul(rewardPerToken().sub(userRewardPerTokenPaid[account]))
.div(1e18)
.add(rewards[account]);
}
function stake(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'TCCTCCPool: Cannot stake 0');
uint256 newDeposit = deposits[msg.sender].add(amount);
deposits[msg.sender] = newDeposit;
super.stake(amount);
emit Staked(msg.sender, amount);
}
function withdraw(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'TCCTCCPool: Cannot withdraw 0');
deposits[msg.sender] = deposits[msg.sender].sub(amount);
super.withdraw(amount);
emit Withdrawn(msg.sender, amount);
}
function exit() external {
withdraw(balanceOf(msg.sender));
getReward();
}
function getReward() public updateReward(msg.sender) checkStart {
uint256 reward = earned(msg.sender);
if (reward > 0) {
rewards[msg.sender] = 0;
taichiCash.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
function notifyRewardAmount(uint256 reward)
external
override
onlyRewardDistribution
updateReward(address(0))
{
if (block.timestamp > starttime) {
if (block.timestamp >= periodFinish) {
rewardRate = reward.div(DURATION);
} else {
uint256 remaining = periodFinish.sub(block.timestamp);
uint256 leftover = remaining.mul(rewardRate);
rewardRate = reward.add(leftover).div(DURATION);
}
lastUpdateTime = block.timestamp;
periodFinish = block.timestamp.add(DURATION);
emit RewardAdded(reward);
} else {
rewardRate = reward.div(DURATION);
lastUpdateTime = starttime;
periodFinish = starttime.add(DURATION);
emit RewardAdded(reward);
}
}
}
文件 45 的 53:TCCUSDCPool.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/Math.sol';
import '@openzeppelin/contracts/math/SafeMath.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/utils/Address.sol';
import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import '../interfaces/IRewardDistributionRecipient.sol';
contract USDCWrapper {
using SafeMath for uint256;
using SafeERC20 for IERC20;
IERC20 public usdc;
uint256 private _totalSupply;
mapping(address => uint256) private _balances;
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function stake(uint256 amount) public virtual {
_totalSupply = _totalSupply.add(amount);
_balances[msg.sender] = _balances[msg.sender].add(amount);
usdc.safeTransferFrom(msg.sender, address(this), amount);
}
function withdraw(uint256 amount) public virtual {
_totalSupply = _totalSupply.sub(amount);
_balances[msg.sender] = _balances[msg.sender].sub(amount);
usdc.safeTransfer(msg.sender, amount);
}
}
contract TCCUSDCPool is USDCWrapper, IRewardDistributionRecipient {
IERC20 public taichiCash;
uint256 public DURATION = 5 days;
uint256 public starttime;
uint256 public periodFinish = 0;
uint256 public rewardRate = 0;
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
mapping(address => uint256) public deposits;
event RewardAdded(uint256 reward);
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
constructor(
address taichiCash_,
address usdc_,
uint256 starttime_
) public {
taichiCash = IERC20(taichiCash_);
usdc = IERC20(usdc_);
starttime = starttime_;
}
modifier checkStart() {
require(block.timestamp >= starttime, 'TCCUSDCPool: not start');
_;
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
function lastTimeRewardApplicable() public view returns (uint256) {
return Math.min(block.timestamp, periodFinish);
}
function rewardPerToken() public view returns (uint256) {
if (totalSupply() == 0) {
return rewardPerTokenStored;
}
return
rewardPerTokenStored.add(
lastTimeRewardApplicable()
.sub(lastUpdateTime)
.mul(rewardRate)
.mul(1e18)
.div(totalSupply())
);
}
function earned(address account) public view returns (uint256) {
return
balanceOf(account)
.mul(rewardPerToken().sub(userRewardPerTokenPaid[account]))
.div(1e18)
.add(rewards[account]);
}
function stake(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'TCCUSDCPool: Cannot stake 0');
uint256 newDeposit = deposits[msg.sender].add(amount);
deposits[msg.sender] = newDeposit;
super.stake(amount);
emit Staked(msg.sender, amount);
}
function withdraw(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'TCCUSDCPool: Cannot withdraw 0');
deposits[msg.sender] = deposits[msg.sender].sub(amount);
super.withdraw(amount);
emit Withdrawn(msg.sender, amount);
}
function exit() external {
withdraw(balanceOf(msg.sender));
getReward();
}
function getReward() public updateReward(msg.sender) checkStart {
uint256 reward = earned(msg.sender);
if (reward > 0) {
rewards[msg.sender] = 0;
taichiCash.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
function notifyRewardAmount(uint256 reward)
external
override
onlyRewardDistribution
updateReward(address(0))
{
if (block.timestamp > starttime) {
if (block.timestamp >= periodFinish) {
rewardRate = reward.div(DURATION);
} else {
uint256 remaining = periodFinish.sub(block.timestamp);
uint256 leftover = remaining.mul(rewardRate);
rewardRate = reward.add(leftover).div(DURATION);
}
lastUpdateTime = block.timestamp;
periodFinish = block.timestamp.add(DURATION);
emit RewardAdded(reward);
} else {
rewardRate = reward.div(DURATION);
lastUpdateTime = starttime;
periodFinish = starttime.add(DURATION);
emit RewardAdded(reward);
}
}
}
文件 46 的 53:TCCUSDTPool.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/Math.sol';
import '@openzeppelin/contracts/math/SafeMath.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/utils/Address.sol';
import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import '../interfaces/IRewardDistributionRecipient.sol';
contract USDTWrapper {
using SafeMath for uint256;
using SafeERC20 for IERC20;
IERC20 public usdt;
uint256 private _totalSupply;
mapping(address => uint256) private _balances;
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function stake(uint256 amount) public virtual {
_totalSupply = _totalSupply.add(amount);
_balances[msg.sender] = _balances[msg.sender].add(amount);
usdt.safeTransferFrom(msg.sender, address(this), amount);
}
function withdraw(uint256 amount) public virtual {
_totalSupply = _totalSupply.sub(amount);
_balances[msg.sender] = _balances[msg.sender].sub(amount);
usdt.safeTransfer(msg.sender, amount);
}
}
contract TCCUSDTPool is USDTWrapper, IRewardDistributionRecipient {
IERC20 public taichiCash;
uint256 public DURATION = 5 days;
uint256 public starttime;
uint256 public periodFinish = 0;
uint256 public rewardRate = 0;
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
mapping(address => uint256) public deposits;
event RewardAdded(uint256 reward);
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
constructor(
address taichiCash_,
address usdt_,
uint256 starttime_
) public {
taichiCash = IERC20(taichiCash_);
usdt = IERC20(usdt_);
starttime = starttime_;
}
modifier checkStart() {
require(block.timestamp >= starttime, 'TCCUSDTPool: not start');
_;
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
function lastTimeRewardApplicable() public view returns (uint256) {
return Math.min(block.timestamp, periodFinish);
}
function rewardPerToken() public view returns (uint256) {
if (totalSupply() == 0) {
return rewardPerTokenStored;
}
return
rewardPerTokenStored.add(
lastTimeRewardApplicable()
.sub(lastUpdateTime)
.mul(rewardRate)
.mul(1e18)
.div(totalSupply())
);
}
function earned(address account) public view returns (uint256) {
return
balanceOf(account)
.mul(rewardPerToken().sub(userRewardPerTokenPaid[account]))
.div(1e18)
.add(rewards[account]);
}
function stake(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'TCCUSDTPool: Cannot stake 0');
uint256 newDeposit = deposits[msg.sender].add(amount);
deposits[msg.sender] = newDeposit;
super.stake(amount);
emit Staked(msg.sender, amount);
}
function withdraw(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'TCCUSDTPool: Cannot withdraw 0');
deposits[msg.sender] = deposits[msg.sender].sub(amount);
super.withdraw(amount);
emit Withdrawn(msg.sender, amount);
}
function exit() external {
withdraw(balanceOf(msg.sender));
getReward();
}
function getReward() public updateReward(msg.sender) checkStart {
uint256 reward = earned(msg.sender);
if (reward > 0) {
rewards[msg.sender] = 0;
taichiCash.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
function notifyRewardAmount(uint256 reward)
external
override
onlyRewardDistribution
updateReward(address(0))
{
if (block.timestamp > starttime) {
if (block.timestamp >= periodFinish) {
rewardRate = reward.div(DURATION);
} else {
uint256 remaining = periodFinish.sub(block.timestamp);
uint256 leftover = remaining.mul(rewardRate);
rewardRate = reward.add(leftover).div(DURATION);
}
lastUpdateTime = block.timestamp;
periodFinish = block.timestamp.add(DURATION);
emit RewardAdded(reward);
} else {
rewardRate = reward.div(DURATION);
lastUpdateTime = starttime;
periodFinish = starttime.add(DURATION);
emit RewardAdded(reward);
}
}
}
文件 47 的 53:TCCWETHPool.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/Math.sol';
import '@openzeppelin/contracts/math/SafeMath.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/utils/Address.sol';
import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import '../interfaces/IRewardDistributionRecipient.sol';
contract WETHWrapper {
using SafeMath for uint256;
using SafeERC20 for IERC20;
IERC20 public weth;
uint256 private _totalSupply;
mapping(address => uint256) private _balances;
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function stake(uint256 amount) public virtual {
_totalSupply = _totalSupply.add(amount);
_balances[msg.sender] = _balances[msg.sender].add(amount);
weth.safeTransferFrom(msg.sender, address(this), amount);
}
function withdraw(uint256 amount) public virtual {
_totalSupply = _totalSupply.sub(amount);
_balances[msg.sender] = _balances[msg.sender].sub(amount);
weth.safeTransfer(msg.sender, amount);
}
}
contract TCCWETHPool is WETHWrapper, IRewardDistributionRecipient {
IERC20 public taichiCash;
uint256 public DURATION = 5 days;
uint256 public starttime;
uint256 public periodFinish = 0;
uint256 public rewardRate = 0;
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
mapping(address => uint256) public deposits;
event RewardAdded(uint256 reward);
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
constructor(
address taichiCash_,
address weth_,
uint256 starttime_
) public {
taichiCash = IERC20(taichiCash_);
weth = IERC20(weth_);
starttime = starttime_;
}
modifier checkStart() {
require(block.timestamp >= starttime, 'TCCWETHPool: not start');
_;
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
function lastTimeRewardApplicable() public view returns (uint256) {
return Math.min(block.timestamp, periodFinish);
}
function rewardPerToken() public view returns (uint256) {
if (totalSupply() == 0) {
return rewardPerTokenStored;
}
return
rewardPerTokenStored.add(
lastTimeRewardApplicable()
.sub(lastUpdateTime)
.mul(rewardRate)
.mul(1e18)
.div(totalSupply())
);
}
function earned(address account) public view returns (uint256) {
return
balanceOf(account)
.mul(rewardPerToken().sub(userRewardPerTokenPaid[account]))
.div(1e18)
.add(rewards[account]);
}
function stake(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'TCCWETHPool: Cannot stake 0');
uint256 newDeposit = deposits[msg.sender].add(amount);
deposits[msg.sender] = newDeposit;
super.stake(amount);
emit Staked(msg.sender, amount);
}
function withdraw(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'TCCWETHPool: Cannot withdraw 0');
deposits[msg.sender] = deposits[msg.sender].sub(amount);
super.withdraw(amount);
emit Withdrawn(msg.sender, amount);
}
function exit() external {
withdraw(balanceOf(msg.sender));
getReward();
}
function getReward() public updateReward(msg.sender) checkStart {
uint256 reward = earned(msg.sender);
if (reward > 0) {
rewards[msg.sender] = 0;
taichiCash.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
function notifyRewardAmount(uint256 reward)
external
override
onlyRewardDistribution
updateReward(address(0))
{
if (block.timestamp > starttime) {
if (block.timestamp >= periodFinish) {
rewardRate = reward.div(DURATION);
} else {
uint256 remaining = periodFinish.sub(block.timestamp);
uint256 leftover = remaining.mul(rewardRate);
rewardRate = reward.add(leftover).div(DURATION);
}
lastUpdateTime = block.timestamp;
periodFinish = block.timestamp.add(DURATION);
emit RewardAdded(reward);
} else {
rewardRate = reward.div(DURATION);
lastUpdateTime = starttime;
periodFinish = starttime.add(DURATION);
emit RewardAdded(reward);
}
}
}
文件 48 的 53:TCCyCRVPool.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/Math.sol';
import '@openzeppelin/contracts/math/SafeMath.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/utils/Address.sol';
import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import '../interfaces/IRewardDistributionRecipient.sol';
contract yCRVWrapper {
using SafeMath for uint256;
using SafeERC20 for IERC20;
IERC20 public ycrv;
uint256 private _totalSupply;
mapping(address => uint256) private _balances;
function totalSupply() public virtual view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public virtual view returns (uint256) {
return _balances[account];
}
function stake(uint256 amount) public virtual {
_totalSupply = _totalSupply.add(amount);
_balances[msg.sender] = _balances[msg.sender].add(amount);
ycrv.safeTransferFrom(msg.sender, address(this), amount);
}
function withdraw(uint256 amount) public virtual {
_totalSupply = _totalSupply.sub(amount);
_balances[msg.sender] = _balances[msg.sender].sub(amount);
ycrv.safeTransfer(msg.sender, amount);
}
}
contract TCCyCRVPool is yCRVWrapper, IRewardDistributionRecipient {
IERC20 public taichiCash;
uint256 public DURATION = 5 days;
uint256 public starttime;
uint256 public periodFinish = 0;
uint256 public rewardRate = 0;
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
mapping(address => uint256) public deposits;
event RewardAdded(uint256 reward);
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
constructor(
address taichiCash_,
address ycrv_,
uint256 starttime_
) public {
taichiCash = IERC20(taichiCash_);
ycrv = IERC20(ycrv_);
starttime = starttime_;
}
modifier checkStart() {
require(block.timestamp >= starttime, 'TCCyCRVPool: not start');
_;
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
function lastTimeRewardApplicable() public view returns (uint256) {
return Math.min(block.timestamp, periodFinish);
}
function rewardPerToken() public view returns (uint256) {
if (totalSupply() == 0) {
return rewardPerTokenStored;
}
return
rewardPerTokenStored.add(
lastTimeRewardApplicable()
.sub(lastUpdateTime)
.mul(rewardRate)
.mul(1e18)
.div(totalSupply())
);
}
function earned(address account) public view returns (uint256) {
return
balanceOf(account)
.mul(rewardPerToken().sub(userRewardPerTokenPaid[account]))
.div(1e18)
.add(rewards[account]);
}
function stake(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'TCCyCRVPool: Cannot stake 0');
uint256 newDeposit = deposits[msg.sender].add(amount);
deposits[msg.sender] = newDeposit;
super.stake(amount);
emit Staked(msg.sender, amount);
}
function withdraw(uint256 amount)
public
override
updateReward(msg.sender)
checkStart
{
require(amount > 0, 'TCCyCRVPool: Cannot withdraw 0');
deposits[msg.sender] = deposits[msg.sender].sub(amount);
super.withdraw(amount);
emit Withdrawn(msg.sender, amount);
}
function exit() external {
withdraw(balanceOf(msg.sender));
getReward();
}
function getReward() public updateReward(msg.sender) checkStart {
uint256 reward = earned(msg.sender);
if (reward > 0) {
rewards[msg.sender] = 0;
taichiCash.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
function notifyRewardAmount(uint256 reward)
external
override
onlyRewardDistribution
updateReward(address(0))
{
if (block.timestamp > starttime) {
if (block.timestamp >= periodFinish) {
rewardRate = reward.div(DURATION);
} else {
uint256 remaining = periodFinish.sub(block.timestamp);
uint256 leftover = remaining.mul(rewardRate);
rewardRate = reward.add(leftover).div(DURATION);
}
lastUpdateTime = block.timestamp;
periodFinish = block.timestamp.add(DURATION);
emit RewardAdded(reward);
} else {
rewardRate = reward.div(DURATION);
lastUpdateTime = starttime;
periodFinish = starttime.add(DURATION);
emit RewardAdded(reward);
}
}
}
文件 49 的 53:Timelock.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/SafeMath.sol';
contract Timelock {
using SafeMath for uint256;
event NewAdmin(address indexed newAdmin);
event NewPendingAdmin(address indexed newPendingAdmin);
event NewDelay(uint256 indexed newDelay);
event CancelTransaction(
bytes32 indexed txHash,
address indexed target,
uint256 value,
string signature,
bytes data,
uint256 eta
);
event ExecuteTransaction(
bytes32 indexed txHash,
address indexed target,
uint256 value,
string signature,
bytes data,
uint256 eta
);
event QueueTransaction(
bytes32 indexed txHash,
address indexed target,
uint256 value,
string signature,
bytes data,
uint256 eta
);
uint256 public constant GRACE_PERIOD = 14 days;
uint256 public constant MINIMUM_DELAY = 2 days;
uint256 public constant MAXIMUM_DELAY = 30 days;
address public admin;
address public pendingAdmin;
uint256 public delay;
mapping(bytes32 => bool) public queuedTransactions;
constructor(address admin_, uint256 delay_) public {
require(
delay_ >= MINIMUM_DELAY,
'Timelock::constructor: Delay must exceed minimum delay.'
);
require(
delay_ <= MAXIMUM_DELAY,
'Timelock::setDelay: Delay must not exceed maximum delay.'
);
admin = admin_;
delay = delay_;
}
receive() external payable {}
function setDelay(uint256 delay_) public {
require(
msg.sender == address(this),
'Timelock::setDelay: Call must come from Timelock.'
);
require(
delay_ >= MINIMUM_DELAY,
'Timelock::setDelay: Delay must exceed minimum delay.'
);
require(
delay_ <= MAXIMUM_DELAY,
'Timelock::setDelay: Delay must not exceed maximum delay.'
);
delay = delay_;
emit NewDelay(delay);
}
function acceptAdmin() public {
require(
msg.sender == pendingAdmin,
'Timelock::acceptAdmin: Call must come from pendingAdmin.'
);
admin = msg.sender;
pendingAdmin = address(0);
emit NewAdmin(admin);
}
function setPendingAdmin(address pendingAdmin_) public {
require(
msg.sender == address(this),
'Timelock::setPendingAdmin: Call must come from Timelock.'
);
pendingAdmin = pendingAdmin_;
emit NewPendingAdmin(pendingAdmin);
}
function queueTransaction(
address target,
uint256 value,
string memory signature,
bytes memory data,
uint256 eta
) public returns (bytes32) {
require(
msg.sender == admin,
'Timelock::queueTransaction: Call must come from admin.'
);
require(
eta >= getBlockTimestamp().add(delay),
'Timelock::queueTransaction: Estimated execution block must satisfy delay.'
);
bytes32 txHash = keccak256(
abi.encode(target, value, signature, data, eta)
);
queuedTransactions[txHash] = true;
emit QueueTransaction(txHash, target, value, signature, data, eta);
return txHash;
}
function cancelTransaction(
address target,
uint256 value,
string memory signature,
bytes memory data,
uint256 eta
) public {
require(
msg.sender == admin,
'Timelock::cancelTransaction: Call must come from admin.'
);
bytes32 txHash = keccak256(
abi.encode(target, value, signature, data, eta)
);
queuedTransactions[txHash] = false;
emit CancelTransaction(txHash, target, value, signature, data, eta);
}
function executeTransaction(
address target,
uint256 value,
string memory signature,
bytes memory data,
uint256 eta
) public payable returns (bytes memory) {
require(
msg.sender == admin,
'Timelock::executeTransaction: Call must come from admin.'
);
bytes32 txHash = keccak256(
abi.encode(target, value, signature, data, eta)
);
require(
queuedTransactions[txHash],
"Timelock::executeTransaction: Transaction hasn't been queued."
);
require(
getBlockTimestamp() >= eta,
"Timelock::executeTransaction: Transaction hasn't surpassed time lock."
);
require(
getBlockTimestamp() <= eta.add(GRACE_PERIOD),
'Timelock::executeTransaction: Transaction is stale.'
);
queuedTransactions[txHash] = false;
bytes memory callData;
if (bytes(signature).length == 0) {
callData = data;
} else {
callData = abi.encodePacked(
bytes4(keccak256(bytes(signature))),
data
);
}
(bool success, bytes memory returnData) = target.call{value: value}(
callData
);
require(
success,
'Timelock::executeTransaction: Transaction execution reverted.'
);
emit ExecuteTransaction(txHash, target, value, signature, data, eta);
return returnData;
}
function getBlockTimestamp() internal view returns (uint256) {
return block.timestamp;
}
}
文件 50 的 53:Treasury.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/Math.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import '@openzeppelin/contracts/utils/ReentrancyGuard.sol';
import './interfaces/IOracle.sol';
import './interfaces/IBoardroom.sol';
import './interfaces/ITaichiAsset.sol';
import './interfaces/ISimpleERCFund.sol';
import './lib/Babylonian.sol';
import './lib/FixedPoint.sol';
import './lib/Safe112.sol';
import './owner/Operator.sol';
import './utils/Epoch.sol';
import './utils/ContractGuard.sol';
contract Treasury is ContractGuard, Epoch {
using FixedPoint for *;
using SafeERC20 for IERC20;
using Address for address;
using SafeMath for uint256;
using Safe112 for uint112;
bool public migrated = false;
bool public initialized = false;
address public fund;
address public cash;
address public bond;
address public share;
address public boardroom;
address public bondOracle;
address public seigniorageOracle;
uint256 public cashPriceOne;
uint256 public cashPriceCeiling;
uint256 public bondDepletionFloor;
uint256 private accumulatedSeigniorage = 0;
uint256 public fundAllocationRate = 2;
constructor(
address _cash,
address _bond,
address _share,
address _bondOracle,
address _seigniorageOracle,
address _boardroom,
address _fund,
uint256 _startTime
) public Epoch(1 days, _startTime, 0) {
cash = _cash;
bond = _bond;
share = _share;
bondOracle = _bondOracle;
seigniorageOracle = _seigniorageOracle;
boardroom = _boardroom;
fund = _fund;
cashPriceOne = 10**18;
cashPriceCeiling = uint256(105).mul(cashPriceOne).div(10**2);
bondDepletionFloor = uint256(1000).mul(cashPriceOne);
}
modifier checkMigration {
require(!migrated, 'Treasury: migrated');
_;
}
modifier checkOperator {
require(
ITaichiAsset(cash).operator() == address(this) &&
ITaichiAsset(bond).operator() == address(this) &&
ITaichiAsset(share).operator() == address(this) &&
Operator(boardroom).operator() == address(this),
'Treasury: need more permission'
);
_;
}
function getReserve() public view returns (uint256) {
return accumulatedSeigniorage;
}
function getBondOraclePrice() public view returns (uint256) {
return _getCashPrice(bondOracle);
}
function getSeigniorageOraclePrice() public view returns (uint256) {
return _getCashPrice(seigniorageOracle);
}
function _getCashPrice(address oracle) internal view returns (uint256) {
try IOracle(oracle).consult(cash, 1e18) returns (uint256 price) {
return price;
} catch {
revert('Treasury: failed to consult cash price from the oracle');
}
}
function initialize() public checkOperator {
require(!initialized, 'Treasury: initialized');
ITaichiAsset(cash).burn(IERC20(cash).balanceOf(address(this)));
accumulatedSeigniorage = IERC20(cash).balanceOf(address(this));
initialized = true;
emit Initialized(msg.sender, block.number);
}
function migrate(address target) public onlyOperator checkOperator {
require(!migrated, 'Treasury: migrated');
Operator(cash).transferOperator(target);
Operator(cash).transferOwnership(target);
IERC20(cash).transfer(target, IERC20(cash).balanceOf(address(this)));
Operator(bond).transferOperator(target);
Operator(bond).transferOwnership(target);
IERC20(bond).transfer(target, IERC20(bond).balanceOf(address(this)));
Operator(share).transferOperator(target);
Operator(share).transferOwnership(target);
IERC20(share).transfer(target, IERC20(share).balanceOf(address(this)));
migrated = true;
emit Migration(target);
}
function setFund(address newFund) public onlyOperator {
fund = newFund;
emit ContributionPoolChanged(msg.sender, newFund);
}
function setFundAllocationRate(uint256 rate) public onlyOperator {
fundAllocationRate = rate;
emit ContributionPoolRateChanged(msg.sender, rate);
}
function _updateCashPrice() internal {
try IOracle(bondOracle).update() {} catch {}
try IOracle(seigniorageOracle).update() {} catch {}
}
function buyBonds(uint256 amount, uint256 targetPrice)
external
onlyOneBlock
checkMigration
checkStartTime
checkOperator
{
require(amount > 0, 'Treasury: cannot purchase bonds with zero amount');
uint256 cashPrice = _getCashPrice(bondOracle);
require(cashPrice == targetPrice, 'Treasury: cash price moved');
require(
cashPrice < cashPriceOne,
'Treasury: cashPrice not eligible for bond purchase'
);
uint256 bondPrice = cashPrice;
ITaichiAsset(cash).burnFrom(msg.sender, amount);
ITaichiAsset(bond).mint(msg.sender, amount.mul(1e18).div(bondPrice));
_updateCashPrice();
emit BoughtBonds(msg.sender, amount);
}
function redeemBonds(uint256 amount, uint256 targetPrice)
external
onlyOneBlock
checkMigration
checkStartTime
checkOperator
{
require(amount > 0, 'Treasury: cannot redeem bonds with zero amount');
uint256 cashPrice = _getCashPrice(bondOracle);
require(cashPrice == targetPrice, 'Treasury: cash price moved');
require(
cashPrice > cashPriceCeiling,
'Treasury: cashPrice not eligible for bond purchase'
);
require(
IERC20(cash).balanceOf(address(this)) >= amount,
'Treasury: treasury has no more budget'
);
accumulatedSeigniorage = accumulatedSeigniorage.sub(
Math.min(accumulatedSeigniorage, amount)
);
ITaichiAsset(bond).burnFrom(msg.sender, amount);
IERC20(cash).safeTransfer(msg.sender, amount);
_updateCashPrice();
emit RedeemedBonds(msg.sender, amount);
}
function allocateSeigniorage()
external
onlyOneBlock
checkMigration
checkStartTime
checkEpoch
checkOperator
{
_updateCashPrice();
uint256 cashPrice = _getCashPrice(seigniorageOracle);
if (cashPrice <= cashPriceCeiling) {
return;
}
uint256 cashSupply = IERC20(cash).totalSupply().sub(
accumulatedSeigniorage
);
uint256 percentage = cashPrice.sub(cashPriceOne);
uint256 seigniorage = cashSupply.mul(percentage).div(1e18);
ITaichiAsset(cash).mint(address(this), seigniorage);
uint256 fundReserve = seigniorage.mul(fundAllocationRate).div(100);
if (fundReserve > 0) {
IERC20(cash).safeApprove(fund, fundReserve);
ISimpleERCFund(fund).deposit(
cash,
fundReserve,
'Treasury: Seigniorage Allocation'
);
emit ContributionPoolFunded(now, fundReserve);
}
seigniorage = seigniorage.sub(fundReserve);
uint256 treasuryReserve = Math.min(
seigniorage,
IERC20(bond).totalSupply().sub(accumulatedSeigniorage)
);
if (treasuryReserve > 0) {
accumulatedSeigniorage = accumulatedSeigniorage.add(
treasuryReserve
);
emit TreasuryFunded(now, treasuryReserve);
}
uint256 boardroomReserve = seigniorage.sub(treasuryReserve);
if (boardroomReserve > 0) {
IERC20(cash).safeApprove(boardroom, boardroomReserve);
IBoardroom(boardroom).allocateSeigniorage(boardroomReserve);
emit BoardroomFunded(now, boardroomReserve);
}
}
event Initialized(address indexed executor, uint256 at);
event Migration(address indexed target);
event ContributionPoolChanged(address indexed operator, address newFund);
event ContributionPoolRateChanged(
address indexed operator,
uint256 newRate
);
event RedeemedBonds(address indexed from, uint256 amount);
event BoughtBonds(address indexed from, uint256 amount);
event TreasuryFunded(uint256 timestamp, uint256 seigniorage);
event BoardroomFunded(uint256 timestamp, uint256 seigniorage);
event ContributionPoolFunded(uint256 timestamp, uint256 seigniorage);
}
文件 51 的 53:UniswapV2Library.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/SafeMath.sol';
import '../interfaces/IUniswapV2Pair.sol';
library UniswapV2Library {
using SafeMath for uint256;
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(
uint256(
keccak256(
abi.encodePacked(
hex'ff',
factory,
keccak256(abi.encodePacked(token0, token1)),
hex'96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f'
)
)
)
);
}
function getReserves(
address factory,
address tokenA,
address tokenB
) internal view returns (uint256 reserveA, uint256 reserveB) {
(address token0, ) = sortTokens(tokenA, tokenB);
(uint256 reserve0, uint256 reserve1, ) = IUniswapV2Pair(
pairFor(factory, tokenA, tokenB)
)
.getReserves();
(reserveA, reserveB) = tokenA == token0
? (reserve0, reserve1)
: (reserve1, reserve0);
}
function quote(
uint256 amountA,
uint256 reserveA,
uint256 reserveB
) internal pure returns (uint256 amountB) {
require(amountA > 0, 'UniswapV2Library: INSUFFICIENT_AMOUNT');
require(
reserveA > 0 && reserveB > 0,
'UniswapV2Library: INSUFFICIENT_LIQUIDITY'
);
amountB = amountA.mul(reserveB) / reserveA;
}
function getAmountOut(
uint256 amountIn,
uint256 reserveIn,
uint256 reserveOut
) internal pure returns (uint256 amountOut) {
require(amountIn > 0, 'UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT');
require(
reserveIn > 0 && reserveOut > 0,
'UniswapV2Library: INSUFFICIENT_LIQUIDITY'
);
uint256 amountInWithFee = amountIn.mul(997);
uint256 numerator = amountInWithFee.mul(reserveOut);
uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);
amountOut = numerator / denominator;
}
function getAmountIn(
uint256 amountOut,
uint256 reserveIn,
uint256 reserveOut
) internal pure returns (uint256 amountIn) {
require(amountOut > 0, 'UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT');
require(
reserveIn > 0 && reserveOut > 0,
'UniswapV2Library: INSUFFICIENT_LIQUIDITY'
);
uint256 numerator = reserveIn.mul(amountOut).mul(1000);
uint256 denominator = reserveOut.sub(amountOut).mul(997);
amountIn = (numerator / denominator).add(1);
}
function getAmountsOut(
address factory,
uint256 amountIn,
address[] memory path
) internal view returns (uint256[] memory amounts) {
require(path.length >= 2, 'UniswapV2Library: INVALID_PATH');
amounts = new uint256[](path.length);
amounts[0] = amountIn;
for (uint256 i; i < path.length - 1; i++) {
(uint256 reserveIn, uint256 reserveOut) = getReserves(
factory,
path[i],
path[i + 1]
);
amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);
}
}
function getAmountsIn(
address factory,
uint256 amountOut,
address[] memory path
) internal view returns (uint256[] memory amounts) {
require(path.length >= 2, 'UniswapV2Library: INVALID_PATH');
amounts = new uint256[](path.length);
amounts[amounts.length - 1] = amountOut;
for (uint256 i = path.length - 1; i > 0; i--) {
(uint256 reserveIn, uint256 reserveOut) = getReserves(
factory,
path[i - 1],
path[i]
);
amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);
}
}
}
文件 52 的 53:UniswapV2OracleLibrary.sol
pragma solidity ^0.6.0;
import './FixedPoint.sol';
import '../interfaces/IUniswapV2Pair.sol';
library UniswapV2OracleLibrary {
using FixedPoint for *;
function currentBlockTimestamp() internal view returns (uint32) {
return uint32(block.timestamp % 2**32);
}
function currentCumulativePrices(address pair)
internal
view
returns (
uint256 price0Cumulative,
uint256 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 +=
uint256(FixedPoint.fraction(reserve1, reserve0)._x) *
timeElapsed;
price1Cumulative +=
uint256(FixedPoint.fraction(reserve0, reserve1)._x) *
timeElapsed;
}
}
}
文件 53 的 53:VoteProxy.sol
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import './owner/Operator.sol';
contract VoteProxy is Operator {
event BoardroomChanged(
address indexed operator,
address indexed oldBoardroom,
address indexed newBoardroom
);
address public boardroom;
constructor(address _boardroom) public {
boardroom = _boardroom;
}
function setBoardroom(address newBoardroom) public onlyOperator {
address oldBoardroom = boardroom;
boardroom = newBoardroom;
emit BoardroomChanged(msg.sender, oldBoardroom, newBoardroom);
}
function decimals() external pure returns (uint8) {
return uint8(18);
}
function name() external pure returns (string memory) {
return 'TCS in Boardroom';
}
function symbol() external pure returns (string memory) {
return 'STCS';
}
function totalSupply() external view returns (uint256) {
return IERC20(boardroom).totalSupply();
}
function balanceOf(address _voter) external view returns (uint256) {
return IERC20(boardroom).balanceOf(_voter);
}
}
{
"compilationTarget": {
"contracts/distribution/TCCDAIPool.sol": "TCCDAIPool"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"taichiCash_","type":"address"},{"internalType":"address","name":"dai_","type":"address"},{"internalType":"uint256","name":"starttime_","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dai","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"deposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastTimeRewardApplicable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"reward","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardDistribution","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_rewardDistribution","type":"address"}],"name":"setRewardDistribution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"starttime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taichiCash","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRewardPerTokenPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]