| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- // SPDX-License-Identifier: Apache-2.0
- use crate::build_solidity;
- use indexmap::Equivalent;
- use soroban_sdk::{testutils::Address as _, Address, FromVal, IntoVal, Val};
- #[test]
- fn get_fields_via_dot() {
- let runtime = build_solidity(
- r#"
- contract locker {
- struct Lock {
- uint64 release_time;
- address beneficiary;
- uint64 amount;
- }
- mapping(address => Lock) locks;
- function create_lock(
- uint64 release_time,
- address beneficiary,
- uint64 amount
- ) public returns (uint64) {
- Lock memory l = Lock({
- release_time: release_time,
- beneficiary: beneficiary,
- amount: amount
- });
- locks[beneficiary] = l;
- return l.amount;
- }
- function get_lock_amount(address beneficiary) public view returns (uint64) {
- return locks[beneficiary].amount;
- }
- function get_lock_release(address beneficiary) public view returns (uint64) {
- return locks[beneficiary].release_time;
- }
- function get_lock_beneficiary(address key) public view returns (address) {
- return locks[key].beneficiary;
- }
- // Extended functionality: increase amount in-place and return new total
- function increase_lock_amount(address beneficiary, uint64 delta) public returns (uint64) {
- locks[beneficiary].amount += delta;
- return locks[beneficiary].amount;
- }
- // Extended functionality: move a lock to a different beneficiary
- function move_lock(address from, address to) public {
- Lock memory l = locks[from];
- require(l.amount != 0, "no lock");
- l.beneficiary = to;
- locks[to] = l;
- // emulate delete by zeroing fields
- locks[from].amount = 0;
- locks[from].release_time = 0;
- }
- // Extended functionality: clear lock for a beneficiary
- function clear_lock(address beneficiary) public {
- // emulate delete by zeroing fields
- locks[beneficiary].amount = 0;
- locks[beneficiary].release_time = 0;
- }
- }
- "#,
- |_| {},
- );
- let addr = runtime.contracts.last().unwrap();
- let user1 = Address::generate(&runtime.env);
- let user2 = Address::generate(&runtime.env);
- let release_time: Val = 1_000_u64.into_val(&runtime.env);
- let amount: Val = 500_u64.into_val(&runtime.env);
- // Create a new lock for user1
- let create_args = vec![release_time, user1.clone().into_val(&runtime.env), amount];
- let res = runtime.invoke_contract(addr, "create_lock", create_args);
- assert!(amount.shallow_eq(&res));
- // Verify getters
- let get_amt_args = vec![user1.clone().into_val(&runtime.env)];
- let get_rel_args = vec![user1.clone().into_val(&runtime.env)];
- let get_ben_args = vec![user1.clone().into_val(&runtime.env)];
- let got_amount = runtime.invoke_contract(addr, "get_lock_amount", get_amt_args);
- let got_release = runtime.invoke_contract(addr, "get_lock_release", get_rel_args);
- let got_beneficiary = runtime.invoke_contract(addr, "get_lock_beneficiary", get_ben_args);
- assert!(amount.shallow_eq(&got_amount));
- assert!(release_time.shallow_eq(&got_release));
- let addr_val = Address::from_val(&runtime.env, &got_beneficiary);
- assert!(addr_val.equivalent(&user1));
- // Increase amount and verify new total
- let delta: Val = 250_u64.into_val(&runtime.env);
- let inc_args = vec![user1.clone().into_val(&runtime.env), delta];
- let new_total = runtime.invoke_contract(addr, "increase_lock_amount", inc_args);
- let expected_total: Val = 750_u64.into_val(&runtime.env);
- assert!(expected_total.shallow_eq(&new_total));
- // Move lock from user1 to user2
- let move_args = vec![
- user1.clone().into_val(&runtime.env),
- user2.clone().into_val(&runtime.env),
- ];
- let _ = runtime.invoke_contract(addr, "move_lock", move_args);
- // After moving, user1 should have no lock (amount == 0)
- let zero: Val = 0_u64.into_val(&runtime.env);
- let amt_user1 = runtime.invoke_contract(
- addr,
- "get_lock_amount",
- vec![user1.clone().into_val(&runtime.env)],
- );
- assert!(zero.shallow_eq(&amt_user1));
- // And user2 should now hold the moved lock with the updated total amount
- let amt_user2 = runtime.invoke_contract(
- addr,
- "get_lock_amount",
- vec![user2.clone().into_val(&runtime.env)],
- );
- assert!(expected_total.shallow_eq(&amt_user2));
- // Beneficiary for user2's lock should be user2
- let ben_user2 = runtime.invoke_contract(
- addr,
- "get_lock_beneficiary",
- vec![user2.clone().into_val(&runtime.env)],
- );
- let ben2 = Address::from_val(&runtime.env, &ben_user2);
- assert!(ben2.equivalent(&user2));
- // Clear user2's lock and verify
- let _ = runtime.invoke_contract(
- addr,
- "clear_lock",
- vec![user2.clone().into_val(&runtime.env)],
- );
- let amt_user2_after_clear =
- runtime.invoke_contract(addr, "get_lock_amount", vec![user2.into_val(&runtime.env)]);
- assert!(zero.shallow_eq(&amt_user2_after_clear));
- }
- // Removed: keep only two tests as requested
- #[test]
- fn get_whole_struct() {
- let runtime = build_solidity(
- r#"
- contract locker {
- struct Lock {
- uint64 release_time;
- address beneficiary;
- uint64 amount;
- }
- mapping(address => Lock) locks;
- function create_lock(
- uint64 release_time,
- address beneficiary,
- uint64 amount
- ) public returns (uint64) {
- Lock memory l = Lock({
- release_time: release_time,
- beneficiary: beneficiary,
- amount: amount
- });
- locks[beneficiary] = l;
- return l.amount;
- }
- function get_lock_amount(address beneficiary) public view returns (uint64) {
- return locks[beneficiary].amount;
- }
- function get_lock_release(address beneficiary) public view returns (uint64) {
- return locks[beneficiary].release_time;
- }
- function get_lock_beneficiary(address key) public view returns (address) {
- return locks[key].beneficiary;
- }
- }
- "#,
- |_| {},
- );
- let addr = runtime.contracts.last().unwrap();
- let user = Address::generate(&runtime.env);
- let release_time: Val = 42_u64.into_val(&runtime.env);
- let amount: Val = 7_u64.into_val(&runtime.env);
- // Create lock
- let _ = runtime.invoke_contract(
- addr,
- "create_lock",
- vec![release_time, user.clone().into_val(&runtime.env), amount],
- );
- // Retrieve each field via accessors (no multiple returns)
- let rt_val = runtime.invoke_contract(
- addr,
- "get_lock_release",
- vec![user.clone().into_val(&runtime.env)],
- );
- let ben_val = runtime.invoke_contract(
- addr,
- "get_lock_beneficiary",
- vec![user.clone().into_val(&runtime.env)],
- );
- let amt_val = runtime.invoke_contract(
- addr,
- "get_lock_amount",
- vec![user.clone().into_val(&runtime.env)],
- );
- let rt: u64 = FromVal::from_val(&runtime.env, &rt_val);
- let ben = Address::from_val(&runtime.env, &ben_val);
- let amt: u64 = FromVal::from_val(&runtime.env, &amt_val);
- assert_eq!(rt, 42);
- assert!(ben.equivalent(&user));
- assert_eq!(amt, 7);
- }
|