文件 1 的 1:Untitled.sol
abstract contract TokenManager {
address constant COMPOUND_DEPOSIT_ADDRESS = 0xeB21209ae4C2c9FF2a86ACA31E123764A3B6Bc06;
address constant Y_DEPOSIT_ADDRESS = 0xbBC81d23Ea2c3ec7e56D39296F0cbB648873a5d3;
address constant BUSD_DEPOSIT_ADDRESS = 0xb6c057591E073249F2D9D88Ba59a46CFC9B59EdB;
address constant PAX_DEPOSIT_ADDRESS = 0xA50cCc70b6a011CffDdf45057E39679379187287;
address constant REN_DEPOSIT_ADDRESS = 0x93054188d876f558f4a66B2EF1d97d16eDf0895B;
address constant SBTC_DEPOSIT_ADDRESS = 0x7fC77b5c7614E1533320Ea6DDc2Eb61fa00A9714;
address constant HBTC_DEPOSIT_ADDRESS = 0x4CA9b3063Ec5866A4B82E437059D2C43d1be596F;
address constant SWERVE_DEPOSIT_ADDRESS = 0x329239599afB305DA0A2eC69c58F8a6697F9F88d;
address constant COMPOUND_TOKEN_ADDRESS = 0x845838DF265Dcd2c412A1Dc9e959c7d08537f8a2;
address constant Y_TOKEN_ADDRESS = 0xdF5e0e81Dff6FAF3A7e52BA697820c5e32D806A8;
address constant BUSD_TOKEN_ADDRESS = 0x3B3Ac5386837Dc563660FB6a0937DFAa5924333B;
address constant PAX_TOKEN_ADDRESS = 0xD905e2eaeBe188fc92179b6350807D8bd91Db0D8;
address constant REN_TOKEN_ADDRESS = 0x49849C98ae39Fff122806C06791Fa73784FB3675;
address constant SBTC_TOKEN_ADDRESS = 0x075b1bb99792c9E1041bA13afEf80C91a1e70fB3;
address constant HBTC_TOKEN_ADDRESS = 0xb19059ebb43466C323583928285a49f558E572Fd;
address constant SRW_TOKEN_ADDRESS = 0x77C6E4a580c0dCE4E5c7a17d0bc077188a83A059;
address constant COMPOUND_GAUGE_ADDRESS = 0x7ca5b0a2910B33e9759DC7dDB0413949071D7575;
address constant Y_GAUGE_ADDRESS = 0xFA712EE4788C042e2B7BB55E6cb8ec569C4530c1;
address constant BUSD_GAUGE_ADDRESS = 0x69Fb7c45726cfE2baDeE8317005d3F94bE838840;
address constant PAX_GAUGE_ADDRESS = 0x64E3C23bfc40722d3B649844055F1D51c1ac041d;
address constant REN_GAUGE_ADDRESS = 0xB1F2cdeC61db658F091671F5f199635aEF202CAC;
address constant SBTC_GAUGE_ADDRESS = 0x705350c4BcD35c9441419DdD5d2f097d7a55410F;
address constant SWERVE_GAUGE_ADDRESS = 0xb4d0C929cD3A1FbDc6d57E7D3315cF0C4d6B4bFa;
address constant HBTC_GAUGE_ADDRESS = 0x4c18E409Dc8619bFb6a1cB56D114C3f592E0aE79;
address constant CRV_TOKEN_MINTER_ADDRESS = 0xd061D61a4d941c39E5453435B6345Dc261C2fcE0;
address constant SWERVE_TOKEN_MINTER_ADDRESS = 0x2c988c3974AD7E604E276AE0294a7228DEf67974;
address constant CRV_TOKEN_ADDRESS = 0xD533a949740bb3306d119CC777fa900bA034cd52;
address constant SWERVE_TOKEN_ADDRESS = 0xB8BAa0e4287890a5F79863aB62b7F175ceCbD433;
address constant VOTING_ESCROW = 0x5f3b5DfEb7B28CDbD7FAba78963EE202a494e2A2;
address constant EXCHANGE_CONTRACT = 0xC586BeF4a0992C495Cf22e1aeEE4E446CECDee0E;
address constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
address constant DAI_ADDRESS = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
address constant WBTC_ADDRESS = 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599;
address constant USDC_ADDRESS = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
address constant USDT_ADDRESS = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
address constant TUSD_ADDRESS = 0x0000000000085d4780B73119b644AE5ecd22b376;
mapping(address => address[]) public supportAddresses;
function getSupportAddresses(address _depositAddress) public view returns(address[] memory){
return supportAddresses[_depositAddress];
}
constructor() public {
supportAddresses[COMPOUND_DEPOSIT_ADDRESS].push(COMPOUND_TOKEN_ADDRESS);
supportAddresses[COMPOUND_DEPOSIT_ADDRESS].push(COMPOUND_GAUGE_ADDRESS);
supportAddresses[Y_DEPOSIT_ADDRESS].push(Y_TOKEN_ADDRESS);
supportAddresses[Y_DEPOSIT_ADDRESS].push(Y_GAUGE_ADDRESS);
supportAddresses[BUSD_DEPOSIT_ADDRESS].push(BUSD_TOKEN_ADDRESS);
supportAddresses[BUSD_DEPOSIT_ADDRESS].push(BUSD_GAUGE_ADDRESS);
supportAddresses[PAX_DEPOSIT_ADDRESS].push(PAX_TOKEN_ADDRESS);
supportAddresses[PAX_DEPOSIT_ADDRESS].push(PAX_GAUGE_ADDRESS);
supportAddresses[REN_DEPOSIT_ADDRESS].push(REN_TOKEN_ADDRESS);
supportAddresses[REN_DEPOSIT_ADDRESS].push(REN_GAUGE_ADDRESS);
supportAddresses[SBTC_DEPOSIT_ADDRESS].push(SBTC_TOKEN_ADDRESS);
supportAddresses[SBTC_DEPOSIT_ADDRESS].push(SBTC_GAUGE_ADDRESS);
supportAddresses[HBTC_DEPOSIT_ADDRESS].push(HBTC_TOKEN_ADDRESS);
supportAddresses[HBTC_DEPOSIT_ADDRESS].push(HBTC_GAUGE_ADDRESS);
supportAddresses[SWERVE_DEPOSIT_ADDRESS].push(SRW_TOKEN_ADDRESS);
supportAddresses[SWERVE_DEPOSIT_ADDRESS].push(SWERVE_GAUGE_ADDRESS);
}
}
pragma solidity ^0.6.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return _functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
return _functionCallWithValue(target, data, value, errorMessage);
}
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
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);
}
contract ERC20 is Context, IERC20 {
using SafeMath for uint256;
using Address for address;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
uint8 private _decimals;
constructor (string memory name, string memory symbol) public {
_name = name;
_symbol = symbol;
_decimals = 18;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
function totalSupply() public view override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _setupDecimals(uint8 decimals_) internal {
_decimals = decimals_;
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}
contract PoolToken is ERC20 {
address public owner;
address public poolManager;
modifier onlyOwner {
require(msg.sender == owner);
_;
}
constructor() public ERC20("PRJ Token BTC", "PRJ BTC") {
owner = msg.sender;
}
function setPoolManager(address _newManagerAddress) public onlyOwner {
poolManager = _newManagerAddress;
}
function mint(address account, uint amount) public {
require(msg.sender == poolManager);
_mint(account, amount);
}
function burn(address account, uint256 amount) public {
require(msg.sender == poolManager);
_burn(account, amount);
}
}
abstract contract IOneSplitView {
uint256 public constant FLAG_DISABLE_UNISWAP = 0x01;
uint256 public constant FLAG_DISABLE_KYBER = 0x02;
uint256 public constant FLAG_ENABLE_KYBER_UNISWAP_RESERVE = 0x100000000;
uint256 public constant FLAG_ENABLE_KYBER_OASIS_RESERVE = 0x200000000;
uint256 public constant FLAG_ENABLE_KYBER_BANCOR_RESERVE = 0x400000000;
uint256 public constant FLAG_DISABLE_BANCOR = 0x04;
uint256 public constant FLAG_DISABLE_OASIS = 0x08;
uint256 public constant FLAG_DISABLE_COMPOUND = 0x10;
uint256 public constant FLAG_DISABLE_FULCRUM = 0x20;
uint256 public constant FLAG_DISABLE_CHAI = 0x40;
uint256 public constant FLAG_DISABLE_AAVE = 0x80;
uint256 public constant FLAG_DISABLE_SMART_TOKEN = 0x100;
uint256 public constant FLAG_ENABLE_MULTI_PATH_ETH = 0x200;
uint256 public constant FLAG_DISABLE_BDAI = 0x400;
uint256 public constant FLAG_DISABLE_IEARN = 0x800;
uint256 public constant FLAG_DISABLE_CURVE_COMPOUND = 0x1000;
uint256 public constant FLAG_DISABLE_CURVE_USDT = 0x2000;
uint256 public constant FLAG_DISABLE_CURVE_Y = 0x4000;
uint256 public constant FLAG_DISABLE_CURVE_BINANCE = 0x8000;
uint256 public constant FLAG_ENABLE_MULTI_PATH_DAI = 0x10000;
uint256 public constant FLAG_ENABLE_MULTI_PATH_USDC = 0x20000;
uint256 public constant FLAG_DISABLE_CURVE_SYNTHETIX = 0x40000;
uint256 public constant FLAG_DISABLE_WETH = 0x80000;
uint256 public constant FLAG_ENABLE_UNISWAP_COMPOUND = 0x100000;
function getExpectedReturn(
IERC20 fromToken,
IERC20 toToken,
uint256 amount,
uint256 parts,
uint256 disableFlags
)
virtual
public
view
returns(
uint256 returnAmount,
uint256[] memory distribution
);
}
abstract contract IOneSplit is IOneSplitView {
function swap(
IERC20 fromToken,
IERC20 toToken,
uint256 amount,
uint256 minReturn,
uint256[] memory distribution,
uint256 disableFlags
) virtual public payable;
}
contract PoolFactoryProxy is TokenManager {
address public owner;
address public implementation;
address public poolTokenAddress;
address public poolTokenBTCAddress;
address public poolProxy;
mapping (address => address) public usersStablePools;
mapping (address => address) public usersBTCPools;
uint public totalBalance;
mapping(bool => address) public bestBoost;
constructor(address _poolProxyAddress, address _poolTokenAddress, address _poolTokenBTCAddress, address _impl) public {
implementation = _impl;
poolProxy = _poolProxyAddress;
poolTokenAddress = _poolTokenAddress;
poolTokenBTCAddress = _poolTokenBTCAddress;
owner = msg.sender;
}
function setImplementation(address _newImpl) public {
require(msg.sender == owner);
implementation = _newImpl;
}
fallback() virtual external {
address impl = implementation;
assembly {
let ptr := mload(0x40)
calldatacopy(ptr, 0, calldatasize())
let result := delegatecall(gas(), impl, ptr, calldatasize(), 0, 0)
let size := returndatasize()
returndatacopy(ptr, 0, size)
switch result
case 0 { revert(ptr, size) }
default { return(ptr, size) }
}
}
}
contract PoolFactory is TokenManager {
address public owner;
address public implementation;
address public poolTokenAddress;
address public poolTokenBTCAddress;
address public poolProxy;
mapping (address => address) public usersStablePools;
mapping (address => address) public usersBTCPools;
uint public totalBalance;
mapping(bool => address) public bestBoost;
event NewPool(address indexed poolAddress, address indexed sender, bool isBTC);
modifier poolOnly(address userAddress) {
require(msg.sender == usersStablePools[userAddress] || msg.sender == usersBTCPools[userAddress]);
_;
}
function setPoolProxyAddress(address _newProxy) public {
require(msg.sender == owner);
poolProxy = _newProxy;
}
function newStablePool() public {
require(usersStablePools[msg.sender] == address(0), "pool already created");
PoolProxy pool = new PoolProxy(msg.sender, false);
usersStablePools[msg.sender] = address(pool);
emit NewPool(address(pool), msg.sender, false);
}
function newBTCPool() public {
require(usersBTCPools[msg.sender] == address(0), "pool already created");
PoolProxy pool = new PoolProxy(msg.sender, true);
usersBTCPools[msg.sender] = address(pool);
emit NewPool(address(pool), msg.sender, true);
}
function setBestBoost(address _newBestBoost, address _newBestBoostBTC) public {
require(msg.sender == owner);
bestBoost[false] = _newBestBoost;
bestBoost[true] = _newBestBoostBTC;
}
function mint(address to, uint amount, bool isBTCPool) public poolOnly(to) {
if(isBTCPool) {
PoolToken(poolTokenBTCAddress).mint(to, amount);
} else {
PoolToken(poolTokenAddress).mint(to, amount);
}
}
function burn(address from, uint amount, bool isBTCPool) public poolOnly(from) {
if(isBTCPool) {
if (PoolToken(poolTokenBTCAddress).balanceOf(from) > amount) {
PoolToken(poolTokenBTCAddress).burn(from, amount);
} else {
PoolToken(poolTokenBTCAddress).burn(from, PoolToken(poolTokenBTCAddress).balanceOf(from));
}
} else {
if (PoolToken(poolTokenAddress).balanceOf(from) > amount) {
PoolToken(poolTokenAddress).burn(from, amount);
} else {
PoolToken(poolTokenAddress).burn(from, PoolToken(poolTokenAddress).balanceOf(from));
}
}
}
}
contract Deposit2Tokens {
function add_liquidity(uint256[2] memory uamounts, uint256 min_mint_amount) public{}
function remove_liquidity_one_coin(uint256 _token_amount, int128 i, uint256 min_uamount, bool donate_dust) public{}
uint[100000000000000000000000000000] public period_timestamp;
}
contract Deposit3Tokens {
function add_liquidity(uint256[3] memory uamounts, uint256 min_mint_amount) public{}
function remove_liquidity_one_coin(uint256 _token_amount, int128 i, uint256 min_uamount) public{}
uint[100000000000000000000000000000] public period_timestamp;
}
abstract contract Deposit4Tokens {
function add_liquidity(uint[4] memory uamounts, uint256 min_mint_amount) virtual public;
function remove_liquidity(uint256 _amount, uint256[4] memory min_amounts) public{}
function remove_liquidity_one_coin(uint256 _token_amount, int128 i, uint256 min_uamount, bool donate_dust) virtual public;
uint[100000000000000000000000000000] public period_timestamp;
}
abstract contract IGauge {
function deposit(uint256 _value) virtual public;
function withdraw(uint256 _value) virtual public;
mapping(address => uint) public balanceOf;
}
abstract contract TokenMinter {
function mint(address gauge_addr) virtual public;
}
contract PoolProxy is TokenManager {
address public owner;
address public poolFactoryAddress;
bool public isBTCPool;
constructor(address _owner, bool _isBTCPool) public {
poolFactoryAddress = msg.sender;
owner = _owner;
isBTCPool = _isBTCPool;
}
fallback() external payable {
address impl = implementation();
assembly {
let ptr := mload(0x40)
calldatacopy(ptr, 0, calldatasize())
let result := delegatecall(gas(), impl, ptr, calldatasize(), 0, 0)
let size := returndatasize()
returndatacopy(ptr, 0, size)
switch result
case 0 { revert(ptr, size) }
default { return(ptr, size) }
}
}
function implementation() public view returns(address) {
return PoolFactory(poolFactoryAddress).poolProxy();
}
}
contract Pool is TokenManager {
address public owner;
address public poolFactoryAddress;
bool public isBTCPool;
modifier onlyOwner() {
require (msg.sender == owner);
_;
}
function deposit(address tokenAddress, uint amount) public payable {
address poolAddress = PoolFactory(poolFactoryAddress).bestBoost(isBTCPool);
if (isBTCPool) {
_btcDeposit(poolAddress, tokenAddress, amount);
return;
}
if (msg.value > 0) {
_ethDeposit(poolAddress);
return;
}
uint _amount = amount;
uint[] memory _distribution;
IERC20(tokenAddress).transferFrom(msg.sender, address(this), amount);
if (tokenAddress != DAI_ADDRESS) {
IERC20(tokenAddress).approve(EXCHANGE_CONTRACT, amount);
(_amount, _distribution) = IOneSplit(EXCHANGE_CONTRACT).getExpectedReturn(IERC20(tokenAddress), IERC20(DAI_ADDRESS), amount, 100, 0);
IOneSplit(EXCHANGE_CONTRACT).swap(IERC20(tokenAddress), IERC20(DAI_ADDRESS), amount, _amount, _distribution, 0);
}
(address lpTokenAddress, address gaugeAddress) = _deposit(poolAddress, _amount);
PoolFactory(poolFactoryAddress).mint(msg.sender, IERC20(lpTokenAddress).balanceOf(address(this)), isBTCPool);
depositLPTokens(lpTokenAddress, gaugeAddress, IERC20(lpTokenAddress).balanceOf(address(this)));
}
function _btcDeposit(address poolAddress, address tokenAddress, uint amount) internal {
uint _amount;
uint[] memory _distribution;
if (msg.value > 0) {
(_amount, _distribution) = IOneSplit(EXCHANGE_CONTRACT).getExpectedReturn(IERC20(ETH_ADDRESS), IERC20(WBTC_ADDRESS), msg.value, 100, 0);
IOneSplit(EXCHANGE_CONTRACT).swap.value(msg.value)(IERC20(ETH_ADDRESS), IERC20(WBTC_ADDRESS), msg.value, _amount, _distribution, 0);
uint wBTCamount = IERC20(WBTC_ADDRESS).balanceOf(address(this));
(address lpTokenAddress, address gaugeAddress) = _deposit(poolAddress, _amount);
uint lpAmount = IERC20(lpTokenAddress).balanceOf(address(this));
PoolFactory(poolFactoryAddress).mint(msg.sender, IERC20(lpTokenAddress).balanceOf(address(this)), isBTCPool);
depositLPTokens(lpTokenAddress, gaugeAddress, IERC20(lpTokenAddress).balanceOf(address(this)));
return;
}
IERC20(tokenAddress).transferFrom(msg.sender, address(this), amount);
if (tokenAddress != WBTC_ADDRESS) {
IERC20(tokenAddress).approve(EXCHANGE_CONTRACT, amount);
(_amount, _distribution) = IOneSplit(EXCHANGE_CONTRACT).getExpectedReturn(IERC20(tokenAddress), IERC20(WBTC_ADDRESS), amount, 100, 0);
IOneSplit(EXCHANGE_CONTRACT).swap(IERC20(tokenAddress), IERC20(WBTC_ADDRESS), amount, _amount, _distribution, 0);
}
(address lpTokenAddress, address gaugeAddress) = _deposit(poolAddress, _amount);
PoolFactory(poolFactoryAddress).mint(msg.sender, IERC20(lpTokenAddress).balanceOf(address(this)), isBTCPool);
depositLPTokens(lpTokenAddress, gaugeAddress, IERC20(lpTokenAddress).balanceOf(address(this)));
}
function claimReward(address _depositAddress, bool isHarvest) public onlyOwner {
address[] memory supAddresses = getSupportAddresses(_depositAddress);
if (supAddresses[1] == SWERVE_GAUGE_ADDRESS) {
TokenMinter(SWERVE_TOKEN_MINTER_ADDRESS).mint(supAddresses[1]);
} else {
TokenMinter(CRV_TOKEN_MINTER_ADDRESS).mint(supAddresses[1]);
}
uint swerveTokenBalance = IERC20(SWERVE_TOKEN_ADDRESS).balanceOf(address(this));
uint crvTokenBalance = IERC20(CRV_TOKEN_ADDRESS).balanceOf(address(this));
if (isHarvest) {
uint _amount;
uint[] memory _distribution;
if (swerveTokenBalance > 0) {
IERC20(SWERVE_TOKEN_ADDRESS).approve(EXCHANGE_CONTRACT, swerveTokenBalance);
(_amount, _distribution) = IOneSplit(EXCHANGE_CONTRACT).getExpectedReturn(IERC20(SWERVE_TOKEN_ADDRESS), IERC20(DAI_ADDRESS), swerveTokenBalance, 100, 0);
IOneSplit(EXCHANGE_CONTRACT).swap(IERC20(SWERVE_TOKEN_ADDRESS), IERC20(DAI_ADDRESS), swerveTokenBalance, _amount, _distribution, 0);
}
if (crvTokenBalance > 0) {
IERC20(CRV_TOKEN_ADDRESS).approve(EXCHANGE_CONTRACT, crvTokenBalance);
(_amount, _distribution) = IOneSplit(EXCHANGE_CONTRACT).getExpectedReturn(IERC20(CRV_TOKEN_ADDRESS), IERC20(DAI_ADDRESS), crvTokenBalance, 100, 0);
IOneSplit(EXCHANGE_CONTRACT).swap(IERC20(CRV_TOKEN_ADDRESS), IERC20(DAI_ADDRESS), crvTokenBalance, _amount, _distribution, 0);
}
uint daiBalance = IERC20(DAI_ADDRESS).balanceOf(address(this));
if(daiBalance > 0) {
IERC20(DAI_ADDRESS).transfer(msg.sender, daiBalance);
}
return;
}
if(swerveTokenBalance > 0) {
IERC20(SWERVE_TOKEN_ADDRESS).transfer(msg.sender, swerveTokenBalance);
}
if(crvTokenBalance > 0) {
IERC20(CRV_TOKEN_ADDRESS).transfer(msg.sender, crvTokenBalance);
}
}
function exit(address _depositAddress, uint value) public onlyOwner {
claimReward(_depositAddress, false);
address[] memory supAddresses = getSupportAddresses(_depositAddress);
require(IGauge(supAddresses[1]).balanceOf(address(this)) > 0);
IGauge(supAddresses[1]).withdraw(IGauge(supAddresses[1]).balanceOf(address(this)));
uint bal = IERC20(supAddresses[0]).balanceOf(address(this));
require(bal > 0);
PoolFactory(poolFactoryAddress).burn(msg.sender, bal, isBTCPool);
IERC20(supAddresses[0]).approve(_depositAddress, bal);
if (!isBTCPool) {
if (_depositAddress == SWERVE_DEPOSIT_ADDRESS) {
uint[4] memory buf;
Deposit4Tokens(_depositAddress).remove_liquidity(bal, buf);
} else {
Deposit2Tokens(_depositAddress).remove_liquidity_one_coin(bal, 0, 1, true);
}
} else {
Deposit3Tokens(_depositAddress).remove_liquidity_one_coin(bal, 1, 1);
}
if (!isBTCPool) {
if(IERC20(DAI_ADDRESS).balanceOf(address(this)) > 0) {
IERC20(DAI_ADDRESS).transfer(msg.sender, IERC20(DAI_ADDRESS).balanceOf(address(this)));
}
if(IERC20(USDC_ADDRESS).balanceOf(address(this)) > 0) {
IERC20(USDC_ADDRESS).transfer(msg.sender, IERC20(USDC_ADDRESS).balanceOf(address(this)));
}
if(IERC20(TUSD_ADDRESS).balanceOf(address(this)) > 0) {
IERC20(TUSD_ADDRESS).transfer(msg.sender, IERC20(TUSD_ADDRESS).balanceOf(address(this)));
}
} else {
IERC20(WBTC_ADDRESS).transfer(msg.sender, IERC20(WBTC_ADDRESS).balanceOf(address(this)));
}
}
function withdrawTokenFromContract(address tokenAddress, uint amount) public onlyOwner {
IERC20(tokenAddress).transfer(msg.sender, amount);
}
function _ethDeposit(address poolAddress) private {
uint _amount;
uint[] memory _distribution;
(_amount, _distribution) = IOneSplit(EXCHANGE_CONTRACT).getExpectedReturn(IERC20(ETH_ADDRESS), IERC20(DAI_ADDRESS), msg.value, 100, 0);
IOneSplit(EXCHANGE_CONTRACT).swap.value(msg.value)(IERC20(ETH_ADDRESS), IERC20(DAI_ADDRESS), msg.value, _amount, _distribution, 0);
(address lpTokenAddress, address gaugeAddress) = _deposit(poolAddress, _amount);
PoolFactory(poolFactoryAddress).mint(msg.sender, IERC20(lpTokenAddress).balanceOf(address(this)), isBTCPool);
depositLPTokens(lpTokenAddress, gaugeAddress, IERC20(lpTokenAddress).balanceOf(address(this)));
}
function depositLPTokens(address lpTokenAddress, address gaugeAddress, uint value) internal {
IERC20(lpTokenAddress).approve(gaugeAddress, value);
IGauge(gaugeAddress).deposit(value);
}
function _deposit(address _depositPool, uint amount) internal returns(address, address) {
IERC20(DAI_ADDRESS).approve(_depositPool, amount);
if(_depositPool == COMPOUND_DEPOSIT_ADDRESS) {
uint[2] memory uamounts;
uamounts[0] = amount;
Deposit2Tokens(_depositPool).add_liquidity(uamounts, 0);
return (COMPOUND_TOKEN_ADDRESS, COMPOUND_GAUGE_ADDRESS);
}
if(_depositPool == Y_DEPOSIT_ADDRESS) {
uint[4] memory uamounts;
uamounts[0] = amount;
Deposit4Tokens(_depositPool).add_liquidity(uamounts, 0);
return (Y_TOKEN_ADDRESS, Y_GAUGE_ADDRESS);
}
if(_depositPool == BUSD_DEPOSIT_ADDRESS) {
uint[4] memory uamounts;
uamounts[0] = amount;
Deposit4Tokens(_depositPool).add_liquidity(uamounts, 0);
return (BUSD_TOKEN_ADDRESS, BUSD_GAUGE_ADDRESS);
}
if(_depositPool == PAX_DEPOSIT_ADDRESS) {
uint[4] memory uamounts;
uamounts[0] = amount;
Deposit4Tokens(_depositPool).add_liquidity(uamounts, 0);
return (PAX_TOKEN_ADDRESS, PAX_GAUGE_ADDRESS);
}
if(_depositPool == REN_DEPOSIT_ADDRESS) {
IERC20(WBTC_ADDRESS).approve(_depositPool, amount);
uint[2] memory uamounts;
uamounts[1] = amount;
Deposit2Tokens(_depositPool).add_liquidity(uamounts, 0);
return (REN_TOKEN_ADDRESS, REN_GAUGE_ADDRESS);
}
if(_depositPool == SBTC_DEPOSIT_ADDRESS) {
IERC20(WBTC_ADDRESS).approve(_depositPool, amount);
uint[3] memory uamounts;
uamounts[1] = amount;
Deposit3Tokens(_depositPool).add_liquidity(uamounts, 0);
return (SBTC_TOKEN_ADDRESS, SBTC_GAUGE_ADDRESS);
}
if(_depositPool == HBTC_DEPOSIT_ADDRESS) {
IERC20(WBTC_ADDRESS).approve(_depositPool, amount);
uint[2] memory uamounts;
uamounts[1] = amount;
Deposit2Tokens(_depositPool).add_liquidity(uamounts, 0);
return (HBTC_TOKEN_ADDRESS, HBTC_GAUGE_ADDRESS);
}
if(_depositPool == SWERVE_DEPOSIT_ADDRESS) {
uint[4] memory uamounts;
uamounts[0] = amount;
Deposit4Tokens(_depositPool).add_liquidity(uamounts, 0);
return (SRW_TOKEN_ADDRESS, SWERVE_GAUGE_ADDRESS);
}
}
}