templar_common/versioned_state/
macros.rs

1#[macro_export]
2macro_rules! impl_versioned_state {
3    ($contract: ident, $current_state: ty, $migrations: ty) => {
4        #[::near_sdk::near]
5        impl $crate::versioned_state::MigrateExternalInterface for $contract {
6            fn get_stored_state_version() -> u32 {
7                $crate::versioned_state::read_state_version()
8                    .unwrap_or_else(|e| ::near_sdk::env::panic_str(&e.to_string()))
9            }
10
11            fn get_target_state_version() -> u32 {
12                <$current_state as $crate::versioned_state::StateVersion>::VERSION
13            }
14
15            fn needs_migration() -> bool {
16                <$current_state as $crate::versioned_state::StateVersion>::needs_migration()
17                    .unwrap_or_else(|e| ::near_sdk::env::panic_str(&e.to_string()))
18            }
19        }
20
21        #[cfg_attr(target_arch = "wasm32", unsafe(no_mangle))]
22        #[cfg_attr(not(target_arch = "wasm32"), allow(dead_code))]
23        pub fn migrate() {
24            use near_sdk::env;
25            env::setup_panic_hook();
26
27            ::near_sdk::require!(
28                env::predecessor_account_id() == env::current_account_id(),
29                "migrate function is private",
30            );
31
32            let input = env::input().unwrap_or_else(|| env::panic_str("no input"));
33
34            let args: $migrations = ::near_sdk::serde_json::from_slice(&input)
35                .unwrap_or_else(|e| env::panic_str(&e.to_string()));
36
37            // A contract may launch at its first state version with no migrations defined, making
38            // `$migrations` an uninhabited (empty) enum. The deserialize above then has type `!`
39            // (it can only panic), so this call is statically unreachable — expected, not a bug.
40            #[allow(unreachable_code)]
41            $crate::versioned_state::Migrator::run(args);
42        }
43    };
44}
45
46pub use impl_versioned_state;