编译器
0.6.11+commit.5ef660b1
文件 1 的 71:AccessControl.sol
pragma solidity >=0.6.0 <0.8.0;
import "../utils/EnumerableSet.sol";
import "../utils/Address.sol";
import "../utils/Context.sol";
abstract contract AccessControl is Context {
using EnumerableSet for EnumerableSet.AddressSet;
using Address for address;
struct RoleData {
EnumerableSet.AddressSet members;
bytes32 adminRole;
}
mapping (bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function hasRole(bytes32 role, address account) public view returns (bool) {
return _roles[role].members.contains(account);
}
function getRoleMemberCount(bytes32 role) public view returns (uint256) {
return _roles[role].members.length();
}
function getRoleMember(bytes32 role, uint256 index) public view returns (address) {
return _roles[role].members.at(index);
}
function getRoleAdmin(bytes32 role) public view returns (bytes32) {
return _roles[role].adminRole;
}
function grantRole(bytes32 role, address account) public virtual {
require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant");
_grantRole(role, account);
}
function revokeRole(bytes32 role, address account) public virtual {
require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke");
_revokeRole(role, account);
}
function renounceRole(bytes32 role, address account) public virtual {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);
_roles[role].adminRole = adminRole;
}
function _grantRole(bytes32 role, address account) private {
if (_roles[role].members.add(account)) {
emit RoleGranted(role, account, _msgSender());
}
}
function _revokeRole(bytes32 role, address account) private {
if (_roles[role].members.remove(account)) {
emit RoleRevoked(role, account, _msgSender());
}
}
}
文件 2 的 71:AccessControlUpgradeable.sol
pragma solidity >=0.6.0 <0.8.0;
import "../utils/EnumerableSetUpgradeable.sol";
import "../utils/AddressUpgradeable.sol";
import "../utils/ContextUpgradeable.sol";
import "../proxy/Initializable.sol";
abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable {
function __AccessControl_init() internal initializer {
__Context_init_unchained();
__AccessControl_init_unchained();
}
function __AccessControl_init_unchained() internal initializer {
}
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;
using AddressUpgradeable for address;
struct RoleData {
EnumerableSetUpgradeable.AddressSet members;
bytes32 adminRole;
}
mapping (bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function hasRole(bytes32 role, address account) public view returns (bool) {
return _roles[role].members.contains(account);
}
function getRoleMemberCount(bytes32 role) public view returns (uint256) {
return _roles[role].members.length();
}
function getRoleMember(bytes32 role, uint256 index) public view returns (address) {
return _roles[role].members.at(index);
}
function getRoleAdmin(bytes32 role) public view returns (bytes32) {
return _roles[role].adminRole;
}
function grantRole(bytes32 role, address account) public virtual {
require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant");
_grantRole(role, account);
}
function revokeRole(bytes32 role, address account) public virtual {
require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke");
_revokeRole(role, account);
}
function renounceRole(bytes32 role, address account) public virtual {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);
_roles[role].adminRole = adminRole;
}
function _grantRole(bytes32 role, address account) private {
if (_roles[role].members.add(account)) {
emit RoleGranted(role, account, _msgSender());
}
}
function _revokeRole(bytes32 role, address account) private {
if (_roles[role].members.remove(account)) {
emit RoleRevoked(role, account, _msgSender());
}
}
uint256[49] private __gap;
}
文件 3 的 71:Address.sol
pragma solidity >=0.6.2 <0.8.0;
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");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 4 的 71:AddressUpgradeable.sol
pragma solidity >=0.6.2 <0.8.0;
library AddressUpgradeable {
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");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 5 的 71:AggregatorV3Interface.sol
pragma solidity >=0.6.0;
interface AggregatorV3Interface {
function decimals() external view returns (uint8);
function description() external view returns (string memory);
function version() external view returns (uint256);
function getRoundData(uint80 _roundId)
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}
文件 6 的 71:AirdropPush.sol
pragma solidity 0.6.11;
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract AirdropPush {
using SafeERC20 for IERC20;
function distribute(
IERC20 token,
address[] calldata accounts,
uint256[] calldata amounts
) external {
require(accounts.length == amounts.length, "LENGTH_MISMATCH");
for (uint256 i = 0; i < accounts.length; i++) {
token.safeTransferFrom(msg.sender, accounts[i], amounts[i]);
}
}
}
文件 7 的 71:BalancerController.sol
pragma solidity 0.6.11;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "../interfaces/balancer/IBalancerPool.sol";
contract BalancerController {
using SafeERC20 for IERC20;
using Address for address;
using Address for address payable;
using SafeMath for uint256;
function deploy(
address poolAddress,
IERC20[] calldata tokens,
uint256[] calldata amounts,
bytes calldata data
) external {
require(tokens.length == amounts.length, "TOKEN_AMOUNTS_COUNT_MISMATCH");
require(tokens.length > 0, "TOKENS_AMOUNTS_NOT_PROVIDED");
for (uint256 i = 0; i < tokens.length; i++) {
_approve(tokens[i], poolAddress, amounts[i]);
}
(uint256 poolAmountOut, uint256[] memory maxAmountsIn) =
abi.decode(data, (uint256, uint256[]));
IBalancerPool(poolAddress).joinPool(poolAmountOut, maxAmountsIn);
}
function withdraw(address poolAddress, bytes calldata data) external {
(uint256 poolAmountIn, uint256[] memory minAmountsOut) =
abi.decode(data, (uint256, uint256[]));
_approve(IERC20(poolAddress), poolAddress, poolAmountIn);
IBalancerPool(poolAddress).exitPool(poolAmountIn, minAmountsOut);
}
function _approve(
IERC20 token,
address poolAddress,
uint256 amount
) internal {
uint256 currentAllowance = token.allowance(address(this), poolAddress);
if (currentAllowance < amount) {
token.safeIncreaseAllowance(poolAddress, type(uint256).max.sub(currentAllowance));
}
}
}
文件 8 的 71:Context.sol
pragma solidity >=0.6.0 <0.8.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;
}
}
文件 9 的 71:ContextUpgradeable.sol
pragma solidity >=0.6.0 <0.8.0;
import "../proxy/Initializable.sol";
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal initializer {
__Context_init_unchained();
}
function __Context_init_unchained() internal initializer {
}
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
uint256[50] private __gap;
}
文件 10 的 71:CoreEvent.sol
pragma solidity 0.6.11;
pragma experimental ABIEncoderV2;
import "../interfaces/ICoreEvent.sol";
import "../interfaces/ILiquidityPool.sol";
import "@openzeppelin/contracts/math/Math.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/utils/EnumerableSet.sol";
import "@openzeppelin/contracts/cryptography/MerkleProof.sol";
contract CoreEvent is Ownable, ICoreEvent {
using SafeMath for uint256;
using SafeERC20 for IERC20;
using Address for address;
using EnumerableSet for EnumerableSet.AddressSet;
DurationInfo public durationInfo;
address public immutable treasuryAddress;
EnumerableSet.AddressSet private supportedTokenAddresses;
mapping(address => SupportedTokenData) public supportedTokens;
mapping(address => mapping(address => AccountData)) public accountData;
mapping(address => RateData) public tokenRates;
WhitelistSettings public whitelistSettings;
bool public stage1Locked;
modifier hasEnded() {
require(_hasEnded(), "TOO_EARLY");
_;
}
constructor(
address treasury,
SupportedTokenData[] memory tokensToSupport
) public {
treasuryAddress = treasury;
addSupportedTokens(tokensToSupport);
}
function configureWhitelist(WhitelistSettings memory settings) external override onlyOwner {
whitelistSettings = settings;
emit WhitelistConfigured(settings);
}
function setDuration(uint256 _blockDuration) external override onlyOwner {
require(durationInfo.startingBlock == 0, "ALREADY_STARTED");
durationInfo.startingBlock = block.number;
durationInfo.blockDuration = _blockDuration;
emit DurationSet(durationInfo);
}
function addSupportedTokens(SupportedTokenData[] memory tokensToSupport) public override onlyOwner {
require (tokensToSupport.length > 0, "NO_TOKENS");
for (uint256 i = 0; i < tokensToSupport.length; i++) {
require(
!supportedTokenAddresses.contains(tokensToSupport[i].token),
"DUPLICATE_TOKEN"
);
require(tokensToSupport[i].token != address(0), "ZERO_ADDRESS");
require(!tokensToSupport[i].systemFinalized, "FINALIZED_MUST_BE_FALSE");
supportedTokenAddresses.add(tokensToSupport[i].token);
supportedTokens[tokensToSupport[i].token] = tokensToSupport[i];
}
emit SupportedTokensAdded(tokensToSupport);
}
function deposit(TokenData[] calldata tokenData, bytes32[] calldata proof) external override {
require(durationInfo.startingBlock > 0, "NOT_STARTED");
require(!_hasEnded(), "RATES_LOCKED");
require(tokenData.length > 0, "NO_TOKENS");
if (whitelistSettings.enabled) {
require(verifyDepositor(msg.sender, whitelistSettings.root, proof), "PROOF_INVALID");
}
for (uint256 i = 0; i < tokenData.length; i++) {
uint256 amount = tokenData[i].amount;
require(amount > 0, "0_BALANCE");
address token = tokenData[i].token;
require(supportedTokenAddresses.contains(token), "NOT_SUPPORTED");
IERC20 erc20Token = IERC20(token);
AccountData storage data = accountData[msg.sender][token];
require(
data.depositedBalance.add(amount) <= supportedTokens[token].maxUserLimit,
"OVER_LIMIT"
);
data.depositedBalance = data.depositedBalance.add(amount);
data.token = token;
erc20Token.safeTransferFrom(msg.sender, address(this), amount);
}
emit Deposited(msg.sender, tokenData);
}
function withdraw(TokenData[] calldata tokenData) external override {
require(!_hasEnded(), "RATES_LOCKED");
require(tokenData.length > 0, "NO_TOKENS");
for (uint256 i = 0; i < tokenData.length; i++) {
uint256 amount = tokenData[i].amount;
require(amount > 0, "ZERO_BALANCE");
address token = tokenData[i].token;
IERC20 erc20Token = IERC20(token);
AccountData storage data = accountData[msg.sender][token];
require(data.token != address(0), "ZERO_ADDRESS");
require(amount <= data.depositedBalance, "INSUFFICIENT_FUNDS");
data.depositedBalance = data.depositedBalance.sub(amount);
if (data.depositedBalance == 0) {
delete accountData[msg.sender][token];
}
erc20Token.safeTransfer(msg.sender, amount);
}
emit Withdrawn(msg.sender, tokenData);
}
function increaseDuration(uint256 _blockDuration) external override onlyOwner {
require(durationInfo.startingBlock > 0, "NOT_STARTED");
require(_blockDuration > durationInfo.blockDuration, "INCREASE_ONLY");
require(!stage1Locked, "STAGE1_LOCKED");
durationInfo.blockDuration = _blockDuration;
emit DurationIncreased(durationInfo);
}
function setRates(RateData[] calldata rates) external override onlyOwner hasEnded {
uint256 length = rates.length;
for (uint256 i = 0; i < length; i++) {
RateData memory data = rates[i];
require(supportedTokenAddresses.contains(data.token), "UNSUPPORTED_ADDRESS");
require(!supportedTokens[data.token].systemFinalized, "ALREADY_FINALIZED");
if (data.tokeNumerator > 0) {
require(data.tokeDenominator > 0, "INVALID_TOKE_DENOMINATOR");
require(data.overNumerator > 0, "INVALID_OVER_NUMERATOR");
require(data.overDenominator > 0, "INVALID_OVER_DENOMINATOR");
tokenRates[data.token] = data;
} else {
delete tokenRates[data.token];
}
}
stage1Locked = true;
emit RatesPublished(rates);
}
function transferToTreasury(address[] calldata tokens) external override onlyOwner hasEnded {
uint256 length = tokens.length;
TokenData[] memory transfers = new TokenData[](length);
for (uint256 i = 0; i < length; i++) {
address token = tokens[i];
require(tokenRates[token].tokeNumerator > 0, "NO_SWAP_TOKEN");
require(!supportedTokens[token].systemFinalized, "ALREADY_FINALIZED");
uint256 balance = IERC20(token).balanceOf(address(this));
(uint256 effective, , ) = getRateAdjustedAmounts(balance, token);
transfers[i].token = token;
transfers[i].amount = effective;
supportedTokens[token].systemFinalized = true;
IERC20(token).safeTransfer(treasuryAddress, effective);
}
emit TreasuryTransfer(transfers);
}
function setNoSwap(address[] calldata tokens) external override onlyOwner hasEnded {
uint256 length = tokens.length;
for (uint256 i = 0; i < length; i++) {
address token = tokens[i];
require(supportedTokenAddresses.contains(token), "UNSUPPORTED_ADDRESS");
require(tokenRates[token].tokeNumerator == 0, "ALREADY_SET_TO_SWAP");
require(!supportedTokens[token].systemFinalized, "ALREADY_FINALIZED");
supportedTokens[token].systemFinalized = true;
}
stage1Locked = true;
emit SetNoSwap(tokens);
}
function finalize(TokenFarming[] calldata tokens) external override hasEnded {
require(tokens.length > 0, "NO_TOKENS");
uint256 length = tokens.length;
FinalizedAccountData[] memory results = new FinalizedAccountData[](length);
for(uint256 i = 0; i < length; i++) {
TokenFarming calldata farm = tokens[i];
AccountData storage account = accountData[msg.sender][farm.token];
require(!account.finalized, "ALREADY_FINALIZED");
require(farm.token != address(0), "ZERO_ADDRESS");
require(supportedTokens[farm.token].systemFinalized, "NOT_SYSTEM_FINALIZED");
require(account.depositedBalance > 0, "INSUFFICIENT_FUNDS");
RateData storage rate = tokenRates[farm.token];
uint256 amtToTransfer = 0;
if (rate.tokeNumerator > 0) {
(, uint256 ineffectiveAmt, ) = getRateAdjustedAmounts(account.depositedBalance, farm.token);
amtToTransfer = ineffectiveAmt;
} else {
amtToTransfer = account.depositedBalance;
}
require(amtToTransfer > 0, "NOTHING_TO_MOVE");
account.finalized = true;
if (farm.sendToFarming) {
require(rate.pool != address(0), "NO_FARMING");
uint256 currentAllowance = IERC20(farm.token).allowance(address(this), rate.pool);
if (currentAllowance < amtToTransfer) {
IERC20(farm.token).safeIncreaseAllowance(rate.pool, amtToTransfer.sub(currentAllowance));
}
ILiquidityPool(rate.pool).depositFor(msg.sender, amtToTransfer);
results[i] = FinalizedAccountData({
token: farm.token,
transferredToFarm: amtToTransfer,
refunded: 0
});
} else {
IERC20(farm.token).safeTransfer(msg.sender, amtToTransfer);
results[i] = FinalizedAccountData({
token: farm.token,
transferredToFarm: 0,
refunded: amtToTransfer
});
}
}
emit AssetsFinalized(msg.sender, results);
}
function getRateAdjustedAmounts(uint256 balance, address token) public override view returns (uint256 effectiveAmt, uint256 ineffectiveAmt, uint256 actualReceived) {
RateData memory rateInfo = tokenRates[token];
uint256 effectiveTokenBalance =
balance.mul(rateInfo.overNumerator).div(rateInfo.overDenominator);
uint256 ineffectiveTokenBalance =
balance.mul(rateInfo.overDenominator.sub(rateInfo.overNumerator))
.div(rateInfo.overDenominator);
uint256 actual =
effectiveTokenBalance.mul(rateInfo.tokeDenominator).div(rateInfo.tokeNumerator);
return (effectiveTokenBalance, ineffectiveTokenBalance, actual);
}
function getRates() external override view returns (RateData[] memory rates) {
uint256 length = supportedTokenAddresses.length();
rates = new RateData[](length);
for (uint256 i = 0; i < length; i++) {
address token = supportedTokenAddresses.at(i);
rates[i] = tokenRates[token];
}
}
function getAccountData(address account) external view override returns (AccountData[] memory data) {
uint256 length = supportedTokenAddresses.length();
data = new AccountData[](length);
for(uint256 i = 0; i < length; i++) {
address token = supportedTokenAddresses.at(i);
data[i] = accountData[account][token];
data[i].token = token;
}
}
function getSupportedTokens() external view override returns (SupportedTokenData[] memory supportedTokensArray) {
uint256 supportedTokensLength = supportedTokenAddresses.length();
supportedTokensArray = new SupportedTokenData[](supportedTokensLength);
for (uint256 i = 0; i < supportedTokensLength; i++) {
supportedTokensArray[i] = supportedTokens[supportedTokenAddresses.at(i)];
}
return supportedTokensArray;
}
function _hasEnded() private view returns (bool) {
return durationInfo.startingBlock > 0 && block.number >= durationInfo.blockDuration + durationInfo.startingBlock;
}
function verifyDepositor(address participant, bytes32 root, bytes32[] memory proof) internal pure returns (bool) {
bytes32 leaf = keccak256((abi.encodePacked((participant))));
return MerkleProof.verify(proof, root, leaf);
}
}
文件 11 的 71:DefiRound.sol
pragma solidity 0.6.11;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/math/Math.sol";
import "@openzeppelin/contracts/utils/SafeCast.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/utils/EnumerableSet.sol";
import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
import "../interfaces/ILiquidityPool.sol";
import "../interfaces/IDefiRound.sol";
import "../interfaces/IWETH.sol";
import "@openzeppelin/contracts/cryptography/MerkleProof.sol";
contract DefiRound is IDefiRound, Ownable {
using SafeMath for uint256;
using SafeCast for int256;
using SafeERC20 for IERC20;
using Address for address;
using Address for address payable;
using EnumerableSet for EnumerableSet.AddressSet;
address public immutable WETH;
address public override immutable treasury;
OversubscriptionRate public overSubscriptionRate;
mapping(address => uint256) public override totalSupply;
mapping(address => AccountData) private accountData;
mapping(address => RateData) private tokenRates;
mapping(address => SupportedTokenData) private tokenSettings;
EnumerableSet.AddressSet private supportedTokens;
EnumerableSet.AddressSet private configuredTokenRates;
STAGES public override currentStage;
WhitelistSettings public whitelistSettings;
uint256 public lastLookExpiration = type(uint256).max;
uint256 private immutable maxTotalValue;
bool private stage1Locked;
constructor(
address _WETH,
address _treasury,
uint256 _maxTotalValue
) public {
require(_WETH != address(0), "INVALID_WETH");
require(_treasury != address(0), "INVALID_TREASURY");
require(_maxTotalValue > 0, "INVALID_MAXTOTAL");
WETH = _WETH;
treasury = _treasury;
currentStage = STAGES.STAGE_1;
maxTotalValue = _maxTotalValue;
}
function deposit(TokenData calldata tokenInfo, bytes32[] memory proof) external payable override {
require(currentStage == STAGES.STAGE_1, "DEPOSITS_NOT_ACCEPTED");
require(!stage1Locked, "DEPOSITS_LOCKED");
if (whitelistSettings.enabled) {
require(verifyDepositor(msg.sender, whitelistSettings.root, proof), "PROOF_INVALID");
}
TokenData memory data = tokenInfo;
address token = data.token;
uint256 tokenAmount = data.amount;
require(supportedTokens.contains(token), "UNSUPPORTED_TOKEN");
require(tokenAmount > 0, "INVALID_AMOUNT");
if (token == WETH && msg.value > 0) {
require(tokenAmount == msg.value, "INVALID_MSG_VALUE");
IWETH(WETH).deposit{value: tokenAmount}();
} else {
require(msg.value == 0, "NO_ETH");
}
AccountData storage tokenAccountData = accountData[msg.sender];
if (tokenAccountData.token == address(0)) {
tokenAccountData.token = token;
}
require(tokenAccountData.token == token, "SINGLE_ASSET_DEPOSITS");
tokenAccountData.initialDeposit = tokenAccountData.initialDeposit.add(tokenAmount);
tokenAccountData.currentBalance = tokenAccountData.currentBalance.add(tokenAmount);
require(tokenAccountData.currentBalance <= tokenSettings[token].maxLimit, "MAX_LIMIT_EXCEEDED");
if (!(token == WETH && msg.value > 0)) {
IERC20(token).safeTransferFrom(msg.sender, address(this), tokenAmount);
}
if(_totalValue() > maxTotalValue) {
stage1Locked = true;
}
emit Deposited(msg.sender, tokenInfo);
}
receive() external payable
{
require(msg.sender == WETH);
}
function withdraw(TokenData calldata tokenInfo, bool asETH) external override {
require(currentStage == STAGES.STAGE_2, "WITHDRAWS_NOT_ACCEPTED");
require(!_isLastLookComplete(), "WITHDRAWS_EXPIRED");
TokenData memory data = tokenInfo;
address token = data.token;
uint256 tokenAmount = data.amount;
require(supportedTokens.contains(token), "UNSUPPORTED_TOKEN");
require(tokenAmount > 0, "INVALID_AMOUNT");
AccountData storage tokenAccountData = accountData[msg.sender];
require(token == tokenAccountData.token, "INVALID_TOKEN");
tokenAccountData.currentBalance = tokenAccountData.currentBalance.sub(tokenAmount);
accountData[msg.sender] = tokenAccountData;
if (token == WETH && asETH) {
IWETH(WETH).withdraw(tokenAmount);
msg.sender.sendValue(tokenAmount);
} else {
IERC20(token).safeTransfer(msg.sender, tokenAmount);
}
emit Withdrawn(msg.sender, tokenInfo, asETH);
}
function configureWhitelist(WhitelistSettings memory settings) external override onlyOwner {
whitelistSettings = settings;
emit WhitelistConfigured(settings);
}
function addSupportedTokens(SupportedTokenData[] calldata tokensToSupport)
external
override
onlyOwner
{
uint256 tokensLength = tokensToSupport.length;
for (uint256 i = 0; i < tokensLength; i++) {
SupportedTokenData memory data = tokensToSupport[i];
require(supportedTokens.add(data.token), "TOKEN_EXISTS");
tokenSettings[data.token] = data;
}
emit SupportedTokensAdded(tokensToSupport);
}
function getSupportedTokens() external view override returns (address[] memory tokens) {
uint256 tokensLength = supportedTokens.length();
tokens = new address[](tokensLength);
for (uint256 i = 0; i < tokensLength; i++) {
tokens[i] = supportedTokens.at(i);
}
}
function publishRates(RateData[] calldata ratesData, OversubscriptionRate memory oversubRate, uint256 lastLookDuration) external override onlyOwner {
require(currentStage == STAGES.STAGE_1, "RATES_ALREADY_SET");
require(lastLookDuration > 0, "INVALID_DURATION");
require(oversubRate.overDenominator > 0, "INVALID_DENOMINATOR");
require(oversubRate.overNumerator > 0, "INVALID_NUMERATOR");
uint256 ratesLength = ratesData.length;
for (uint256 i = 0; i < ratesLength; i++) {
RateData memory data = ratesData[i];
require(data.numerator > 0, "INVALID_NUMERATOR");
require(data.denominator > 0, "INVALID_DENOMINATOR");
require(tokenRates[data.token].token == address(0), "RATE_ALREADY_SET");
require(configuredTokenRates.add(data.token), "ALREADY_CONFIGURED");
tokenRates[data.token] = data;
}
require(configuredTokenRates.length() == supportedTokens.length(), "MISSING_RATE");
currentStage = STAGES.STAGE_2;
lastLookExpiration = block.number + lastLookDuration;
overSubscriptionRate = oversubRate;
emit RatesPublished(ratesData);
}
function getRates(address[] calldata tokens) external view override returns (RateData[] memory rates) {
uint256 tokensLength = tokens.length;
rates = new RateData[](tokensLength);
for (uint256 i = 0; i < tokensLength; i++) {
rates[i] = tokenRates[tokens[i]];
}
}
function getTokenValue(address token, uint256 balance) internal view returns (uint256 value) {
uint256 tokenDecimals = ERC20(token).decimals();
(, int256 tokenRate, , , ) = AggregatorV3Interface(tokenSettings[token].oracle).latestRoundData();
uint256 rate = tokenRate.toUint256();
value = (balance.mul(rate)).div(10**tokenDecimals);
}
function totalValue() external view override returns (uint256) {
return _totalValue();
}
function _totalValue() internal view returns (uint256 value) {
uint256 tokensLength = supportedTokens.length();
for (uint256 i = 0; i < tokensLength; i++) {
address token = supportedTokens.at(i);
uint256 tokenBalance = IERC20(token).balanceOf(address(this));
value = value.add(getTokenValue(token, tokenBalance));
}
}
function accountBalance(address account) external view override returns (uint256 value) {
uint256 tokenBalance = accountData[account].currentBalance;
value = value.add(getTokenValue(accountData[account].token, tokenBalance));
}
function finalizeAssets(bool depositToGenesis) external override {
require(currentStage == STAGES.STAGE_3, "NOT_SYSTEM_FINAL");
AccountData storage data = accountData[msg.sender];
address token = data.token;
require(token != address(0), "NO_DATA");
( , uint256 ineffective, ) = _getRateAdjustedAmounts(data.currentBalance, token);
require(ineffective > 0, "NOTHING_TO_MOVE");
data.currentBalance = 0;
accountData[msg.sender] = data;
if (depositToGenesis) {
address pool = tokenSettings[token].genesis;
uint256 currentAllowance = IERC20(token).allowance(address(this), pool);
if (currentAllowance < ineffective) {
IERC20(token).safeIncreaseAllowance(pool, ineffective.sub(currentAllowance));
}
ILiquidityPool(pool).depositFor(msg.sender, ineffective);
emit GenesisTransfer(msg.sender, ineffective);
} else {
IERC20(token).safeTransfer(msg.sender, ineffective);
}
emit AssetsFinalized(msg.sender, token, ineffective);
}
function getGenesisPools(address[] calldata tokens)
external
view
override
returns (address[] memory genesisAddresses)
{
uint256 tokensLength = tokens.length;
genesisAddresses = new address[](tokensLength);
for (uint256 i = 0; i < tokensLength; i++) {
require(supportedTokens.contains(tokens[i]), "TOKEN_UNSUPPORTED");
genesisAddresses[i] = tokenSettings[supportedTokens.at(i)].genesis;
}
}
function getTokenOracles(address[] calldata tokens)
external
view
override
returns (address[] memory oracleAddresses)
{
uint256 tokensLength = tokens.length;
oracleAddresses = new address[](tokensLength);
for (uint256 i = 0; i < tokensLength; i++) {
require(supportedTokens.contains(tokens[i]), "TOKEN_UNSUPPORTED");
oracleAddresses[i] = tokenSettings[tokens[i]].oracle;
}
}
function getAccountData(address account) external view override returns (AccountDataDetails[] memory data) {
uint256 supportedTokensLength = supportedTokens.length();
data = new AccountDataDetails[](supportedTokensLength);
for (uint256 i = 0; i < supportedTokensLength; i++) {
address token = supportedTokens.at(i);
AccountData memory accountTokenInfo = accountData[account];
if (currentStage >= STAGES.STAGE_2 && accountTokenInfo.token != address(0)) {
(uint256 effective, uint256 ineffective, uint256 actual) = _getRateAdjustedAmounts(accountTokenInfo.currentBalance, token);
AccountDataDetails memory details = AccountDataDetails(
token,
accountTokenInfo.initialDeposit,
accountTokenInfo.currentBalance,
effective,
ineffective,
actual
);
data[i] = details;
} else {
data[i] = AccountDataDetails(token, accountTokenInfo.initialDeposit, accountTokenInfo.currentBalance, 0, 0, 0);
}
}
}
function transferToTreasury() external override onlyOwner {
require(_isLastLookComplete(), "CURRENT_STAGE_INVALID");
require(currentStage == STAGES.STAGE_2, "ONLY_TRANSFER_ONCE");
uint256 supportedTokensLength = supportedTokens.length();
TokenData[] memory tokens = new TokenData[](supportedTokensLength);
for (uint256 i = 0; i < supportedTokensLength; i++) {
address token = supportedTokens.at(i);
uint256 balance = IERC20(token).balanceOf(address(this));
(uint256 effective, , ) = _getRateAdjustedAmounts(balance, token);
tokens[i].token = token;
tokens[i].amount = effective;
IERC20(token).safeTransfer(treasury, effective);
}
currentStage = STAGES.STAGE_3;
emit TreasuryTransfer(tokens);
}
function getRateAdjustedAmounts(uint256 balance, address token) external override view returns (uint256,uint256,uint256) {
return _getRateAdjustedAmounts(balance, token);
}
function getMaxTotalValue() external view override returns (uint256) {
return maxTotalValue;
}
function _getRateAdjustedAmounts(uint256 balance, address token) internal view returns (uint256,uint256,uint256) {
require(currentStage >= STAGES.STAGE_2, "RATES_NOT_PUBLISHED");
RateData memory rateInfo = tokenRates[token];
uint256 effectiveTokenBalance =
balance.mul(overSubscriptionRate.overNumerator).div(overSubscriptionRate.overDenominator);
uint256 ineffectiveTokenBalance =
balance.mul(overSubscriptionRate.overDenominator.sub(overSubscriptionRate.overNumerator))
.div(overSubscriptionRate.overDenominator);
uint256 actualReceived =
effectiveTokenBalance.mul(rateInfo.denominator).div(rateInfo.numerator);
return (effectiveTokenBalance, ineffectiveTokenBalance, actualReceived);
}
function verifyDepositor(address participant, bytes32 root, bytes32[] memory proof) internal pure returns (bool) {
bytes32 leaf = keccak256((abi.encodePacked((participant))));
return MerkleProof.verify(proof, root, leaf);
}
function _isLastLookComplete() internal view returns (bool) {
return block.number >= lastLookExpiration;
}
}
文件 12 的 71:ECDSA.sol
pragma solidity >=0.6.0 <0.8.0;
library ECDSA {
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
if (signature.length != 65) {
revert("ECDSA: invalid signature length");
}
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return recover(hash, v, r, s);
}
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "ECDSA: invalid signature 's' value");
require(v == 27 || v == 28, "ECDSA: invalid signature 'v' value");
address signer = ecrecover(hash, v, r, s);
require(signer != address(0), "ECDSA: invalid signature");
return signer;
}
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
}
文件 13 的 71:ERC20.sol
pragma solidity >=0.6.0 <0.8.0;
import "../../utils/Context.sol";
import "./IERC20.sol";
import "../../math/SafeMath.sol";
contract ERC20 is Context, IERC20 {
using SafeMath for uint256;
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 virtual returns (string memory) {
return _name;
}
function symbol() public view virtual returns (string memory) {
return _symbol;
}
function decimals() public view virtual returns (uint8) {
return _decimals;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual 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 virtual {
_decimals = decimals_;
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}
文件 14 的 71:ERC20Burnable.sol
pragma solidity >=0.6.0 <0.8.0;
import "../../utils/Context.sol";
import "./ERC20.sol";
abstract contract ERC20Burnable is Context, ERC20 {
using SafeMath for uint256;
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);
}
}
文件 15 的 71:ERC20Pausable.sol
pragma solidity >=0.6.0 <0.8.0;
import "./ERC20.sol";
import "../../utils/Pausable.sol";
abstract contract ERC20Pausable is ERC20, Pausable {
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
super._beforeTokenTransfer(from, to, amount);
require(!paused(), "ERC20Pausable: token transfer while paused");
}
}
文件 16 的 71:ERC20PresetMinterPauser.sol
pragma solidity >=0.6.0 <0.8.0;
import "../access/AccessControl.sol";
import "../utils/Context.sol";
import "../token/ERC20/ERC20.sol";
import "../token/ERC20/ERC20Burnable.sol";
import "../token/ERC20/ERC20Pausable.sol";
contract ERC20PresetMinterPauser is Context, AccessControl, ERC20Burnable, ERC20Pausable {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
constructor(string memory name, string memory symbol) public ERC20(name, symbol) {
_setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
_setupRole(MINTER_ROLE, _msgSender());
_setupRole(PAUSER_ROLE, _msgSender());
}
function mint(address to, uint256 amount) public virtual {
require(hasRole(MINTER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have minter role to mint");
_mint(to, amount);
}
function pause() public virtual {
require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to pause");
_pause();
}
function unpause() public virtual {
require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to unpause");
_unpause();
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override(ERC20, ERC20Pausable) {
super._beforeTokenTransfer(from, to, amount);
}
}
文件 17 的 71:ERC20Upgradeable.sol
pragma solidity >=0.6.0 <0.8.0;
import "../../utils/ContextUpgradeable.sol";
import "./IERC20Upgradeable.sol";
import "../../math/SafeMathUpgradeable.sol";
import "../../proxy/Initializable.sol";
contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable {
using SafeMathUpgradeable for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
uint8 private _decimals;
function __ERC20_init(string memory name_, string memory symbol_) internal initializer {
__Context_init_unchained();
__ERC20_init_unchained(name_, symbol_);
}
function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {
_name = name_;
_symbol = symbol_;
_decimals = 18;
}
function name() public view virtual returns (string memory) {
return _name;
}
function symbol() public view virtual returns (string memory) {
return _symbol;
}
function decimals() public view virtual returns (uint8) {
return _decimals;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual 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 virtual {
_decimals = decimals_;
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
uint256[44] private __gap;
}
文件 18 的 71:EnumerableSet.sol
pragma solidity >=0.6.0 <0.8.0;
library EnumerableSet {
struct Set {
bytes32[] _values;
mapping (bytes32 => uint256) _indexes;
}
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
function _remove(Set storage set, bytes32 value) private returns (bool) {
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
bytes32 lastvalue = set._values[lastIndex];
set._values[toDeleteIndex] = lastvalue;
set._indexes[lastvalue] = toDeleteIndex + 1;
set._values.pop();
delete set._indexes[value];
return true;
} else {
return false;
}
}
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
function _at(Set storage set, uint256 index) private view returns (bytes32) {
require(set._values.length > index, "EnumerableSet: index out of bounds");
return set._values[index];
}
struct Bytes32Set {
Set _inner;
}
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
struct AddressSet {
Set _inner;
}
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
struct UintSet {
Set _inner;
}
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
}
文件 19 的 71:EnumerableSetUpgradeable.sol
pragma solidity >=0.6.0 <0.8.0;
library EnumerableSetUpgradeable {
struct Set {
bytes32[] _values;
mapping (bytes32 => uint256) _indexes;
}
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
function _remove(Set storage set, bytes32 value) private returns (bool) {
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
bytes32 lastvalue = set._values[lastIndex];
set._values[toDeleteIndex] = lastvalue;
set._indexes[lastvalue] = toDeleteIndex + 1;
set._values.pop();
delete set._indexes[value];
return true;
} else {
return false;
}
}
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
function _at(Set storage set, uint256 index) private view returns (bytes32) {
require(set._values.length > index, "EnumerableSet: index out of bounds");
return set._values[index];
}
struct Bytes32Set {
Set _inner;
}
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
struct AddressSet {
Set _inner;
}
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
struct UintSet {
Set _inner;
}
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
}
文件 20 的 71:EthPool.sol
pragma solidity 0.6.11;
import "../interfaces/ILiquidityEthPool.sol";
import "../interfaces/IManager.sol";
import "../interfaces/IWETH.sol";
import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";
import {AddressUpgradeable as Address} from "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import {MathUpgradeable as Math} from "@openzeppelin/contracts-upgradeable/math/MathUpgradeable.sol";
import {SafeMathUpgradeable as SafeMath} from "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";
import {OwnableUpgradeable as Ownable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {ERC20Upgradeable as ERC20} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import {IERC20Upgradeable as IERC20} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import {SafeERC20Upgradeable as SafeERC20} from "@openzeppelin/contracts-upgradeable/token/ERC20/SafeERC20Upgradeable.sol";
import {PausableUpgradeable as Pausable} from "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol";
contract EthPool is ILiquidityEthPool, Initializable, ERC20, Ownable, Pausable {
using SafeMath for uint256;
using SafeERC20 for IERC20;
using Address for address;
using Address for address payable;
IWETH public override weth;
IManager public manager;
uint256 public override withheldLiquidity;
mapping(address => WithdrawalInfo) public override requestedWithdrawals;
receive() external payable {}
function initialize(
IWETH _weth,
IManager _manager,
string memory _name,
string memory _symbol
) public initializer {
require(address(_weth) != address(0), "ZERO_ADDRESS");
require(address(_manager) != address(0), "ZERO_ADDRESS");
__Context_init_unchained();
__Ownable_init_unchained();
__Pausable_init_unchained();
__ERC20_init_unchained(_name, _symbol);
weth = _weth;
manager = _manager;
withheldLiquidity = 0;
}
function deposit(uint256 amount) external payable override whenNotPaused {
_deposit(msg.sender, msg.sender, amount, msg.value);
}
function depositFor(address account, uint256 amount) external payable override whenNotPaused {
_deposit(msg.sender, account, amount, msg.value);
}
function underlyer() external view override returns (address) {
return address(weth);
}
function withdraw(uint256 requestedAmount, bool asEth) external override whenNotPaused {
require(
requestedAmount <= requestedWithdrawals[msg.sender].amount,
"WITHDRAW_INSUFFICIENT_BALANCE"
);
require(requestedAmount > 0, "NO_WITHDRAWAL");
require(weth.balanceOf(address(this)) >= requestedAmount, "INSUFFICIENT_POOL_BALANCE");
require(
requestedWithdrawals[msg.sender].minCycle <= manager.getCurrentCycleIndex(),
"INVALID_CYCLE"
);
requestedWithdrawals[msg.sender].amount = requestedWithdrawals[msg.sender].amount.sub(
requestedAmount
);
if (requestedWithdrawals[msg.sender].amount == 0) {
delete requestedWithdrawals[msg.sender];
}
withheldLiquidity = withheldLiquidity.sub(requestedAmount);
_burn(msg.sender, requestedAmount);
if (asEth) {
weth.withdraw(requestedAmount);
msg.sender.sendValue(requestedAmount);
} else {
IERC20(weth).safeTransfer(msg.sender, requestedAmount);
}
}
function requestWithdrawal(uint256 amount) external override {
require(amount > 0, "INVALID_AMOUNT");
require(amount <= balanceOf(msg.sender), "INSUFFICIENT_BALANCE");
withheldLiquidity = withheldLiquidity.sub(requestedWithdrawals[msg.sender].amount).add(
amount
);
requestedWithdrawals[msg.sender].amount = amount;
if (manager.getRolloverStatus()) {
requestedWithdrawals[msg.sender].minCycle = manager.getCurrentCycleIndex().add(2);
} else {
requestedWithdrawals[msg.sender].minCycle = manager.getCurrentCycleIndex().add(1);
}
}
function preTransferAdjustWithheldLiquidity(address sender, uint256 amount) internal {
if (requestedWithdrawals[sender].amount > 0) {
uint256 newRequestedWithdrawl = requestedWithdrawals[sender].amount.sub(
Math.min(amount, requestedWithdrawals[sender].amount)
);
withheldLiquidity = withheldLiquidity.sub(
requestedWithdrawals[msg.sender].amount.sub(newRequestedWithdrawl)
);
requestedWithdrawals[msg.sender].amount = newRequestedWithdrawl;
if (requestedWithdrawals[msg.sender].amount == 0) {
delete requestedWithdrawals[msg.sender];
}
}
}
function approveManager(uint256 amount) public override onlyOwner {
uint256 currentAllowance = IERC20(weth).allowance(address(this), address(manager));
if (currentAllowance < amount) {
uint256 delta = amount.sub(currentAllowance);
IERC20(weth).safeIncreaseAllowance(address(manager), delta);
} else {
uint256 delta = currentAllowance.sub(amount);
IERC20(weth).safeDecreaseAllowance(address(manager), delta);
}
}
function transfer(address recipient, uint256 amount) public override returns (bool) {
preTransferAdjustWithheldLiquidity(msg.sender, amount);
return super.transfer(recipient, amount);
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public override returns (bool) {
preTransferAdjustWithheldLiquidity(sender, amount);
return super.transferFrom(sender, recipient, amount);
}
function pause() external override onlyOwner {
_pause();
}
function unpause() external override onlyOwner {
_unpause();
}
function _deposit(
address fromAccount,
address toAccount,
uint256 amount,
uint256 msgValue
) internal {
require(amount > 0, "INVALID_AMOUNT");
require(toAccount != address(0), "INVALID_ADDRESS");
_mint(toAccount, amount);
if (msgValue > 0) {
require(msgValue == amount, "AMT_VALUE_MISMATCH");
weth.deposit{value: amount}();
} else {
IERC20(weth).safeTransferFrom(fromAccount, address(this), amount);
}
}
}
文件 21 的 71:IBalancerPool.sol
pragma solidity 0.6.11;
interface IBalancerPool {
event Approval(address indexed src, address indexed dst, uint amt);
event Transfer(address indexed src, address indexed dst, uint amt);
function totalSupply() external view returns (uint);
function balanceOf(address whom) external view returns (uint);
function allowance(address src, address dst) external view returns (uint);
function approve(address dst, uint amt) external returns (bool);
function transfer(address dst, uint amt) external returns (bool);
function transferFrom(
address src, address dst, uint amt
) external returns (bool);
function joinPool(uint poolAmountOut, uint[] calldata maxAmountsIn) external;
function exitPool(uint poolAmountIn, uint[] calldata minAmountsOut) external;
function getBalance(address token) external view returns (uint);
function decimals() external view returns(uint8);
function isFinalized() external view returns (bool);
function getFinalTokens()
external view
returns (address[] memory tokens);
}
文件 22 的 71:ICoreEvent.sol
pragma solidity 0.6.11;
pragma experimental ABIEncoderV2;
interface ICoreEvent {
struct SupportedTokenData {
address token;
uint256 maxUserLimit;
bool systemFinalized;
}
struct DurationInfo {
uint256 startingBlock;
uint256 blockDuration;
}
struct RateData {
address token;
uint256 tokeNumerator;
uint256 tokeDenominator;
uint256 overNumerator;
uint256 overDenominator;
address pool;
}
struct TokenData {
address token;
uint256 amount;
}
struct AccountData {
address token;
uint256 depositedBalance;
bool finalized;
}
struct FinalizedAccountData {
address token;
uint256 transferredToFarm;
uint256 refunded;
}
struct TokenFarming {
address token;
bool sendToFarming;
}
struct WhitelistSettings {
bool enabled;
bytes32 root;
}
event SupportedTokensAdded(SupportedTokenData[] tokenData);
event TreasurySet(address treasury);
event DurationSet(DurationInfo duration);
event DurationIncreased(DurationInfo duration);
event Deposited(address depositor, TokenData[] tokenInfo);
event Withdrawn(address withdrawer, TokenData[] tokenInfo);
event RatesPublished(RateData[] ratesData);
event AssetsFinalized(address user, FinalizedAccountData[] data);
event TreasuryTransfer(TokenData[] tokens);
event WhitelistConfigured(WhitelistSettings settings);
event SetNoSwap(address[] tokens);
function configureWhitelist(WhitelistSettings memory settings) external;
function setDuration(uint256 blockDuration) external;
function addSupportedTokens(SupportedTokenData[] memory tokensToSupport) external;
function deposit(TokenData[] calldata tokenData, bytes32[] calldata proof) external;
function withdraw(TokenData[] calldata tokenData) external;
function increaseDuration(uint256 blockDuration) external;
function setRates(RateData[] calldata rates) external;
function transferToTreasury(address[] calldata tokens) external;
function setNoSwap(address[] calldata tokens) external;
function finalize(TokenFarming[] calldata tokens) external;
function getRateAdjustedAmounts(uint256 balance, address token) external view returns (uint256 effectiveAmt, uint256 ineffectiveAmt, uint256 actualReceived);
function getRates() external view returns (RateData[] memory rates);
function getAccountData(address account) external view returns (AccountData[] calldata data);
function getSupportedTokens() external view returns (SupportedTokenData[] memory supportedTokensArray);
}
文件 23 的 71:IDefiRound.sol
pragma solidity 0.6.11;
pragma experimental ABIEncoderV2;
interface IDefiRound {
enum STAGES {STAGE_1, STAGE_2, STAGE_3}
struct AccountData {
address token;
uint256 initialDeposit;
uint256 currentBalance;
}
struct AccountDataDetails {
address token;
uint256 initialDeposit;
uint256 currentBalance;
uint256 effectiveAmt;
uint256 ineffectiveAmt;
uint256 actualTokeReceived;
}
struct TokenData {
address token;
uint256 amount;
}
struct SupportedTokenData {
address token;
address oracle;
address genesis;
uint256 maxLimit;
}
struct RateData {
address token;
uint256 numerator;
uint256 denominator;
}
struct OversubscriptionRate {
uint256 overNumerator;
uint256 overDenominator;
}
event Deposited(address depositor, TokenData tokenInfo);
event Withdrawn(address withdrawer, TokenData tokenInfo, bool asETH);
event SupportedTokensAdded(SupportedTokenData[] tokenData);
event RatesPublished(RateData[] ratesData);
event GenesisTransfer(address user, uint256 amountTransferred);
event AssetsFinalized(address claimer, address token, uint256 assetsMoved);
event WhitelistConfigured(WhitelistSettings settings);
event TreasuryTransfer(TokenData[] tokens);
struct TokenValues {
uint256 effectiveTokenValue;
uint256 ineffectiveTokenValue;
}
struct WhitelistSettings {
bool enabled;
bytes32 root;
}
function configureWhitelist(WhitelistSettings calldata settings) external;
function currentStage() external returns (STAGES stage);
function deposit(TokenData calldata tokenData, bytes32[] memory proof) external payable;
function totalValue() external view returns (uint256 value);
function getMaxTotalValue() external view returns (uint256 value);
function treasury() external returns (address treasuryAddress);
function totalSupply(address token) external returns (uint256 amount);
function withdraw(TokenData calldata tokenData, bool asEth) external;
function addSupportedTokens(SupportedTokenData[] calldata tokensToSupport) external;
function getSupportedTokens() external view returns (address[] calldata tokens);
function getTokenOracles(address[] calldata tokens)
external
view
returns (address[] calldata oracleAddresses);
function publishRates(
RateData[] calldata ratesData,
OversubscriptionRate memory overSubRate,
uint256 lastLookDuration
) external;
function getRates(address[] calldata tokens) external view returns (RateData[] calldata rates);
function accountBalance(address account) external view returns (uint256 value);
function finalizeAssets(bool depositToGenesis) external;
function getGenesisPools(address[] calldata tokens)
external
view
returns (address[] memory genesisAddresses);
function getAccountData(address account)
external
view
returns (AccountDataDetails[] calldata data);
function transferToTreasury() external;
function getRateAdjustedAmounts(uint256 balance, address token)
external
view
returns (
uint256,
uint256,
uint256
);
}
文件 24 的 71:IERC20.sol
pragma solidity >=0.6.0 <0.8.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);
}
文件 25 的 71:IERC20TokenV06.sol
pragma solidity ^0.6.5;
interface IERC20TokenV06 {
event Transfer(
address indexed from,
address indexed to,
uint256 value
);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
function transfer(address to, uint256 value)
external
returns (bool);
function transferFrom(
address from,
address to,
uint256 value
)
external
returns (bool);
function approve(address spender, uint256 value)
external
returns (bool);
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 decimals()
external
view
returns (uint8);
}
文件 26 的 71:IERC20Upgradeable.sol
pragma solidity >=0.6.0 <0.8.0;
interface IERC20Upgradeable {
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);
}
文件 27 的 71:ILiquidityEthPool.sol
pragma solidity 0.6.11;
import "../interfaces/IWETH.sol";
import "../interfaces/IManager.sol";
interface ILiquidityEthPool {
struct WithdrawalInfo {
uint256 minCycle;
uint256 amount;
}
function deposit(uint256 amount) external payable;
function depositFor(address account, uint256 amount) external payable;
function requestWithdrawal(uint256 amount) external;
function approveManager(uint256 amount) external;
function withdraw(uint256 amount, bool asEth) external;
function weth() external view returns (IWETH);
function underlyer() external view returns (address);
function withheldLiquidity() external view returns (uint256);
function requestedWithdrawals(address account) external view returns (uint256, uint256);
function pause() external;
function unpause() external;
}
文件 28 的 71:ILiquidityPool.sol
pragma solidity 0.6.11;
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "../interfaces/IManager.sol";
interface ILiquidityPool {
struct WithdrawalInfo {
uint256 minCycle;
uint256 amount;
}
function deposit(uint256 amount) external;
function depositFor(address account, uint256 amount) external;
function requestWithdrawal(uint256 amount) external;
function approveManager(uint256 amount) external;
function withdraw(uint256 amount) external;
function underlyer() external view returns (ERC20Upgradeable);
function withheldLiquidity() external view returns (uint256);
function requestedWithdrawals(address account) external view returns (uint256, uint256);
function pause() external;
function unpause() external;
}
文件 29 的 71:IManager.sol
pragma solidity 0.6.11;
pragma experimental ABIEncoderV2;
interface IManager {
struct ControllerTransferData {
bytes32 controllerId;
bytes data;
}
struct PoolTransferData {
address pool;
uint256 amount;
}
struct MaintenanceExecution {
ControllerTransferData[] cycleSteps;
}
struct RolloverExecution {
PoolTransferData[] poolData;
ControllerTransferData[] cycleSteps;
address[] poolsForWithdraw;
bool complete;
string rewardsIpfsHash;
}
event ControllerRegistered(bytes32 id, address controller);
event ControllerUnregistered(bytes32 id, address controller);
event PoolRegistered(address pool);
event PoolUnregistered(address pool);
event CycleDurationSet(uint256 duration);
event LiquidityMovedToManager(address pool, uint256 amount);
event DeploymentStepExecuted(bytes32 controller, address adapaterAddress, bytes data);
event LiquidityMovedToPool(address pool, uint256 amount);
event CycleRolloverStarted(uint256 blockNumber);
event CycleRolloverComplete(uint256 blockNumber);
function registerController(bytes32 id, address controller) external;
function registerPool(address pool) external;
function unRegisterController(bytes32 id) external;
function unRegisterPool(address pool) external;
function getPools() external view returns (address[] memory);
function getControllers() external view returns (bytes32[] memory);
function setCycleDuration(uint256 duration) external;
function startCycleRollover() external;
function executeMaintenance(MaintenanceExecution calldata params) external;
function executeRollover(RolloverExecution calldata params) external;
function completeRollover(string calldata rewardsIpfsHash) external;
function cycleRewardsHashes(uint256 index) external view returns (string memory);
function getCurrentCycle() external view returns (uint256);
function getCurrentCycleIndex() external view returns (uint256);
function getCycleDuration() external view returns (uint256);
function getRolloverStatus() external view returns (bool);
}
文件 30 的 71:INativeOrdersEvents.sol
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "../libs/LibSignature.sol";
import "../libs/LibNativeOrder.sol";
interface INativeOrdersEvents {
event LimitOrderFilled(
bytes32 orderHash,
address maker,
address taker,
address feeRecipient,
address makerToken,
address takerToken,
uint128 takerTokenFilledAmount,
uint128 makerTokenFilledAmount,
uint128 takerTokenFeeFilledAmount,
uint256 protocolFeePaid,
bytes32 pool
);
event RfqOrderFilled(
bytes32 orderHash,
address maker,
address taker,
address makerToken,
address takerToken,
uint128 takerTokenFilledAmount,
uint128 makerTokenFilledAmount,
bytes32 pool
);
event OrderCancelled(
bytes32 orderHash,
address maker
);
event PairCancelledLimitOrders(
address maker,
address makerToken,
address takerToken,
uint256 minValidSalt
);
event PairCancelledRfqOrders(
address maker,
address makerToken,
address takerToken,
uint256 minValidSalt
);
event RfqOrderOriginsAllowed(
address origin,
address[] addrs,
bool allowed
);
event OrderSignerRegistered(
address maker,
address signer,
bool allowed
);
}
文件 31 的 71:INativeOrdersFeature.sol
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "../libs/LibSignature.sol";
import "../libs/LibNativeOrder.sol";
import "./INativeOrdersEvents.sol";
interface INativeOrdersFeature is
INativeOrdersEvents
{
function transferProtocolFeesForPools(bytes32[] calldata poolIds)
external;
function fillLimitOrder(
LibNativeOrder.LimitOrder calldata order,
LibSignature.Signature calldata signature,
uint128 takerTokenFillAmount
)
external
payable
returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount);
function fillRfqOrder(
LibNativeOrder.RfqOrder calldata order,
LibSignature.Signature calldata signature,
uint128 takerTokenFillAmount
)
external
returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount);
function fillOrKillLimitOrder(
LibNativeOrder.LimitOrder calldata order,
LibSignature.Signature calldata signature,
uint128 takerTokenFillAmount
)
external
payable
returns (uint128 makerTokenFilledAmount);
function fillOrKillRfqOrder(
LibNativeOrder.RfqOrder calldata order,
LibSignature.Signature calldata signature,
uint128 takerTokenFillAmount
)
external
returns (uint128 makerTokenFilledAmount);
function _fillLimitOrder(
LibNativeOrder.LimitOrder calldata order,
LibSignature.Signature calldata signature,
uint128 takerTokenFillAmount,
address taker,
address sender
)
external
payable
returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount);
function _fillRfqOrder(
LibNativeOrder.RfqOrder calldata order,
LibSignature.Signature calldata signature,
uint128 takerTokenFillAmount,
address taker
)
external
returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount);
function cancelLimitOrder(LibNativeOrder.LimitOrder calldata order)
external;
function cancelRfqOrder(LibNativeOrder.RfqOrder calldata order)
external;
function registerAllowedRfqOrigins(address[] memory origins, bool allowed)
external;
function batchCancelLimitOrders(LibNativeOrder.LimitOrder[] calldata orders)
external;
function batchCancelRfqOrders(LibNativeOrder.RfqOrder[] calldata orders)
external;
function cancelPairLimitOrders(
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
uint256 minValidSalt
)
external;
function cancelPairLimitOrdersWithSigner(
address maker,
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
uint256 minValidSalt
)
external;
function batchCancelPairLimitOrders(
IERC20TokenV06[] calldata makerTokens,
IERC20TokenV06[] calldata takerTokens,
uint256[] calldata minValidSalts
)
external;
function batchCancelPairLimitOrdersWithSigner(
address maker,
IERC20TokenV06[] memory makerTokens,
IERC20TokenV06[] memory takerTokens,
uint256[] memory minValidSalts
)
external;
function cancelPairRfqOrders(
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
uint256 minValidSalt
)
external;
function cancelPairRfqOrdersWithSigner(
address maker,
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
uint256 minValidSalt
)
external;
function batchCancelPairRfqOrders(
IERC20TokenV06[] calldata makerTokens,
IERC20TokenV06[] calldata takerTokens,
uint256[] calldata minValidSalts
)
external;
function batchCancelPairRfqOrdersWithSigner(
address maker,
IERC20TokenV06[] memory makerTokens,
IERC20TokenV06[] memory takerTokens,
uint256[] memory minValidSalts
)
external;
function getLimitOrderInfo(LibNativeOrder.LimitOrder calldata order)
external
view
returns (LibNativeOrder.OrderInfo memory orderInfo);
function getRfqOrderInfo(LibNativeOrder.RfqOrder calldata order)
external
view
returns (LibNativeOrder.OrderInfo memory orderInfo);
function getLimitOrderHash(LibNativeOrder.LimitOrder calldata order)
external
view
returns (bytes32 orderHash);
function getRfqOrderHash(LibNativeOrder.RfqOrder calldata order)
external
view
returns (bytes32 orderHash);
function getProtocolFeeMultiplier()
external
view
returns (uint32 multiplier);
function getLimitOrderRelevantState(
LibNativeOrder.LimitOrder calldata order,
LibSignature.Signature calldata signature
)
external
view
returns (
LibNativeOrder.OrderInfo memory orderInfo,
uint128 actualFillableTakerTokenAmount,
bool isSignatureValid
);
function getRfqOrderRelevantState(
LibNativeOrder.RfqOrder calldata order,
LibSignature.Signature calldata signature
)
external
view
returns (
LibNativeOrder.OrderInfo memory orderInfo,
uint128 actualFillableTakerTokenAmount,
bool isSignatureValid
);
function batchGetLimitOrderRelevantStates(
LibNativeOrder.LimitOrder[] calldata orders,
LibSignature.Signature[] calldata signatures
)
external
view
returns (
LibNativeOrder.OrderInfo[] memory orderInfos,
uint128[] memory actualFillableTakerTokenAmounts,
bool[] memory isSignatureValids
);
function batchGetRfqOrderRelevantStates(
LibNativeOrder.RfqOrder[] calldata orders,
LibSignature.Signature[] calldata signatures
)
external
view
returns (
LibNativeOrder.OrderInfo[] memory orderInfos,
uint128[] memory actualFillableTakerTokenAmounts,
bool[] memory isSignatureValids
);
function registerAllowedOrderSigner(
address signer,
bool allowed
)
external;
function isValidOrderSigner(
address maker,
address signer
)
external
view
returns (bool isAllowed);
}
文件 32 的 71:IStaking.sol
pragma solidity 0.6.11;
pragma experimental ABIEncoderV2;
interface IStaking {
struct StakingSchedule {
uint256 cliff;
uint256 duration;
uint256 interval;
bool setup;
bool isActive;
uint256 hardStart;
bool isPublic;
}
struct StakingScheduleInfo {
StakingSchedule schedule;
uint256 index;
}
struct StakingDetails {
uint256 initial;
uint256 withdrawn;
uint256 slashed;
uint256 started;
uint256 scheduleIx;
}
struct WithdrawalInfo {
uint256 minCycleIndex;
uint256 amount;
}
event ScheduleAdded(uint256 scheduleIndex, uint256 cliff, uint256 duration, uint256 interval, bool setup, bool isActive, uint256 hardStart);
event ScheduleRemoved(uint256 scheduleIndex);
event WithdrawalRequested(address account, uint256 amount);
event WithdrawCompleted(address account, uint256 amount);
event Deposited(address account, uint256 amount, uint256 scheduleIx);
event Slashed(address account, uint256 amount, uint256 scheduleIx);
function permissionedDepositors(address account) external returns (bool);
function setUserSchedules(address account, uint256[] calldata userSchedulesIdxs) external;
function addSchedule(StakingSchedule memory schedule) external;
function getSchedules() external view returns (StakingScheduleInfo[] memory);
function setPermissionedDepositor(address account, bool canDeposit) external;
function removeSchedule(uint256 scheduleIndex) external;
function getStakes(address account) external view returns(StakingDetails[] memory);
function balanceOf(address account) external view returns(uint256);
function availableForWithdrawal(address account, uint256 scheduleIndex) external view returns (uint256);
function unvested(address account, uint256 scheduleIndex) external view returns(uint256);
function vested(address account, uint256 scheduleIndex) external view returns(uint256);
function deposit(uint256 amount, uint256 scheduleIndex) external;
function depositFor(address account, uint256 amount, uint256 scheduleIndex) external;
function depositWithSchedule(address account, uint256 amount, StakingSchedule calldata schedule) external;
function requestWithdrawal(uint256 amount) external;
function withdraw(uint256 amount) external;
function pause() external;
function unpause() external;
}
文件 33 的 71:IUniswapV2ERC20.sol
pragma solidity >=0.5.0;
interface IUniswapV2ERC20 {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
}
文件 34 的 71:IUniswapV2Factory.sol
pragma solidity >=0.5.0;
interface IUniswapV2Factory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint);
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function migrator() external view returns (address);
function getPair(address tokenA, address tokenB) external view returns (address pair);
function allPairs(uint) external view returns (address pair);
function allPairsLength() external view returns (uint);
function createPair(address tokenA, address tokenB) external returns (address pair);
function setFeeTo(address) external;
function setFeeToSetter(address) external;
function setMigrator(address) external;
}
文件 35 的 71:IUniswapV2Router01.sol
pragma solidity >=0.6.2;
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}
文件 36 的 71:IUniswapV2Router02.sol
pragma solidity >=0.6.2;
import './IUniswapV2Router01.sol';
interface IUniswapV2Router02 is IUniswapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}
文件 37 的 71:IWETH.sol
pragma solidity 0.6.11;
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
interface IWETH is IERC20Upgradeable {
function deposit() external payable;
function withdraw(uint256) external;
}
文件 38 的 71:IWallet.sol
pragma solidity 0.6.11;
interface IWallet {
function registerAllowedOrderSigner(address signer, bool allowed) external;
function deposit(address[] calldata tokens, uint256[] calldata amounts) external;
function withdraw(address[] calldata tokens, uint256[] calldata amounts) external;
}
文件 39 的 71:Imports.sol
pragma solidity 0.6.11;
import "@gnosis.pm/mock-contract/contracts/MockContract.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/presets/ERC20PresetMinterPauser.sol";
import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol";
import "@uniswap/v2-core/contracts/interfaces/IUniswapV2ERC20.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import "@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Router02.sol" as ISushiswapV2Router;
import "@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol" as ISushiswapV2Factory;
import "@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2ERC20.sol" as ISushiswapV2ERC20;
文件 40 的 71:Initializable.sol
pragma solidity >=0.4.24 <0.8.0;
import "../utils/AddressUpgradeable.sol";
abstract contract Initializable {
bool private _initialized;
bool private _initializing;
modifier initializer() {
require(_initializing || _isConstructor() || !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
function _isConstructor() private view returns (bool) {
return !AddressUpgradeable.isContract(address(this));
}
}
文件 41 的 71:LibNativeOrder.sol
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "../../errors/LibNativeOrdersRichErrors.sol";
library LibNativeOrder {
using LibSafeMathV06 for uint256;
using LibRichErrorsV06 for bytes;
enum OrderStatus {
INVALID,
FILLABLE,
FILLED,
CANCELLED,
EXPIRED
}
struct LimitOrder {
IERC20TokenV06 makerToken;
IERC20TokenV06 takerToken;
uint128 makerAmount;
uint128 takerAmount;
uint128 takerTokenFeeAmount;
address maker;
address taker;
address sender;
address feeRecipient;
bytes32 pool;
uint64 expiry;
uint256 salt;
}
struct RfqOrder {
IERC20TokenV06 makerToken;
IERC20TokenV06 takerToken;
uint128 makerAmount;
uint128 takerAmount;
address maker;
address taker;
address txOrigin;
bytes32 pool;
uint64 expiry;
uint256 salt;
}
struct OtcOrder {
IERC20TokenV06 makerToken;
IERC20TokenV06 takerToken;
uint128 makerAmount;
uint128 takerAmount;
address maker;
address taker;
address txOrigin;
uint256 expiryAndNonce;
}
struct OrderInfo {
bytes32 orderHash;
OrderStatus status;
uint128 takerTokenFilledAmount;
}
struct OtcOrderInfo {
bytes32 orderHash;
OrderStatus status;
}
uint256 private constant UINT_128_MASK = (1 << 128) - 1;
uint256 private constant UINT_64_MASK = (1 << 64) - 1;
uint256 private constant ADDRESS_MASK = (1 << 160) - 1;
uint256 private constant _LIMIT_ORDER_TYPEHASH =
0xce918627cb55462ddbb85e73de69a8b322f2bc88f4507c52fcad6d4c33c29d49;
uint256 private constant _RFQ_ORDER_TYPEHASH =
0xe593d3fdfa8b60e5e17a1b2204662ecbe15c23f2084b9ad5bae40359540a7da9;
uint256 private constant _OTC_ORDER_TYPEHASH =
0x2f754524de756ae72459efbe1ec88c19a745639821de528ac3fb88f9e65e35c8;
function getLimitOrderStructHash(LimitOrder memory order)
internal
pure
returns (bytes32 structHash)
{
assembly {
let mem := mload(0x40)
mstore(mem, _LIMIT_ORDER_TYPEHASH)
mstore(add(mem, 0x20), and(ADDRESS_MASK, mload(order)))
mstore(add(mem, 0x40), and(ADDRESS_MASK, mload(add(order, 0x20))))
mstore(add(mem, 0x60), and(UINT_128_MASK, mload(add(order, 0x40))))
mstore(add(mem, 0x80), and(UINT_128_MASK, mload(add(order, 0x60))))
mstore(add(mem, 0xA0), and(UINT_128_MASK, mload(add(order, 0x80))))
mstore(add(mem, 0xC0), and(ADDRESS_MASK, mload(add(order, 0xA0))))
mstore(add(mem, 0xE0), and(ADDRESS_MASK, mload(add(order, 0xC0))))
mstore(add(mem, 0x100), and(ADDRESS_MASK, mload(add(order, 0xE0))))
mstore(add(mem, 0x120), and(ADDRESS_MASK, mload(add(order, 0x100))))
mstore(add(mem, 0x140), mload(add(order, 0x120)))
mstore(add(mem, 0x160), and(UINT_64_MASK, mload(add(order, 0x140))))
mstore(add(mem, 0x180), mload(add(order, 0x160)))
structHash := keccak256(mem, 0x1A0)
}
}
function getRfqOrderStructHash(RfqOrder memory order)
internal
pure
returns (bytes32 structHash)
{
assembly {
let mem := mload(0x40)
mstore(mem, _RFQ_ORDER_TYPEHASH)
mstore(add(mem, 0x20), and(ADDRESS_MASK, mload(order)))
mstore(add(mem, 0x40), and(ADDRESS_MASK, mload(add(order, 0x20))))
mstore(add(mem, 0x60), and(UINT_128_MASK, mload(add(order, 0x40))))
mstore(add(mem, 0x80), and(UINT_128_MASK, mload(add(order, 0x60))))
mstore(add(mem, 0xA0), and(ADDRESS_MASK, mload(add(order, 0x80))))
mstore(add(mem, 0xC0), and(ADDRESS_MASK, mload(add(order, 0xA0))))
mstore(add(mem, 0xE0), and(ADDRESS_MASK, mload(add(order, 0xC0))))
mstore(add(mem, 0x100), mload(add(order, 0xE0)))
mstore(add(mem, 0x120), and(UINT_64_MASK, mload(add(order, 0x100))))
mstore(add(mem, 0x140), mload(add(order, 0x120)))
structHash := keccak256(mem, 0x160)
}
}
function getOtcOrderStructHash(OtcOrder memory order)
internal
pure
returns (bytes32 structHash)
{
assembly {
let mem := mload(0x40)
mstore(mem, _OTC_ORDER_TYPEHASH)
mstore(add(mem, 0x20), and(ADDRESS_MASK, mload(order)))
mstore(add(mem, 0x40), and(ADDRESS_MASK, mload(add(order, 0x20))))
mstore(add(mem, 0x60), and(UINT_128_MASK, mload(add(order, 0x40))))
mstore(add(mem, 0x80), and(UINT_128_MASK, mload(add(order, 0x60))))
mstore(add(mem, 0xA0), and(ADDRESS_MASK, mload(add(order, 0x80))))
mstore(add(mem, 0xC0), and(ADDRESS_MASK, mload(add(order, 0xA0))))
mstore(add(mem, 0xE0), and(ADDRESS_MASK, mload(add(order, 0xC0))))
mstore(add(mem, 0x100), mload(add(order, 0xE0)))
structHash := keccak256(mem, 0x120)
}
}
function refundExcessProtocolFeeToSender(uint256 ethProtocolFeePaid)
internal
{
if (msg.value > ethProtocolFeePaid && msg.sender != address(this)) {
uint256 refundAmount = msg.value.safeSub(ethProtocolFeePaid);
(bool success,) = msg
.sender
.call{value: refundAmount}("");
if (!success) {
LibNativeOrdersRichErrors.ProtocolFeeRefundFailed(
msg.sender,
refundAmount
).rrevert();
}
}
}
}
文件 42 的 71:LibNativeOrdersRichErrors.sol
pragma solidity ^0.6.5;
library LibNativeOrdersRichErrors {
function ProtocolFeeRefundFailed(
address receiver,
uint256 refundAmount
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("ProtocolFeeRefundFailed(address,uint256)")),
receiver,
refundAmount
);
}
function OrderNotFillableByOriginError(
bytes32 orderHash,
address txOrigin,
address orderTxOrigin
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("OrderNotFillableByOriginError(bytes32,address,address)")),
orderHash,
txOrigin,
orderTxOrigin
);
}
function OrderNotFillableError(
bytes32 orderHash,
uint8 orderStatus
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("OrderNotFillableError(bytes32,uint8)")),
orderHash,
orderStatus
);
}
function OrderNotSignedByMakerError(
bytes32 orderHash,
address signer,
address maker
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("OrderNotSignedByMakerError(bytes32,address,address)")),
orderHash,
signer,
maker
);
}
function OrderNotSignedByTakerError(
bytes32 orderHash,
address signer,
address taker
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("OrderNotSignedByTakerError(bytes32,address,address)")),
orderHash,
signer,
taker
);
}
function InvalidSignerError(
address maker,
address signer
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("InvalidSignerError(address,address)")),
maker,
signer
);
}
function OrderNotFillableBySenderError(
bytes32 orderHash,
address sender,
address orderSender
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("OrderNotFillableBySenderError(bytes32,address,address)")),
orderHash,
sender,
orderSender
);
}
function OrderNotFillableByTakerError(
bytes32 orderHash,
address taker,
address orderTaker
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("OrderNotFillableByTakerError(bytes32,address,address)")),
orderHash,
taker,
orderTaker
);
}
function CancelSaltTooLowError(
uint256 minValidSalt,
uint256 oldMinValidSalt
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("CancelSaltTooLowError(uint256,uint256)")),
minValidSalt,
oldMinValidSalt
);
}
function FillOrKillFailedError(
bytes32 orderHash,
uint256 takerTokenFilledAmount,
uint256 takerTokenFillAmount
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("FillOrKillFailedError(bytes32,uint256,uint256)")),
orderHash,
takerTokenFilledAmount,
takerTokenFillAmount
);
}
function OnlyOrderMakerAllowed(
bytes32 orderHash,
address sender,
address maker
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("OnlyOrderMakerAllowed(bytes32,address,address)")),
orderHash,
sender,
maker
);
}
function BatchFillIncompleteError(
bytes32 orderHash,
uint256 takerTokenFilledAmount,
uint256 takerTokenFillAmount
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("BatchFillIncompleteError(bytes32,uint256,uint256)")),
orderHash,
takerTokenFilledAmount,
takerTokenFillAmount
);
}
}
文件 43 的 71:LibRichErrorsV06.sol
pragma solidity ^0.6.5;
library LibRichErrorsV06 {
bytes4 internal constant STANDARD_ERROR_SELECTOR = 0x08c379a0;
function StandardError(string memory message)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
STANDARD_ERROR_SELECTOR,
bytes(message)
);
}
function rrevert(bytes memory errorData)
internal
pure
{
assembly {
revert(add(errorData, 0x20), mload(errorData))
}
}
}
文件 44 的 71:LibSafeMathRichErrorsV06.sol
pragma solidity ^0.6.5;
library LibSafeMathRichErrorsV06 {
bytes4 internal constant UINT256_BINOP_ERROR_SELECTOR =
0xe946c1bb;
bytes4 internal constant UINT256_DOWNCAST_ERROR_SELECTOR =
0xc996af7b;
enum BinOpErrorCodes {
ADDITION_OVERFLOW,
MULTIPLICATION_OVERFLOW,
SUBTRACTION_UNDERFLOW,
DIVISION_BY_ZERO
}
enum DowncastErrorCodes {
VALUE_TOO_LARGE_TO_DOWNCAST_TO_UINT32,
VALUE_TOO_LARGE_TO_DOWNCAST_TO_UINT64,
VALUE_TOO_LARGE_TO_DOWNCAST_TO_UINT96,
VALUE_TOO_LARGE_TO_DOWNCAST_TO_UINT128
}
function Uint256BinOpError(
BinOpErrorCodes errorCode,
uint256 a,
uint256 b
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
UINT256_BINOP_ERROR_SELECTOR,
errorCode,
a,
b
);
}
function Uint256DowncastError(
DowncastErrorCodes errorCode,
uint256 a
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
UINT256_DOWNCAST_ERROR_SELECTOR,
errorCode,
a
);
}
}
文件 45 的 71:LibSafeMathV06.sol
pragma solidity ^0.6.5;
import "./errors/LibRichErrorsV06.sol";
import "./errors/LibSafeMathRichErrorsV06.sol";
library LibSafeMathV06 {
function safeMul(uint256 a, uint256 b)
internal
pure
returns (uint256)
{
if (a == 0) {
return 0;
}
uint256 c = a * b;
if (c / a != b) {
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
LibSafeMathRichErrorsV06.BinOpErrorCodes.MULTIPLICATION_OVERFLOW,
a,
b
));
}
return c;
}
function safeDiv(uint256 a, uint256 b)
internal
pure
returns (uint256)
{
if (b == 0) {
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
LibSafeMathRichErrorsV06.BinOpErrorCodes.DIVISION_BY_ZERO,
a,
b
));
}
uint256 c = a / b;
return c;
}
function safeSub(uint256 a, uint256 b)
internal
pure
returns (uint256)
{
if (b > a) {
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
LibSafeMathRichErrorsV06.BinOpErrorCodes.SUBTRACTION_UNDERFLOW,
a,
b
));
}
return a - b;
}
function safeAdd(uint256 a, uint256 b)
internal
pure
returns (uint256)
{
uint256 c = a + b;
if (c < a) {
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
LibSafeMathRichErrorsV06.BinOpErrorCodes.ADDITION_OVERFLOW,
a,
b
));
}
return c;
}
function max256(uint256 a, uint256 b)
internal
pure
returns (uint256)
{
return a >= b ? a : b;
}
function min256(uint256 a, uint256 b)
internal
pure
returns (uint256)
{
return a < b ? a : b;
}
function safeMul128(uint128 a, uint128 b)
internal
pure
returns (uint128)
{
if (a == 0) {
return 0;
}
uint128 c = a * b;
if (c / a != b) {
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
LibSafeMathRichErrorsV06.BinOpErrorCodes.MULTIPLICATION_OVERFLOW,
a,
b
));
}
return c;
}
function safeDiv128(uint128 a, uint128 b)
internal
pure
returns (uint128)
{
if (b == 0) {
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
LibSafeMathRichErrorsV06.BinOpErrorCodes.DIVISION_BY_ZERO,
a,
b
));
}
uint128 c = a / b;
return c;
}
function safeSub128(uint128 a, uint128 b)
internal
pure
returns (uint128)
{
if (b > a) {
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
LibSafeMathRichErrorsV06.BinOpErrorCodes.SUBTRACTION_UNDERFLOW,
a,
b
));
}
return a - b;
}
function safeAdd128(uint128 a, uint128 b)
internal
pure
returns (uint128)
{
uint128 c = a + b;
if (c < a) {
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
LibSafeMathRichErrorsV06.BinOpErrorCodes.ADDITION_OVERFLOW,
a,
b
));
}
return c;
}
function max128(uint128 a, uint128 b)
internal
pure
returns (uint128)
{
return a >= b ? a : b;
}
function min128(uint128 a, uint128 b)
internal
pure
returns (uint128)
{
return a < b ? a : b;
}
function safeDowncastToUint128(uint256 a)
internal
pure
returns (uint128)
{
if (a > type(uint128).max) {
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256DowncastError(
LibSafeMathRichErrorsV06.DowncastErrorCodes.VALUE_TOO_LARGE_TO_DOWNCAST_TO_UINT128,
a
));
}
return uint128(a);
}
}
文件 46 的 71:LibSignature.sol
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "../../errors/LibSignatureRichErrors.sol";
library LibSignature {
using LibRichErrorsV06 for bytes;
uint256 private constant ETH_SIGN_HASH_PREFIX =
0x19457468657265756d205369676e6564204d6573736167653a0a333200000000;
uint256 private constant ECDSA_SIGNATURE_R_LIMIT =
uint256(0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141);
uint256 private constant ECDSA_SIGNATURE_S_LIMIT = ECDSA_SIGNATURE_R_LIMIT / 2 + 1;
enum SignatureType {
ILLEGAL,
INVALID,
EIP712,
ETHSIGN
}
struct Signature {
SignatureType signatureType;
uint8 v;
bytes32 r;
bytes32 s;
}
function getSignerOfHash(
bytes32 hash,
Signature memory signature
)
internal
pure
returns (address recovered)
{
_validateHashCompatibleSignature(hash, signature);
if (signature.signatureType == SignatureType.EIP712) {
recovered = ecrecover(
hash,
signature.v,
signature.r,
signature.s
);
} else if (signature.signatureType == SignatureType.ETHSIGN) {
bytes32 ethSignHash;
assembly {
mstore(0, ETH_SIGN_HASH_PREFIX)
mstore(28, hash)
ethSignHash := keccak256(0, 60)
}
recovered = ecrecover(
ethSignHash,
signature.v,
signature.r,
signature.s
);
}
if (recovered == address(0)) {
LibSignatureRichErrors.SignatureValidationError(
LibSignatureRichErrors.SignatureValidationErrorCodes.BAD_SIGNATURE_DATA,
hash
).rrevert();
}
}
function _validateHashCompatibleSignature(
bytes32 hash,
Signature memory signature
)
private
pure
{
if (uint256(signature.r) >= ECDSA_SIGNATURE_R_LIMIT ||
uint256(signature.s) >= ECDSA_SIGNATURE_S_LIMIT)
{
LibSignatureRichErrors.SignatureValidationError(
LibSignatureRichErrors.SignatureValidationErrorCodes.BAD_SIGNATURE_DATA,
hash
).rrevert();
}
if (signature.signatureType == SignatureType.ILLEGAL) {
LibSignatureRichErrors.SignatureValidationError(
LibSignatureRichErrors.SignatureValidationErrorCodes.ILLEGAL,
hash
).rrevert();
}
if (signature.signatureType == SignatureType.INVALID) {
LibSignatureRichErrors.SignatureValidationError(
LibSignatureRichErrors.SignatureValidationErrorCodes.ALWAYS_INVALID,
hash
).rrevert();
}
}
}
文件 47 的 71:LibSignatureRichErrors.sol
pragma solidity ^0.6.5;
library LibSignatureRichErrors {
enum SignatureValidationErrorCodes {
ALWAYS_INVALID,
INVALID_LENGTH,
UNSUPPORTED,
ILLEGAL,
WRONG_SIGNER,
BAD_SIGNATURE_DATA
}
function SignatureValidationError(
SignatureValidationErrorCodes code,
bytes32 hash,
address signerAddress,
bytes memory signature
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("SignatureValidationError(uint8,bytes32,address,bytes)")),
code,
hash,
signerAddress,
signature
);
}
function SignatureValidationError(
SignatureValidationErrorCodes code,
bytes32 hash
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("SignatureValidationError(uint8,bytes32)")),
code,
hash
);
}
}
文件 48 的 71:Manager.sol
pragma solidity 0.6.11;
pragma experimental ABIEncoderV2;
import "../interfaces/IManager.sol";
import "../interfaces/ILiquidityPool.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";
import {IERC20Upgradeable as IERC20} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import {SafeERC20Upgradeable as SafeERC20} from "@openzeppelin/contracts-upgradeable/token/ERC20/SafeERC20Upgradeable.sol";
import {EnumerableSetUpgradeable as EnumerableSet} from "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol";
import {SafeMathUpgradeable as SafeMath} from "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";
import {AccessControlUpgradeable as AccessControl} from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
contract Manager is IManager, Initializable, AccessControl {
using SafeMath for uint256;
using SafeERC20 for IERC20;
using Address for address;
using EnumerableSet for EnumerableSet.AddressSet;
using EnumerableSet for EnumerableSet.Bytes32Set;
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant ROLLOVER_ROLE = keccak256("ROLLOVER_ROLE");
bytes32 public constant MID_CYCLE_ROLE = keccak256("MID_CYCLE_ROLE");
uint256 public currentCycle;
uint256 public currentCycleIndex;
uint256 public cycleDuration;
bool public rolloverStarted;
mapping(bytes32 => address) public registeredControllers;
mapping(uint256 => string) public override cycleRewardsHashes;
EnumerableSet.AddressSet private pools;
EnumerableSet.Bytes32Set private controllerIds;
modifier onlyAdmin() {
require(hasRole(ADMIN_ROLE, _msgSender()), "NOT_ADMIN_ROLE");
_;
}
modifier onlyRollover() {
require(hasRole(ROLLOVER_ROLE, _msgSender()), "NOT_ROLLOVER_ROLE");
_;
}
modifier onlyMidCycle() {
require(hasRole(MID_CYCLE_ROLE, _msgSender()), "NOT_MID_CYCLE_ROLE");
_;
}
function initialize(uint256 _cycleDuration) public initializer {
__Context_init_unchained();
__AccessControl_init_unchained();
cycleDuration = _cycleDuration;
_setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
_setupRole(ADMIN_ROLE, _msgSender());
_setupRole(ROLLOVER_ROLE, _msgSender());
_setupRole(MID_CYCLE_ROLE, _msgSender());
}
function registerController(bytes32 id, address controller) external override onlyAdmin {
require(!controllerIds.contains(id), "CONTROLLER_EXISTS");
registeredControllers[id] = controller;
controllerIds.add(id);
emit ControllerRegistered(id, controller);
}
function unRegisterController(bytes32 id) external override onlyAdmin {
require(controllerIds.contains(id), "INVALID_CONTROLLER");
emit ControllerUnregistered(id, registeredControllers[id]);
delete registeredControllers[id];
controllerIds.remove(id);
}
function registerPool(address pool) external override onlyAdmin {
require(!pools.contains(pool), "POOL_EXISTS");
pools.add(pool);
emit PoolRegistered(pool);
}
function unRegisterPool(address pool) external override onlyAdmin {
require(pools.contains(pool), "INVALID_POOL");
pools.remove(pool);
emit PoolUnregistered(pool);
}
function setCycleDuration(uint256 duration) external override onlyAdmin {
cycleDuration = duration;
emit CycleDurationSet(duration);
}
function getPools() external view override returns (address[] memory) {
address[] memory returnData = new address[](pools.length());
for (uint256 i = 0; i < pools.length(); i++) {
returnData[i] = pools.at(i);
}
return returnData;
}
function getControllers() external view override returns (bytes32[] memory) {
bytes32[] memory returnData = new bytes32[](controllerIds.length());
for (uint256 i = 0; i < controllerIds.length(); i++) {
returnData[i] = controllerIds.at(i);
}
return returnData;
}
function completeRollover(string calldata rewardsIpfsHash) external override onlyRollover {
require(block.number > (currentCycle.add(cycleDuration)), "PREMATURE_EXECUTION");
_completeRollover(rewardsIpfsHash);
}
function executeMaintenance(MaintenanceExecution calldata params)
external
override
onlyMidCycle
{
for (uint256 x = 0; x < params.cycleSteps.length; x++) {
_executeControllerCommand(params.cycleSteps[x]);
}
}
function executeRollover(RolloverExecution calldata params) external override onlyRollover {
require(block.number > (currentCycle.add(cycleDuration)), "PREMATURE_EXECUTION");
for (uint256 i = 0; i < params.poolData.length; i++) {
require(pools.contains(params.poolData[i].pool), "INVALID_POOL");
ILiquidityPool pool = ILiquidityPool(params.poolData[i].pool);
IERC20 underlyingToken = pool.underlyer();
underlyingToken.safeTransferFrom(
address(pool),
address(this),
params.poolData[i].amount
);
emit LiquidityMovedToManager(params.poolData[i].pool, params.poolData[i].amount);
}
for (uint256 x = 0; x < params.cycleSteps.length; x++) {
_executeControllerCommand(params.cycleSteps[x]);
}
for (uint256 y = 0; y < params.poolsForWithdraw.length; y++) {
require(pools.contains(params.poolsForWithdraw[y]), "INVALID_POOL");
ILiquidityPool pool = ILiquidityPool(params.poolsForWithdraw[y]);
IERC20 underlyingToken = pool.underlyer();
uint256 managerBalance = underlyingToken.balanceOf(address(this));
if (managerBalance > 0) {
underlyingToken.safeTransfer(address(pool), managerBalance);
}
emit LiquidityMovedToPool(params.poolsForWithdraw[y], managerBalance);
}
if (params.complete) {
_completeRollover(params.rewardsIpfsHash);
}
}
function _executeControllerCommand(ControllerTransferData calldata transfer) private {
address controllerAddress = registeredControllers[transfer.controllerId];
require(controllerAddress != address(0), "INVALID_CONTROLLER");
controllerAddress.functionDelegateCall(transfer.data, "CYCLE_STEP_EXECUTE_FAILED");
emit DeploymentStepExecuted(transfer.controllerId, controllerAddress, transfer.data);
}
function startCycleRollover() external override onlyRollover {
rolloverStarted = true;
emit CycleRolloverStarted(block.number);
}
function _completeRollover(string calldata rewardsIpfsHash) private {
currentCycle = block.number;
cycleRewardsHashes[currentCycleIndex] = rewardsIpfsHash;
currentCycleIndex = currentCycleIndex.add(1);
rolloverStarted = false;
emit CycleRolloverComplete(block.number);
}
function getCurrentCycle() external view override returns (uint256) {
return currentCycle;
}
function getCycleDuration() external view override returns (uint256) {
return cycleDuration;
}
function getCurrentCycleIndex() external view override returns (uint256) {
return currentCycleIndex;
}
function getRolloverStatus() external view override returns (bool) {
return rolloverStarted;
}
}
文件 49 的 71:Math.sol
pragma solidity >=0.6.0 <0.8.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);
}
}
文件 50 的 71:MathUpgradeable.sol
pragma solidity >=0.6.0 <0.8.0;
library MathUpgradeable {
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);
}
}
文件 51 的 71:MerkleProof.sol
pragma solidity >=0.6.0 <0.8.0;
library MerkleProof {
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
bytes32 proofElement = proof[i];
if (computedHash <= proofElement) {
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
} else {
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
}
}
return computedHash == root;
}
}
文件 52 的 71:MockContract.sol
pragma solidity ^0.6.0;
interface MockInterface {
function givenAnyReturn(bytes calldata response) external;
function givenAnyReturnBool(bool response) external;
function givenAnyReturnUint(uint response) external;
function givenAnyReturnAddress(address response) external;
function givenAnyRevert() external;
function givenAnyRevertWithMessage(string calldata message) external;
function givenAnyRunOutOfGas() external;
function givenMethodReturn(bytes calldata method, bytes calldata response) external;
function givenMethodReturnBool(bytes calldata method, bool response) external;
function givenMethodReturnUint(bytes calldata method, uint response) external;
function givenMethodReturnAddress(bytes calldata method, address response) external;
function givenMethodRevert(bytes calldata method) external;
function givenMethodRevertWithMessage(bytes calldata method, string calldata message) external;
function givenMethodRunOutOfGas(bytes calldata method) external;
function givenCalldataReturn(bytes calldata call, bytes calldata response) external;
function givenCalldataReturnBool(bytes calldata call, bool response) external;
function givenCalldataReturnUint(bytes calldata call, uint response) external;
function givenCalldataReturnAddress(bytes calldata call, address response) external;
function givenCalldataRevert(bytes calldata call) external;
function givenCalldataRevertWithMessage(bytes calldata call, string calldata message) external;
function givenCalldataRunOutOfGas(bytes calldata call) external;
function invocationCount() external returns (uint);
function invocationCountForMethod(bytes calldata method) external returns (uint);
function invocationCountForCalldata(bytes calldata call) external returns (uint);
function reset() external;
}
contract MockContract is MockInterface {
enum MockType { Return, Revert, OutOfGas }
bytes32 public constant MOCKS_LIST_START = hex"01";
bytes public constant MOCKS_LIST_END = "0xff";
bytes32 public constant MOCKS_LIST_END_HASH = keccak256(MOCKS_LIST_END);
bytes4 public constant SENTINEL_ANY_MOCKS = hex"01";
bytes public constant DEFAULT_FALLBACK_VALUE = abi.encode(false);
mapping(bytes32 => bytes) calldataMocks;
mapping(bytes => MockType) calldataMockTypes;
mapping(bytes => bytes) calldataExpectations;
mapping(bytes => string) calldataRevertMessage;
mapping(bytes32 => uint) calldataInvocations;
mapping(bytes4 => bytes4) methodIdMocks;
mapping(bytes4 => MockType) methodIdMockTypes;
mapping(bytes4 => bytes) methodIdExpectations;
mapping(bytes4 => string) methodIdRevertMessages;
mapping(bytes32 => uint) methodIdInvocations;
MockType fallbackMockType;
bytes fallbackExpectation = DEFAULT_FALLBACK_VALUE;
string fallbackRevertMessage;
uint invocations;
uint resetCount;
constructor() public {
calldataMocks[MOCKS_LIST_START] = MOCKS_LIST_END;
methodIdMocks[SENTINEL_ANY_MOCKS] = SENTINEL_ANY_MOCKS;
}
function trackCalldataMock(bytes memory call) private {
bytes32 callHash = keccak256(call);
if (calldataMocks[callHash].length == 0) {
calldataMocks[callHash] = calldataMocks[MOCKS_LIST_START];
calldataMocks[MOCKS_LIST_START] = call;
}
}
function trackMethodIdMock(bytes4 methodId) private {
if (methodIdMocks[methodId] == 0x0) {
methodIdMocks[methodId] = methodIdMocks[SENTINEL_ANY_MOCKS];
methodIdMocks[SENTINEL_ANY_MOCKS] = methodId;
}
}
function _givenAnyReturn(bytes memory response) internal {
fallbackMockType = MockType.Return;
fallbackExpectation = response;
}
function givenAnyReturn(bytes calldata response) override external {
_givenAnyReturn(response);
}
function givenAnyReturnBool(bool response) override external {
uint flag = response ? 1 : 0;
_givenAnyReturn(uintToBytes(flag));
}
function givenAnyReturnUint(uint response) override external {
_givenAnyReturn(uintToBytes(response));
}
function givenAnyReturnAddress(address response) override external {
_givenAnyReturn(uintToBytes(uint(response)));
}
function givenAnyRevert() override external {
fallbackMockType = MockType.Revert;
fallbackRevertMessage = "";
}
function givenAnyRevertWithMessage(string calldata message) override external {
fallbackMockType = MockType.Revert;
fallbackRevertMessage = message;
}
function givenAnyRunOutOfGas() override external {
fallbackMockType = MockType.OutOfGas;
}
function _givenCalldataReturn(bytes memory call, bytes memory response) private {
calldataMockTypes[call] = MockType.Return;
calldataExpectations[call] = response;
trackCalldataMock(call);
}
function givenCalldataReturn(bytes calldata call, bytes calldata response) override external {
_givenCalldataReturn(call, response);
}
function givenCalldataReturnBool(bytes calldata call, bool response) override external {
uint flag = response ? 1 : 0;
_givenCalldataReturn(call, uintToBytes(flag));
}
function givenCalldataReturnUint(bytes calldata call, uint response) override external {
_givenCalldataReturn(call, uintToBytes(response));
}
function givenCalldataReturnAddress(bytes calldata call, address response) override external {
_givenCalldataReturn(call, uintToBytes(uint(response)));
}
function _givenMethodReturn(bytes memory call, bytes memory response) private {
bytes4 method = bytesToBytes4(call);
methodIdMockTypes[method] = MockType.Return;
methodIdExpectations[method] = response;
trackMethodIdMock(method);
}
function givenMethodReturn(bytes calldata call, bytes calldata response) override external {
_givenMethodReturn(call, response);
}
function givenMethodReturnBool(bytes calldata call, bool response) override external {
uint flag = response ? 1 : 0;
_givenMethodReturn(call, uintToBytes(flag));
}
function givenMethodReturnUint(bytes calldata call, uint response) override external {
_givenMethodReturn(call, uintToBytes(response));
}
function givenMethodReturnAddress(bytes calldata call, address response) override external {
_givenMethodReturn(call, uintToBytes(uint(response)));
}
function givenCalldataRevert(bytes calldata call) override external {
calldataMockTypes[call] = MockType.Revert;
calldataRevertMessage[call] = "";
trackCalldataMock(call);
}
function givenMethodRevert(bytes calldata call) override external {
bytes4 method = bytesToBytes4(call);
methodIdMockTypes[method] = MockType.Revert;
trackMethodIdMock(method);
}
function givenCalldataRevertWithMessage(bytes calldata call, string calldata message) override external {
calldataMockTypes[call] = MockType.Revert;
calldataRevertMessage[call] = message;
trackCalldataMock(call);
}
function givenMethodRevertWithMessage(bytes calldata call, string calldata message) override external {
bytes4 method = bytesToBytes4(call);
methodIdMockTypes[method] = MockType.Revert;
methodIdRevertMessages[method] = message;
trackMethodIdMock(method);
}
function givenCalldataRunOutOfGas(bytes calldata call) override external {
calldataMockTypes[call] = MockType.OutOfGas;
trackCalldataMock(call);
}
function givenMethodRunOutOfGas(bytes calldata call) override external {
bytes4 method = bytesToBytes4(call);
methodIdMockTypes[method] = MockType.OutOfGas;
trackMethodIdMock(method);
}
function invocationCount() override external returns (uint) {
return invocations;
}
function invocationCountForMethod(bytes calldata call) override external returns (uint) {
bytes4 method = bytesToBytes4(call);
return methodIdInvocations[keccak256(abi.encodePacked(resetCount, method))];
}
function invocationCountForCalldata(bytes calldata call) override external returns (uint) {
return calldataInvocations[keccak256(abi.encodePacked(resetCount, call))];
}
function reset() override external {
bytes memory nextMock = calldataMocks[MOCKS_LIST_START];
bytes32 mockHash = keccak256(nextMock);
while(mockHash != MOCKS_LIST_END_HASH) {
calldataMockTypes[nextMock] = MockType.Return;
calldataExpectations[nextMock] = hex"";
calldataRevertMessage[nextMock] = "";
nextMock = calldataMocks[mockHash];
calldataMocks[mockHash] = "";
mockHash = keccak256(nextMock);
}
calldataMocks[MOCKS_LIST_START] = MOCKS_LIST_END;
bytes4 nextAnyMock = methodIdMocks[SENTINEL_ANY_MOCKS];
while(nextAnyMock != SENTINEL_ANY_MOCKS) {
bytes4 currentAnyMock = nextAnyMock;
methodIdMockTypes[currentAnyMock] = MockType.Return;
methodIdExpectations[currentAnyMock] = hex"";
methodIdRevertMessages[currentAnyMock] = "";
nextAnyMock = methodIdMocks[currentAnyMock];
methodIdMocks[currentAnyMock] = 0x0;
}
methodIdMocks[SENTINEL_ANY_MOCKS] = SENTINEL_ANY_MOCKS;
fallbackExpectation = DEFAULT_FALLBACK_VALUE;
fallbackMockType = MockType.Return;
invocations = 0;
resetCount += 1;
}
function useAllGas() private {
while(true) {
bool s;
assembly {
s := call(sub(gas(), 2000), 6, 0, 0x0, 0xc0, 0x0, 0x60)
}
}
}
function bytesToBytes4(bytes memory b) private pure returns (bytes4) {
bytes4 out;
for (uint i = 0; i < 4; i++) {
out |= bytes4(b[i] & 0xFF) >> (i * 8);
}
return out;
}
function uintToBytes(uint256 x) private pure returns (bytes memory b) {
b = new bytes(32);
assembly { mstore(add(b, 32), x) }
}
function updateInvocationCount(bytes4 methodId, bytes memory originalMsgData) public {
require(msg.sender == address(this), "Can only be called from the contract itself");
invocations += 1;
methodIdInvocations[keccak256(abi.encodePacked(resetCount, methodId))] += 1;
calldataInvocations[keccak256(abi.encodePacked(resetCount, originalMsgData))] += 1;
}
fallback () payable external {
bytes4 methodId;
assembly {
methodId := calldataload(0)
}
if (calldataMockTypes[msg.data] == MockType.Revert) {
revert(calldataRevertMessage[msg.data]);
}
if (calldataMockTypes[msg.data] == MockType.OutOfGas) {
useAllGas();
}
bytes memory result = calldataExpectations[msg.data];
if (result.length == 0) {
if (methodIdMockTypes[methodId] == MockType.Revert) {
revert(methodIdRevertMessages[methodId]);
}
if (methodIdMockTypes[methodId] == MockType.OutOfGas) {
useAllGas();
}
result = methodIdExpectations[methodId];
}
if (result.length == 0) {
if (fallbackMockType == MockType.Revert) {
revert(fallbackRevertMessage);
}
if (fallbackMockType == MockType.OutOfGas) {
useAllGas();
}
result = fallbackExpectation;
}
(, bytes memory r) = address(this).call{gas: 100000}(abi.encodeWithSignature("updateInvocationCount(bytes4,bytes)", methodId, msg.data));
assert(r.length == 0);
assembly {
return(add(0x20, result), mload(result))
}
}
}
文件 53 的 71:Ownable.sol
pragma solidity >=0.6.0 <0.8.0;
import "../utils/Context.sol";
abstract 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 virtual 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;
}
}
文件 54 的 71:OwnableUpgradeable.sol
pragma solidity >=0.6.0 <0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/Initializable.sol";
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
function __Ownable_init() internal initializer {
__Context_init_unchained();
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal initializer {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view virtual 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;
}
uint256[49] private __gap;
}
文件 55 的 71:Pausable.sol
pragma solidity >=0.6.0 <0.8.0;
import "./Context.sol";
abstract contract Pausable is Context {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
constructor () internal {
_paused = false;
}
function paused() public view virtual returns (bool) {
return _paused;
}
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
文件 56 的 71:PausableUpgradeable.sol
pragma solidity >=0.6.0 <0.8.0;
import "./ContextUpgradeable.sol";
import "../proxy/Initializable.sol";
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
function __Pausable_init() internal initializer {
__Context_init_unchained();
__Pausable_init_unchained();
}
function __Pausable_init_unchained() internal initializer {
_paused = false;
}
function paused() public view virtual returns (bool) {
return _paused;
}
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
uint256[49] private __gap;
}
文件 57 的 71:Pool.sol
pragma solidity 0.6.11;
import "../interfaces/ILiquidityPool.sol";
import "../interfaces/IManager.sol";
import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";
import {SafeMathUpgradeable as SafeMath} from "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";
import {MathUpgradeable as Math} from "@openzeppelin/contracts-upgradeable/math/MathUpgradeable.sol";
import {OwnableUpgradeable as Ownable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {ERC20Upgradeable as ERC20} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import {IERC20Upgradeable as IERC20} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import {SafeERC20Upgradeable as SafeERC20} from "@openzeppelin/contracts-upgradeable/token/ERC20/SafeERC20Upgradeable.sol";
import {PausableUpgradeable as Pausable} from "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol";
contract Pool is ILiquidityPool, Initializable, ERC20, Ownable, Pausable {
using SafeMath for uint256;
using SafeERC20 for ERC20;
ERC20 public override underlyer;
IManager public manager;
uint256 public override withheldLiquidity;
mapping(address => WithdrawalInfo) public override requestedWithdrawals;
function initialize(
ERC20 _underlyer,
IManager _manager,
string memory _name,
string memory _symbol
) public initializer {
require(address(_underlyer) != address(0), "ZERO_ADDRESS");
require(address(_manager) != address(0), "ZERO_ADDRESS");
__Context_init_unchained();
__Ownable_init_unchained();
__Pausable_init_unchained();
__ERC20_init_unchained(_name, _symbol);
underlyer = _underlyer;
manager = _manager;
}
function decimals() public view override returns (uint8) {
return underlyer.decimals();
}
function deposit(uint256 amount) external override whenNotPaused {
_deposit(msg.sender, msg.sender, amount);
}
function depositFor(address account, uint256 amount) external override whenNotPaused {
_deposit(msg.sender, account, amount);
}
function withdraw(uint256 requestedAmount) external override whenNotPaused {
require(
requestedAmount <= requestedWithdrawals[msg.sender].amount,
"WITHDRAW_INSUFFICIENT_BALANCE"
);
require(requestedAmount > 0, "NO_WITHDRAWAL");
require(underlyer.balanceOf(address(this)) >= requestedAmount, "INSUFFICIENT_POOL_BALANCE");
require(
requestedWithdrawals[msg.sender].minCycle <= manager.getCurrentCycleIndex(),
"INVALID_CYCLE"
);
requestedWithdrawals[msg.sender].amount = requestedWithdrawals[msg.sender].amount.sub(
requestedAmount
);
if (requestedWithdrawals[msg.sender].amount == 0) {
delete requestedWithdrawals[msg.sender];
}
withheldLiquidity = withheldLiquidity.sub(requestedAmount);
_burn(msg.sender, requestedAmount);
underlyer.safeTransfer(msg.sender, requestedAmount);
}
function requestWithdrawal(uint256 amount) external override {
require(amount > 0, "INVALID_AMOUNT");
require(amount <= balanceOf(msg.sender), "INSUFFICIENT_BALANCE");
withheldLiquidity = withheldLiquidity.sub(requestedWithdrawals[msg.sender].amount).add(
amount
);
requestedWithdrawals[msg.sender].amount = amount;
if (manager.getRolloverStatus()) {
requestedWithdrawals[msg.sender].minCycle = manager.getCurrentCycleIndex().add(2);
} else {
requestedWithdrawals[msg.sender].minCycle = manager.getCurrentCycleIndex().add(1);
}
}
function preTransferAdjustWithheldLiquidity(address sender, uint256 amount) internal {
if (requestedWithdrawals[sender].amount > 0) {
uint256 newRequestedWithdrawl = requestedWithdrawals[sender].amount.sub(
Math.min(amount, requestedWithdrawals[sender].amount)
);
withheldLiquidity = withheldLiquidity.sub(
requestedWithdrawals[sender].amount.sub(newRequestedWithdrawl)
);
requestedWithdrawals[sender].amount = newRequestedWithdrawl;
if (requestedWithdrawals[sender].amount == 0) {
delete requestedWithdrawals[sender];
}
}
}
function approveManager(uint256 amount) public override onlyOwner {
uint256 currentAllowance = underlyer.allowance(address(this), address(manager));
if (currentAllowance < amount) {
uint256 delta = amount.sub(currentAllowance);
underlyer.safeIncreaseAllowance(address(manager), delta);
} else {
uint256 delta = currentAllowance.sub(amount);
underlyer.safeDecreaseAllowance(address(manager), delta);
}
}
function transfer(address recipient, uint256 amount)
public
override
whenNotPaused
returns (bool)
{
preTransferAdjustWithheldLiquidity(msg.sender, amount);
return super.transfer(recipient, amount);
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public override whenNotPaused returns (bool) {
preTransferAdjustWithheldLiquidity(sender, amount);
return super.transferFrom(sender, recipient, amount);
}
function pause() external override onlyOwner {
_pause();
}
function unpause() external override onlyOwner {
_unpause();
}
function _deposit(
address fromAccount,
address toAccount,
uint256 amount
) internal {
require(amount > 0, "INVALID_AMOUNT");
require(toAccount != address(0), "INVALID_ADDRESS");
_mint(toAccount, amount);
underlyer.safeTransferFrom(fromAccount, address(this), amount);
}
}
文件 58 的 71:PreToke.sol
pragma solidity 0.6.11;
import "@openzeppelin/contracts/presets/ERC20PresetMinterPauser.sol";
contract PreToke is ERC20PresetMinterPauser("PreToke", "PTOKE") {
}
文件 59 的 71:Redeem.sol
pragma solidity 0.6.11;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "../interfaces/IStaking.sol";
contract Redeem is Ownable {
using SafeERC20 for IERC20;
address public immutable fromToken;
address public immutable toToken;
address public immutable stakingContract;
uint256 public immutable expirationBlock;
uint256 public immutable stakingSchedule;
constructor(
address _fromToken,
address _toToken,
address _stakingContract,
uint256 _expirationBlock,
uint256 _stakingSchedule
) public {
require(_fromToken != address(0), "INVALID_FROMTOKEN");
require(_toToken != address(0), "INVALID_TOTOKEN");
require(_stakingContract != address(0), "INVALID_STAKING");
fromToken = _fromToken;
toToken = _toToken;
stakingContract = _stakingContract;
expirationBlock = _expirationBlock;
stakingSchedule = _stakingSchedule;
IERC20(_toToken).safeApprove(_stakingContract, type(uint256).max);
}
function convert() external {
uint256 fromBal = IERC20(fromToken).balanceOf(msg.sender);
require(fromBal > 0, "INSUFFICIENT_BALANCE");
ERC20Burnable(fromToken).burnFrom(msg.sender, fromBal);
IStaking(stakingContract).depositFor(msg.sender, fromBal, stakingSchedule);
}
function recoupRemaining() external onlyOwner {
require(block.number >= expirationBlock, "EXPIRATION_NOT_PASSED");
uint256 bal = IERC20(toToken).balanceOf(address(this));
IERC20(toToken).safeTransfer(msg.sender, bal);
}
}
文件 60 的 71:Rewards.sol
pragma solidity 0.6.11;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/math/Math.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
contract Rewards is Ownable {
using SafeMath for uint256;
using ECDSA for bytes32;
using SafeERC20 for IERC20;
mapping(address => uint256) public claimedAmounts;
event SignerSet(address newSigner);
event Claimed(uint256 cycle, address recipient, uint256 amount);
struct EIP712Domain {
string name;
string version;
uint256 chainId;
address verifyingContract;
}
struct Recipient {
uint256 chainId;
uint256 cycle;
address wallet;
uint256 amount;
}
bytes32 private constant EIP712_DOMAIN_TYPEHASH =
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
bytes32 private constant RECIPIENT_TYPEHASH =
keccak256("Recipient(uint256 chainId,uint256 cycle,address wallet,uint256 amount)");
bytes32 private immutable domainSeparator;
IERC20 public immutable tokeToken;
address public rewardsSigner;
constructor(IERC20 token, address signerAddress) public {
require(address(token) != address(0), "Invalid TOKE Address");
require(signerAddress != address(0), "Invalid Signer Address");
tokeToken = token;
rewardsSigner = signerAddress;
domainSeparator = _hashDomain(
EIP712Domain({
name: "TOKE Distribution",
version: "1",
chainId: _getChainID(),
verifyingContract: address(this)
})
);
}
function _hashDomain(EIP712Domain memory eip712Domain) private pure returns (bytes32) {
return
keccak256(
abi.encode(
EIP712_DOMAIN_TYPEHASH,
keccak256(bytes(eip712Domain.name)),
keccak256(bytes(eip712Domain.version)),
eip712Domain.chainId,
eip712Domain.verifyingContract
)
);
}
function _hashRecipient(Recipient memory recipient) private pure returns (bytes32) {
return
keccak256(
abi.encode(
RECIPIENT_TYPEHASH,
recipient.chainId,
recipient.cycle,
recipient.wallet,
recipient.amount
)
);
}
function _hash(Recipient memory recipient) private view returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, _hashRecipient(recipient)));
}
function _getChainID() private pure returns (uint256) {
uint256 id;
assembly {
id := chainid()
}
return id;
}
function setSigner(address newSigner) external onlyOwner {
require(newSigner != address(0), "Invalid Signer Address");
rewardsSigner = newSigner;
}
function getClaimableAmount(
Recipient calldata recipient
) external view returns (uint256) {
return recipient.amount.sub(claimedAmounts[recipient.wallet]);
}
function claim(
Recipient calldata recipient,
uint8 v,
bytes32 r,
bytes32 s
) external {
address signatureSigner = _hash(recipient).recover(v, r, s);
require(signatureSigner == rewardsSigner, "Invalid Signature");
require(recipient.chainId == _getChainID(), "Invalid chainId");
require(recipient.wallet == msg.sender, "Sender wallet Mismatch");
uint256 claimableAmount = recipient.amount.sub(claimedAmounts[recipient.wallet]);
require(claimableAmount > 0, "Invalid claimable amount");
require(tokeToken.balanceOf(address(this)) >= claimableAmount, "Insufficient Funds");
claimedAmounts[recipient.wallet] = claimedAmounts[recipient.wallet].add(claimableAmount);
tokeToken.safeTransfer(recipient.wallet, claimableAmount);
emit Claimed(recipient.cycle, recipient.wallet, claimableAmount);
}
}
文件 61 的 71:SafeCast.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeCast {
function toUint128(uint256 value) internal pure returns (uint128) {
require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits");
return uint128(value);
}
function toUint64(uint256 value) internal pure returns (uint64) {
require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits");
return uint64(value);
}
function toUint32(uint256 value) internal pure returns (uint32) {
require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits");
return uint32(value);
}
function toUint16(uint256 value) internal pure returns (uint16) {
require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits");
return uint16(value);
}
function toUint8(uint256 value) internal pure returns (uint8) {
require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits");
return uint8(value);
}
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
function toInt128(int256 value) internal pure returns (int128) {
require(value >= -2**127 && value < 2**127, "SafeCast: value doesn\'t fit in 128 bits");
return int128(value);
}
function toInt64(int256 value) internal pure returns (int64) {
require(value >= -2**63 && value < 2**63, "SafeCast: value doesn\'t fit in 64 bits");
return int64(value);
}
function toInt32(int256 value) internal pure returns (int32) {
require(value >= -2**31 && value < 2**31, "SafeCast: value doesn\'t fit in 32 bits");
return int32(value);
}
function toInt16(int256 value) internal pure returns (int16) {
require(value >= -2**15 && value < 2**15, "SafeCast: value doesn\'t fit in 16 bits");
return int16(value);
}
function toInt8(int256 value) internal pure returns (int8) {
require(value >= -2**7 && value < 2**7, "SafeCast: value doesn\'t fit in 8 bits");
return int8(value);
}
function toInt256(uint256 value) internal pure returns (int256) {
require(value < 2**255, "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}
文件 62 的 71:SafeERC20.sol
pragma solidity >=0.6.0 <0.8.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");
}
}
}
文件 63 的 71:SafeERC20Upgradeable.sol
pragma solidity >=0.6.0 <0.8.0;
import "./IERC20Upgradeable.sol";
import "../../math/SafeMathUpgradeable.sol";
import "../../utils/AddressUpgradeable.sol";
library SafeERC20Upgradeable {
using SafeMathUpgradeable for uint256;
using AddressUpgradeable for address;
function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20Upgradeable 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(IERC20Upgradeable 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(IERC20Upgradeable 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(IERC20Upgradeable 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");
}
}
}
文件 64 的 71:SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
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) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
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) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
文件 65 的 71:SafeMathUpgradeable.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeMathUpgradeable {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
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) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
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) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
文件 66 的 71:Staking.sol
pragma solidity 0.6.11;
pragma experimental ABIEncoderV2;
import "../interfaces/IStaking.sol";
import "../interfaces/IManager.sol";
import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";
import {SafeMathUpgradeable as SafeMath} from "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";
import {MathUpgradeable as Math} from "@openzeppelin/contracts-upgradeable/math/MathUpgradeable.sol";
import {IERC20Upgradeable as IERC20} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import {SafeERC20Upgradeable as SafeERC20} from "@openzeppelin/contracts-upgradeable/token/ERC20/SafeERC20Upgradeable.sol";
import {OwnableUpgradeable as Ownable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {EnumerableSetUpgradeable as EnumerableSet} from "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol";
import {PausableUpgradeable as Pausable} from "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol";
contract Staking is IStaking, Initializable, Ownable, Pausable {
using SafeMath for uint256;
using SafeERC20 for IERC20;
using EnumerableSet for EnumerableSet.UintSet;
IERC20 public tokeToken;
IManager public manager;
address public treasury;
uint256 public withheldLiquidity;
mapping(address => WithdrawalInfo) public requestedWithdrawals;
mapping(address => mapping(uint256 => StakingDetails)) public userStakings;
mapping(address => uint256[]) public userStakingSchedules;
uint256 public nextScheduleIndex;
mapping(uint256 => StakingSchedule) public schedules;
EnumerableSet.UintSet private scheduleIdxs;
mapping(address => bool) public override permissionedDepositors;
modifier onlyPermissionedDepositors() {
require(_isAllowedPermissionedDeposit(), "CALLER_NOT_PERMISSIONED");
_;
}
function initialize(
IERC20 _tokeToken,
IManager _manager,
address _treasury
) public initializer {
__Context_init_unchained();
__Ownable_init_unchained();
__Pausable_init_unchained();
require(address(_tokeToken) != address(0), "INVALID_TOKETOKEN");
require(address(_manager) != address(0), "INVALID_MANAGER");
require(_treasury != address(0), "INVALID_TREASURY");
tokeToken = _tokeToken;
manager = _manager;
treasury = _treasury;
_addSchedule(
StakingSchedule({
cliff: 0,
duration: 1,
interval: 1,
setup: true,
isActive: true,
hardStart: 0,
isPublic: true
})
);
}
function addSchedule(StakingSchedule memory schedule) external override onlyOwner {
_addSchedule(schedule);
}
function setPermissionedDepositor(address account, bool canDeposit)
external
override
onlyOwner
{
permissionedDepositors[account] = canDeposit;
}
function setUserSchedules(address account, uint256[] calldata userSchedulesIdxs)
external
override
onlyOwner
{
userStakingSchedules[account] = userSchedulesIdxs;
}
function getSchedules()
external
view
override
returns (StakingScheduleInfo[] memory retSchedules)
{
uint256 length = scheduleIdxs.length();
retSchedules = new StakingScheduleInfo[](length);
for (uint256 i = 0; i < length; i++) {
retSchedules[i] = StakingScheduleInfo(
schedules[scheduleIdxs.at(i)],
scheduleIdxs.at(i)
);
}
}
function removeSchedule(uint256 scheduleIndex) external override onlyOwner {
require(scheduleIdxs.contains(scheduleIndex), "INVALID_SCHEDULE");
scheduleIdxs.remove(scheduleIndex);
delete schedules[scheduleIndex];
emit ScheduleRemoved(scheduleIndex);
}
function getStakes(address account)
external
view
override
returns (StakingDetails[] memory stakes)
{
stakes = _getStakes(account);
}
function balanceOf(address account) external view override returns (uint256 value) {
value = 0;
uint256 scheduleCount = userStakingSchedules[account].length;
for (uint256 i = 0; i < scheduleCount; i++) {
uint256 remaining = userStakings[account][userStakingSchedules[account][i]].initial.sub(
userStakings[account][userStakingSchedules[account][i]].withdrawn
);
uint256 slashed = userStakings[account][userStakingSchedules[account][i]].slashed;
if (remaining > slashed) {
value = value.add(remaining.sub(slashed));
}
}
}
function availableForWithdrawal(address account, uint256 scheduleIndex)
external
view
override
returns (uint256)
{
return _availableForWithdrawal(account, scheduleIndex);
}
function unvested(address account, uint256 scheduleIndex)
external
view
override
returns (uint256 value)
{
value = 0;
StakingDetails memory stake = userStakings[account][scheduleIndex];
value = stake.initial.sub(_vested(account, scheduleIndex));
}
function vested(address account, uint256 scheduleIndex)
external
view
override
returns (uint256 value)
{
return _vested(account, scheduleIndex);
}
function deposit(uint256 amount, uint256 scheduleIndex) external override {
_depositFor(msg.sender, amount, scheduleIndex);
}
function depositFor(
address account,
uint256 amount,
uint256 scheduleIndex
) external override {
_depositFor(account, amount, scheduleIndex);
}
function depositWithSchedule(
address account,
uint256 amount,
StakingSchedule calldata schedule
) external override onlyPermissionedDepositors {
uint256 scheduleIx = nextScheduleIndex;
_addSchedule(schedule);
_depositFor(account, amount, scheduleIx);
}
function requestWithdrawal(uint256 amount) external override {
require(amount > 0, "INVALID_AMOUNT");
StakingDetails[] memory stakes = _getStakes(msg.sender);
uint256 length = stakes.length;
uint256 stakedAvailable = 0;
for (uint256 i = 0; i < length; i++) {
stakedAvailable = stakedAvailable.add(
_availableForWithdrawal(msg.sender, stakes[i].scheduleIx)
);
}
require(stakedAvailable >= amount, "INSUFFICIENT_AVAILABLE");
withheldLiquidity = withheldLiquidity.sub(requestedWithdrawals[msg.sender].amount).add(
amount
);
requestedWithdrawals[msg.sender].amount = amount;
if (manager.getRolloverStatus()) {
requestedWithdrawals[msg.sender].minCycleIndex = manager.getCurrentCycleIndex().add(2);
} else {
requestedWithdrawals[msg.sender].minCycleIndex = manager.getCurrentCycleIndex().add(1);
}
emit WithdrawalRequested(msg.sender, amount);
}
function withdraw(uint256 amount) external override {
require(amount <= requestedWithdrawals[msg.sender].amount, "WITHDRAW_INSUFFICIENT_BALANCE");
require(amount > 0, "NO_WITHDRAWAL");
require(
requestedWithdrawals[msg.sender].minCycleIndex <= manager.getCurrentCycleIndex(),
"INVALID_CYCLE"
);
StakingDetails[] memory stakes = _getStakes(msg.sender);
uint256 available = 0;
uint256 length = stakes.length;
uint256 remainingAmount = amount;
uint256 stakedAvailable = 0;
for (uint256 i = 0; i < length && remainingAmount > 0; i++) {
stakedAvailable = _availableForWithdrawal(msg.sender, stakes[i].scheduleIx);
available = available.add(stakedAvailable);
if (stakedAvailable < remainingAmount) {
remainingAmount = remainingAmount.sub(stakedAvailable);
stakes[i].withdrawn = stakes[i].withdrawn.add(stakedAvailable);
} else {
stakes[i].withdrawn = stakes[i].withdrawn.add(remainingAmount);
remainingAmount = 0;
}
userStakings[msg.sender][stakes[i].scheduleIx] = stakes[i];
}
require(remainingAmount == 0, "INSUFFICIENT_AVAILABLE");
requestedWithdrawals[msg.sender].amount = requestedWithdrawals[msg.sender].amount.sub(
amount
);
if (requestedWithdrawals[msg.sender].amount == 0) {
delete requestedWithdrawals[msg.sender];
}
withheldLiquidity = withheldLiquidity.sub(amount);
tokeToken.safeTransfer(msg.sender, amount);
emit WithdrawCompleted(msg.sender, amount);
}
function slash(
address account,
uint256 amount,
uint256 scheduleIndex
) external onlyOwner {
StakingSchedule storage schedule = schedules[scheduleIndex];
require(amount > 0, "INVALID_AMOUNT");
require(schedule.setup, "INVALID_SCHEDULE");
StakingDetails memory userStake = userStakings[account][scheduleIndex];
require(userStake.initial > 0, "NO_VESTING");
uint256 availableToSlash = 0;
uint256 remaining = userStake.initial.sub(userStake.withdrawn);
if (remaining > userStake.slashed) {
availableToSlash = remaining.sub(userStake.slashed);
}
require(availableToSlash >= amount, "INSUFFICIENT_AVAILABLE");
userStake.slashed = userStake.slashed.add(amount);
userStakings[account][scheduleIndex] = userStake;
tokeToken.safeTransfer(treasury, amount);
emit Slashed(account, amount, scheduleIndex);
}
function pause() external override onlyOwner {
_pause();
}
function unpause() external override onlyOwner {
_unpause();
}
function _availableForWithdrawal(address account, uint256 scheduleIndex)
private
view
returns (uint256)
{
StakingDetails memory stake = userStakings[account][scheduleIndex];
uint256 vestedWoWithdrawn = _vested(account, scheduleIndex).sub(stake.withdrawn);
if (stake.slashed > vestedWoWithdrawn) return 0;
return vestedWoWithdrawn.sub(stake.slashed);
}
function _depositFor(
address account,
uint256 amount,
uint256 scheduleIndex
) private {
StakingSchedule memory schedule = schedules[scheduleIndex];
require(!paused(), "Pausable: paused");
require(amount > 0, "INVALID_AMOUNT");
require(schedule.setup, "INVALID_SCHEDULE");
require(schedule.isActive, "INACTIVE_SCHEDULE");
require(account != address(0), "INVALID_ADDRESS");
require(schedule.isPublic || _isAllowedPermissionedDeposit(), "PERMISSIONED_SCHEDULE");
StakingDetails memory userStake = userStakings[account][scheduleIndex];
if (userStake.initial == 0) {
userStakingSchedules[account].push(scheduleIndex);
}
userStake.initial = userStake.initial.add(amount);
if (schedule.hardStart > 0) {
userStake.started = schedule.hardStart;
} else {
userStake.started = block.timestamp;
}
userStake.scheduleIx = scheduleIndex;
userStakings[account][scheduleIndex] = userStake;
tokeToken.safeTransferFrom(msg.sender, address(this), amount);
emit Deposited(account, amount, scheduleIndex);
}
function _vested(address account, uint256 scheduleIndex) private view returns (uint256) {
uint256 timestamp = block.timestamp;
uint256 value = 0;
StakingDetails memory stake = userStakings[account][scheduleIndex];
StakingSchedule memory schedule = schedules[scheduleIndex];
uint256 cliffTimestamp = stake.started.add(schedule.cliff);
if (cliffTimestamp <= timestamp) {
if (cliffTimestamp.add(schedule.duration) <= timestamp) {
value = stake.initial;
} else {
uint256 secondsStaked = Math.max(timestamp.sub(cliffTimestamp), 1);
uint256 effectiveSecondsStaked = (secondsStaked.mul(schedule.interval)).div(
schedule.interval
);
value = stake.initial.mul(effectiveSecondsStaked).div(schedule.duration);
}
}
return value;
}
function _addSchedule(StakingSchedule memory schedule) private {
require(schedule.duration > 0, "INVALID_DURATION");
require(schedule.interval > 0, "INVALID_INTERVAL");
schedule.setup = true;
uint256 index = nextScheduleIndex;
schedules[index] = schedule;
scheduleIdxs.add(index);
nextScheduleIndex = nextScheduleIndex.add(1);
emit ScheduleAdded(
index,
schedule.cliff,
schedule.duration,
schedule.interval,
schedule.setup,
schedule.isActive,
schedule.hardStart
);
}
function _getStakes(address account) private view returns (StakingDetails[] memory stakes) {
uint256 stakeCnt = userStakingSchedules[account].length;
stakes = new StakingDetails[](stakeCnt);
for (uint256 i = 0; i < stakeCnt; i++) {
stakes[i] = userStakings[account][userStakingSchedules[account][i]];
}
}
function _isAllowedPermissionedDeposit() private view returns (bool) {
return permissionedDepositors[msg.sender] || msg.sender == owner();
}
}
文件 67 的 71:SushiswapController.sol
pragma solidity 0.6.11;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Router02.sol";
import "@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol";
contract SushiswapController {
using SafeERC20 for IERC20;
using Address for address;
using Address for address payable;
using SafeMath for uint256;
IUniswapV2Router02 public immutable SUSHISWAP_ROUTER;
IUniswapV2Factory public immutable SUSHISWAP_FACTORY;
constructor(IUniswapV2Router02 router, IUniswapV2Factory factory) public {
require(address(router) != address(0), "INVALID_ROUTER");
require(address(factory) != address(0), "INVALID_FACTORY");
SUSHISWAP_ROUTER = router;
SUSHISWAP_FACTORY = factory;
}
function deploy(bytes calldata data) external {
(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) = abi.decode(
data,
(address, address, uint256, uint256, uint256, uint256, address, uint256)
);
_approve(IERC20(tokenA), amountADesired);
_approve(IERC20(tokenB), amountBDesired);
SUSHISWAP_ROUTER.addLiquidity(
tokenA,
tokenB,
amountADesired,
amountBDesired,
amountAMin,
amountBMin,
to,
deadline
);
}
function withdraw(bytes calldata data) external {
(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) = abi.decode(data, (address, address, uint256, uint256, uint256, address, uint256));
address pair = SUSHISWAP_FACTORY.getPair(tokenA, tokenB);
require(pair != address(0), "pair doesn't exist");
_approve(IERC20(pair), liquidity);
SUSHISWAP_ROUTER.removeLiquidity(
tokenA,
tokenB,
liquidity,
amountAMin,
amountBMin,
to,
deadline
);
}
function _approve(IERC20 token, uint256 amount) internal {
uint256 currentAllowance = token.allowance(address(this), address(SUSHISWAP_ROUTER));
if (currentAllowance < amount) {
token.safeIncreaseAllowance(
address(SUSHISWAP_ROUTER),
type(uint256).max.sub(currentAllowance)
);
}
}
}
文件 68 的 71:Toke.sol
pragma solidity 0.6.11;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract Toke is ERC20Pausable, Ownable {
uint256 private constant SUPPLY = 100_000_000e18;
constructor() public ERC20("Tokemak", "TOKE") {
_mint(msg.sender, SUPPLY);
}
function pause() external onlyOwner {
_pause();
}
function unpause() external onlyOwner {
_unpause();
}
}
文件 69 的 71:UniswapController.sol
pragma solidity 0.6.11;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol";
contract UniswapController {
using SafeERC20 for IERC20;
using Address for address;
using Address for address payable;
using SafeMath for uint256;
IUniswapV2Router02 public immutable UNISWAP_ROUTER;
IUniswapV2Factory public immutable UNISWAP_FACTORY;
constructor(IUniswapV2Router02 router, IUniswapV2Factory factory) public {
require(address(router) != address(0), "INVALID_ROUTER");
require(address(factory) != address(0), "INVALID_FACTORY");
UNISWAP_ROUTER = router;
UNISWAP_FACTORY = factory;
}
function deploy(bytes calldata data) external {
(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) = abi.decode(
data,
(address, address, uint256, uint256, uint256, uint256, address, uint256)
);
_approve(IERC20(tokenA), amountADesired);
_approve(IERC20(tokenB), amountBDesired);
UNISWAP_ROUTER.addLiquidity(
tokenA,
tokenB,
amountADesired,
amountBDesired,
amountAMin,
amountBMin,
to,
deadline
);
}
function withdraw(bytes calldata data) external {
(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) = abi.decode(data, (address, address, uint256, uint256, uint256, address, uint256));
address pair = UNISWAP_FACTORY.getPair(tokenA, tokenB);
require(pair != address(0), "pair doesn't exist");
_approve(IERC20(pair), liquidity);
UNISWAP_ROUTER.removeLiquidity(
tokenA,
tokenB,
liquidity,
amountAMin,
amountBMin,
to,
deadline
);
}
function _approve(IERC20 token, uint256 amount) internal {
uint256 currentAllowance = token.allowance(address(this), address(UNISWAP_ROUTER));
if (currentAllowance < amount) {
token.safeIncreaseAllowance(
address(UNISWAP_ROUTER),
type(uint256).max.sub(currentAllowance)
);
}
}
}
文件 70 的 71:ZeroExController.sol
pragma solidity 0.6.11;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "../interfaces/IWallet.sol";
contract ZeroExController {
using SafeERC20 for IERC20;
using Address for address;
using Address for address payable;
using SafeMath for uint256;
IWallet public immutable WALLET;
constructor(IWallet wallet) public {
require(address(wallet) != address(0), "INVALID_WALLET");
WALLET = wallet;
}
function deploy(bytes calldata data) external {
(address[] memory tokens, uint256[] memory amounts) = abi.decode(
data,
(address[], uint256[])
);
uint256 tokensLength = tokens.length;
for (uint256 i = 0; i < tokensLength; i++) {
_approve(IERC20(tokens[i]), amounts[i]);
}
WALLET.deposit(tokens, amounts);
}
function withdraw(bytes calldata data) external {
(address[] memory tokens, uint256[] memory amounts) = abi.decode(
data,
(address[], uint256[])
);
WALLET.withdraw(tokens, amounts);
}
function _approve(IERC20 token, uint256 amount) internal {
uint256 currentAllowance = token.allowance(address(this), address(WALLET));
if (currentAllowance < amount) {
token.safeIncreaseAllowance(address(WALLET), type(uint256).max.sub(currentAllowance));
}
}
}
文件 71 的 71:ZeroExTradeWallet.sol
pragma solidity 0.6.11;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/EnumerableSet.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@0x/contracts-zero-ex/contracts/src/features/interfaces/INativeOrdersFeature.sol";
import "../interfaces/IWallet.sol";
contract ZeroExTradeWallet is IWallet, Ownable {
using SafeERC20 for IERC20;
using Address for address;
using Address for address payable;
using SafeMath for uint256;
using EnumerableSet for EnumerableSet.AddressSet;
INativeOrdersFeature public zeroExRouter;
address public manager;
EnumerableSet.AddressSet internal tokens;
modifier onlyManager() {
require(msg.sender == manager, "INVALID_MANAGER");
_;
}
constructor(address newRouter, address newManager) public {
require(newRouter != address(0), "INVALID_ROUTER");
require(newManager != address(0), "INVALID_MANAGER");
zeroExRouter = INativeOrdersFeature(newRouter);
manager = newManager;
}
function getTokens() external view returns (address[] memory) {
address[] memory returnData = new address[](tokens.length());
for (uint256 i = 0; i < tokens.length(); i++) {
returnData[i] = tokens.at(i);
}
return returnData;
}
function registerAllowedOrderSigner(address signer, bool allowed) external override onlyOwner {
require(signer != address(0), "INVALID_SIGNER");
zeroExRouter.registerAllowedOrderSigner(signer, allowed);
}
function deposit(address[] calldata tokensToAdd, uint256[] calldata amounts)
external
override
onlyManager
{
uint256 tokensLength = tokensToAdd.length;
uint256 amountsLength = amounts.length;
require(tokensLength > 0, "EMPTY_TOKEN_LIST");
require(tokensLength == amountsLength, "LENGTH_MISMATCH");
for (uint256 i = 0; i < tokensLength; i++) {
IERC20(tokensToAdd[i]).safeTransferFrom(msg.sender, address(this), amounts[i]);
_approve(IERC20(tokensToAdd[i]));
tokens.add(address(tokensToAdd[i]));
}
}
function withdraw(address[] calldata tokensToWithdraw, uint256[] calldata amounts)
external
override
onlyManager
{
uint256 tokensLength = tokensToWithdraw.length;
uint256 amountsLength = amounts.length;
require(tokensLength > 0, "EMPTY_TOKEN_LIST");
require(tokensLength == amountsLength, "LENGTH_MISMATCH");
for (uint256 i = 0; i < tokensLength; i++) {
IERC20(tokensToWithdraw[i]).safeTransfer(msg.sender, amounts[i]);
if (IERC20(tokensToWithdraw[i]).balanceOf(address(this)) == 0) {
tokens.remove(address(tokensToWithdraw[i]));
}
}
}
function _approve(IERC20 token) internal {
uint256 allowance = token.allowance(address(this), address(zeroExRouter));
if (allowance < token.balanceOf(address(this))) {
if (allowance != 0) {
token.safeApprove(address(zeroExRouter), 0);
}
token.safeApprove(address(zeroExRouter), type(uint256).max);
}
}
}
{
"compilationTarget": {
"contracts/rewards/Rewards.sol": "Rewards"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 999999
},
"remappings": []
}
[{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"signerAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"cycle","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claimed","type":"event"},{"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":"address","name":"newSigner","type":"address"}],"name":"SignerSet","type":"event"},{"inputs":[{"components":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint256","name":"cycle","type":"uint256"},{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Rewards.Recipient","name":"recipient","type":"tuple"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"claimedAmounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint256","name":"cycle","type":"uint256"},{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Rewards.Recipient","name":"recipient","type":"tuple"}],"name":"getClaimableAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardsSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newSigner","type":"address"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tokeToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]