Guest User

Untitled

a guest
Dec 20th, 2020
66
20 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. var fs = require('fs');
  2. var http = require('http');
  3. const data = JSON.parse(fs.readFileSync('data.json', 'utf8'));
  4. const liquidation_data = JSON.parse(fs.readFileSync('liquidation_data.json', 'utf8'));
  5. const transaction_data = JSON.parse(fs.readFileSync('transaction_data.json', 'utf8'));
  6.  
  7. const liquidation_penalty_pct = 1.08;
  8.  
  9. const DAI_manipulated_value = 1.17; // TODO source from transaction. Currently set to value it was at one of the blocks
  10.  
  11. // TODO source from transaction. Currently using min value on coingecko around the time of the event
  12. // USD values of corresponding real tokens (not cTokens) at time of event
  13. const token_values = {
  14.     'cDAI': 1.03,
  15.     'cUSDC': 1,
  16.     'cUSDT': 1,
  17.     'cETH': 489, // Is 520.22 on my transaction, but using this value to steelman
  18.     'cWBTC': 16485,
  19.     'cCOMP': 99.6,
  20.     'cUNI': 3.16,
  21.     'cZRX': 0.3777,
  22.     'cBAT': 0.216,
  23.     'cREP': 13.95,
  24.     'cSAI': 2.6 ,
  25. };
  26.  
  27. // TODO source from transactions
  28. const c_token_values = {
  29.     'cDAI': 0.021415,
  30.     'cUSDC': 0.021,
  31.     'cUSDT': 0.0204,
  32.     'cETH': 9.83,
  33.     'cWBTC': 336.55,
  34.     'cCOMP': 2.03,
  35.     'cUNI': 0.063,
  36.     'cZRX': 0.007665,
  37.     'cBAT': 0.004314,
  38.     'cREP': 0.292,
  39.     'cSAI': 0.059523,
  40. };
  41.  
  42. function cTokenCountToUSDValue(v, token) {
  43.     return c_token_values[token] * v / 100000000;
  44. }
  45.  
  46. // Collateral factors for each token
  47. const token_collateral_factors = {
  48.     'cDAI': 0.75,
  49.     'cUSDC': 0.75,
  50.     'cUSDT': 0,
  51.     'cETH': 0.75,
  52.     'cWBTC': 0.6,
  53.     'cCOMP': 0.6,
  54.     'cUNI': 0.6,
  55.     'cZRX': 0.6,
  56.     'cBAT': 0.6,
  57.     'cREP': 0.4,
  58.     'cSAI': 0,
  59. };
  60.  
  61. var output = {};
  62.  
  63. // Damage = False liquidation damage - what would have actually been liquidated given correct prices
  64. for (let row of data) {
  65.     let filtered_liquidations = liquidation_data.filter(function (liquidation) {return liquidation.address === row.address;});
  66.     let liquidation_data_point = filtered_liquidations[0];
  67.  
  68.     function GetBorrowAndSupply(dai_price) {
  69.         var total_supply = 0;
  70.         var total_supply_per_collateral_factor = 0;
  71.         var total_borrow = 0;
  72.         for (let token of row.tokens) {
  73.             var token_value = token.symbol === 'cDAI' ? dai_price : token_values[token.symbol];
  74.             total_supply += +token.supply_balance_underlying.value * token_value;
  75.             total_supply_per_collateral_factor += +token.supply_balance_underlying.value
  76.                                                   * token_value
  77.                                                   * token_collateral_factors[token.symbol];
  78.             total_borrow += +token.borrow_balance_underlying.value * token_value;
  79.         }
  80.  
  81.         return {
  82.             supply_USD: total_supply,
  83.             supply_per_collateral_factor_USD: total_supply_per_collateral_factor,
  84.             borrow_USD: total_borrow
  85.         };
  86.     };
  87.  
  88.     let borrow_USD = GetBorrowAndSupply(token_values['cDAI']).borrow_USD;
  89.     let supply_USD = GetBorrowAndSupply(token_values['cDAI']).supply_USD;
  90.     let supply_cf_USD = GetBorrowAndSupply(token_values['cDAI']).supply_per_collateral_factor_USD;
  91.     let manipulated_borrow_USD = GetBorrowAndSupply(DAI_manipulated_value).borrow_USD;
  92.     let manipulated_supply_USD = GetBorrowAndSupply(DAI_manipulated_value).supply_USD;
  93.     let manipulated_supply_cf_USD = GetBorrowAndSupply(DAI_manipulated_value).supply_per_collateral_factor_USD;
  94.  
  95.     // If this is true, the price manipulation event actually prevented liquidation for this address
  96.     let escaped_liquidation = manipulated_supply_cf_USD > borrow_USD && supply_cf_USD < borrow_USD;
  97.  
  98.     // This does not include opportunity cost of losing access to the asset,
  99.     // just the immediate monetary impact of the event
  100.     let DAI_repaid = +liquidation_data_point.DAI_repaid;
  101.  
  102.     let value_of_amount_liquidated_in_USD = cTokenCountToUSDValue(+liquidation_data_point.amount, liquidation_data_point.token);
  103.     let liquidation_penalty_in_DAI = DAI_repaid * liquidation_penalty_pct - DAI_repaid;
  104.     // For DAI to DAI use the value directly, as the loss is simply the liquidation penalty in this case
  105.     let liquidation_penalty_in_USD = liquidation_data_point.token == "cDAI"
  106.                                    ? liquidation_penalty_in_DAI * token_values["cDAI"]
  107.                                    : liquidation_penalty_in_DAI * DAI_manipulated_value;
  108.  
  109.     // If the DAI price was correct and the position was liquidated (regardless of whether it was over the threshold)
  110.     // this is what the damage would be.
  111.     let value_of_DAI_liquidated_at_real_price_in_USD = (DAI_repaid * token_values['cDAI']) * liquidation_penalty_pct;
  112.    
  113.     // Whether or not the position would have been liquidated based on using the correct DAI price
  114.     let would_have_been_otherwise_liquidated = borrow_USD >= supply_cf_USD;
  115.  
  116.     var total_damage = 0;
  117.     var liquidation_penalty_at_correct_DAI_price_in_USD = (liquidation_penalty_in_USD / DAI_manipulated_value * token_values["cDAI"]);
  118.     if (would_have_been_otherwise_liquidated) {
  119.         // In this case they would have been liquidated anyway,
  120.         // and we simply take the delta between the liquidation penalty at the manipulated price vs correct price
  121.         total_damage = liquidation_penalty_in_USD - liquidation_penalty_at_correct_DAI_price_in_USD;
  122.     } else {
  123.         // This model takes the liquidation penalty + anything extra introduced by the fact that the DAI was incorrect as the total damages.
  124.         // This does not include external factors like opportunity cost, taxes, secondary effects etc...
  125.         total_damage = value_of_amount_liquidated_in_USD
  126.                      - value_of_DAI_liquidated_at_real_price_in_USD
  127.                      + liquidation_penalty_in_USD;
  128.     }
  129.  
  130.     output[row.address] = {
  131.         'escaped_liquidation' : escaped_liquidation,
  132.         'would_have_been_otherwise_liquidated' : would_have_been_otherwise_liquidated,
  133.         'value_of_amount_liquidated_in_USD' : value_of_amount_liquidated_in_USD,
  134.         'value_of_DAI_liquidated_at_real_price_in_USD' : value_of_DAI_liquidated_at_real_price_in_USD,
  135.         'liquidation_penalty_in_USD' : liquidation_penalty_in_USD,
  136.         'liquidation_penalty_at_correct_DAI_price_in_USD' : liquidation_penalty_at_correct_DAI_price_in_USD,
  137.         'total_damage' : total_damage
  138.     };
  139. }
  140.  
  141. console.log(output)
RAW Paste Data