|
1 | 1 | #![cfg(test)] |
2 | 2 |
|
3 | 3 | use super::*; |
4 | | -use soroban_sdk::testutils::storage::Persistent as _; |
5 | | -use soroban_sdk::testutils::{Address as _, Ledger}; |
| 4 | +use soroban_sdk::testutils::storage::{Instance as _, Persistent as _}; |
| 5 | +use soroban_sdk::testutils::{Address as _, Ledger, MockAuth, MockAuthInvoke}; |
| 6 | +use soroban_sdk::IntoVal; |
6 | 7 |
|
7 | 8 | const DEFAULT_BOND: i128 = 100; |
8 | 9 | const DEFAULT_CHALLENGE_WINDOW: u64 = 3600; |
@@ -2863,6 +2864,122 @@ fn test_set_paused_v2_blocks_new_assertions() { |
2863 | 2864 | f.client.assert_outcome(&asserter, &true); |
2864 | 2865 | } |
2865 | 2866 |
|
| 2867 | +#[test] |
| 2868 | +fn test_admin_state_changes_renew_instance_storage_ttl() { |
| 2869 | + let f = Fixture::new(); |
| 2870 | + |
| 2871 | + let instance_ttl = || { |
| 2872 | + f.env |
| 2873 | + .as_contract(&f.client.address, || f.env.storage().instance().get_ttl()) |
| 2874 | + }; |
| 2875 | + |
| 2876 | + assert_eq!(instance_ttl(), INSTANCE_BUMP_AMOUNT); |
| 2877 | + |
| 2878 | + f.env |
| 2879 | + .ledger() |
| 2880 | + .with_mut(|l| l.sequence_number += INSTANCE_BUMP_AMOUNT - 10); |
| 2881 | + f.client.set_paused_v2(&true); |
| 2882 | + assert_eq!(instance_ttl(), INSTANCE_BUMP_AMOUNT); |
| 2883 | + |
| 2884 | + f.env |
| 2885 | + .ledger() |
| 2886 | + .with_mut(|l| l.sequence_number += INSTANCE_BUMP_AMOUNT - 10); |
| 2887 | + f.client.set_admin(&f.generate()); |
| 2888 | + assert_eq!(instance_ttl(), INSTANCE_BUMP_AMOUNT); |
| 2889 | +} |
| 2890 | + |
| 2891 | +#[test] |
| 2892 | +fn test_admin_rotation_updates_authority() { |
| 2893 | + let env = Env::default(); |
| 2894 | + let token_id = setup(&env); |
| 2895 | + let contract_id = env.register(TholosV2, ()); |
| 2896 | + let client = TholosV2Client::new(&env, &contract_id); |
| 2897 | + let old_admin = Address::generate(&env); |
| 2898 | + let new_admin = Address::generate(&env); |
| 2899 | + let arbitrary = Address::generate(&env); |
| 2900 | + |
| 2901 | + env.mock_auths(&[MockAuth { |
| 2902 | + address: &old_admin, |
| 2903 | + invoke: &MockAuthInvoke { |
| 2904 | + contract: &contract_id, |
| 2905 | + fn_name: "initialize", |
| 2906 | + args: ( |
| 2907 | + old_admin.clone(), |
| 2908 | + token_id.clone(), |
| 2909 | + DEFAULT_BOND, |
| 2910 | + DEFAULT_CHALLENGE_WINDOW, |
| 2911 | + DEFAULT_FINALIZE_REWARD_BPS, |
| 2912 | + DEFAULT_REGISTRATION_SECS, |
| 2913 | + DEFAULT_ANTI_SNIPE_EXT_SECS, |
| 2914 | + DEFAULT_ANTI_SNIPE_HARD_MAX_SECS, |
| 2915 | + DEFAULT_REVEAL_SECS, |
| 2916 | + DEFAULT_MAX_POSITION, |
| 2917 | + DEFAULT_MAX_TOTAL_WEIGHT, |
| 2918 | + ) |
| 2919 | + .into_val(&env), |
| 2920 | + sub_invokes: &[], |
| 2921 | + }, |
| 2922 | + }]); |
| 2923 | + init( |
| 2924 | + &client, |
| 2925 | + &old_admin, |
| 2926 | + &token_id, |
| 2927 | + DEFAULT_BOND, |
| 2928 | + DEFAULT_CHALLENGE_WINDOW, |
| 2929 | + DEFAULT_FINALIZE_REWARD_BPS, |
| 2930 | + ) |
| 2931 | + .unwrap() |
| 2932 | + .unwrap(); |
| 2933 | + |
| 2934 | + // An arbitrary address cannot authorize a rotation: set_admin always |
| 2935 | + // requires the admin currently stored by the contract. |
| 2936 | + env.mock_auths(&[MockAuth { |
| 2937 | + address: &arbitrary, |
| 2938 | + invoke: &MockAuthInvoke { |
| 2939 | + contract: &contract_id, |
| 2940 | + fn_name: "set_admin", |
| 2941 | + args: (new_admin.clone(),).into_val(&env), |
| 2942 | + sub_invokes: &[], |
| 2943 | + }, |
| 2944 | + }]); |
| 2945 | + assert!(client.try_set_admin(&new_admin).is_err()); |
| 2946 | + |
| 2947 | + env.mock_auths(&[MockAuth { |
| 2948 | + address: &old_admin, |
| 2949 | + invoke: &MockAuthInvoke { |
| 2950 | + contract: &contract_id, |
| 2951 | + fn_name: "set_admin", |
| 2952 | + args: (new_admin.clone(),).into_val(&env), |
| 2953 | + sub_invokes: &[], |
| 2954 | + }, |
| 2955 | + }]); |
| 2956 | + client.set_admin(&new_admin); |
| 2957 | + |
| 2958 | + // Rotation is immediate: the previous admin can no longer use an |
| 2959 | + // admin-only entrypoint, while the new admin can. |
| 2960 | + env.mock_auths(&[MockAuth { |
| 2961 | + address: &old_admin, |
| 2962 | + invoke: &MockAuthInvoke { |
| 2963 | + contract: &contract_id, |
| 2964 | + fn_name: "set_paused_v2", |
| 2965 | + args: (true,).into_val(&env), |
| 2966 | + sub_invokes: &[], |
| 2967 | + }, |
| 2968 | + }]); |
| 2969 | + assert!(client.try_set_paused_v2(&true).is_err()); |
| 2970 | + |
| 2971 | + env.mock_auths(&[MockAuth { |
| 2972 | + address: &new_admin, |
| 2973 | + invoke: &MockAuthInvoke { |
| 2974 | + contract: &contract_id, |
| 2975 | + fn_name: "set_paused_v2", |
| 2976 | + args: (true,).into_val(&env), |
| 2977 | + sub_invokes: &[], |
| 2978 | + }, |
| 2979 | + }]); |
| 2980 | + client.set_paused_v2(&true); |
| 2981 | +} |
| 2982 | + |
2866 | 2983 | #[test] |
2867 | 2984 | fn test_set_paused_v2_does_not_block_existing_round() { |
2868 | 2985 | // The narrower v2 pause only ever gates assert_outcome: an |
|
0 commit comments