Ton

Форк
0
297 строк · 8.8 Кб
1
;;
2
;; Low level operations
3
;;
4

5
() add_member_pending_withdraw(int delta) impure inline {
6
    ctx_balance_pending_withdraw = ctx_balance_pending_withdraw + delta;
7
    ctx_member_pending_withdraw = ctx_member_pending_withdraw + delta;
8
} 
9
() set_member_pending_withdraw(int value) impure inline {
10
    add_member_pending_withdraw(value - ctx_member_pending_withdraw);
11
}
12

13
() add_member_pending_deposit(int delta) impure inline {
14
    ctx_member_pending_deposit = ctx_member_pending_deposit + delta;
15
    ctx_balance_pending_deposits = ctx_balance_pending_deposits + delta;
16
}
17
() set_member_pending_deposit(int value) impure inline {
18
    add_member_pending_deposit(value - ctx_member_pending_deposit);
19
}
20

21
int compose_profit(int a, int b) {
22
    ;; (a + 1) * (b + 1) - 1
23
    return (((a + params::ppc_precision()) * (b + params::ppc_precision())) / params::ppc_precision()) - params::ppc_precision(); ;; NOTE: Rounded down
24
}
25

26
int apply_profit(int value, int value_profit, int profit) {
27
    return ((params::ppc_precision() + profit) * value) / (params::ppc_precision() + value_profit); ;; NOTE: Rounded down
28
}
29

30
;;
31
;; Deposit
32
;;
33

34
() member_update_balance() impure {
35
    
36
    ;; Update profit (for non-owner)
37
    if (ctx_member != owner_id()) {
38
        if (ctx_profit_per_coin != ctx_member_profit_per_coin) {
39
            int new_balance = apply_profit(ctx_member_balance, ctx_member_profit_per_coin, ctx_profit_per_coin);
40
            int delta_balance = new_balance - ctx_member_balance;
41
            ctx_member_balance = ctx_member_balance + delta_balance;
42
            ctx_member_profit_per_coin = ctx_profit_per_coin;
43
        }
44
    }
45

46
    ;; Update pending withdraw
47
    if (ctx_member_pending_withdraw_all) {
48
       if (ctx_member_pending_withdraw != ctx_member_balance) {
49
           set_member_pending_withdraw(ctx_member_balance);
50
        }
51
    } else {
52
        if (ctx_member_pending_withdraw > ctx_member_balance) {
53
            set_member_pending_withdraw(ctx_member_balance);
54
        }
55
    }
56
}
57

58
() member_reset_pending_withdraw() impure {
59
    set_member_pending_withdraw(0);
60
    ctx_member_pending_withdraw_all = false;
61
}
62

63
() member_stake_deposit(int value) impure {
64
    throw_unless(error::invalid_stake_value(), value > 0);
65

66
    ;; Update balances
67
    member_update_balance();
68

69
    ;; Reset pending withdrawal
70
    member_reset_pending_withdraw();
71

72
    ;; Add deposit to pending
73
    ;; NOTE: We are not adding directly deposit to member's balance
74
    ;;       and we are always confirming acception of deposit to a pool
75
    ;;       via sending accept message. This could be done on- and off-chain.
76
    ;;       This could be useful to make private nominator pools or black lists.
77
    ;;       Anyone always could withdraw their deposits though.
78
    add_member_pending_deposit(value);
79
}
80

81
() member_accept_stake() impure {
82

83
    ;; Checks if there are pending deposits
84
    throw_unless(error::invalid_message(), ctx_member_pending_deposit > 0);
85

86
    ;; Check if not locked
87
    throw_if(error::invalid_message(), ctx_locked);
88

89
    ;; Recalculate balance
90
    member_update_balance();
91

92
    ;; Move deposit to member's balance
93
    var amount = ctx_member_pending_deposit;
94
    set_member_pending_deposit(0);
95

96

97
    ctx_member_balance = ctx_member_balance + amount;
98
    ctx_balance =  ctx_balance + amount;
99
}
100

101
;;
102
;; Withdraw
103
;;
104

105
(int, int) member_stake_withdraw(int value) impure {
106

107
    ;; Check input
108
    throw_unless(error::invalid_stake_value(), value >= 0);
109

110
    ;; Update balances
111
    member_update_balance();
112

113
    ;; Reset pending withdrawal: would be overwritten later
114
    member_reset_pending_withdraw();
115

116
    ;; Pre-flight withdraw check
117
    throw_unless(error::invalid_stake_value(), value >= 0);
118
    throw_unless(error::invalid_stake_value(), ctx_member_balance + ctx_member_withdraw + ctx_member_pending_deposit >= value);
119

120
    ;; Check withdraw all
121
    var withdraw_all = false;
122
    if (value == 0) {
123
        withdraw_all = true;
124
        value = ctx_member_pending_deposit + ctx_member_balance + ctx_member_withdraw;
125
    }
126

127
    ;; Trying to withdraw immediatelly
128
    var remaining = value;
129
    var withdrawed = 0;
130
    
131
    ;; Try to withdraw from pending deposit
132
    if ((remaining > 0) & (ctx_member_pending_deposit >= 0)) {
133
        int delta = min(ctx_member_pending_deposit, remaining);
134
        add_member_pending_deposit(- delta);
135
        withdrawed = withdrawed + delta;
136
        remaining = remaining - delta;
137
    }
138

139
    ;; Try to withdraw from withdraw balance
140
    if ((remaining > 0) & ctx_member_withdraw > 0) {
141
        int delta = min(ctx_member_withdraw, remaining);
142
        ctx_member_withdraw = ctx_member_withdraw - delta;
143
        ctx_balance_withdraw = ctx_balance_withdraw - delta;
144
        withdrawed = withdrawed + delta;
145
        remaining = remaining - delta;
146
    }
147

148
    ;; Try to withdraw from balance
149
    if ((remaining > 0) & (~ ctx_locked) & (ctx_member_balance > 0)) {
150
        int delta = min(ctx_member_balance, remaining);
151
        ctx_member_balance = ctx_member_balance - delta;
152
        ctx_balance = ctx_balance - delta;
153
        withdrawed = withdrawed + delta;
154
        remaining = remaining - delta;
155
    }
156

157
    ;; Add to pending withdrawals
158
    if (remaining > 0) {
159
        add_member_pending_withdraw(remaining);
160
        ctx_member_pending_withdraw_all = withdraw_all;
161
    }
162

163
    ;; Return withdraw result
164
    return (withdrawed, remaining == 0);
165
}
166

