编译器
0.6.12+commit.27d51765
文件 1 的 12: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 的 12:Color.sol
pragma solidity 0.6.12;
contract BBronze {
function getColor() external pure returns (bytes32) {
return bytes32("BRONZE");
}
}
文件 3 的 12: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 的 12:IBFactory.sol
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
interface IBPool {
function rebind(
address token,
uint balance,
uint denorm
) 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 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 getVault() external view returns (address);
function getUserVault() external view returns (address);
function getVaultAddress() external view returns (address);
function getOracleAddress() 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);
}
文件 5 的 12: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 adminList(address) external view returns (bool);
function getController() external view returns (address);
function vaultAddress() external view returns (address);
}
文件 6 的 12: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);
}
文件 7 的 12:LiquidityPool.sol
pragma solidity 0.6.12;
import "./LpToken.sol";
import "./Math.sol";
import "../interfaces/IBFactory.sol";
import "../interfaces/IConfigurableRightsPool.sol";
import "../libraries/Address.sol";
import "../libraries/SafeERC20.sol";
contract LiquidityPool is BBronze, LpToken, Math {
using Address for address;
using SafeERC20 for IERC20;
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;
bool private _finalized;
address[] private _tokens;
mapping(address => Record) private _records;
uint private _totalWeight;
constructor() public {
_controller = msg.sender;
_factory = IBFactory(msg.sender);
_publicSwap = false;
_finalized = false;
}
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) {
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");
Oracles oracle = Oracles(_factory.getOracleAddress());
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) {
return _records[token].balance;
}
function getController() external view _viewlock_ returns (address) {
return _controller;
}
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 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 rebindPure(
address token,
uint balance,
uint denorm,
bool isBound
) public _logs_ _lock_ {
require(msg.sender == _controller, "ERR_NOT_CONTROLLER");
if (!isBound) {
require(_tokens.length < MAX_BOUND_TOKENS, "ERR_MAX_TOKENS");
_records[token] = Record({
bound: true,
index: _tokens.length,
denorm: denorm,
balance: balance
});
_tokens.push(token);
} else {
_records[token].denorm = denorm;
_records[token].balance = balance;
}
}
function gulp(address token) external _logs_ _lock_ {
require(IConfigurableRightsPool(_controller).adminList(msg.sender), 'NOT_ADMIN');
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(msg.sender == _controller, "ERR_NOT_CONTROLLER");
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(msg.sender == _controller, "ERR_NOT_CONTROLLER");
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 _pullUnderlying(
address erc20,
address from,
uint amount
) internal {
IERC20(erc20).safeTransferFrom(from, address(this), amount);
}
function _pushUnderlying(
address erc20,
address to,
uint amount
) internal {
IERC20(erc20).safeTransfer(to, amount);
}
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 {}
}
文件 8 的 12: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;
}
}
文件 9 的 12: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;
}
}
文件 10 的 12: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;
}
}
文件 11 的 12:SafeERC20.sol
pragma solidity 0.6.12;
import {IERC20} from "../interfaces/IERC20.sol";
import {SafeMath} from "./SafeMath.sol";
import {Address} from "./Address.sol";
library SafeERC20 {
using SafeMath for uint;
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint value
) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint value
) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint 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 callOptionalReturn(IERC20 token, bytes memory data) private {
require(address(token).isContract(), "SafeERC20: call to non-contract");
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 12 的 12: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;
}
}
{
"compilationTarget": {
"contracts/base/LiquidityPool.sol": "LiquidityPool"
},
"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":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"internalType":"bytes4","name":"sig","type":"bytes4"},{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"LOG_CALL","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmountOut","type":"uint256"}],"name":"LOG_EXIT","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmountIn","type":"uint256"}],"name":"LOG_JOIN","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenA","type":"address"},{"indexed":true,"internalType":"address","name":"tokenB","type":"address"},{"indexed":false,"internalType":"uint256","name":"newWeightA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newWeightB","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalanceA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalanceB","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isSoldout","type":"bool"}],"name":"LOG_REBALANCE","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"BONE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BPOW_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXIT_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INIT_POOL_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BOUND_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BPOW_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_IN_RATIO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_OUT_RATIO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TOTAL_WEIGHT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_WEIGHT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_BALANCE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_BOUND_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_BPOW_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_WEIGHT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amt","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"whom","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"denorm","type":"uint256"}],"name":"bind","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceIn","type":"uint256"},{"internalType":"uint256","name":"tokenWeightIn","type":"uint256"},{"internalType":"uint256","name":"tokenBalanceOut","type":"uint256"},{"internalType":"uint256","name":"tokenWeightOut","type":"uint256"},{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcInGivenOut","outputs":[{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceIn","type":"uint256"},{"internalType":"uint256","name":"tokenWeightIn","type":"uint256"},{"internalType":"uint256","name":"tokenBalanceOut","type":"uint256"},{"internalType":"uint256","name":"tokenWeightOut","type":"uint256"},{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcOutGivenIn","outputs":[{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceOut","type":"uint256"},{"internalType":"uint256","name":"tokenWeightOut","type":"uint256"},{"internalType":"uint256","name":"poolSupply","type":"uint256"},{"internalType":"uint256","name":"totalWeight","type":"uint256"},{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcPoolInGivenSingleOut","outputs":[{"internalType":"uint256","name":"poolAmountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceIn","type":"uint256"},{"internalType":"uint256","name":"tokenWeightIn","type":"uint256"},{"internalType":"uint256","name":"poolSupply","type":"uint256"},{"internalType":"uint256","name":"totalWeight","type":"uint256"},{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcPoolOutGivenSingleIn","outputs":[{"internalType":"uint256","name":"poolAmountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceIn","type":"uint256"},{"internalType":"uint256","name":"tokenWeightIn","type":"uint256"},{"internalType":"uint256","name":"poolSupply","type":"uint256"},{"internalType":"uint256","name":"totalWeight","type":"uint256"},{"internalType":"uint256","name":"poolAmountOut","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcSingleInGivenPoolOut","outputs":[{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceOut","type":"uint256"},{"internalType":"uint256","name":"tokenWeightOut","type":"uint256"},{"internalType":"uint256","name":"poolSupply","type":"uint256"},{"internalType":"uint256","name":"totalWeight","type":"uint256"},{"internalType":"uint256","name":"poolAmountIn","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcSingleOutGivenPoolIn","outputs":[{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceIn","type":"uint256"},{"internalType":"uint256","name":"tokenWeightIn","type":"uint256"},{"internalType":"uint256","name":"tokenBalanceOut","type":"uint256"},{"internalType":"uint256","name":"tokenWeightOut","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcSpotPrice","outputs":[{"internalType":"uint256","name":"spotPrice","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amt","type":"uint256"}],"name":"decreaseApproval","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"execute","outputs":[{"internalType":"bytes","name":"_returnValue","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"poolAmountIn","type":"uint256"},{"internalType":"uint256[]","name":"minAmountsOut","type":"uint256[]"}],"name":"exitPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finalize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getColor","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getController","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentTokens","outputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getDenormalizedWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFinalTokens","outputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getNormalizedWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getNumTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalDenormalizedWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"gulp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amt","type":"uint256"}],"name":"increaseApproval","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"t","type":"address"}],"name":"isBound","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isFinalized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPublicSwap","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"poolAmountOut","type":"uint256"},{"internalType":"uint256[]","name":"maxAmountsIn","type":"uint256[]"}],"name":"joinPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"denorm","type":"uint256"}],"name":"rebind","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"denorm","type":"uint256"},{"internalType":"bool","name":"isBound","type":"bool"}],"name":"rebindPure","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"manager","type":"address"}],"name":"setController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"public_","type":"bool"}],"name":"setPublicSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amt","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amt","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"unbind","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"unbindPure","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]