Unit ID
r6ZQJFNR5wG3KCIbhgsWchMTRCRRvV4KT4JS/K24V2E=
Received
22.09.2020 10:06:42
Confirmation delay (full node)
5 minutes 4 seconds
Confirmation delay (light node)
7 minutes 59 seconds
Messages
Definition
Definition: [ "autonomous agent", { "doc_url": "https://ostable.org/bonded-stablecoin-deposits.json", "getters": "{ $_get_param = ($name, $state_params, $initial_params, $default_params) => { $state_value = $state_params[$name]; if (exists($state_value)) return $state_value; $initial_value = $initial_params[$name]; if (exists($initial_value)) return $initial_value; $default_params[$name] }; $get_curve_aa = () => params.curve_aa; $get_curve_aa_params = () => definition[params.curve_aa][1].params; $get_deposit_params = () => { $default_params = { min_deposit_term: 2 * 3600, challenging_period: 12 * 3600, challenge_immunity_period: 3600, reporter_share: 0.2, // 20% }; $curve_aa_params = $get_curve_aa_params(); $deposit_state_params = var[params.curve_aa]['deposit_params']; { min_deposit_term: $_get_param('min_deposit_term', $deposit_state_params, $curve_aa_params.deposits, $default_params), challenging_period: $_get_param('challenging_period', $deposit_state_params, $curve_aa_params.deposits, $default_params), challenge_immunity_period: $_get_param('challenge_immunity_period', $deposit_state_params, $curve_aa_params.deposits, $default_params), reporter_share: $_get_param('reporter_share', $deposit_state_params, $curve_aa_params.deposits, $default_params), } }; }", "init": "{ $bank_aa = 'GV5YXIIRH3DH5FTEECW7IS2EQTAYJJ6S'; $curve_aa = params.curve_aa; // tokens $asset = var['asset']; $interest_rate = var[$curve_aa]['interest_rate']; $term = (timestamp - var[$curve_aa]['rate_update_ts']) / (360 * 24 * 3600); // in years $growth_factor = var[$curve_aa]['growth_factor'] * (1 + $interest_rate)^$term; $curve_aa_params = $get_curve_aa_params(); $reserve_asset = $curve_aa_params.reserve_asset;// OTHERWISE 'base'; $interest_asset = var[$curve_aa]['asset2']; $deposit_params = $get_deposit_params(); $min_deposit_term = $deposit_params.min_deposit_term; $challenging_period = $deposit_params.challenging_period; $challenge_immunity_period = $deposit_params.challenge_immunity_period; $reporter_share = $deposit_params.reporter_share; $remove_deposit = ($id, $stable_amount) => { var['deposit_' || $id] = false; var['supply'] -= $stable_amount; }; }", "messages": { "cases": [ { "if": "{ trigger.data.define AND !$asset }", "messages": [ { "app": "asset", "payload": { "is_private": false, "is_transferrable": true, "auto_destroy": false, "fixed_denominations": false, "issued_by_definer_only": true, "cosigned_by_definer": false, "spender_attested": false } }, { "if": "{trigger.data.factory}", "app": "data", "payload": { "write_stable_asset": 1, "curve_aa": "{$curve_aa}" } }, { "if": "{trigger.data.factory}", "app": "payment", "payload": { "asset": "base", "outputs": [ { "address": "{trigger.data.factory}" } ] } }, { "app": "state", "state": "{ var['asset'] = response_unit; response['asset'] = response_unit; }" } ] }, { "if": "{ $asset AND trigger.output[[asset=$interest_asset]] > 0 }", "init": "{ if (exists(trigger.data.interest_recipient) AND !is_valid_address(trigger.data.interest_recipient)) bounce("bad address of interest recipient"); if (exists(trigger.data.to) AND !is_valid_address(trigger.data.to)) bounce("bad to-address"); if (exists(trigger.data.owner) AND !is_valid_address(trigger.data.owner)) bounce("bad owner address"); $to = trigger.data.to OTHERWISE trigger.address; $owner = trigger.data.owner OTHERWISE $to; $deposit_amount = trigger.output[[asset=$interest_asset]]; $stable_amount = floor($deposit_amount * $growth_factor); $protection = max(0, trigger.output[[asset=$reserve_asset]] - ($reserve_asset == 'base' ? 10000 : 0)); $id = trigger.unit; }", "messages": [ { "app": "payment", "payload": { "asset": "{$asset}", "outputs": [ { "address": "{$to}", "amount": "{ $stable_amount }" } ] } }, { "if": "{trigger.data.to AND is_aa(trigger.data.to)}", "app": "data", "payload": { "to": "{trigger.address}" } }, { "app": "state", "state": "{ response['id'] = $id; $deposit = { amount: $deposit_amount, stable_amount: $stable_amount, owner: $owner, ts: timestamp, }; if (trigger.data.interest_recipient) $deposit.interest_recipient = trigger.data.interest_recipient; if ($protection) $deposit.protection = $protection; var['deposit_' || $id] = $deposit; var['supply'] += $stable_amount; }" } ] }, { "if": "{ $asset AND trigger.output[[asset=$asset]] > 0 AND trigger.data.id }", "init": "{ if (exists(trigger.data.to) AND !is_valid_address(trigger.data.to)) bounce("bad to-address"); $to = trigger.data.to OTHERWISE trigger.address; $id = trigger.data.id; $deposit = var['deposit_' || $id]; if (!$deposit) bounce("no such deposit"); if (timestamp < $deposit.ts + $min_deposit_term) bounce("the deposit is too new to be closed"); $bOwner = ($deposit.owner == trigger.address); $bForceClose = !$bOwner; if (var['deposit_' || $id || '_force_close']) bounce("force-close already requested"); if ($deposit.interest_recipient AND $deposit.interest_recipient != $deposit.owner OR $bForceClose){ $new_stable_amount = floor($deposit.amount * $growth_factor); $interest = $new_stable_amount - $deposit.stable_amount; $expected_stable_amount = $new_stable_amount; } else $expected_stable_amount = $deposit.stable_amount; if ($expected_stable_amount > trigger.output[[asset=$asset]]) bounce("expected " || $expected_stable_amount); $change = trigger.output[[asset=$asset]] - $expected_stable_amount; $to_aa = trigger.data.to AND is_aa(trigger.data.to); }", "messages": [ { "if": "{$bOwner}", "app": "payment", "payload": { "asset": "{$interest_asset}", "outputs": [ { "address": "{$to}", "amount": "{ $deposit.amount }" } ] } }, { "if": "{$to_aa AND $bOwner}", "app": "data", "payload": { "to": "{trigger.address}" } }, { "if": "{$to_aa AND $bOwner}", "app": "payment", "payload": { "asset": "base", "outputs": [ { "address": "{$to}", "amount": 2000 } ] } }, { "app": "payment", "payload": { "asset": "{$asset}", "outputs": [ { "if": "{$interest AND $bOwner}", "address": "{$deposit.interest_recipient}", "amount": "{ $interest }" }, { "address": "{trigger.address}", "amount": "{$change}" } ] } }, { "if": "{$deposit.protection AND $bOwner}", "app": "payment", "payload": { "asset": "{$reserve_asset}", "outputs": [ { "address": "{$deposit.owner}", "amount": "{ $deposit.protection }" } ] } }, { "app": "state", "state": "{ if ($bOwner) $remove_deposit($id, $deposit.stable_amount); else // force close var['deposit_' || $id || '_force_close'] = { ts: timestamp, closer: trigger.address, interest: $interest, protection_ratio: $deposit.protection / $deposit.amount, }; }" } ] }, { "if": "{ $asset AND trigger.data.commit_force_close AND trigger.data.id }", "init": "{ $id = trigger.data.id; $deposit = var['deposit_' || $id]; if (!$deposit) bounce("no such deposit"); $force_close = var['deposit_' || $id || '_force_close']; if (!$force_close) bounce("this deposit was not force closed"); if (timestamp < $force_close.ts + $challenging_period) bounce("challenging period has not expired yet"); $interest_recipient = $deposit.interest_recipient OTHERWISE $deposit.owner; $payments = [ { // the closer gets the deposited interest asset address: $force_close.closer, asset: $interest_asset, amount: $deposit.amount }, { // pay the accrued interest to the interest recipient // interest is remembered from the time of the request, it stops accruing during the challenging period address: $interest_recipient, asset: $asset, amount: $force_close.interest }, { // pay the protection back to the owner address: $deposit.owner, asset: $reserve_asset, amount: $deposit.protection }, ]; foreach($payments, 3, ($i, $payment) => { $payments[$i].is_aa = is_aa($payment.address); }); $res = $bank_aa.$get_payment_messages($payments); $payment_messages = $res.payment_messages; $buffer_recipients = $res.buffer_recipients; }", "messages": [ "{$payment_messages[0] OTHERWISE ''}", "{$payment_messages[1] OTHERWISE ''}", "{$payment_messages[2] OTHERWISE ''}", "{$payment_messages[3] OTHERWISE ''}", { "if": "{length($buffer_recipients)}", "app": "data", "payload": { "recipients": "{$buffer_recipients}" } }, { "app": "state", "state": "{ $remove_deposit($id, $deposit.stable_amount); var['deposit_' || $id || '_force_close'] = false; var['last_force_closed_protection_ratio'] = $force_close.protection_ratio; }" } ] }, { "if": "{ $asset AND trigger.data.challenge_force_close AND trigger.data.id AND trigger.data.weaker_id }", "init": "{ $id = trigger.data.id; $weaker_id = trigger.data.weaker_id; $deposit = var['deposit_' || $id]; if (!$deposit) bounce("deposit not found"); // challenge is accepted even if the request has already expired but has not been committed yet $force_close = var['deposit_' || $id || '_force_close']; if (!$force_close) bounce("this deposit was not force closed"); $weaker_deposit = var['deposit_' || $weaker_id]; if (!$weaker_deposit) bounce("weaker deposit doesn't exist"); if (var['deposit_' || $weaker_id || '_force_close']) bounce("the weaker deposit is also challenged"); if ($weaker_deposit.ts + $min_deposit_term + $challenge_immunity_period > $force_close.ts) bounce("the weaker deposit is too new"); $weaker_protection_withdrawal_ts = $weaker_deposit.protection_withdrawal_ts OTHERWISE 0; if ($weaker_protection_withdrawal_ts > $force_close.ts - $challenge_immunity_period) bounce("weaker deposit's protection was decreased recently"); $weaker_protection_ratio = $weaker_deposit.protection / $weaker_deposit.amount; if ($weaker_protection_ratio >= $force_close.protection_ratio) bounce("the weaker deposit does not appear to be weaker: " || $weaker_protection_ratio); $closer_amount = $deposit.stable_amount + $force_close.interest; $reporter_reward_amount = ceil($closer_amount * $reporter_share); $closer_refund_amount = $closer_amount - $reporter_reward_amount; // pay the reward to the reporter and refund the rest to the closer $payments = [ { address: $force_close.closer, asset: $asset, amount: $closer_refund_amount, is_aa: is_aa($force_close.closer) }, { address: trigger.address, asset: $asset, amount: $reporter_reward_amount, is_aa: false // it might be an AA but the reporter is supposed to know what he's doing }, ]; $res = $bank_aa.$get_payment_messages($payments); $payment_messages = $res.payment_messages; $buffer_recipients = $res.buffer_recipients; }", "messages": [ "{$payment_messages[0] OTHERWISE ''}", "{$payment_messages[1] OTHERWISE ''}", { "if": "{length($buffer_recipients)}", "app": "data", "payload": { "recipients": "{$buffer_recipients}" } }, { "app": "state", "state": "{ // discard the fraudulent close request var['deposit_' || $id || '_force_close'] = false; }" } ] }, { "if": "{ $asset AND trigger.data.id AND trigger.data.add_protection AND trigger.output[[asset=$reserve_asset]] > 0 }", "init": "{ $id = trigger.data.id; if (exists(trigger.data.to) AND !is_valid_address(trigger.data.to)) bounce("bad to-address"); $to = trigger.data.to OTHERWISE trigger.address; $deposit = var['deposit_' || $id]; if (!$deposit) bounce("deposit not found"); if ($deposit.owner != $to) bounce("you are not the owner"); }", "messages": [ { "app": "state", "state": "{ $deposit.protection = $deposit.protection + trigger.output[[asset=$reserve_asset]]; var['deposit_' || $id] = $deposit; }" } ] }, { "if": "{ $asset AND trigger.data.id AND trigger.data.withdraw_protection AND trigger.data.amount }", "init": "{ $id = trigger.data.id; if (exists(trigger.data.to) AND !is_valid_address(trigger.data.to)) bounce("bad to-address"); $to = trigger.data.to OTHERWISE trigger.address; $deposit = var['deposit_' || $id]; if (!$deposit) bounce("deposit not found"); if ($deposit.owner != trigger.address) bounce("you are not the owner"); $amount = trigger.data.amount; if ($amount == 'all') $withdraw_amount = $deposit.protection; else { if (!is_integer($amount) OR $amount <= 0) bounce("bad amount: " || $amount); $withdraw_amount = $amount; } if ($withdraw_amount > $deposit.protection) bounce("trying to withdraw more than you have: " || $deposit.protection); }", "messages": [ { "app": "payment", "payload": { "asset": "{$reserve_asset}", "outputs": [ { "address": "{$to}", "amount": "{ $withdraw_amount }" } ] } }, { "app": "state", "state": "{ $deposit.protection = $deposit.protection - $withdraw_amount; $deposit.protection_withdrawal_ts = timestamp; var['deposit_' || $id] = $deposit; }" } ] }, { "if": "{ $asset AND trigger.data.id AND trigger.data.change_interest_recipient }", "init": "{ // if trigger.data.interest_recipient is not specified then the owner wants to get interest himself if (exists(trigger.data.interest_recipient) AND !is_valid_address(trigger.data.interest_recipient)) bounce("bad address of new interest recipient"); $id = trigger.data.id; $deposit = var['deposit_' || $id]; if (!$deposit) bounce("deposit not found"); if ($deposit.owner != trigger.address) bounce("you are not the owner"); if (var['deposit_' || $id || '_force_close']) bounce("force-close requested, can't change interest recipient"); $old_recipient = $deposit.interest_recipient OTHERWISE trigger.address; $new_stable_amount = floor($deposit.amount * $growth_factor); $interest = $new_stable_amount - $deposit.stable_amount; if ($interest < 0) bounce("negative interest?"); }", "messages": [ { "if": "{$interest > 0}", "app": "payment", "payload": { "asset": "{$asset}", "outputs": [ { "address": "{$old_recipient}", "amount": "{ $interest }" } ] } }, { "app": "state", "state": "{ $deposit.stable_amount = $new_stable_amount; if (trigger.data.interest_recipient) $deposit.interest_recipient = trigger.data.interest_recipient; else // can be false to redirect interest to self delete($deposit, 'interest_recipient'); var['deposit_' || $id] = $deposit; var['supply'] += $interest; }" } ] }, { "if": "{ $asset AND trigger.data.id }", "init": "{ $id = trigger.data.id; $deposit = var['deposit_' || $id]; if (!$deposit) bounce("deposit not found"); $recipient = $deposit.interest_recipient OTHERWISE trigger.address; // if interest recipient is not assigned, only the owner can trigger an interest payment if (!$deposit.interest_recipient AND $deposit.owner != trigger.address) bounce("you are not the owner"); if (var['deposit_' || $id || '_force_close']) bounce("force-close requested, can't pay interest"); $new_stable_amount = floor($deposit.amount * $growth_factor); $interest = $new_stable_amount - $deposit.stable_amount; if ($interest < 0) bounce("negative interest?"); // if ($interest == 0) // bounce("0 interest accrued"); }", "messages": [ { "app": "payment", "payload": { "asset": "{$asset}", "outputs": [ { "address": "{$recipient}", "amount": "{ $interest }" } ] } }, { "app": "state", "state": "{ $deposit.stable_amount = $new_stable_amount; var['deposit_' || $id] = $deposit; var['supply'] += $interest; }" } ] } ] } } ]
Technical information
Fees:
15,774 bytes
(451 headers, 15323 payload)
Level:5915549
Witnessed level:5915537
Main chain index:5771215
Latest included mc index:5771214
Status:stable/confirmed/final