Skip to content

Commit 602a1ea

Browse files
test: add tests for UID fallback, circular datatype fix, and compound type parenthesization
- uid_param_vec_value: UID fallback + vector value type (parenthesization) - uid_param_multi_type_params: multiple type params on &UID (circular fix) - uid_param_multi_ops: multiple df operations with different types on same &UID - uid_param_nested_generic: generic calling generic on &UID (transitive fallback) - vec_value_concrete: vector value type on normal object (parenthesization) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a4d8cd3 commit 602a1ea

10 files changed

+176
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
module 0x42::foo;
2+
3+
use prover::prover::{requires, ensures};
4+
use sui::dynamic_field as df;
5+
6+
public struct NameKey has copy, store, drop {}
7+
public struct CountKey has copy, store, drop {}
8+
9+
public struct MyObject has key {
10+
id: UID,
11+
}
12+
13+
public fun initialize(uid: &mut UID, count: u64) {
14+
df::add<NameKey, bool>(uid, NameKey {}, true);
15+
df::add<CountKey, u64>(uid, CountKey {}, count);
16+
}
17+
18+
#[spec(prove)]
19+
fun verify_initialize(obj: &mut MyObject, count: u64) {
20+
requires(!df::exists_with_type<NameKey, bool>(&obj.id, NameKey {}));
21+
requires(!df::exists_with_type<CountKey, u64>(&obj.id, CountKey {}));
22+
initialize(&mut obj.id, count);
23+
ensures(df::exists_with_type<NameKey, bool>(&obj.id, NameKey {}));
24+
ensures(df::exists_with_type<CountKey, u64>(&obj.id, CountKey {}));
25+
ensures(*df::borrow<CountKey, u64>(&obj.id, CountKey {}) == count);
26+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
module 0x42::foo;
2+
3+
use prover::prover::{requires, ensures};
4+
use sui::dynamic_field as df;
5+
6+
public struct MyObject has key {
7+
id: UID,
8+
}
9+
10+
public fun generic_add<K: copy + store + drop, V: store>(uid: &mut UID, key: K, val: V) {
11+
df::add<K, V>(uid, key, val);
12+
}
13+
14+
public fun generic_exists<K: copy + store + drop, V: store>(uid: &UID, key: K): bool {
15+
df::exists_with_type<K, V>(uid, key)
16+
}
17+
18+
#[spec(prove)]
19+
fun generic_add_u64_bool_spec(obj: &mut MyObject, key: u64, val: bool) {
20+
requires(!df::exists_with_type<u64, bool>(&obj.id, key));
21+
generic_add<u64, bool>(&mut obj.id, key, val);
22+
ensures(df::exists_with_type<u64, bool>(&obj.id, key));
23+
ensures(*df::borrow<u64, bool>(&obj.id, key) == val);
24+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
module 0x42::foo;
2+
3+
use prover::prover::{requires, ensures};
4+
use sui::dynamic_field as df;
5+
6+
public struct MyObject has key {
7+
id: UID,
8+
}
9+
10+
public fun has_field<K: copy + store + drop, V: store>(uid: &UID, key: K): bool {
11+
df::exists_with_type<K, V>(uid, key)
12+
}
13+
14+
public fun get_field<K: copy + store + drop, V: store + copy + drop>(uid: &UID, key: K, default: V): V {
15+
if (has_field<K, V>(uid, key)) {
16+
*df::borrow<K, V>(uid, key)
17+
} else {
18+
default
19+
}
20+
}
21+
22+
#[spec(prove)]
23+
fun verify_get_field(obj: &MyObject, key: u64): u64 {
24+
requires(df::exists_with_type<u64, u64>(&obj.id, key));
25+
requires(*df::borrow<u64, u64>(&obj.id, key) == 42);
26+
let result = get_field<u64, u64>(&obj.id, key, 0);
27+
ensures(result == 42);
28+
result
29+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module 0x42::foo;
2+
3+
use prover::prover::{requires, ensures};
4+
use sui::dynamic_field as df;
5+
6+
public struct MyObject has key {
7+
id: UID,
8+
}
9+
10+
public fun set_scores(uid: &mut UID, key: u64, scores: vector<u64>) {
11+
df::add(uid, key, scores);
12+
}
13+
14+
#[spec(prove)]
15+
fun verify_set_scores(obj: &mut MyObject, key: u64, scores: vector<u64>) {
16+
requires(!df::exists_with_type<u64, vector<u64>>(&obj.id, key));
17+
set_scores(&mut obj.id, key, scores);
18+
ensures(df::exists_with_type<u64, vector<u64>>(&obj.id, key));
19+
ensures(*df::borrow<u64, vector<u64>>(&obj.id, key) == scores);
20+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module 0x42::foo;
2+
3+
use prover::prover::{requires, ensures};
4+
use sui::dynamic_field as df;
5+
6+
public struct Foo has key {
7+
id: UID,
8+
}
9+
10+
fun store_list(x: &mut Foo, key: u64, items: vector<u64>) {
11+
df::add<u64, vector<u64>>(&mut x.id, key, items);
12+
}
13+
14+
#[spec(prove)]
15+
fun store_list_spec(x: &mut Foo, key: u64, items: vector<u64>) {
16+
requires(!df::exists_with_type<u64, vector<u64>>(&x.id, key));
17+
store_list(x, key, items);
18+
ensures(df::exists_with_type<u64, vector<u64>>(&x.id, key));
19+
ensures(*df::borrow<u64, vector<u64>>(&x.id, key) == items);
20+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
source: crates/sui-prover/tests/integration.rs
3+
expression: output
4+
---
5+
Verification successful
6+
warning: UID object type not found, dynamic fields will be placed under UID
7+
┌─ tests/inputs/dynamic_field/uid_param_multi_ops.ok.move:14:5
8+
9+
14df::add<NameKey, bool>(uid, NameKey {}, true);
10+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
11+
12+
warning: UID object type not found, dynamic fields will be placed under UID
13+
┌─ tests/inputs/dynamic_field/uid_param_multi_ops.ok.move:15:5
14+
15+
15df::add<CountKey, u64>(uid, CountKey {}, count);
16+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
source: crates/sui-prover/tests/integration.rs
3+
expression: output
4+
---
5+
Verification successful
6+
warning: UID object type not found, dynamic fields will be placed under UID
7+
┌─ tests/inputs/dynamic_field/uid_param_multi_type_params.ok.move:11:5
8+
9+
11df::add<K, V>(uid, key, val);
10+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
source: crates/sui-prover/tests/integration.rs
3+
expression: output
4+
---
5+
Verification successful
6+
warning: UID object type not found, dynamic fields will be placed under UID
7+
┌─ tests/inputs/dynamic_field/uid_param_nested_generic.ok.move:16:10
8+
9+
16 │ *df::borrow<K, V>(uid, key)
10+
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^
11+
12+
warning: UID object type not found, dynamic fields will be placed under UID
13+
┌─ tests/inputs/dynamic_field/uid_param_nested_generic.ok.move:11:5
14+
15+
11df::exists_with_type<K, V>(uid, key)
16+
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
source: crates/sui-prover/tests/integration.rs
3+
expression: output
4+
---
5+
Verification successful
6+
warning: UID object type not found, dynamic fields will be placed under UID
7+
┌─ tests/inputs/dynamic_field/uid_param_vec_value.ok.move:11:5
8+
9+
11df::add(uid, key, scores);
10+
^^^^^^^^^^^^^^^^^^^^^^^^^
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
source: crates/sui-prover/tests/integration.rs
3+
expression: output
4+
---
5+
Verification successful

0 commit comments

Comments
 (0)