167
() member_accept_withdraw() impure {
168
    
169
    ;; Checks if there are pending withdrawals
170
    throw_unless(error::invalid_message(), ctx_member_pending_withdraw > 0);
171

172
    ;; Check if not locked
173
    throw_if(error::invalid_message(), ctx_locked);
174

175
    ;; Recalculate balance
176
    member_update_balance();
177

178
    ;; Move deposit to member's balance
179
    var amount = ctx_member_pending_withdraw;
180

181
    ctx_member_balance = ctx_member_balance - amount;
182
    ctx_member_withdraw = ctx_member_withdraw + amount;
183
    ctx_balance = ctx_balance - amount;
184
    ctx_balance_withdraw = ctx_balance_withdraw + amount;
185
    ctx_balance_pending_withdraw = ctx_balance_pending_withdraw - amount;
186
    ctx_member_pending_withdraw = 0;
187
    ctx_member_pending_withdraw_all = false;
188
}
189

190
() distribute_profit(int profit) impure {
191

192
    ;; Load extras
193
    var (enabled, udpates_enabled, min_stake, deposit_fee, withdraw_fee, pool_fee, receipt_price) = ctx_extras;
194

195
    ;; Load owner balances
196
    load_member(0);
197

198
    ;; Loss
199
    if (profit < 0) {
200

201
        ;; Stakes
202
        var owner_stake = ctx_member_balance;
203
        var nominators_stake = ctx_balance - owner_stake;
204

205
        ;; Distribute loss to everyone
206
        var cycleProfitPerCoin = profit * params::ppc_precision()  / ctx_balance;
207
        var nominators_profit = (nominators_stake * cycleProfitPerCoin) / params::ppc_precision();
208
        var owner_profit = profit - nominators_profit;
209

210
        ;; Update balances
211
        ctx_balance = ctx_balance + profit;
212
        ctx_member_balance = ctx_member_balance + owner_profit;
213
        ctx_profit_per_coin = compose_profit(ctx_profit_per_coin, cycleProfitPerCoin);
214

215
        ;; Persist
216
        store_member();
217

218
        return ();
219
    }
220

221
    ;; Profit
222
    if (profit > 0) {
223

224
        ;; Stakes
225
        var owner_stake = ctx_member_balance;
226
        var nominators_stake = ctx_balance - owner_stake;
227

228
        ;; Distribute profit
229
        var cycleProfitPerCoin = profit * params::ppc_precision() * (100 * 100 - pool_fee) / (ctx_balance * 100 * 100);
230
        var nominators_profit = (nominators_stake * cycleProfitPerCoin) / params::ppc_precision();
231
        var owner_profit = profit - nominators_profit;
232

233
        ;; Update balances
234
        ctx_balance = ctx_balance + profit;
235
        ctx_member_balance = ctx_member_balance + owner_profit;
236
        ctx_profit_per_coin = compose_profit(ctx_profit_per_coin, cycleProfitPerCoin);
237

238
        ;; Persist
239
        store_member();
240

241
        return ();
242
    }
243
}
244

245
;;
246
;; Validator
247
;;
248

249
() on_locked() impure {
250
    if (~ ctx_locked) {
251
        
252
        ;; Allow locking only on no pending withdrawals
253
        throw_unless(error::invalid_message(), ctx_balance_pending_withdraw == 0);
254
        
255
        ;; Update state
256
        ctx_locked = true;
257
    }
258
}
259

260
() on_unlocked() impure {
261
    if (ctx_locked) {
262

263
        ;; Update state
264
        ctx_locked = false;
265
    }
266
}
267

268
int available_to_stake() {
269
    return ctx_balance - ctx_balance_sent;
270
}
271

272
int owned_balance() {
273
    return ctx_balance - ctx_balance_sent + ctx_balance_pending_deposits + ctx_balance_withdraw + fees::storage_reserve();
274
}
275

276
() on_stake_sent(int stake) impure {
277
    ctx_balance_sent = ctx_balance_sent + stake;
278
}
279

280
() on_stake_sent_failed(int stake) impure {
281
    ctx_balance_sent = ctx_balance_sent - stake;
282
}
283

284
() on_stake_recovered(int stake) impure {
285

286
    ;; Calculate profit
287
    ;; NOTE: ctx_locked is true meaning that ctx_balance 
288
    ;;       have the same value as was when stake was sent
289
    ;;       balances are going to be unlocked after profit distribution
290
    var profit = stake - ctx_balance_sent;
291

292
    ;; Distribute profit
293
    distribute_profit(profit);
294

295
    ;; Reset sent amount
296
    ctx_balance_sent = 0;
297
}

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.