/ test / finance / OptionsExchange / TestOptionLiquidation.t.sol
TestOptionLiquidation.t.sol
  1  pragma solidity >=0.6.0;
  2  
  3  import "truffle/Assert.sol";
  4  import "../../../contracts/utils/MoreMath.sol";
  5  import "../../common/utils/MoreAssert.t.sol";
  6  import "./Base.t.sol";
  7  
  8  
  9  contract TestOptionLiquidation is Base {
 10      
 11      function testLiquidationBeforeAllowed() public {
 12  
 13          uint mu = MoreMath.sqrtAndMultiply(10, upperVol);
 14          depositTokens(address(bob), mu);
 15          address _tk = bob.writeOption(CALL, ethInitialPrice, 10 days, pool);
 16  
 17          bob.transferOptions(address(alice), _tk, 1);
 18              
 19          (bool success,) = address(bob).call(
 20              abi.encodePacked(
 21                  bob.liquidateOptions.selector,
 22                  abi.encode(_tk, address(bob))
 23              )
 24          );
 25          
 26          Assert.isFalse(success, "liquidate should fail");
 27      }
 28  
 29      function testPartialLiquidationWhenIssuerLacksCollateral() public {
 30          
 31          int step = 40e18;
 32  
 33          uint mu = MoreMath.sqrtAndMultiply(10, upperVol);
 34          depositTokens(address(bob), mu);
 35          address _tk = bob.writeOption(CALL, ethInitialPrice, 10 days, pool);
 36  
 37          bob.transferOptions(address(alice), _tk, 1);
 38  
 39          feed.setPrice(ethInitialPrice + step);
 40  
 41          Assert.equal(bob.calcCollateral(), mu + uint(step), "bob collateral before liquidation");
 42  
 43          OptionToken tk = OptionToken(_tk);
 44          uint v1 = tk.writtenVolume(address(bob));
 45          collateralManager.liquidateOptions(_tk, address(bob));
 46          uint v2 = tk.writtenVolume(address(bob));
 47  
 48          Assert.isTrue(v1 > v2, "written volume liquidation");
 49  
 50          MoreAssert.equal(bob.calcCollateral(), bob.balance(), cBase, "bob final collateral");
 51          Assert.equal(alice.calcCollateral(), 0, "alice final collateral");
 52  
 53          Assert.equal(bob.calcSurplus(), 0, "bob final surplus");
 54          Assert.equal(alice.calcSurplus(), 0, "alice final surplus");
 55  
 56          Assert.equal(getBookLength(), 2, "book length");
 57      }
 58  
 59      function testMultipleLiquidationsWhenIssuerLacksCollateral() public {
 60          
 61          int step = 20e18;
 62  
 63          uint mu = MoreMath.sqrtAndMultiply(10, upperVol);
 64          depositTokens(address(bob), mu);
 65          address _tk = bob.writeOption(CALL, ethInitialPrice, 10 days, pool);
 66  
 67          bob.transferOptions(address(alice), _tk, 1);
 68  
 69          feed.setPrice(ethInitialPrice + 1 * step);
 70          uint v1 = collateralManager.liquidateOptions(_tk, address(bob));
 71          Assert.isTrue(v1 > 0, "liquidation value t1");
 72          Assert.equal(bob.balance(), mu - v1, "bob balance t1");
 73          MoreAssert.equal(bob.calcCollateral(), mu - v1, cBase, "bob collateral t1");
 74  
 75          feed.setPrice(ethInitialPrice + 2 * step);
 76          uint v2 = collateralManager.liquidateOptions(_tk, address(bob));
 77          Assert.isTrue(v2 > 0, "liquidation value t2");
 78          Assert.equal(bob.balance(), mu - v1 - v2, "bob balance t2");
 79          MoreAssert.equal(bob.calcCollateral(), mu - v1 - v2, cBase, "bob collateral t2");
 80  
 81          feed.setPrice(ethInitialPrice + 3 * step);
 82          uint v3 = collateralManager.liquidateOptions(_tk, address(bob));
 83          Assert.isTrue(v3 > 0, "liquidation value t3");
 84          Assert.equal(bob.balance(), mu - v1 - v2 - v3, "bob balance t3");
 85          MoreAssert.equal(bob.calcCollateral(), mu - v1 - v2 - v3, cBase, "bob collateral t3");
 86  
 87          Assert.equal(getBookLength(), 2, "book length");
 88      }
 89  
 90      function testFullLiquidationsWhenIssuerLacksCollateral() public {
 91          
 92          int step = 100e18;
 93  
 94          uint mu = MoreMath.sqrtAndMultiply(10, upperVol);
 95          depositTokens(address(bob), mu);
 96          address _tk = bob.writeOption(CALL, ethInitialPrice, 10 days, pool);
 97  
 98          bob.transferOptions(address(alice), _tk, 1);
 99  
100          feed.setPrice(ethInitialPrice + 1 * step);
101          uint v1 = collateralManager.liquidateOptions(_tk, address(bob));
102          Assert.isTrue(v1 > mu, "liquidation value t1");
103          Assert.equal(bob.balance(), 0, "bob balance t1");
104          MoreAssert.equal(bob.calcCollateral(), 0, cBase, "bob collateral t1");
105  
106          Assert.equal(getBookLength(), 1, "book length");
107      }
108  
109      function testLiquidationAtMaturityOTM() public {
110          
111          int step = 40e18;
112  
113          uint mu = MoreMath.sqrtAndMultiply(10, upperVol);
114          depositTokens(address(bob), mu);
115          address _tk = bob.writeOption(CALL, ethInitialPrice, 10 days, pool);
116          
117          bob.transferOptions(address(alice), _tk, 1);
118  
119          feed.setPrice(ethInitialPrice - step);
120          time.setTimeOffset(10 days);
121  
122          Assert.equal(bob.calcCollateral(), 0, "bob collateral before liquidation");
123  
124          collateralManager.liquidateOptions(_tk, address(bob));
125  
126          Assert.equal(bob.calcCollateral(), 0, "bob final collateral");
127          Assert.equal(alice.calcCollateral(), 0, "alice final collateral");
128  
129          Assert.equal(bob.calcSurplus(), mu, "bob final surplus");
130          Assert.equal(alice.calcSurplus(), 0, "alice final surplus");
131      }
132  
133      function testLiquidationAtMaturityITM() public {
134          
135          int step = 40e18;
136  
137          uint mu = MoreMath.sqrtAndMultiply(10, upperVol);
138          depositTokens(address(bob), mu);
139          address _tk = bob.writeOption(PUT, ethInitialPrice, 10 days, pool);
140          
141          bob.transferOptions(address(alice), _tk, 1);
142  
143          feed.setPrice(ethInitialPrice - step);
144          time.setTimeOffset(10 days);
145  
146          uint iv = uint(exchange.calcIntrinsicValue(_tk));
147  
148          Assert.equal(bob.calcCollateral(), iv, "bob collateral before liquidation");
149  
150          collateralManager.liquidateOptions(_tk, address(bob));
151  
152          Assert.equal(iv, uint(step), "intrinsic value");
153  
154          Assert.equal(bob.calcCollateral(), 0, "bob final collateral");
155          Assert.equal(alice.calcCollateral(), 0, "alice final collateral");
156  
157          Assert.equal(bob.calcSurplus(), mu - iv, "bob final surplus");
158          Assert.equal(alice.calcSurplus(), 0, "alice final surplus");
159      }
160  }