Skip to content

Commit f26e7fc

Browse files
authored
fix: invariant func type params (#309)
* fix: invariant func type params * cleanup * fixed useless code * cleanup * feat: simplify * feat: removed clone * feat: cleanup
1 parent e0f9c74 commit f26e7fc

3 files changed

Lines changed: 143 additions & 0 deletions

File tree

crates/move-stackless-bytecode/src/mono_analysis.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,8 @@ impl Analyzer<'_> {
374374
}
375375
}
376376

377+
self.analyze_type_invariant_functions();
378+
377379
// Next do todo-list for regular functions, while self.inst_opt contains the
378380
// specific instantiation.
379381
while let Some((fun, variant, inst)) = self.todo_funs.pop() {
@@ -608,6 +610,25 @@ impl Analyzer<'_> {
608610
}
609611
}
610612

613+
fn analyze_type_invariant_functions(&mut self) {
614+
let items_to_process: Vec<_> = self
615+
.info
616+
.structs
617+
.iter()
618+
.filter_map(|(struct_qid, type_instantiations)| {
619+
self.targets
620+
.get_inv_by_datatype(struct_qid)
621+
.map(|inv_fun_qid| (*inv_fun_qid, type_instantiations.clone()))
622+
})
623+
.collect();
624+
625+
for (inv_fun_qid, type_instantiations) in items_to_process {
626+
for type_inst in type_instantiations.iter() {
627+
self.push_todo_fun(inv_fun_qid, type_inst.clone());
628+
}
629+
}
630+
}
631+
611632
// Expression and Spec Fun Analysis
612633
// --------------------------------
613634

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
module 0x42::inv_types_detection;
2+
3+
use sui::balance::{Self, Balance};
4+
use sui::sui::SUI;
5+
use sui::table::{Self, Table};
6+
7+
public struct StakingPool has key, store {
8+
id: UID,
9+
activation_epoch: Option<u64>,
10+
deactivation_epoch: Option<u64>,
11+
sui_balance: u64,
12+
rewards_pool: Balance<SUI>,
13+
pool_token_balance: u64,
14+
exchange_rates: Table<u64, PoolTokenExchangeRate>,
15+
pending_stake: u64,
16+
pending_total_sui_withdraw: u64,
17+
pending_pool_token_withdraw: u64,
18+
}
19+
20+
public struct PoolTokenExchangeRate has store, copy, drop {
21+
sui_amount: u64,
22+
pool_token_amount: u64,
23+
}
24+
25+
public struct StakedSui has key, store {
26+
id: UID,
27+
pool_id: ID,
28+
stake_activation_epoch: u64,
29+
}
30+
31+
public(package) fun new(ctx: &mut TxContext): StakingPool {
32+
let exchange_rates = table::new(ctx);
33+
StakingPool {
34+
id: object::new(ctx),
35+
activation_epoch: option::none(),
36+
deactivation_epoch: option::none(),
37+
sui_balance: 0,
38+
rewards_pool: balance::zero(),
39+
pool_token_balance: 0,
40+
exchange_rates,
41+
pending_stake: 0,
42+
pending_total_sui_withdraw: 0,
43+
pending_pool_token_withdraw: 0,
44+
}
45+
}
46+
47+
public fun is_preactive(pool: &StakingPool): bool{
48+
pool.activation_epoch.is_none()
49+
}
50+
51+
public fun is_equal_staking_metadata(self: &StakedSui, other: &StakedSui): bool {
52+
(self.pool_id == other.pool_id) &&
53+
(self.stake_activation_epoch == other.stake_activation_epoch)
54+
}
55+
56+
public fun pool_token_exchange_rate_at_epoch(pool: &StakingPool, epoch: u64): PoolTokenExchangeRate {
57+
if (is_preactive_at_epoch(pool, epoch)) {
58+
return initial_exchange_rate()
59+
};
60+
let clamped_epoch = pool.deactivation_epoch.get_with_default(epoch);
61+
let mut epoch = clamped_epoch.min(epoch);
62+
let activation_epoch = *pool.activation_epoch.borrow();
63+
while (epoch >= activation_epoch) {
64+
if (pool.exchange_rates.contains(epoch)) {
65+
return pool.exchange_rates[epoch]
66+
};
67+
epoch = epoch - 1;
68+
};
69+
initial_exchange_rate()
70+
}
71+
72+
fun is_preactive_at_epoch(pool: &StakingPool, epoch: u64): bool{
73+
is_preactive(pool) || (*pool.activation_epoch.borrow() > epoch)
74+
}
75+
76+
fun initial_exchange_rate(): PoolTokenExchangeRate {
77+
PoolTokenExchangeRate { sui_amount: 0, pool_token_amount: 0 }
78+
}
79+
80+
#[spec_only]
81+
use prover::prover::requires;
82+
83+
#[spec(prove, no_opaque)]
84+
public fun is_equal_staking_metadata_spec(self: &StakedSui, other: &StakedSui): bool {
85+
is_equal_staking_metadata(self, other)
86+
}
87+
88+
#[spec_only]
89+
public fun activation_epoch_is_positive(pool: &StakingPool): bool {
90+
pool.activation_epoch.is_some() &&
91+
*pool.activation_epoch.borrow() > 0
92+
}
93+
94+
#[spec()]
95+
public fun pool_token_exchange_rate_at_epoch_spec(
96+
pool: &StakingPool,
97+
epoch: u64,
98+
): PoolTokenExchangeRate {
99+
requires(! pool.is_preactive());
100+
requires(activation_epoch_is_positive(pool));
101+
pool_token_exchange_rate_at_epoch(pool, epoch)
102+
}
103+
104+
105+
#[spec_only(inv_target=std::option::Option)]
106+
fun Option_inv<T>(self: &Option<T>): bool {
107+
if (self.is_some()) {
108+
let o = prover::prover::val(self.borrow());
109+
let x = std::option::some(o);
110+
let b = self == x;
111+
prover::prover::drop(x);
112+
b
113+
} else {
114+
true
115+
}
116+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
source: crates/sui-prover/tests/integration.rs
3+
assertion_line: 270
4+
expression: output
5+
---
6+
Verification successful

0 commit comments

Comments
 (0)