Unit ID
D7wz4eUM9b+7hcUe0xqZrRAZAWVPXsawi4RtPKs433o=
Received
23.02.2022 15:20:20
Confirmation delay (full node)
8 minutes 31 seconds
Confirmation delay (light node)
15 minutes 3 seconds
Messages
Definition
Definition: [ "autonomous agent", { "doc_url": "https://oswap.io/v1-v2-arb.json", "getters": "{ }", "init": "{ $v1_aa = params.oswap_v1_aa; $v2_aa = params.oswap_v2_aa; $v1_params = definition[$v1_aa][1].params; $v2_params = definition[$v2_aa][1].params; $x_asset = $v2_params.x_asset; $y_asset = $v2_params.y_asset; $non_base = $x_asset != 'base' AND $y_asset != 'base'; require( $v1_params.asset0 == $x_asset AND $v1_params.asset1 == $y_asset OR $v1_params.asset0 == $y_asset AND $v1_params.asset1 == $x_asset, 'non-matching assets' ); $get_param = ($name, $default) => { $value = var[$v2_aa][$name]; exists($value) ? $value : (exists($v2_params[$name]) ? $v2_params[$name] : $default) }; $get_shifts = () => { $mid_price = $get_param('mid_price', 0); // price of x_asset in terms of y_asset if ($mid_price){ $alpha = $get_param('alpha', 0.5); $beta = 1 - $alpha; $gamma = $get_param('price_deviation', 0); $lp_shares = var[$v2_aa]['lp_shares']; $s_curve = $lp_shares.linear * $lp_shares.coef; $x0 = $s_curve / $mid_price^$beta / $gamma; $y0 = $x0 * $mid_price; } // else{ // $x0 = 0; // $y0 = 0; // } {x0: $x0, y0: $y0} }; $get_denom = ($balances, $l_balances, $shifts, $pxy, $beta) => { $leverages = [2, 5, 10, 20, 50, 100]; // account for leveraged positions $L_sums = {x: 0}; foreach($leverages, 6, $L => { $L_sums.x = $L_sums.x + ($L - 1) * ($l_balances[$L||'x'].balance + $l_balances[-$L||'x'].balance / $pxy); }); $denom = $beta * ($balances.x + $shifts.x0) - $L_sums.x; // log({denom: $denom, sum: $L_sums.x, share: $L_sums.x/$denom}); require($denom > 0, "negative denom " || $denom); $denom }; $get_available_balance = ($asset) => balance[$asset] - ($asset == 'base' ? 10000 : 0); $scale_amounts_down_if_necessary = ($amounts, $x_balance, $y_balance) => { if ($amounts.x > $x_balance AND $amounts.y > $y_balance){ $x_factor = $x_balance/$amounts.x; $y_factor = $y_balance/$amounts.y; if ($x_factor >= $y_factor){ $amounts.x = $x_balance; $amounts.y = $x_factor * $amounts.y; } else { $amounts.y = $y_balance; $amounts.x = $y_factor * $amounts.x; } log('scaled down to', $amounts); } }; }", "messages": { "cases": [ { "if": "{ trigger.data.arb}", "init": "{ $share = trigger.data.share OTHERWISE 1; // for incomplete arb $precalculated = trigger.data.amount AND trigger.data.from; if (!$precalculated) { $v1_fee = $v1_params.swap_fee / 1e11; $v2_fee = $get_param('swap_fee', 0.003); $v1_x_balance = balance[$v1_aa][$x_asset]; $v1_y_balance = balance[$v1_aa][$y_asset]; $p1 = $v1_y_balance / $v1_x_balance; $balances = var[$v2_aa]['balances']; $l_balances = var[$v2_aa]['leveraged_balances']; $shifts = $get_shifts(); $alpha = $get_param('alpha', 0.5); $beta = 1 - $alpha; $p2 = $alpha/$beta * ($balances.y + $shifts.y0) / ($balances.x + $shifts.x0); $denom1 = $v1_x_balance/2; // beta = 1/2 $denom2 = $get_denom($balances, $l_balances, $shifts, $p2, $beta); $Lambda = $get_param('pool_leverage', 1); $x_balance = $get_available_balance($x_asset); $y_balance = $get_available_balance($y_asset); $amounts = {x: 0, y: 0}; // profitable to buy x on v2 and sell on v1 if ($p2 * (1 + $v2_fee) < $p1 * (1 - $v1_fee)){ $p2_plus_fee = $p2 * (1 + $v2_fee); $p1_minus_fee = $p1 * (1 - $v1_fee); $amounts.x = ($p1_minus_fee - $p2_plus_fee)/$p1_minus_fee / (1/$denom2 + 1/$denom1); $amounts.y = $p1_minus_fee * $amounts.x; // overestimate $scale_amounts_down_if_necessary($amounts, $x_balance, $y_balance); $final_p = $p2 * (1 + $amounts.x/$denom2 * $share); // log({p1: $p1, p2: $p2, p1_minus_fee: $p1_minus_fee, p2_plus_fee: $p2_plus_fee, final_p: $final_p, denom2: $denom2, amounts: $amounts}); if ($amounts.y <= $y_balance){ $from = 'v2y'; $asset = $y_asset; $amount = ceil($amounts.y); $address = $v2_aa; $data = { final_price: $final_p, hops: [ { // next oswap in the chain address: $v1_aa, change_address: this_address, data: {to: this_address}, }, ] }; } else{ $from = 'v1x'; $asset = $x_asset; $amount = ceil($amounts.x); $address = $v1_aa; $data = {to: this_address}; // v1 sends y back to us, and we then send it to v2 $stored_data = { final_price: $final_p, }; } } // profitable to buy x on v1 and sell on v2 else if ($p2 * (1 - $v2_fee) > $p1 * (1 + $v1_fee)){ $p2_minus_fee = $p2 * (1 - $v2_fee); $p1_plus_fee = $p1 * (1 + $v1_fee); $amounts.x = ($p2_minus_fee - $p1_plus_fee)/$p2_minus_fee / (1/$denom2 + 1/$denom1); $amounts.y = $amounts.x * $p2_minus_fee; // overestimate $scale_amounts_down_if_necessary($amounts, $x_balance, $y_balance); $final_pyx = 1/$p2 * (1 + $amounts.x/($denom2 + $beta * $Lambda * $amounts.x) * $share); // log({p1: $p1, p2: $p2, p1_plus_fee: $p1_plus_fee, p2_minus_fee: $p2_minus_fee, final_pyx: $final_pyx, denom2: $denom2, amounts: $amounts}); if ($amounts.x <= $x_balance){ $from = 'v2x'; $asset = $x_asset; $amount = ceil($amounts.x); $address = $v2_aa; $data = { final_price: $final_pyx, hops: [ { // next oswap in the chain address: $v1_aa, change_address: this_address, data: {to: this_address}, }, ] }; } else { $from = 'v1y'; $asset = $y_asset; $amount = ceil($amounts.y); $address = $v1_aa; $data = {to: this_address}; // v1 sends x back to us, and we then send it to v2 $stored_data = { final_price: $final_pyx, }; } } else bounce("no arb opportunity exists"); } else { // overridden in the request, don't calc $amount = trigger.data.amount; $from = trigger.data.from; if ($from == 'v2y'){ $asset = $y_asset; $address = $v2_aa; $data = { final_price: trigger.data.final_p, hops: [ { // next oswap in the chain address: $v1_aa, change_address: this_address, data: {to: this_address}, }, ] }; } else if ($from == 'v1x'){ $asset = $x_asset; $address = $v1_aa; $data = {to: this_address}; // v1 sends y back to us, and we then send it to v2 $stored_data = { final_price: trigger.data.final_p, }; } else if ($from == 'v2x'){ $asset = $x_asset; $address = $v2_aa; $data = { final_price: trigger.data.final_pyx, hops: [ { // next oswap in the chain address: $v1_aa, change_address: this_address, data: {to: this_address}, }, ] }; } else if ($from == 'v1y'){ $asset = $y_asset; $address = $v1_aa; $data = {to: this_address}; // v1 sends x back to us, and we then send it to v2 $stored_data = { final_price: trigger.data.final_pyx, }; } } }", "messages": [ { "app": "payment", "payload": { "asset": "{$asset}", "outputs": [ { "address": "{$address}", "amount": "{ $amount }" } ] } }, { "if": "{$non_base}", "app": "payment", "payload": { "asset": "base", "outputs": [ { "address": "{$address}", "amount": 3000 } ] } }, { "app": "data", "payload": "{$data}" }, { "app": "state", "state": "{ $arb = { from: $from, avg_price: ($p1 + $p2) / 2, sent: {}, received: {}, }; $arb.sent[$asset] = $amount; if ($stored_data) $arb.stored_data = $stored_data; var['arb'] = $arb; // log({arb: $arb}); response['sent_amount'] = $amount; if ($from == 'v2y') response['message'] = 'will arb by buying X from v2 and selling to v1'; else if ($from == 'v1x') response['message'] = 'will arb by selling X to v1 and buying from v2'; else if ($from == 'v2x') response['message'] = 'will arb by selling X to v2 and buying from v1'; else if ($from == 'v1y') response['message'] = 'will arb by buying X from v1 and selling to v2'; }" } ] }, { "if": "{ $received_x = trigger.output[[asset=$x_asset]]; $received_y = trigger.output[[asset=$y_asset]]; $arb = var['arb']; ($received_x > 0 OR $received_y > 0) AND (trigger.address == $v1_aa OR trigger.address == $v2_aa) AND $arb }", "init": "{ $from_v1 = $arb.from == 'v1x' OR $arb.from == 'v1y'; if ($from_v1) require($arb.stored_data, 'no data for v2'); $forward = $from_v1 AND trigger.address == $v1_aa; if ($forward){ if ($received_x > 0 AND $received_y > 0) bounce('received both assets from v1'); $received_asset = $received_x > 0 ? $x_asset : $y_asset; } }", "messages": [ { "if": "{$forward}", "app": "payment", "payload": { "asset": "{$received_asset}", "outputs": [ { "address": "{$v2_aa}", "amount": "{ $received_x OTHERWISE $received_y }" } ] } }, { "if": "{$forward AND $non_base}", "app": "payment", "payload": { "asset": "base", "outputs": [ { "address": "{$v2_aa}", "amount": 3000 } ] } }, { "if": "{$forward}", "app": "data", "payload": "{$arb.stored_data}" }, { "app": "state", "state": "{ if ($forward){ response['message'] = 'forwarded to v2'; // log('forwarded to v2', $received_x, $received_y); return; } $arb.received[$x_asset] = $arb.received[$x_asset] + $received_x; $arb.received[$y_asset] = $arb.received[$y_asset] + $received_y; $change = !$from_v1 AND trigger.address == $v2_aa; if ($change){ var['arb'] = $arb; response['message'] = 'received the change from v2'; // log('received the change from v2', $received_x, $received_y); return; } // log('received proceeds', $received_x, $received_y); $sent = $arb.sent[$y_asset] + $arb.sent[$x_asset] * $arb.avg_price; $received = $arb.received[$y_asset] + $arb.received[$x_asset] * $arb.avg_price; $profit = $received - $sent; // log({p1: balance[$v1_aa][$y_asset]/balance[$v1_aa][$x_asset], p2: $v2_aa#28.$get_price('x'), arb: $arb}); require($profit > 0, "unprofitable " || $arb.from || ": " || $received || " < " || $sent); response['profit'] = $profit; // in Y var['arb'] = false; }" } ] }, { "if": "{ trigger.data.withdraw AND trigger.data.asset AND trigger.address == params.owner }", "init": "{ if (trigger.data.asset == 'x') $asset = $x_asset; else if (trigger.data.asset == 'y') $asset = $y_asset; else $asset = trigger.data.asset; }", "messages": [ { "app": "payment", "payload": { "asset": "{$asset}", "outputs": [ { "address": "{params.owner}", "amount": "{ trigger.data.amount OTHERWISE '' }" } ] } } ] }, { "if": "{ trigger.output[[asset=$x_asset]] > 0 OR trigger.output[[asset=$y_asset]] > 0 }", "messages": [ { "app": "state", "state": "{ response['message'] = 'added'; }" } ] } ] } } ]
Technical information
Fees:
11,790 bytes
(451 headers, 11339 payload)
Level:8814036
Witnessed level:8814027
Main chain index:8481320
Latest included mc index:8481319
Status:stable/confirmed/final