Skip to main content

stellar_upgrader/
contract.rs

1use stellar_axelar_std::interfaces::UpgradableClient;
2use stellar_axelar_std::{
3    contract, contractimpl, ensure, soroban_sdk, symbol_short, Address, BytesN, Env, String,
4    Symbol, Val,
5};
6
7use crate::error::ContractError;
8use crate::interface::UpgraderInterface;
9
10const MIGRATE: Symbol = symbol_short!("migrate");
11
12#[contract]
13pub struct Upgrader;
14
15#[contractimpl]
16impl Upgrader {
17    pub fn __constructor(_env: Env) {}
18}
19
20#[contractimpl]
21impl UpgraderInterface for Upgrader {
22    fn upgrade(
23        env: Env,
24        contract_address: Address,
25        new_version: String,
26        new_wasm_hash: BytesN<32>,
27        migration_data: stellar_axelar_std::Vec<Val>,
28    ) -> Result<(), ContractError> {
29        let contract_client = UpgradableClient::new(&env, &contract_address);
30
31        contract_client.required_auths().iter().for_each(|addr| {
32            addr.require_auth();
33        });
34
35        ensure!(
36            contract_client.version() != new_version,
37            ContractError::SameVersion
38        );
39
40        contract_client.upgrade(&new_wasm_hash);
41        // The types of the arguments to the migrate function are unknown to this contract, so we need to call it with invoke_contract.
42        // The migrate function's return value can be safely cast to Val no matter what it really is
43        // because it will panic on failure anyway
44        env.invoke_contract::<Val>(&contract_address, &MIGRATE, migration_data);
45
46        ensure!(
47            contract_client.version() == new_version,
48            ContractError::UnexpectedNewVersion
49        );
50        Ok(())
51    }
52}