编译器
0.6.12+commit.27d51765
文件 1 的 18:Address.sol
pragma solidity 0.6.12;
library Address {
function isContract(address account) internal view returns (bool) {
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
assembly {
codehash := extcodehash(account)
}
return (codehash != accountHash && codehash != 0x0);
}
function sendValue(address payable recipient, uint 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,
uint value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint 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,
uint weiValue,
string memory errorMessage
) private returns (bytes memory) {
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: weiValue}(data);
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 18:Color.sol
pragma solidity 0.6.12;
contract BBronze {
function getColor() external pure returns (bytes32) {
return bytes32("BRONZE");
}
}
文件 3 的 18:Const.sol
pragma solidity 0.6.12;
import "./Color.sol";
contract Const is BBronze {
uint public constant BONE = 10**18;
uint public constant MIN_BOUND_TOKENS = 1;
uint public constant MAX_BOUND_TOKENS = 16;
uint public constant MIN_FEE = BONE / 10**6;
uint public constant MAX_FEE = BONE / 10;
uint public constant EXIT_FEE = 0;
uint public constant MIN_WEIGHT = BONE;
uint public constant MAX_WEIGHT = BONE * 50;
uint public constant MAX_TOTAL_WEIGHT = BONE * 50;
uint public constant MIN_BALANCE = 0;
uint public constant INIT_POOL_SUPPLY = BONE * 100;
uint public constant MIN_BPOW_BASE = 1 wei;
uint public constant MAX_BPOW_BASE = (2 * BONE) - 1 wei;
uint public constant BPOW_PRECISION = BONE / 10**10;
uint public constant MAX_IN_RATIO = BONE / 2;
uint public constant MAX_OUT_RATIO = (BONE / 3) + 1 wei;
}
文件 4 的 18:DesynConstants.sol
pragma solidity 0.6.12;
library DesynConstants {
uint public constant BONE = 10**18;
uint public constant MIN_WEIGHT = BONE;
uint public constant MAX_WEIGHT = BONE * 50;
uint public constant MAX_TOTAL_WEIGHT = BONE * 50;
uint public constant MIN_BALANCE = 0;
uint public constant MAX_BALANCE = BONE * 10**12;
uint public constant MIN_POOL_SUPPLY = BONE * 100;
uint public constant MAX_POOL_SUPPLY = BONE * 10**9;
uint public constant MIN_FEE = BONE / 10**6;
uint public constant MAX_FEE = BONE / 10;
uint public constant MANAGER_MIN_FEE = 0;
uint public constant MANAGER_MAX_FEE = BONE / 10;
uint public constant ISSUE_MIN_FEE = BONE / 1000;
uint public constant ISSUE_MAX_FEE = BONE / 10;
uint public constant REDEEM_MIN_FEE = 0;
uint public constant REDEEM_MAX_FEE = BONE / 10;
uint public constant PERFERMANCE_MIN_FEE = 0;
uint public constant PERFERMANCE_MAX_FEE = BONE / 2;
uint public constant EXIT_FEE = 0;
uint public constant MAX_IN_RATIO = BONE / 2;
uint public constant MAX_OUT_RATIO = (BONE / 3) + 1 wei;
uint public constant MIN_ASSET_LIMIT = 1;
uint public constant MAX_ASSET_LIMIT = 16;
uint public constant MAX_UINT = uint(-1);
uint public constant MAX_COLLECT_PERIOD = 60 days;
}
文件 5 的 18:DesynSafeMath.sol
pragma solidity 0.6.12;
import "./DesynConstants.sol";
library DesynSafeMath {
function badd(uint a, uint b) internal pure returns (uint) {
uint c = a + b;
require(c >= a, "ERR_ADD_OVERFLOW");
return c;
}
function bsub(uint a, uint b) internal pure returns (uint) {
(uint c, bool negativeResult) = bsubSign(a, b);
require(!negativeResult, "ERR_SUB_UNDERFLOW");
return c;
}
function bsubSign(uint a, uint b) internal pure returns (uint, bool) {
if (b <= a) {
return (a - b, false);
} else {
return (b - a, true);
}
}
function bmul(uint a, uint b) internal pure returns (uint) {
if (a == 0) {
return 0;
}
uint c0 = a * b;
require(c0 / a == b, "ERR_MUL_OVERFLOW");
uint c1 = c0 + (DesynConstants.BONE / 2);
require(c1 >= c0, "ERR_MUL_OVERFLOW");
uint c2 = c1 / DesynConstants.BONE;
return c2;
}
function bdiv(uint dividend, uint divisor) internal pure returns (uint) {
require(divisor != 0, "ERR_DIV_ZERO");
if (dividend == 0) {
return 0;
}
uint c0 = dividend * DesynConstants.BONE;
require(c0 / dividend == DesynConstants.BONE, "ERR_DIV_INTERNAL");
uint c1 = c0 + (divisor / 2);
require(c1 >= c0, "ERR_DIV_INTERNAL");
uint c2 = c1 / divisor;
return c2;
}
function bmod(uint dividend, uint divisor) internal pure returns (uint) {
require(divisor != 0, "ERR_MODULO_BY_ZERO");
return dividend % divisor;
}
function bmax(uint a, uint b) internal pure returns (uint) {
return a >= b ? a : b;
}
function bmin(uint a, uint b) internal pure returns (uint) {
return a < b ? a : b;
}
function baverage(uint a, uint b) internal pure returns (uint) {
return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2);
}
function sqrt(uint y) internal pure returns (uint z) {
if (y > 3) {
z = y;
uint x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
}
文件 6 的 18:Factory.sol
pragma solidity 0.6.12;
import "../base/WhiteToken.sol";
import "../base/LiquidityPool.sol";
import "../interfaces/IBFactory.sol";
contract Factory is BBronze, WhiteToken {
event LOG_NEW_POOL(address indexed caller, address indexed pool);
event LOG_BLABS(address indexed caller, address indexed blabs);
event LOG_ROUTER(address indexed caller, address indexed router);
event LOG_VAULT(address indexed vault, address indexed caller);
event LOG_USER_VAULT(address indexed vault, address indexed caller);
event LOG_MANAGER(address indexed manager, address indexed caller);
event LOG_ORACLE(address indexed caller, address indexed oracle);
event MODULE_STATUS_CHANGE(address etf, address module, bool status);
event PAUSED_STATUS(bool state);
mapping(address => bool) private _isLiquidityPool;
mapping(address => mapping(address => bool)) private _isModuleRegistered;
uint private counters;
bytes public bytecodes = type(LiquidityPool).creationCode;
bool public isPaused;
function addTokenToWhitelist(uint[] memory sort, address[] memory token) external onlyBlabs {
require(sort.length == token.length, "ERR_SORT_TOKEN_MISMATCH");
for (uint i = 0; i < sort.length; i++) {
_addTokenToWhitelist(sort[i], token[i]);
}
}
function removeTokenFromWhitelist(uint[] memory sort, address[] memory token) external onlyBlabs {
require(sort.length == token.length, "ERR_SORT_TOKEN_MISMATCH");
for (uint i = 0; i < sort.length; i++) {
_removeTokenFromWhitelist(sort[i], token[i]);
}
}
function isTokenWhitelistedForVerify(uint sort, address token) external view returns (bool) {
return _isTokenWhitelistedForVerify(sort, token);
}
function isTokenWhitelistedForVerify(address token) external view returns (bool) {
return _queryIsTokenWhitelisted(token);
}
function isLiquidityPool(address b) external view returns (bool) {
return _isLiquidityPool[b];
}
function createPool() internal returns (address base) {
bytes memory bytecode = bytecodes;
bytes32 salt = keccak256(abi.encodePacked(counters++));
assembly {
base := create2(0, add(bytecode, 32), mload(bytecode), salt)
if iszero(extcodesize(base)) {
revert(0, 0)
}
}
counters++;
}
function newLiquidityPool() external returns (IBPool) {
address lpool = createPool();
_isLiquidityPool[lpool] = true;
emit LOG_NEW_POOL(msg.sender, lpool);
IBPool(lpool).setController(msg.sender);
return IBPool(lpool);
}
address private _blabs;
address private _swapRouter;
address private _vault;
address private _oracle;
address private _managerOwner;
address private _vaultAddress;
address private _userVaultAddress;
constructor() public {
_blabs = msg.sender;
}
function getBLabs() external view returns (address) {
return _blabs;
}
function setBLabs(address b) external onlyBlabs {
require(b != address(0),"ERR_ZERO_ADDRESS");
emit LOG_BLABS(msg.sender, b);
_blabs = b;
}
function getSwapRouter() external view returns (address) {
return _swapRouter;
}
function getModuleStatus(address etf, address module) external view returns (bool) {
return _isModuleRegistered[etf][module];
}
function getOracleAddress() external view returns (address) {
return _oracle;
}
function setSwapRouter(address router) external onlyBlabs {
require(router != address(0),"ERR_ZERO_ADDRESS");
emit LOG_ROUTER(msg.sender, router);
_swapRouter = router;
}
function registerModule(address etf, address module) external onlyBlabs {
require(etf != address(0), "ZERO ETF ADDRESS");
require(module != address(0), "ZERO ADDRESS");
_isModuleRegistered[etf][module] = true;
emit MODULE_STATUS_CHANGE(etf, module, true);
}
function removeModule(address etf, address module) external onlyBlabs {
require(etf != address(0), "ZERO ETF ADDRESS");
require(module != address(0), "ZERO ADDRESS");
_isModuleRegistered[etf][module] = false;
emit MODULE_STATUS_CHANGE(etf, module, false);
}
function setOracle(address oracle) external onlyBlabs {
require(oracle != address(0),"ERR_ZERO_ADDRESS");
emit LOG_ORACLE(msg.sender, oracle);
_oracle = oracle;
}
function collect(IERC20 token) external onlyBlabs {
uint collected = token.balanceOf(address(this));
bool xfer = token.transfer(_blabs, collected);
require(xfer, "ERR_ERC20_FAILED");
}
function getVault() external view returns (address) {
return _vaultAddress;
}
function setVault(address newVault) external onlyBlabs {
require(newVault != address(0),"ERR_ZERO_ADDRESS");
_vaultAddress = newVault;
emit LOG_VAULT(newVault, msg.sender);
}
function getUserVault() external view returns (address) {
return _userVaultAddress;
}
function setUserVault(address newVault) external onlyBlabs {
require(newVault != address(0),"ERR_ZERO_ADDRESS");
_userVaultAddress = newVault;
emit LOG_USER_VAULT(newVault, msg.sender);
}
function getManagerOwner() external view returns (address) {
return _managerOwner;
}
function setManagerOwner(address newManagerOwner) external onlyBlabs {
require(newManagerOwner != address(0),"ERR_ZERO_ADDRESS");
_managerOwner = newManagerOwner;
emit LOG_MANAGER(newManagerOwner, msg.sender);
}
function setProtocolPaused(bool state) external onlyBlabs {
isPaused = state;
emit PAUSED_STATUS(state);
}
modifier onlyBlabs() {
require(msg.sender == _blabs, "ERR_NOT_BLABS");
_;
}
}
文件 7 的 18:IBFactory.sol
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import "../libraries/SmartPoolManager.sol";
interface IBPool {
function rebind(
address token,
uint balance,
uint denorm
) external;
function rebindSmart(
address tokenA,
address tokenB,
uint deltaWeight,
uint deltaBalance,
bool isSoldout,
uint minAmountOut
) external;
function execute(
address _target,
uint _value,
bytes calldata _data
) external returns (bytes memory _returnValue);
function bind(
address token,
uint balance,
uint denorm
) external;
function unbind(address token) external;
function unbindPure(address token) external;
function isBound(address token) external view returns (bool);
function getBalance(address token) external view returns (uint);
function totalSupply() external view returns (uint);
function getSwapFee() external view returns (uint);
function isPublicSwap() external view returns (bool);
function getDenormalizedWeight(address token) external view returns (uint);
function getTotalDenormalizedWeight() external view returns (uint);
function EXIT_FEE() external view returns (uint);
function getCurrentTokens() external view returns (address[] memory tokens);
function setController(address owner) external;
}
interface IBFactory {
function newLiquidityPool() external returns (IBPool);
function setBLabs(address b) external;
function collect(IBPool pool) external;
function isBPool(address b) external view returns (bool);
function getBLabs() external view returns (address);
function getSwapRouter() external view returns (address);
function getVault() external view returns (address);
function getUserVault() external view returns (address);
function getVaultAddress() external view returns (address);
function getOracleAddress() external view returns (address);
function getManagerOwner() external view returns (address);
function isTokenWhitelistedForVerify(uint sort, address token) external view returns (bool);
function isTokenWhitelistedForVerify(address token) external view returns (bool);
function getModuleStatus(address etf, address module) external view returns (bool);
function isPaused() external view returns (bool);
}
interface IVault {
function depositManagerToken(address[] calldata poolTokens, uint[] calldata tokensAmount) external;
function depositIssueRedeemPToken(
address[] calldata poolTokens,
uint[] calldata tokensAmount,
uint[] calldata tokensAmountP,
bool isPerfermance
) external;
function managerClaim(address pool) external;
function getManagerClaimBool(address pool) external view returns (bool);
}
interface IUserVault {
function recordTokenInfo(
address kol,
address user,
address[] calldata poolTokens,
uint[] calldata tokensAmount
) external;
}
interface Oracles {
function getPrice(address tokenAddress) external returns (uint price);
function getAllPrice(address[] calldata poolTokens, uint[] calldata tokensAmount) external returns (uint);
}
文件 8 的 18:IConfigurableRightsPool.sol
pragma solidity 0.6.12;
interface IConfigurableRightsPool {
function mintPoolShareFromLib(uint amount) external;
function pushPoolShareFromLib(address to, uint amount) external;
function pullPoolShareFromLib(address from, uint amount) external;
function burnPoolShareFromLib(uint amount) external;
function balanceOf(address account) external view returns (uint);
function totalSupply() external view returns (uint);
function getController() external view returns (address);
function vaultAddress() external view returns (address);
}
文件 9 的 18:IERC20.sol
pragma solidity 0.6.12;
interface IERC20 {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function totalSupply() external view returns (uint);
function balanceOf(address account) external view returns (uint);
function decimals() external view returns (uint8);
function symbol() external view returns (string memory);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint amount) external returns (bool);
function transfer(address recipient, uint amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint amount
) external returns (bool);
}
文件 10 的 18:IUniswapV2Router02.sol
pragma solidity 0.6.12;
interface IUniswapV2Router02 {
function swapExactTokensForETH(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
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);
}
文件 11 的 18:LiquidityPool.sol
pragma solidity 0.6.12;
import "./LpToken.sol";
import "./Math.sol";
import "../interfaces/IUniswapV2Router02.sol";
import "../interfaces/IBFactory.sol";
import "../libraries/Address.sol";
contract LiquidityPool is BBronze, LpToken, Math {
using Address for address;
struct Record {
bool bound;
uint index;
uint denorm;
uint balance;
}
event LOG_JOIN(address indexed caller, address indexed tokenIn, uint tokenAmountIn);
event LOG_EXIT(address indexed caller, address indexed tokenOut, uint tokenAmountOut);
event LOG_REBALANCE(address indexed tokenA, address indexed tokenB, uint newWeightA, uint newWeightB, uint newBalanceA, uint newBalanceB, bool isSoldout);
event LOG_CALL(bytes4 indexed sig, address indexed caller, bytes data) anonymous;
modifier _logs_() {
emit LOG_CALL(msg.sig, msg.sender, msg.data);
_;
}
modifier _lock_() {
require(!_mutex, "ERR_REENTRY");
_mutex = true;
_;
_mutex = false;
}
modifier _viewlock_() {
require(!_mutex, "ERR_REENTRY");
_;
}
bool private _mutex;
IBFactory private _factory;
address private _controller;
bool private _publicSwap;
uint private _swapFee;
bool private _finalized;
address[] private _tokens;
mapping(address => Record) private _records;
uint private _totalWeight;
Oracles private oracle;
constructor() public {
_controller = msg.sender;
_factory = IBFactory(msg.sender);
_swapFee = MIN_FEE;
_publicSwap = false;
_finalized = false;
oracle = Oracles(_factory.getOracleAddress());
}
function isPublicSwap() external view returns (bool) {
return _publicSwap;
}
function isFinalized() external view returns (bool) {
return _finalized;
}
function isBound(address t) external view returns (bool) {
return _records[t].bound;
}
function getNumTokens() external view returns (uint) {
return _tokens.length;
}
function getCurrentTokens() external view _viewlock_ returns (address[] memory tokens) {
return _tokens;
}
function getFinalTokens() external view _viewlock_ returns (address[] memory tokens) {
require(_finalized, "ERR_NOT_FINALIZED");
return _tokens;
}
function getDenormalizedWeight(address token) external view _viewlock_ returns (uint) {
require(_records[token].bound, "ERR_NOT_BOUND");
return _records[token].denorm;
}
function getTotalDenormalizedWeight() external view _viewlock_ returns (uint) {
return _totalWeight;
}
function getNormalizedWeight(address token) external _viewlock_ returns (uint) {
require(_records[token].bound, "ERR_NOT_BOUND");
uint denorm = _records[token].denorm;
uint price = oracle.getPrice(token);
uint[] memory _balances = new uint[](_tokens.length);
for (uint i = 0; i < _tokens.length; i++) {
_balances[i] = getBalance(_tokens[i]);
}
uint totalValue = oracle.getAllPrice(_tokens, _balances);
uint currentValue = bmul(price, getBalance(token));
return bdiv(currentValue, totalValue);
}
function getBalance(address token) public view _viewlock_ returns (uint) {
require(_records[token].bound, "ERR_NOT_BOUND");
return _records[token].balance;
}
function getSwapFee() external view _viewlock_ returns (uint) {
return _swapFee;
}
function getController() external view _viewlock_ returns (address) {
return _controller;
}
function setSwapFee(uint swapFee) external _logs_ _lock_ {
require(!_finalized, "ERR_IS_FINALIZED");
require(msg.sender == _controller, "ERR_NOT_CONTROLLER");
require(swapFee >= MIN_FEE, "ERR_MIN_FEE");
require(swapFee <= MAX_FEE, "ERR_MAX_FEE");
_swapFee = swapFee;
}
function setController(address manager) external _logs_ _lock_ {
require(msg.sender == _controller, "ERR_NOT_CONTROLLER");
require(manager != address(0),"ERR_ZERO_ADDRESS");
_controller = manager;
}
function setPublicSwap(bool public_) external _logs_ _lock_ {
require(!_finalized, "ERR_IS_FINALIZED");
require(msg.sender == _controller, "ERR_NOT_CONTROLLER");
_publicSwap = public_;
}
function finalize() external _logs_ _lock_ {
require(msg.sender == _controller, "ERR_NOT_CONTROLLER");
require(!_finalized, "ERR_IS_FINALIZED");
require(_tokens.length >= MIN_BOUND_TOKENS, "ERR_MIN_TOKENS");
_finalized = true;
_publicSwap = true;
_mintPoolShare(INIT_POOL_SUPPLY);
_pushPoolShare(msg.sender, INIT_POOL_SUPPLY);
}
function bind(
address token,
uint balance,
uint denorm
)
external
_logs_
{
require(msg.sender == _controller, "ERR_NOT_CONTROLLER");
require(!_records[token].bound, "ERR_IS_BOUND");
require(!_finalized, "ERR_IS_FINALIZED");
require(_tokens.length < MAX_BOUND_TOKENS, "ERR_MAX_TOKENS");
_records[token] = Record({
bound: true,
index: _tokens.length,
denorm: 0,
balance: 0
});
_tokens.push(token);
rebind(token, balance, denorm);
}
function rebind(
address token,
uint balance,
uint denorm
) public _logs_ _lock_ {
require(msg.sender == _controller, "ERR_NOT_CONTROLLER");
require(_records[token].bound, "ERR_NOT_BOUND");
require(!_finalized, "ERR_IS_FINALIZED");
require(denorm >= MIN_WEIGHT, "ERR_MIN_WEIGHT");
require(denorm <= MAX_WEIGHT, "ERR_MAX_WEIGHT");
require(balance >= MIN_BALANCE, "ERR_MIN_BALANCE");
uint oldWeight = _records[token].denorm;
if (denorm > oldWeight) {
_totalWeight = badd(_totalWeight, bsub(denorm, oldWeight));
require(_totalWeight <= MAX_TOTAL_WEIGHT, "ERR_MAX_TOTAL_WEIGHT");
} else if (denorm < oldWeight) {
_totalWeight = bsub(_totalWeight, bsub(oldWeight, denorm));
}
_records[token].denorm = denorm;
uint oldBalance = _records[token].balance;
_records[token].balance = balance;
if (balance > oldBalance) {
_pullUnderlying(token, msg.sender, bsub(balance, oldBalance));
} else if (balance < oldBalance) {
uint tokenBalanceWithdrawn = bsub(oldBalance, balance);
_pushUnderlying(token, msg.sender, tokenBalanceWithdrawn);
}
}
function rebindSmart(
address tokenA,
address tokenB,
uint deltaWeight,
uint deltaBalance,
bool isSoldout,
uint minAmountOut
) external _logs_ _lock_ {
require(msg.sender == _controller, "ERR_NOT_CONTROLLER");
require(!_finalized, "ERR_IS_FINALIZED");
address[] memory paths = new address[](2);
paths[0] = tokenA;
paths[1] = tokenB;
IUniswapV2Router02 swapRouter = IUniswapV2Router02(_factory.getSwapRouter());
if (_records[tokenB].bound) {
uint oldWeightB = _records[tokenB].denorm;
uint oldBalanceB = _records[tokenB].balance;
uint newWeightB = badd(oldWeightB, deltaWeight);
require(newWeightB <= MAX_WEIGHT, "ERR_MAX_WEIGHT_B");
if (isSoldout) {
require(_tokens.length >= MIN_BOUND_TOKENS, "ERR_MIN_TOKENS");
} else {
require(_records[tokenA].bound, "ERR_NOT_BOUND_A");
uint newWeightA = bsub(_records[tokenA].denorm, deltaWeight);
uint newBalanceA = bsub(_records[tokenA].balance, deltaBalance);
require(newWeightA >= MIN_WEIGHT, "ERR_MIN_WEIGHT_A");
require(newBalanceA >= MIN_BALANCE, "ERR_MIN_BALANCE_A");
_records[tokenA].balance = newBalanceA;
_records[tokenA].denorm = newWeightA;
}
uint balanceBBefore = IERC20(tokenB).balanceOf(address(this));
_safeApprove(IERC20(tokenA), address(swapRouter), uint(-1));
swapRouter.swapExactTokensForTokens(deltaBalance, minAmountOut, paths, address(this), badd(block.timestamp, 1800));
uint balanceBAfter = IERC20(tokenB).balanceOf(address(this));
uint newBalanceB = badd(oldBalanceB, bsub(balanceBAfter, balanceBBefore));
_records[tokenB].balance = newBalanceB;
_records[tokenB].denorm = newWeightB;
}
else {
if (!isSoldout) {
require(_records[tokenA].bound, "ERR_NOT_BOUND_A");
uint newWeightA = bsub(_records[tokenA].denorm, deltaWeight);
uint newBalanceA = bsub(_records[tokenA].balance, deltaBalance);
require(newWeightA >= MIN_WEIGHT, "ERR_MIN_WEIGHT_A");
require(newBalanceA >= MIN_BALANCE, "ERR_MIN_BALANCE_A");
require(_tokens.length < MAX_BOUND_TOKENS, "ERR_MAX_TOKENS");
_records[tokenA].balance = newBalanceA;
_records[tokenA].denorm = newWeightA;
}
uint balanceBBefore = IERC20(tokenB).balanceOf(address(this));
_safeApprove(IERC20(tokenA), address(swapRouter), uint(-1));
swapRouter.swapExactTokensForTokens(deltaBalance, minAmountOut, paths, address(this), badd(block.timestamp, 1800));
uint balanceBAfter = IERC20(tokenB).balanceOf(address(this));
uint newBalanceB = bsub(balanceBAfter, balanceBBefore);
require(newBalanceB >= MIN_BALANCE, "ERR_MIN_BALANCE");
require(deltaWeight >= MIN_WEIGHT, "ERR_MIN_WEIGHT_DELTA");
_records[tokenB] = Record({bound: true, index: _tokens.length, denorm: deltaWeight, balance: newBalanceB});
_tokens.push(tokenB);
}
emit LOG_REBALANCE(tokenA, tokenB, _records[tokenA].denorm, _records[tokenB].denorm, _records[tokenA].balance, _records[tokenB].balance, isSoldout);
}
function execute(
address _target,
uint _value,
bytes calldata _data
) external _logs_ _lock_ returns (bytes memory _returnValue) {
require(msg.sender == _controller, "ERR_NOT_CONTROLLER");
require(!_finalized, "ERR_IS_FINALIZED");
_returnValue = _target.functionCallWithValue(_data, _value);
return _returnValue;
}
function unbind(address token) external _logs_ _lock_ {
require(msg.sender == _controller, "ERR_NOT_CONTROLLER");
require(_records[token].bound, "ERR_NOT_BOUND");
require(!_finalized, "ERR_IS_FINALIZED");
uint tokenBalance = _records[token].balance;
_totalWeight = bsub(_totalWeight, _records[token].denorm);
uint index = _records[token].index;
uint last = _tokens.length - 1;
_tokens[index] = _tokens[last];
_records[_tokens[index]].index = index;
_tokens.pop();
_records[token] = Record({bound: false, index: 0, denorm: 0, balance: 0});
_pushUnderlying(token, msg.sender, tokenBalance);
}
function unbindPure(address token) external _logs_ _lock_ {
require(msg.sender == _controller, "ERR_NOT_CONTROLLER");
require(_records[token].bound, "ERR_NOT_BOUND");
require(!_finalized, "ERR_IS_FINALIZED");
uint index = _records[token].index;
uint last = _tokens.length - 1;
_tokens[index] = _tokens[last];
_records[_tokens[index]].index = index;
_tokens.pop();
_records[token] = Record({bound: false, index: 0, denorm: 0, balance: 0});
}
function gulp(address token) external _logs_ _lock_ {
require(_records[token].bound, "ERR_NOT_BOUND");
_records[token].balance = IERC20(token).balanceOf(address(this));
}
function joinPool(uint poolAmountOut, uint[] calldata maxAmountsIn) external _logs_ _lock_ {
require(_finalized, "ERR_NOT_FINALIZED");
uint poolTotal = this.totalSupply();
uint ratio = bdiv(poolAmountOut, poolTotal);
require(ratio != 0, "ERR_MATH_APPROX");
for (uint i = 0; i < _tokens.length; i++) {
address t = _tokens[i];
uint bal = _records[t].balance;
uint tokenAmountIn = bmul(ratio, bal);
require(tokenAmountIn != 0, "ERR_MATH_APPROX");
require(tokenAmountIn <= maxAmountsIn[i], "ERR_LIMIT_IN");
_records[t].balance = badd(_records[t].balance, tokenAmountIn);
emit LOG_JOIN(msg.sender, t, tokenAmountIn);
_pullUnderlying(t, msg.sender, tokenAmountIn);
}
_mintPoolShare(poolAmountOut);
_pushPoolShare(msg.sender, poolAmountOut);
}
function exitPool(uint poolAmountIn, uint[] calldata minAmountsOut) external _logs_ _lock_ {
require(_finalized, "ERR_NOT_FINALIZED");
uint poolTotal = this.totalSupply();
uint ratio = bdiv(poolAmountIn, poolTotal);
require(ratio != 0, "ERR_MATH_APPROX");
_pullPoolShare(msg.sender, poolAmountIn);
_burnPoolShare(poolAmountIn);
for (uint i = 0; i < _tokens.length; i++) {
address t = _tokens[i];
uint bal = _records[t].balance;
uint tokenAmountOut = bmul(ratio, bal);
require(tokenAmountOut != 0, "ERR_MATH_APPROX");
require(tokenAmountOut >= minAmountsOut[i], "ERR_LIMIT_OUT");
_records[t].balance = bsub(_records[t].balance, tokenAmountOut);
emit LOG_EXIT(msg.sender, t, tokenAmountOut);
_pushUnderlying(t, msg.sender, tokenAmountOut);
}
}
function _safeApprove(
IERC20 token,
address spender,
uint amount
) internal {
if (token.allowance(address(this), spender) > 0) {
token.approve(spender, 0);
}
token.approve(spender, amount);
}
function _pullUnderlying(
address erc20,
address from,
uint amount
) internal {
bool xfer = IERC20(erc20).transferFrom(from, address(this), amount);
require(xfer, "ERR_ERC20_FALSE");
}
function _pushUnderlying(
address erc20,
address to,
uint amount
) internal {
bool xfer = IERC20(erc20).transfer(to, amount);
require(xfer, "ERR_ERC20_FALSE");
}
function _pullPoolShare(address from, uint amount) internal {
_pull(from, amount);
}
function _pushPoolShare(address to, uint amount) internal {
_push(to, amount);
}
function _mintPoolShare(uint amount) internal {
_mint(amount);
}
function _burnPoolShare(uint amount) internal {
_burn(amount);
}
receive() external payable {}
}
文件 12 的 18:LpToken.sol
pragma solidity 0.6.12;
import "./Num.sol";
import "../interfaces/IERC20.sol";
contract LpTokenBase is Num {
mapping(address => uint) internal _balance;
mapping(address => mapping(address => uint)) internal _allowance;
uint internal _totalSupply;
event Approval(address indexed src, address indexed dst, uint amt);
event Transfer(address indexed src, address indexed dst, uint amt);
function _mint(uint amt) internal {
_balance[address(this)] = badd(_balance[address(this)], amt);
_totalSupply = badd(_totalSupply, amt);
emit Transfer(address(0), address(this), amt);
}
function _burn(uint amt) internal {
require(_balance[address(this)] >= amt, "ERR_INSUFFICIENT_BAL");
_balance[address(this)] = bsub(_balance[address(this)], amt);
_totalSupply = bsub(_totalSupply, amt);
emit Transfer(address(this), address(0), amt);
}
function _move(
address src,
address dst,
uint amt
) internal {
require(_balance[src] >= amt, "ERR_INSUFFICIENT_BAL");
_balance[src] = bsub(_balance[src], amt);
_balance[dst] = badd(_balance[dst], amt);
emit Transfer(src, dst, amt);
}
function _push(address to, uint amt) internal {
_move(address(this), to, amt);
}
function _pull(address from, uint amt) internal {
_move(from, address(this), amt);
}
}
contract LpToken is LpTokenBase, IERC20 {
string private _name = "Desyn Pool Token";
string private _symbol = "DPT";
uint8 private _decimals = 18;
function name() external view returns (string memory) {
return _name;
}
function symbol() external view override returns (string memory) {
return _symbol;
}
function decimals() external view override returns (uint8) {
return _decimals;
}
function allowance(address src, address dst) external view override returns (uint) {
return _allowance[src][dst];
}
function balanceOf(address whom) external view override returns (uint) {
return _balance[whom];
}
function totalSupply() external view override returns (uint) {
return _totalSupply;
}
function approve(address dst, uint amt) external override returns (bool) {
_allowance[msg.sender][dst] = amt;
emit Approval(msg.sender, dst, amt);
return true;
}
function increaseApproval(address dst, uint amt) external returns (bool) {
_allowance[msg.sender][dst] = badd(_allowance[msg.sender][dst], amt);
emit Approval(msg.sender, dst, _allowance[msg.sender][dst]);
return true;
}
function decreaseApproval(address dst, uint amt) external returns (bool) {
uint oldValue = _allowance[msg.sender][dst];
if (amt > oldValue) {
_allowance[msg.sender][dst] = 0;
} else {
_allowance[msg.sender][dst] = bsub(oldValue, amt);
}
emit Approval(msg.sender, dst, _allowance[msg.sender][dst]);
return true;
}
function transfer(address dst, uint amt) external override returns (bool) {
require(dst != address(0),"ERR_BAD_RECIVER");
_move(msg.sender, dst, amt);
return true;
}
function transferFrom(
address src,
address dst,
uint amt
) external override returns (bool) {
require(dst != address(0),"ERR_BAD_RECIVER");
require(msg.sender == src || amt <= _allowance[src][msg.sender], "ERR_LPTOKEN_BAD_CALLER");
_move(src, dst, amt);
if (msg.sender != src && _allowance[src][msg.sender] != uint(-1)) {
_allowance[src][msg.sender] = bsub(_allowance[src][msg.sender], amt);
emit Approval(src, msg.sender, _allowance[src][msg.sender]);
}
return true;
}
}
文件 13 的 18:Math.sol
pragma solidity 0.6.12;
import "./Num.sol";
contract Math is BBronze, Const, Num {
function calcSpotPrice(
uint tokenBalanceIn,
uint tokenWeightIn,
uint tokenBalanceOut,
uint tokenWeightOut,
uint swapFee
) external pure returns (uint spotPrice) {
uint numer = bdiv(tokenBalanceIn, tokenWeightIn);
uint denom = bdiv(tokenBalanceOut, tokenWeightOut);
uint ratio = bdiv(numer, denom);
uint scale = bdiv(BONE, bsub(BONE, swapFee));
return (spotPrice = bmul(ratio, scale));
}
function calcOutGivenIn(
uint tokenBalanceIn,
uint tokenWeightIn,
uint tokenBalanceOut,
uint tokenWeightOut,
uint tokenAmountIn,
uint swapFee
) external pure returns (uint tokenAmountOut) {
uint weightRatio = bdiv(tokenWeightIn, tokenWeightOut);
uint adjustedIn = bsub(BONE, swapFee);
adjustedIn = bmul(tokenAmountIn, adjustedIn);
uint y = bdiv(tokenBalanceIn, badd(tokenBalanceIn, adjustedIn));
uint foo = bpow(y, weightRatio);
uint bar = bsub(BONE, foo);
tokenAmountOut = bmul(tokenBalanceOut, bar);
return tokenAmountOut;
}
function calcInGivenOut(
uint tokenBalanceIn,
uint tokenWeightIn,
uint tokenBalanceOut,
uint tokenWeightOut,
uint tokenAmountOut,
uint swapFee
) external pure returns (uint tokenAmountIn) {
uint weightRatio = bdiv(tokenWeightOut, tokenWeightIn);
uint diff = bsub(tokenBalanceOut, tokenAmountOut);
uint y = bdiv(tokenBalanceOut, diff);
uint foo = bpow(y, weightRatio);
foo = bsub(foo, BONE);
tokenAmountIn = bsub(BONE, swapFee);
tokenAmountIn = bdiv(bmul(tokenBalanceIn, foo), tokenAmountIn);
return tokenAmountIn;
}
function calcPoolOutGivenSingleIn(
uint tokenBalanceIn,
uint tokenWeightIn,
uint poolSupply,
uint totalWeight,
uint tokenAmountIn,
uint swapFee
) external pure returns (uint poolAmountOut) {
uint normalizedWeight = bdiv(tokenWeightIn, totalWeight);
uint zaz = bmul(bsub(BONE, normalizedWeight), swapFee);
uint tokenAmountInAfterFee = bmul(tokenAmountIn, bsub(BONE, zaz));
uint newTokenBalanceIn = badd(tokenBalanceIn, tokenAmountInAfterFee);
uint tokenInRatio = bdiv(newTokenBalanceIn, tokenBalanceIn);
uint poolRatio = bpow(tokenInRatio, normalizedWeight);
uint newPoolSupply = bmul(poolRatio, poolSupply);
poolAmountOut = bsub(newPoolSupply, poolSupply);
return poolAmountOut;
}
function calcSingleInGivenPoolOut(
uint tokenBalanceIn,
uint tokenWeightIn,
uint poolSupply,
uint totalWeight,
uint poolAmountOut,
uint swapFee
) external pure returns (uint tokenAmountIn) {
uint normalizedWeight = bdiv(tokenWeightIn, totalWeight);
uint newPoolSupply = badd(poolSupply, poolAmountOut);
uint poolRatio = bdiv(newPoolSupply, poolSupply);
uint boo = bdiv(BONE, normalizedWeight);
uint tokenInRatio = bpow(poolRatio, boo);
uint newTokenBalanceIn = bmul(tokenInRatio, tokenBalanceIn);
uint tokenAmountInAfterFee = bsub(newTokenBalanceIn, tokenBalanceIn);
uint zar = bmul(bsub(BONE, normalizedWeight), swapFee);
tokenAmountIn = bdiv(tokenAmountInAfterFee, bsub(BONE, zar));
return tokenAmountIn;
}
function calcSingleOutGivenPoolIn(
uint tokenBalanceOut,
uint tokenWeightOut,
uint poolSupply,
uint totalWeight,
uint poolAmountIn,
uint swapFee
) external pure returns (uint tokenAmountOut) {
uint normalizedWeight = bdiv(tokenWeightOut, totalWeight);
uint poolAmountInAfterExitFee = bmul(poolAmountIn, bsub(BONE, EXIT_FEE));
uint newPoolSupply = bsub(poolSupply, poolAmountInAfterExitFee);
uint poolRatio = bdiv(newPoolSupply, poolSupply);
uint tokenOutRatio = bpow(poolRatio, bdiv(BONE, normalizedWeight));
uint newTokenBalanceOut = bmul(tokenOutRatio, tokenBalanceOut);
uint tokenAmountOutBeforeSwapFee = bsub(tokenBalanceOut, newTokenBalanceOut);
uint zaz = bmul(bsub(BONE, normalizedWeight), swapFee);
tokenAmountOut = bmul(tokenAmountOutBeforeSwapFee, bsub(BONE, zaz));
return tokenAmountOut;
}
function calcPoolInGivenSingleOut(
uint tokenBalanceOut,
uint tokenWeightOut,
uint poolSupply,
uint totalWeight,
uint tokenAmountOut,
uint swapFee
) external pure returns (uint poolAmountIn) {
uint normalizedWeight = bdiv(tokenWeightOut, totalWeight);
uint zoo = bsub(BONE, normalizedWeight);
uint zar = bmul(zoo, swapFee);
uint tokenAmountOutBeforeSwapFee = bdiv(tokenAmountOut, bsub(BONE, zar));
uint newTokenBalanceOut = bsub(tokenBalanceOut, tokenAmountOutBeforeSwapFee);
uint tokenOutRatio = bdiv(newTokenBalanceOut, tokenBalanceOut);
uint poolRatio = bpow(tokenOutRatio, normalizedWeight);
uint newPoolSupply = bmul(poolRatio, poolSupply);
uint poolAmountInAfterExitFee = bsub(poolSupply, newPoolSupply);
poolAmountIn = bdiv(poolAmountInAfterExitFee, bsub(BONE, EXIT_FEE));
return poolAmountIn;
}
}
文件 14 的 18:Num.sol
pragma solidity 0.6.12;
import "./Const.sol";
contract Num is Const {
function btoi(uint a) internal pure returns (uint) {
return a / BONE;
}
function bfloor(uint a) internal pure returns (uint) {
return btoi(a) * BONE;
}
function badd(uint a, uint b) internal pure returns (uint) {
uint c = a + b;
require(c >= a, "ERR_ADD_OVERFLOW");
return c;
}
function bsub(uint a, uint b) internal pure returns (uint) {
(uint c, bool flag) = bsubSign(a, b);
require(!flag, "ERR_SUB_UNDERFLOW");
return c;
}
function bsubSign(uint a, uint b) internal pure returns (uint, bool) {
if (a >= b) {
return (a - b, false);
} else {
return (b - a, true);
}
}
function bmul(uint a, uint b) internal pure returns (uint) {
uint c0 = a * b;
require(a == 0 || c0 / a == b, "ERR_MUL_OVERFLOW");
uint c1 = c0 + (BONE / 2);
require(c1 >= c0, "ERR_MUL_OVERFLOW");
uint c2 = c1 / BONE;
return c2;
}
function bdiv(uint a, uint b) internal pure returns (uint) {
require(b != 0, "ERR_DIV_ZERO");
uint c0 = a * BONE;
require(a == 0 || c0 / a == BONE, "ERR_DIV_INTERNAL");
uint c1 = c0 + (b / 2);
require(c1 >= c0, "ERR_DIV_INTERNAL");
uint c2 = c1 / b;
return c2;
}
function bpowi(uint a, uint n) internal pure returns (uint) {
uint z = n % 2 != 0 ? a : BONE;
for (n /= 2; n != 0; n /= 2) {
a = bmul(a, a);
if (n % 2 != 0) {
z = bmul(z, a);
}
}
return z;
}
function bpow(uint base, uint exp) internal pure returns (uint) {
require(base >= MIN_BPOW_BASE, "ERR_BPOW_BASE_TOO_LOW");
require(base <= MAX_BPOW_BASE, "ERR_BPOW_BASE_TOO_HIGH");
uint whole = bfloor(exp);
uint remain = bsub(exp, whole);
uint wholePow = bpowi(base, btoi(whole));
if (remain == 0) {
return wholePow;
}
uint partialResult = bpowApprox(base, remain, BPOW_PRECISION);
return bmul(wholePow, partialResult);
}
function bpowApprox(
uint base,
uint exp,
uint precision
) internal pure returns (uint) {
uint a = exp;
(uint x, bool xneg) = bsubSign(base, BONE);
uint term = BONE;
uint sum = term;
bool negative = false;
for (uint i = 1; term >= precision; i++) {
uint bigK = i * BONE;
(uint c, bool cneg) = bsubSign(a, bsub(bigK, BONE));
term = bmul(term, bmul(c, x));
term = bdiv(term, bigK);
if (term == 0) break;
if (xneg) negative = !negative;
if (cneg) negative = !negative;
if (negative) {
sum = bsub(sum, term);
} else {
sum = badd(sum, term);
}
}
return sum;
}
}
文件 15 的 18:SafeApprove.sol
pragma solidity 0.6.12;
import "../interfaces/IERC20.sol";
library SafeApprove {
function safeApprove(
IERC20 token,
address spender,
uint amount
) internal returns (bool) {
uint currentAllowance = token.allowance(address(this), spender);
if (currentAllowance == amount) {
return true;
}
if (currentAllowance != 0) {
token.approve(spender, 0);
}
return token.approve(spender, amount);
}
}
文件 16 的 18:SafeMath.sol
pragma solidity 0.6.12;
library SafeMath {
function add(uint a, uint b) internal pure returns (uint) {
uint c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint a, uint b) internal pure returns (uint) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(
uint a,
uint b,
string memory errorMessage
) internal pure returns (uint) {
require(b <= a, errorMessage);
uint c = a - b;
return c;
}
function mul(uint a, uint b) internal pure returns (uint) {
if (a == 0) {
return 0;
}
uint c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint a, uint b) internal pure returns (uint) {
return div(a, b, "SafeMath: division by zero");
}
function div(
uint a,
uint b,
string memory errorMessage
) internal pure returns (uint) {
require(b > 0, errorMessage);
uint c = a / b;
return c;
}
function mod(uint a, uint b) internal pure returns (uint) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(
uint a,
uint b,
string memory errorMessage
) internal pure returns (uint) {
require(b != 0, errorMessage);
return a % b;
}
}
文件 17 的 18:SmartPoolManager.sol
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import "../interfaces/IERC20.sol";
import "../interfaces/IConfigurableRightsPool.sol";
import "../interfaces/IBFactory.sol";
import "./DesynSafeMath.sol";
import "./SafeMath.sol";
import "./SafeApprove.sol";
library SmartPoolManager {
using SafeApprove for IERC20;
using DesynSafeMath for uint;
using SafeMath for uint;
struct levelParams {
uint level;
uint ratio;
}
struct feeParams {
levelParams firstLevel;
levelParams secondLevel;
levelParams thirdLevel;
levelParams fourLevel;
}
struct KolPoolParams {
feeParams managerFee;
feeParams issueFee;
feeParams redeemFee;
feeParams perfermanceFee;
}
enum Etypes {
OPENED,
CLOSED
}
enum Period {
HALF,
ONE,
TWO
}
struct Status {
uint collectPeriod;
uint collectEndTime;
uint closurePeriod;
uint closureEndTime;
uint upperCap;
uint floorCap;
uint managerFee;
uint redeemFee;
uint issueFee;
uint perfermanceFee;
uint startClaimFeeTime;
}
struct PoolParams {
string poolTokenSymbol;
string poolTokenName;
address[] constituentTokens;
uint[] tokenBalances;
uint[] tokenWeights;
uint swapFee;
uint managerFee;
uint redeemFee;
uint issueFee;
uint perfermanceFee;
Etypes etype;
}
struct PoolTokenRange {
uint bspFloor;
uint bspCap;
}
struct Fund {
uint etfAmount;
uint fundAmount;
}
function initRequire(
uint swapFee,
uint managerFee,
uint issueFee,
uint redeemFee,
uint perfermanceFee,
uint tokenBalancesLength,
uint tokenWeightsLength,
uint constituentTokensLength,
bool initBool
) external pure {
require(!initBool, "Init fail");
require(swapFee >= DesynConstants.MIN_FEE, "ERR_INVALID_SWAP_FEE");
require(swapFee <= DesynConstants.MAX_FEE, "ERR_INVALID_SWAP_FEE");
require(managerFee >= DesynConstants.MANAGER_MIN_FEE, "ERR_INVALID_MANAGER_FEE");
require(managerFee <= DesynConstants.MANAGER_MAX_FEE, "ERR_INVALID_MANAGER_FEE");
require(issueFee >= DesynConstants.ISSUE_MIN_FEE, "ERR_INVALID_ISSUE_MIN_FEE");
require(issueFee <= DesynConstants.ISSUE_MAX_FEE, "ERR_INVALID_ISSUE_MAX_FEE");
require(redeemFee >= DesynConstants.REDEEM_MIN_FEE, "ERR_INVALID_REDEEM_MIN_FEE");
require(redeemFee <= DesynConstants.REDEEM_MAX_FEE, "ERR_INVALID_REDEEM_MAX_FEE");
require(perfermanceFee >= DesynConstants.PERFERMANCE_MIN_FEE, "ERR_INVALID_PERFERMANCE_MIN_FEE");
require(perfermanceFee <= DesynConstants.PERFERMANCE_MAX_FEE, "ERR_INVALID_PERFERMANCE_MAX_FEE");
require(tokenBalancesLength == constituentTokensLength, "ERR_START_BALANCES_MISMATCH");
require(tokenWeightsLength == constituentTokensLength, "ERR_START_WEIGHTS_MISMATCH");
require(constituentTokensLength >= DesynConstants.MIN_ASSET_LIMIT, "ERR_TOO_FEW_TOKENS");
require(constituentTokensLength <= DesynConstants.MAX_ASSET_LIMIT, "ERR_TOO_MANY_TOKENS");
}
function rebalance(
IConfigurableRightsPool self,
IBPool bPool,
address tokenA,
address tokenB,
uint deltaWeight,
uint minAmountOut
) external {
uint currentWeightA = bPool.getDenormalizedWeight(tokenA);
uint currentBalanceA = bPool.getBalance(tokenA);
require(deltaWeight <= currentWeightA, "ERR_DELTA_WEIGHT_TOO_BIG");
uint deltaBalanceA = DesynSafeMath.bmul(currentBalanceA, DesynSafeMath.bdiv(deltaWeight, currentWeightA));
bool soldout;
if (deltaWeight == currentWeightA) {
bPool.unbindPure(tokenA);
soldout = true;
}
bPool.rebindSmart(tokenA, tokenB, deltaWeight, deltaBalanceA, soldout, minAmountOut);
}
function verifyTokenCompliance(address token) external {
verifyTokenComplianceInternal(token);
}
function verifyTokenCompliance(address[] calldata tokens) external {
for (uint i = 0; i < tokens.length; i++) {
verifyTokenComplianceInternal(tokens[i]);
}
}
function createPoolInternalHandle(IBPool bPool, uint initialSupply) external view {
require(initialSupply >= DesynConstants.MIN_POOL_SUPPLY, "ERR_INIT_SUPPLY_MIN");
require(initialSupply <= DesynConstants.MAX_POOL_SUPPLY, "ERR_INIT_SUPPLY_MAX");
require(bPool.EXIT_FEE() == 0, "ERR_NONZERO_EXIT_FEE");
require(DesynConstants.EXIT_FEE == 0, "ERR_NONZERO_EXIT_FEE");
}
function createPoolHandle(
uint collectPeriod,
uint upperCap,
uint initialSupply
) external pure {
require(collectPeriod <= DesynConstants.MAX_COLLECT_PERIOD, "ERR_EXCEEDS_FUND_RAISING_PERIOD");
require(upperCap >= initialSupply, "ERR_CAP_BIGGER_THAN_INITSUPPLY");
}
function exitPoolHandle(
uint _endEtfAmount,
uint _endFundAmount,
uint _beginEtfAmount,
uint _beginFundAmount,
uint poolAmountIn,
uint totalEnd
)
external
pure
returns (
uint endEtfAmount,
uint endFundAmount,
uint profitRate
)
{
endEtfAmount = DesynSafeMath.badd(_endEtfAmount, poolAmountIn);
endFundAmount = DesynSafeMath.badd(_endFundAmount, totalEnd);
uint amount1 = DesynSafeMath.bdiv(endFundAmount, endEtfAmount);
uint amount2 = DesynSafeMath.bdiv(_beginFundAmount, _beginEtfAmount);
if (amount1 > amount2) {
profitRate = DesynSafeMath.bdiv(
DesynSafeMath.bmul(DesynSafeMath.bsub(DesynSafeMath.bdiv(endFundAmount, endEtfAmount), DesynSafeMath.bdiv(_beginFundAmount, _beginEtfAmount)), poolAmountIn),
totalEnd
);
}
}
function exitPoolHandleA(
IConfigurableRightsPool self,
IBPool bPool,
address poolToken,
uint _tokenAmountOut,
uint redeemFee,
uint profitRate,
uint perfermanceFee
)
external
returns (
uint redeemAndPerformanceFeeReceived,
uint finalAmountOut,
uint redeemFeeReceived
)
{
redeemFeeReceived = DesynSafeMath.bmul(_tokenAmountOut, redeemFee);
uint performanceFeeReceived = DesynSafeMath.bmul(DesynSafeMath.bmul(_tokenAmountOut, profitRate), perfermanceFee);
redeemAndPerformanceFeeReceived = DesynSafeMath.badd(performanceFeeReceived, redeemFeeReceived);
finalAmountOut = DesynSafeMath.bsub(_tokenAmountOut, redeemAndPerformanceFeeReceived);
_pushUnderlying(bPool, poolToken, msg.sender, finalAmountOut);
if (redeemFee != 0 || (profitRate > 0 && perfermanceFee != 0)) {
_pushUnderlying(bPool, poolToken, address(this), redeemAndPerformanceFeeReceived);
IERC20(poolToken).safeApprove(self.vaultAddress(), redeemAndPerformanceFeeReceived);
}
}
function exitPoolHandleB(
IConfigurableRightsPool self,
bool bools,
bool isCompletedCollect,
uint closureEndTime,
uint collectEndTime,
uint _etfAmount,
uint _fundAmount,
uint poolAmountIn
) external view returns (uint etfAmount, uint fundAmount, uint actualPoolAmountIn) {
actualPoolAmountIn = poolAmountIn;
if (bools) {
bool isCloseEtfCollectEndWithFailure = isCompletedCollect == false && block.timestamp >= collectEndTime;
bool isCloseEtfClosureEnd = block.timestamp >= closureEndTime;
require(isCloseEtfCollectEndWithFailure || isCloseEtfClosureEnd, "ERR_CLOSURE_TIME_NOT_ARRIVED!");
actualPoolAmountIn = self.balanceOf(msg.sender);
}
fundAmount = _fundAmount;
etfAmount = _etfAmount;
}
function joinPoolHandle(
bool canWhitelistLPs,
bool isList,
bool bools,
uint collectEndTime
) external view {
require(!canWhitelistLPs || isList, "ERR_NOT_ON_WHITELIST");
if (bools) {
require(block.timestamp <= collectEndTime, "ERR_COLLECT_PERIOD_FINISHED!");
}
}
function rebalanceHandle(
IBPool bPool,
bool isCompletedCollect,
bool bools,
uint collectEndTime,
uint closureEndTime,
bool canChangeWeights,
address tokenA,
address tokenB
) external {
require(bPool.isBound(tokenA), "ERR_TOKEN_NOT_BOUND");
if (bools) {
require(isCompletedCollect, "ERROR_COLLECTION_FAILED");
require(block.timestamp > collectEndTime && block.timestamp < closureEndTime, "ERR_NOT_REBALANCE_PERIOD");
}
if (!bPool.isBound(tokenB)) {
bool returnValue = IERC20(tokenB).safeApprove(address(bPool), DesynConstants.MAX_UINT);
require(returnValue, "ERR_ERC20_FALSE");
}
require(canChangeWeights, "ERR_NOT_CONFIGURABLE_WEIGHTS");
require(tokenA != tokenB, "ERR_TOKENS_SAME");
}
function joinPool(
IConfigurableRightsPool self,
IBPool bPool,
uint poolAmountOut,
uint[] calldata maxAmountsIn,
uint issueFee
) external view returns (uint[] memory actualAmountsIn) {
address[] memory tokens = bPool.getCurrentTokens();
require(maxAmountsIn.length == tokens.length, "ERR_AMOUNTS_MISMATCH");
uint poolTotal = self.totalSupply();
uint ratio = DesynSafeMath.bdiv(poolAmountOut, DesynSafeMath.bsub(poolTotal, 1));
require(ratio != 0, "ERR_MATH_APPROX");
actualAmountsIn = new uint[](tokens.length);
uint issueFeeRate = issueFee.bmul(1000);
for (uint i = 0; i < tokens.length; i++) {
address t = tokens[i];
uint bal = bPool.getBalance(t);
uint base = bal.badd(1).bmul(poolAmountOut * uint(1000));
uint tokenAmountIn = base.bdiv(poolTotal.bsub(1) * (uint(1000).bsub(issueFeeRate)));
require(tokenAmountIn != 0, "ERR_MATH_APPROX");
require(tokenAmountIn <= maxAmountsIn[i], "ERR_LIMIT_IN");
actualAmountsIn[i] = tokenAmountIn;
}
}
function exitPool(
IConfigurableRightsPool self,
IBPool bPool,
uint poolAmountIn,
uint[] calldata minAmountsOut
) external view returns (uint[] memory actualAmountsOut) {
address[] memory tokens = bPool.getCurrentTokens();
require(minAmountsOut.length == tokens.length, "ERR_AMOUNTS_MISMATCH");
uint poolTotal = self.totalSupply();
uint ratio = DesynSafeMath.bdiv(poolAmountIn, DesynSafeMath.badd(poolTotal, 1));
require(ratio != 0, "ERR_MATH_APPROX");
actualAmountsOut = new uint[](tokens.length);
for (uint i = 0; i < tokens.length; i++) {
address t = tokens[i];
uint bal = bPool.getBalance(t);
uint tokenAmountOut = DesynSafeMath.bmul(ratio, DesynSafeMath.bsub(bal, 1));
require(tokenAmountOut != 0, "ERR_MATH_APPROX");
require(tokenAmountOut >= minAmountsOut[i], "ERR_LIMIT_OUT");
actualAmountsOut[i] = tokenAmountOut;
}
}
function verifyTokenComplianceInternal(address token) internal {
bool returnValue = IERC20(token).transfer(msg.sender, 0);
require(returnValue, "ERR_NONCONFORMING_TOKEN");
}
function handleTransferInTokens(
IConfigurableRightsPool self,
IBPool bPool,
address poolToken,
uint actualAmountIn,
uint _actualIssueFee
) external returns (uint issueFeeReceived) {
issueFeeReceived = DesynSafeMath.bmul(actualAmountIn, _actualIssueFee);
uint amount = DesynSafeMath.bsub(actualAmountIn, issueFeeReceived);
_pullUnderlying(bPool, poolToken, msg.sender, amount);
if (_actualIssueFee != 0) {
bool xfer = IERC20(poolToken).transferFrom(msg.sender, address(this), issueFeeReceived);
require(xfer, "ERR_ERC20_FALSE");
IERC20(poolToken).safeApprove(self.vaultAddress(), issueFeeReceived);
}
}
function handleClaim(
IConfigurableRightsPool self,
IBPool bPool,
address[] calldata poolTokens,
uint managerFee,
uint timeElapsed,
uint claimPeriod
) external returns (uint[] memory) {
uint[] memory tokensAmount = new uint[](poolTokens.length);
for (uint i = 0; i < poolTokens.length; i++) {
address t = poolTokens[i];
uint tokenBalance = bPool.getBalance(t);
uint tokenAmountOut = tokenBalance.bmul(managerFee).mul(timeElapsed).div(claimPeriod).div(12);
_pushUnderlying(bPool, t, address(this), tokenAmountOut);
IERC20(t).safeApprove(self.vaultAddress(), tokenAmountOut);
tokensAmount[i] = tokenAmountOut;
}
return tokensAmount;
}
function handleCollectionCompleted(
IConfigurableRightsPool self,
IBPool bPool,
address[] calldata poolTokens,
uint issueFee
) external {
if (issueFee != 0) {
uint[] memory tokensAmount = new uint[](poolTokens.length);
for (uint i = 0; i < poolTokens.length; i++) {
address t = poolTokens[i];
uint currentAmount = bPool.getBalance(t);
uint currentAmountFee = DesynSafeMath.bmul(currentAmount, issueFee);
_pushUnderlying(bPool, t, address(this), currentAmountFee);
tokensAmount[i] = currentAmountFee;
IERC20(t).safeApprove(self.vaultAddress(), currentAmountFee);
}
IVault(self.vaultAddress()).depositIssueRedeemPToken(poolTokens, tokensAmount, tokensAmount, false);
}
}
function WhitelistHandle(
bool bool1,
bool bool2,
address adr
) external pure {
require(bool1, "ERR_CANNOT_WHITELIST_LPS");
require(bool2, "ERR_LP_NOT_WHITELISTED");
require(adr != address(0), "ERR_INVALID_ADDRESS");
}
function _pullUnderlying(
IBPool bPool,
address erc20,
address from,
uint amount
) internal {
uint tokenBalance = bPool.getBalance(erc20);
uint tokenWeight = bPool.getDenormalizedWeight(erc20);
bool xfer = IERC20(erc20).transferFrom(from, address(this), amount);
require(xfer, "ERR_ERC20_FALSE");
bPool.rebind(erc20, DesynSafeMath.badd(tokenBalance, amount), tokenWeight);
}
function _pushUnderlying(
IBPool bPool,
address erc20,
address to,
uint amount
) internal {
uint tokenBalance = bPool.getBalance(erc20);
uint tokenWeight = bPool.getDenormalizedWeight(erc20);
bPool.rebind(erc20, DesynSafeMath.bsub(tokenBalance, amount), tokenWeight);
bool xfer = IERC20(erc20).transfer(to, amount);
require(xfer, "ERR_ERC20_FALSE");
}
}
文件 18 的 18:WhiteToken.sol
pragma solidity 0.6.12;
contract WhiteToken {
event LOG_WHITELIST(address indexed spender, uint indexed sort, address indexed caller, address token);
event LOG_DEL_WHITELIST(address indexed spender, uint indexed sort, address indexed caller, address token);
uint private _whiteTokenCount;
mapping(address => bool) private _isTokenWhitelisted;
mapping(uint => mapping(address => bool)) private _tokenWhitelistedInfo;
function _queryIsTokenWhitelisted(address token) internal view returns (bool) {
return _isTokenWhitelisted[token];
}
function _isTokenWhitelistedForVerify(uint sort, address token) internal view returns (bool) {
return _tokenWhitelistedInfo[sort][token];
}
function _addTokenToWhitelist(uint sort, address token) internal {
require(token != address(0), "ERR_INVALID_TOKEN_ADDRESS");
require(_queryIsTokenWhitelisted(token) == false, "ERR_HAS_BEEN_ADDED_WHITE");
_tokenWhitelistedInfo[sort][token] = true;
_isTokenWhitelisted[token] = true;
_whiteTokenCount++;
emit LOG_WHITELIST(address(this), sort, msg.sender, token);
}
function _removeTokenFromWhitelist(uint sort, address token) internal {
require(_queryIsTokenWhitelisted(token) == true, "ERR_NOT_WHITE_TOKEN");
require(_tokenWhitelistedInfo[sort][token], "ERR_SORT_NOT_MATCHED");
_tokenWhitelistedInfo[sort][token] = false;
_isTokenWhitelisted[token] = false;
_whiteTokenCount--;
emit LOG_DEL_WHITELIST(address(this), sort, msg.sender, token);
}
function _initWhiteTokenState() internal view returns (bool) {
return _whiteTokenCount == 0 ? false : true;
}
}
{
"compilationTarget": {
"contracts/deploy/Factory.sol": "Factory"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 20
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"blabs","type":"address"}],"name":"LOG_BLABS","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"sort","type":"uint256"},{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"LOG_DEL_WHITELIST","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"manager","type":"address"},{"indexed":true,"internalType":"address","name":"caller","type":"address"}],"name":"LOG_MANAGER","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"pool","type":"address"}],"name":"LOG_NEW_POOL","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"oracle","type":"address"}],"name":"LOG_ORACLE","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"router","type":"address"}],"name":"LOG_ROUTER","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"address","name":"caller","type":"address"}],"name":"LOG_USER_VAULT","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"address","name":"caller","type":"address"}],"name":"LOG_VAULT","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"sort","type":"uint256"},{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"LOG_WHITELIST","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"etf","type":"address"},{"indexed":false,"internalType":"address","name":"module","type":"address"},{"indexed":false,"internalType":"bool","name":"status","type":"bool"}],"name":"MODULE_STATUS_CHANGE","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"state","type":"bool"}],"name":"PAUSED_STATUS","type":"event"},{"inputs":[{"internalType":"uint256[]","name":"sort","type":"uint256[]"},{"internalType":"address[]","name":"token","type":"address[]"}],"name":"addTokenToWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bytecodes","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"collect","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getBLabs","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getColor","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getManagerOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"etf","type":"address"},{"internalType":"address","name":"module","type":"address"}],"name":"getModuleStatus","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOracleAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSwapRouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUserVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"b","type":"address"}],"name":"isLiquidityPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"sort","type":"uint256"},{"internalType":"address","name":"token","type":"address"}],"name":"isTokenWhitelistedForVerify","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"isTokenWhitelistedForVerify","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"newLiquidityPool","outputs":[{"internalType":"contract IBPool","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"etf","type":"address"},{"internalType":"address","name":"module","type":"address"}],"name":"registerModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"etf","type":"address"},{"internalType":"address","name":"module","type":"address"}],"name":"removeModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"sort","type":"uint256[]"},{"internalType":"address[]","name":"token","type":"address[]"}],"name":"removeTokenFromWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"b","type":"address"}],"name":"setBLabs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newManagerOwner","type":"address"}],"name":"setManagerOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"oracle","type":"address"}],"name":"setOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"state","type":"bool"}],"name":"setProtocolPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"router","type":"address"}],"name":"setSwapRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newVault","type":"address"}],"name":"setUserVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newVault","type":"address"}],"name":"setVault","outputs":[],"stateMutability":"nonpayable","type":"function"}]