Skip to content

Commit

Permalink
refactor the liquidation of donor directed wallets, in including comm…
Browse files Browse the repository at this point in the history
…unity wallet case
  • Loading branch information
0o-de-lally committed Apr 14, 2023
1 parent 0bbe84b commit 2fab676
Show file tree
Hide file tree
Showing 22 changed files with 440 additions and 156 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ compiled_package_info:
? address: "00000000000000000000000000000001"
name: XUS
: DiemFramework
source_digest: 684BEC1163CEA241963C29019D577641E034F25509DDB1D35398228AE0306FE8
source_digest: 17BE96F5B38FE78017CA86174C9B8A86EBB424AB326C4BC53B26CB058C145D02
build_flags:
dev_mode: false
test_mode: false
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ before and after every transaction.
- [Function `init_cumulative_deposits`](#0x1_DiemAccount_init_cumulative_deposits)
- [Function `vm_migrate_cumulative_deposits`](#0x1_DiemAccount_vm_migrate_cumulative_deposits)
- [Function `maybe_update_deposit`](#0x1_DiemAccount_maybe_update_deposit)
- [Function `get_depositors`](#0x1_DiemAccount_get_depositors)
- [Function `deposit_index_curve`](#0x1_DiemAccount_deposit_index_curve)
- [Function `get_cumulative_deposits`](#0x1_DiemAccount_get_cumulative_deposits)
- [Function `get_index_cumu_deposits`](#0x1_DiemAccount_get_index_cumu_deposits)
Expand Down Expand Up @@ -6914,10 +6915,32 @@ Create a Validator Operator account

// also write the receipt <b>to</b> the payee's account.
<a href="Receipts.md#0x1_Receipts_write_receipt">Receipts::write_receipt</a>(payer, payee, deposit_value);

};
}
</code></pre>



</details>

<a name="0x1_DiemAccount_get_depositors"></a>

## Function `get_depositors`



<pre><code><b>public</b> <b>fun</b> <a href="DiemAccount.md#0x1_DiemAccount_get_depositors">get_depositors</a>(payee: <b>address</b>): vector&lt;<b>address</b>&gt;
</code></pre>



<details>
<summary>Implementation</summary>


<pre><code><b>public</b> <b>fun</b> <a href="DiemAccount.md#0x1_DiemAccount_get_depositors">get_depositors</a>(payee: <b>address</b>): vector&lt;<b>address</b>&gt; <b>acquires</b> <a href="DiemAccount.md#0x1_DiemAccount_CumulativeDeposits">CumulativeDeposits</a> {
<b>let</b> cumu = <b>borrow_global</b>&lt;<a href="DiemAccount.md#0x1_DiemAccount_CumulativeDeposits">CumulativeDeposits</a>&gt;(payee);
*&cumu.depositors
}
</code></pre>

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- [Function `publish_beneficiary_policy`](#0x1_PledgeAccounts_publish_beneficiary_policy)
- [Function `maybe_initialize_my_pledges`](#0x1_PledgeAccounts_maybe_initialize_my_pledges)
- [Function `save_pledge`](#0x1_PledgeAccounts_save_pledge)
- [Function `vm_add_to_pledge`](#0x1_PledgeAccounts_vm_add_to_pledge)
- [Function `create_pledge_account`](#0x1_PledgeAccounts_create_pledge_account)
- [Function `add_coin_to_pledge_account`](#0x1_PledgeAccounts_add_coin_to_pledge_account)
- [Function `withdraw_from_all_pledge_accounts`](#0x1_PledgeAccounts_withdraw_from_all_pledge_accounts)
Expand Down Expand Up @@ -352,14 +353,53 @@
address_of_beneficiary: <b>address</b>,
pledge: <a href="Diem.md#0x1_Diem_Diem">Diem::Diem</a>&lt;<a href="GAS.md#0x1_GAS">GAS</a>&gt;
) <b>acquires</b> <a href="PledgeAccounts.md#0x1_PledgeAccounts_MyPledges">MyPledges</a>, <a href="PledgeAccounts.md#0x1_PledgeAccounts_BeneficiaryPolicy">BeneficiaryPolicy</a> {
<b>assert</b>!(<b>exists</b>&lt;<a href="PledgeAccounts.md#0x1_PledgeAccounts_BeneficiaryPolicy">BeneficiaryPolicy</a>&gt;(address_of_beneficiary), <a href="../../../../../../../DPN/releases/artifacts/current/build/MoveStdlib/docs/Errors.md#0x1_Errors_invalid_state">Errors::invalid_state</a>(<a href="PledgeAccounts.md#0x1_PledgeAccounts_ENO_BENEFICIARY_POLICY">ENO_BENEFICIARY_POLICY</a>));
<b>let</b> sender_addr = <a href="../../../../../../../DPN/releases/artifacts/current/build/MoveStdlib/docs/Signer.md#0x1_Signer_address_of">Signer::address_of</a>(sig);
<b>let</b> (found, idx) = <a href="PledgeAccounts.md#0x1_PledgeAccounts_pledge_at_idx">pledge_at_idx</a>(&sender_addr, &address_of_beneficiary);
<b>if</b> (found) {
<a href="PledgeAccounts.md#0x1_PledgeAccounts_add_coin_to_pledge_account">add_coin_to_pledge_account</a>(sig, idx, <a href="Diem.md#0x1_Diem_value">Diem::value</a>(&pledge), pledge)
} <b>else</b> {
<a href="PledgeAccounts.md#0x1_PledgeAccounts_create_pledge_account">create_pledge_account</a>(sig, address_of_beneficiary, pledge)
}

<b>assert</b>!(<b>exists</b>&lt;<a href="PledgeAccounts.md#0x1_PledgeAccounts_BeneficiaryPolicy">BeneficiaryPolicy</a>&gt;(address_of_beneficiary), <a href="../../../../../../../DPN/releases/artifacts/current/build/MoveStdlib/docs/Errors.md#0x1_Errors_invalid_state">Errors::invalid_state</a>(<a href="PledgeAccounts.md#0x1_PledgeAccounts_ENO_BENEFICIARY_POLICY">ENO_BENEFICIARY_POLICY</a>));
<b>let</b> sender_addr = <a href="../../../../../../../DPN/releases/artifacts/current/build/MoveStdlib/docs/Signer.md#0x1_Signer_address_of">Signer::address_of</a>(sig);
<b>let</b> (found, idx) = <a href="PledgeAccounts.md#0x1_PledgeAccounts_pledge_at_idx">pledge_at_idx</a>(&sender_addr, &address_of_beneficiary);
<b>if</b> (found) {
<a href="PledgeAccounts.md#0x1_PledgeAccounts_add_coin_to_pledge_account">add_coin_to_pledge_account</a>(sender_addr, idx, pledge)
} <b>else</b> {
<a href="PledgeAccounts.md#0x1_PledgeAccounts_create_pledge_account">create_pledge_account</a>(sig, address_of_beneficiary, pledge)
}
}
</code></pre>



</details>

<a name="0x1_PledgeAccounts_vm_add_to_pledge"></a>

## Function `vm_add_to_pledge`



<pre><code><b>public</b> <b>fun</b> <a href="PledgeAccounts.md#0x1_PledgeAccounts_vm_add_to_pledge">vm_add_to_pledge</a>(vm: &signer, pledger: <b>address</b>, address_of_beneficiary: <b>address</b>, pledge: &<b>mut</b> <a href="Diem.md#0x1_Diem_Diem">Diem::Diem</a>&lt;<a href="GAS.md#0x1_GAS_GAS">GAS::GAS</a>&gt;)
</code></pre>



<details>
<summary>Implementation</summary>


<pre><code><b>public</b> <b>fun</b> <a href="PledgeAccounts.md#0x1_PledgeAccounts_vm_add_to_pledge">vm_add_to_pledge</a>(
vm: &signer,
pledger: <b>address</b>,
address_of_beneficiary: <b>address</b>,
pledge: &<b>mut</b> <a href="Diem.md#0x1_Diem_Diem">Diem::Diem</a>&lt;<a href="GAS.md#0x1_GAS">GAS</a>&gt;
) <b>acquires</b> <a href="PledgeAccounts.md#0x1_PledgeAccounts_MyPledges">MyPledges</a>, <a href="PledgeAccounts.md#0x1_PledgeAccounts_BeneficiaryPolicy">BeneficiaryPolicy</a> {
<a href="CoreAddresses.md#0x1_CoreAddresses_assert_vm">CoreAddresses::assert_vm</a>(vm);
<b>assert</b>!(<b>exists</b>&lt;<a href="PledgeAccounts.md#0x1_PledgeAccounts_BeneficiaryPolicy">BeneficiaryPolicy</a>&gt;(address_of_beneficiary), <a href="../../../../../../../DPN/releases/artifacts/current/build/MoveStdlib/docs/Errors.md#0x1_Errors_invalid_state">Errors::invalid_state</a>(<a href="PledgeAccounts.md#0x1_PledgeAccounts_ENO_BENEFICIARY_POLICY">ENO_BENEFICIARY_POLICY</a>));

<b>let</b> (found, idx) = <a href="PledgeAccounts.md#0x1_PledgeAccounts_pledge_at_idx">pledge_at_idx</a>(&pledger, &address_of_beneficiary);
<b>let</b> value = <a href="Diem.md#0x1_Diem_value">Diem::value</a>(pledge);
<b>if</b> (found) {
<b>let</b> c = <a href="Diem.md#0x1_Diem_withdraw">Diem::withdraw</a>(pledge, value);
<a href="PledgeAccounts.md#0x1_PledgeAccounts_add_coin_to_pledge_account">add_coin_to_pledge_account</a>(pledger, idx, c)
}
// caller of this function needs <b>to</b> decide what <b>to</b> do <b>if</b> the coin cannot be added. Which is why its a mutable reference.
}
</code></pre>

Expand Down Expand Up @@ -421,7 +461,7 @@



<pre><code><b>fun</b> <a href="PledgeAccounts.md#0x1_PledgeAccounts_add_coin_to_pledge_account">add_coin_to_pledge_account</a>(sender: &signer, idx: u64, amount: u64, coin: <a href="Diem.md#0x1_Diem_Diem">Diem::Diem</a>&lt;<a href="GAS.md#0x1_GAS_GAS">GAS::GAS</a>&gt;)
<pre><code><b>fun</b> <a href="PledgeAccounts.md#0x1_PledgeAccounts_add_coin_to_pledge_account">add_coin_to_pledge_account</a>(sender_addr: <b>address</b>, idx: u64, coin: <a href="Diem.md#0x1_Diem_Diem">Diem::Diem</a>&lt;<a href="GAS.md#0x1_GAS_GAS">GAS::GAS</a>&gt;)
</code></pre>


Expand All @@ -430,10 +470,10 @@
<summary>Implementation</summary>


<pre><code><b>fun</b> <a href="PledgeAccounts.md#0x1_PledgeAccounts_add_coin_to_pledge_account">add_coin_to_pledge_account</a>(sender: &signer, idx: u64, amount: u64, coin: <a href="Diem.md#0x1_Diem_Diem">Diem::Diem</a>&lt;<a href="GAS.md#0x1_GAS">GAS</a>&gt;) <b>acquires</b> <a href="PledgeAccounts.md#0x1_PledgeAccounts_MyPledges">MyPledges</a>, <a href="PledgeAccounts.md#0x1_PledgeAccounts_BeneficiaryPolicy">BeneficiaryPolicy</a> {
<b>let</b> sender_addr = <a href="../../../../../../../DPN/releases/artifacts/current/build/MoveStdlib/docs/Signer.md#0x1_Signer_address_of">Signer::address_of</a>(sender);
<pre><code><b>fun</b> <a href="PledgeAccounts.md#0x1_PledgeAccounts_add_coin_to_pledge_account">add_coin_to_pledge_account</a>(sender_addr: <b>address</b>, idx: u64, coin: <a href="Diem.md#0x1_Diem_Diem">Diem::Diem</a>&lt;<a href="GAS.md#0x1_GAS">GAS</a>&gt;) <b>acquires</b> <a href="PledgeAccounts.md#0x1_PledgeAccounts_MyPledges">MyPledges</a>, <a href="PledgeAccounts.md#0x1_PledgeAccounts_BeneficiaryPolicy">BeneficiaryPolicy</a> {
// <b>let</b> sender_addr = <a href="../../../../../../../DPN/releases/artifacts/current/build/MoveStdlib/docs/Signer.md#0x1_Signer_address_of">Signer::address_of</a>(sender);
// <b>let</b> (found, _idx) = <a href="PledgeAccounts.md#0x1_PledgeAccounts_pledge_at_idx">pledge_at_idx</a>(&sender_addr, &address_of_beneficiary);

<b>let</b> amount = <a href="Diem.md#0x1_Diem_value">Diem::value</a>(&coin);
<b>let</b> my_pledges = <b>borrow_global_mut</b>&lt;<a href="PledgeAccounts.md#0x1_PledgeAccounts_MyPledges">MyPledges</a>&gt;(sender_addr);
<b>let</b> pledge_account = <a href="../../../../../../../DPN/releases/artifacts/current/build/MoveStdlib/docs/Vector.md#0x1_Vector_borrow_mut">Vector::borrow_mut</a>(&<b>mut</b> my_pledges.list, idx);

Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -3747,10 +3747,12 @@ module DiemFramework::DiemAccount {

// also write the receipt to the payee's account.
Receipts::write_receipt(payer, payee, deposit_value);

};
}


public fun get_depositors(payee: address): vector<address> acquires CumulativeDeposits {
let cumu = borrow_global<CumulativeDeposits>(payee);
*&cumu.depositors
}

/// adjust the points of the deposits favoring more recent deposits.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ module DonorDirected {
use DiemFramework::DiemAccount::{Self, WithdrawCapability};
use DiemFramework::DonorDirectedGovernance;
use DiemFramework::Ballot;

// use DiemFramework::Debug::print;
use DiemFramework::Receipts;
use DiemFramework::TransactionFee;

/// Not initialized as a donor directed account.
const ENOT_INIT_DONOR_DIRECTED: u64 = 231001;
Expand All @@ -65,7 +65,8 @@ module DonorDirected {

// root registry for the donor directed accounts
struct Registry has key {
list: vector<address>
list: vector<address>,
liquidation_queue: vector<address>,
}

// Timed transfer schedule pipeline
Expand Down Expand Up @@ -96,7 +97,7 @@ module DonorDirected {
is_frozen: bool,
consecutive_rejections: u64,
unfreeze_votes: vector<address>,
liquidate_to_infra_escrow: bool,
liquidate_to_community_wallets: bool,
}

struct Donors has key {
Expand All @@ -112,7 +113,8 @@ module DonorDirected {
CoreAddresses::assert_diem_root(vm);
if (!is_root_init()) {
move_to<Registry>(vm, Registry {
list: Vector::empty<address>()
list: Vector::empty<address>(),
liquidation_queue: Vector::empty<address>(),
});
};
}
Expand All @@ -127,6 +129,7 @@ module DonorDirected {
if (!is_root_init()) {
move_to<Registry>(vm, Registry {
list,
liquidation_queue: Vector::empty<address>(),
});
};
}
Expand All @@ -140,7 +143,7 @@ module DonorDirected {

// 3. Once the MultiSig is initialized, the account needs to be bricked, before the MultiSig can be used.

public fun set_donor_directed(sig: &signer, liquidate_to_infra_escrow: bool) {
public fun set_donor_directed(sig: &signer, liquidate_to_community_wallets: bool) {
if (!exists<Registry>(@VMReserved)) return;

move_to<Freeze>(
Expand All @@ -149,7 +152,7 @@ module DonorDirected {
is_frozen: false,
consecutive_rejections: 0,
unfreeze_votes: Vector::empty<address>(),
liquidate_to_infra_escrow,
liquidate_to_community_wallets,
}
);

Expand Down Expand Up @@ -491,32 +494,88 @@ module DonorDirected {
DonorDirectedGovernance::propose_liquidate(&state.guid_capability, epochs_duration);
}

fun liquidate_handler(donor: &signer, multisig_address: address) acquires Freeze {
fun liquidate_handler(donor: &signer, multisig_address: address) acquires Freeze, Registry {
DonorDirectedGovernance::assert_authorized(donor, multisig_address);
let res = DonorDirectedGovernance::vote_liquidate(donor, multisig_address);
if (Option::is_some(&res)) {
if (*Option::borrow(&res)) {
liquidate(multisig_address);
// The VM will call this function to liquidate the wallet.
// the donors cannot do this because they cant get the withdrawal capability
// from the multisig account.

// first we freeze it so nothing can happen in the interim.
let f = borrow_global_mut<Freeze>(multisig_address);
f.is_frozen = true;
let f = borrow_global_mut<Registry>(@VMReserved);
Vector::push_back(&mut f.liquidation_queue, multisig_address);
}
}
}
/// The VM will call this function to liquidate all donor directed
/// wallets in the queue.

fun liquidate(multisig_address: address) acquires Freeze{
// first we freeze it
let f = borrow_global_mut<Freeze>(multisig_address);
f.is_frozen = true;
fun vm_liquidate(vm: &signer) acquires Freeze, Registry {
CoreAddresses::assert_vm(vm);
let f = borrow_global_mut<Registry>(@VMReserved);
let len = Vector::length(&f.liquidation_queue);
let i = 0;
while (i < len) {
let multisig_address = Vector::borrow(&f.liquidation_queue, i);

// if this account was tagged a community wallet, then the
// funds get split pro-rata at the current split of the
// burn recycle algorithm.
// Easiest way to do this is to send it to transaction fee account
// so it can be split up by the burn recycle algorithm.
// and trying to call Burn, here will create a circular dependency.

if (liquidates_to_escrow(*multisig_address)) {
let balance = DiemAccount::balance<GAS>(*multisig_address);
let c = DiemAccount::vm_withdraw<GAS>(vm, *multisig_address, balance);
TransactionFee::pay_fee(c);

return
};

// then we split the funds and send it back to the user's wallet
// if this account was tagged a community wallet, then the
// funds go back to infrastructure escrow account.

if (liquidates_to_escrow(multisig_address)) {

} else {

// otherwise the default case is that donors get their funds back.
let (pro_rata_addresses, pro_rata_amounts) = get_pro_rata(*multisig_address);

let k = 0;
let len = Vector::length(&pro_rata_addresses);
// then we split the funds and send it back to the user's wallet
while (k < len) {
let addr = Vector::borrow(&pro_rata_addresses, i);
let amount = Vector::borrow(&pro_rata_amounts, i);
DiemAccount::vm_pay_from<GAS>(*multisig_address, *addr, *amount, b"liquidation", b"", vm);

k = k + 1;
};
i = i + 1;
}
}

fun get_pro_rata(multisig_address: address): (vector<address>, vector<u64>) {
// get total fees
let balance = DiemAccount::balance<GAS>(multisig_address);
let donors = DiemAccount::get_depositors(multisig_address);
let pro_rata_addresses = Vector::empty<address>();
let pro_rata_amounts = Vector::empty<u64>();

let i = 0;
let len = Vector::length(&donors);
while (i < len) {
let donor = Vector::borrow(&donors, i);
let (_, _, cumu) = Receipts::read_receipt(*donor, multisig_address);
let pro_rata = cumu / balance;
Vector::push_back(&mut pro_rata_addresses, *donor);
Vector::push_back(&mut pro_rata_amounts, pro_rata);
i = i + 1;
};

(pro_rata_addresses, pro_rata_amounts)
}

//////// GETTERS ////////
public fun get_tx_params(t: &TimedTransfer): (address, u64, vector<u8>, u64) {
(t.tx.payee, t.tx.value, *&t.tx.description, t.deadline)
Expand Down Expand Up @@ -560,7 +619,7 @@ module DonorDirected {

public fun liquidates_to_escrow(addr: address): bool acquires Freeze{
let f = borrow_global<Freeze>(addr);
f.liquidate_to_infra_escrow
f.liquidate_to_community_wallets
}

//////// TRANSACTION SCRIPTS ////////
Expand All @@ -575,8 +634,8 @@ module DonorDirected {

// we are setting liquidation to infra escrow as false by default
// the user can send another transacton to change this.
let liquidate_to_infra_escrow = false;
set_donor_directed(sponsor, liquidate_to_infra_escrow);
let liquidate_to_community_wallets = false;
set_donor_directed(sponsor, liquidate_to_community_wallets);
make_multisig(sponsor, cfg_n_signers, init_signers);

// if not tracking cumulative donations, then don't use previous balance.
Expand All @@ -586,9 +645,9 @@ module DonorDirected {

/// option to set the liquidation destination to infrastructure escrow
/// must be done before the multisig is finalized and the sponsor cannot control the account.
public fun set_liquidate_to_infra_escrow(sponsor: &signer, liquidate_to_infra_escrow: bool) acquires Freeze {
public fun set_liquidate_to_community_wallets(sponsor: &signer, liquidate_to_community_wallets: bool) acquires Freeze {
let f = borrow_global_mut<Freeze>(Signer::address_of(sponsor));
f.liquidate_to_infra_escrow = liquidate_to_infra_escrow;
f.liquidate_to_community_wallets = liquidate_to_community_wallets;
}

/// the sponsor must finalize the initialization, this is a separate step so that the user can optionally check everything is in order before bricking the account key.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,16 @@ address DiemFramework{
TransactionFee::pay_fee<GAS>(c);
}

// fun genesis_helper_migrate_pledge(vm: &signer, user_sig: &signer, amount: u64) {
// CoreAddresses::assert_diem_root(vm);
// PledgeAccounts::user_pledge_tx(&user_sig, @VMReserved, amount);
// }

// Transaction script for user to pledge to infra escrow.
public(script) fun user_pledge_infra(user_sig: signer, amount: u64){

PledgeAccounts::user_pledge_tx(user_sig, @VMReserved, amount);
}




}
}

0 comments on commit 2fab676

Please sign in to comment.