LinearLiquidityPool.sol
1 pragma experimental ABIEncoderV2; 2 pragma solidity >=0.6.0; 3 4 import "./LinearInterpolator.sol"; 5 import "./LiquidityPool.sol"; 6 7 contract LinearLiquidityPool is LiquidityPool { 8 9 LinearInterpolator private interpolator; 10 11 string private constant _name = "Linear Liquidity Pool Redeemable Token"; 12 string private constant _symbol = "LLPTK"; 13 14 constructor() LiquidityPool(_name) public { 15 16 } 17 18 function initialize(Deployer deployer) override internal { 19 20 super.initialize(deployer); 21 interpolator = LinearInterpolator(deployer.getContractAddress("LinearInterpolator")); 22 } 23 24 function name() override external view returns (string memory) { 25 return _name; 26 } 27 28 function symbol() override external view returns (string memory) { 29 return _symbol; 30 } 31 32 function writeOptions( 33 IOptionToken tk, 34 PricingParameters memory param, 35 uint volume, 36 address to 37 ) 38 internal 39 override 40 { 41 require(tk.writtenVolume(address(this)).add(volume) <= param.buyStock, "excessive volume"); 42 43 IOptionsExchange.OpenExposureInputs memory oEi; 44 45 oEi.symbols[0] = tk.symbol(); 46 oEi.volume[0] = volume; 47 oEi.isShort[0] = true; 48 oEi.isCovered[0] = false; 49 oEi.poolAddrs[0] = address(this); 50 oEi.paymentTokens[0] = address(0); 51 52 exchange.openExposure( 53 oEi, 54 to 55 ); 56 57 require(calcFreeBalance() > 0, "pool balance too low"); 58 } 59 60 function calcOptPrice(PricingParameters memory p, Operation op) 61 internal 62 override 63 view 64 returns (uint) 65 { 66 return interpolator.interpolate( 67 getUdlPrice(p.udlFeed), 68 p.t0, 69 p.t1, 70 p.x, 71 p.y, 72 op == Operation.BUY ? spread.add(fractionBase) : fractionBase.sub(spread) 73 ); 74 } 75 76 function calcVolume( 77 string memory optSymbol, 78 PricingParameters memory p, 79 uint price, 80 Operation op 81 ) 82 internal 83 override 84 view 85 returns (uint volume) 86 { 87 uint r = fractionBase.sub(reserveRatio); 88 89 uint coll = exchange.calcCollateral( 90 p.udlFeed, 91 volumeBase, 92 p.optType, 93 p.strike, 94 p.maturity 95 ); 96 97 if (op == Operation.BUY) { 98 99 volume = coll <= price ? uint(-1) : 100 calcFreeBalance().mul(volumeBase).div( 101 coll.sub(price.mul(r).div(fractionBase)) 102 ); 103 104 } else { 105 106 uint bal = exchange.balanceOf(address(this)); 107 108 uint poolColl = exchange.collateral(address(this)); 109 110 uint writtenColl = IOptionToken( 111 exchange.resolveToken(optSymbol) 112 ).writtenVolume(address(this)).mul(coll); 113 114 poolColl = poolColl > writtenColl ? poolColl.sub(writtenColl) : 0; 115 116 uint iv = uint(exchange.calcIntrinsicValue( 117 p.udlFeed, 118 p.optType, 119 p.strike, 120 p.maturity 121 )); 122 123 volume = price <= iv ? uint(-1) : 124 bal.sub(poolColl.mul(fractionBase).div(r)).mul(volumeBase).div( 125 price.sub(iv) 126 ); 127 128 volume = MoreMath.max( 129 volume, 130 bal.mul(volumeBase).div(price) 131 ); 132 133 volume = MoreMath.min( 134 volume, 135 bal.mul(volumeBase).div(price) 136 ); 137 } 138 } 139 }