Skip to content

Commit a9c42fc

Browse files
committed
caller pays for initing vault
1 parent ebc2a59 commit a9c42fc

1 file changed

Lines changed: 23 additions & 12 deletions

File tree

ex/native/rdb/src/consensus/bic/lockup_vault.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::bcat;
22
use crate::consensus::bic::coin::balance;
33
use crate::consensus::consensus_apply::ApplyEnv;
4-
use crate::consensus::consensus_kv::{kv_delete, kv_get, kv_get_next, kv_increment, kv_put};
4+
use crate::consensus::consensus_kv::{kv_delete, kv_exists, kv_get, kv_get_next, kv_increment, kv_put};
55
use std::collections::{BTreeMap, HashSet};
66
use std::panic::panic_any;
77
use vecpak::{decode, encode, Term};
@@ -269,7 +269,7 @@ pub fn pay_epoch_yield(
269269
let due = base.checked_mul(vault.rate_bps as i128).unwrap_or_else(|| panic_any("yield_overflow")) / APY_EPOCH_DENOM;
270270
let due = due.checked_mul(reduction_pct.min(100) as i128).unwrap_or_else(|| panic_any("yield_overflow")) / 100;
271271
if due > 0 {
272-
due_total += due;
272+
due_total = due_total.checked_add(due).unwrap_or_else(|| panic_any("yield_overflow"));
273273
entries.push((bcat(&[VAULT_KEY_PREFIX, &suffix]), vault, due));
274274
}
275275
}
@@ -294,7 +294,7 @@ pub fn pay_epoch_yield(
294294
let addr = vault.payout_address.as_ref().unwrap_or_else(|| panic_any("invalid_vault_data")).clone();
295295
kv_increment(env, &bcat(&[b"account:", &addr, b":balance:AMA"]), pay);
296296
}
297-
paid_total += pay;
297+
paid_total = paid_total.checked_add(pay).unwrap_or_else(|| panic_any("yield_overflow"));
298298
}
299299
paid_total
300300
}
@@ -342,6 +342,13 @@ fn validate_pk(pk: &[u8], error: &'static str) {
342342
}
343343
}
344344

345+
fn init_balance_if_missing(env: &mut ApplyEnv, address: &[u8]) {
346+
let key = bcat(&[b"account:", address, b":balance:AMA"]);
347+
if !kv_exists(env, &key) {
348+
kv_increment(env, &key, 0);
349+
}
350+
}
351+
345352
//strict reader for a single vecpak map argument (tag 7). the codec already
346353
//guarantees the map is canonical and duplicate-free (decode rejects anything
347354
//else), so this layer only adds the policy the codec can't know: an allow-list
@@ -456,22 +463,31 @@ pub fn call_create(env: &mut ApplyEnv, args: Vec<Vec<u8>>) {
456463
None => tier_duration,
457464
};
458465

466+
let caller = env.caller_env.account_caller.clone();
467+
468+
if amount < MIN_VAULT_AMOUNT {
469+
panic_any("vault_amount_below_minimum")
470+
}
471+
if amount > balance(env, &caller, b"AMA") {
472+
panic_any("insufficient_funds")
473+
}
474+
459475
let validator = match map.opt_bin(b"validator", "invalid_validator_pk") {
460476
Some(pk) => {
461477
validate_pk(&pk, "invalid_validator_pk");
478+
init_balance_if_missing(env, &pk);
462479
Some(pk)
463480
}
464481
None => None,
465482
};
466483
let payout_address = match map.opt_bin(b"payout_address", "invalid_payout_pk") {
467484
Some(addr) => {
468485
validate_pk(&addr, "invalid_payout_pk");
486+
init_balance_if_missing(env, &addr);
469487
Some(addr)
470488
}
471489
None => None,
472490
};
473-
//the caller always pays; the vault is keyed under the owner (caller by default)
474-
let caller = env.caller_env.account_caller.clone();
475491
let owner = match map.opt_bin(b"owner", "invalid_owner_pk") {
476492
Some(pk) => {
477493
validate_pk(&pk, "invalid_owner_pk");
@@ -480,13 +496,6 @@ pub fn call_create(env: &mut ApplyEnv, args: Vec<Vec<u8>>) {
480496
None => caller.clone(),
481497
};
482498

483-
if amount < MIN_VAULT_AMOUNT {
484-
panic_any("vault_amount_below_minimum")
485-
}
486-
if amount > balance(env, &caller, b"AMA") {
487-
panic_any("insufficient_funds")
488-
}
489-
490499
let entry_epoch = env.caller_env.entry_epoch;
491500
//the tier schedule is the floor; unlock_epoch can only extend maturity later
492501
let tier_mature = entry_epoch.saturating_add(duration_epochs);
@@ -583,6 +592,7 @@ pub fn call_set_payout_address(env: &mut ApplyEnv, args: Vec<Vec<u8>>) {
583592
panic_any("vault_is_unlocking")
584593
}
585594
validate_pk(&args[1], "invalid_payout_pk");
595+
init_balance_if_missing(env, &args[1]);
586596
vault.payout_address = Some(args[1].to_vec());
587597
store_vault(env, &key, &vault);
588598
}
@@ -609,6 +619,7 @@ pub fn call_set_validator(env: &mut ApplyEnv, args: Vec<Vec<u8>>) {
609619
}
610620
let validator = args[1].as_slice();
611621
validate_pk(validator, "invalid_validator_pk");
622+
init_balance_if_missing(env, validator);
612623
//the validator the vault is already heading toward: the queued one if a change
613624
//is in flight, otherwise the active one. re-selecting it is a no-op so the
614625
//2-epoch clock is not reset

0 commit comments

Comments
 (0)