> ## Documentation Index
> Fetch the complete documentation index at: https://developers.stellar.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Upgrading Wasm bytecode for a deployed contract

> Upgrade Wasm bytecode for a deployed contract

## Introduction

Upgrading a smart contract allows you to improve or modify your contract without changing its address. This guide will walk you through the process of upgrading a WebAssembly (Wasm) bytecode contract using the Soroban SDK.

### Prerequisites:

* Basic understanding of the [Rust programming language]. To brush up on Rust, check out [Rustlings](https://github.com/rust-lang/rustlings) or [The Rust book](https://doc.rust-lang.org/book).
* Familiarity with [Stellar smart contracts](https://developers.stellar.org/docs/build/smart-contracts/getting-started/hello-world.md)
* Installed [Stellar CLI](https://developers.stellar.org/docs/build/smart-contracts/getting-started/setup.md#install-the-stellar-cli) and Soroban SDK

### Download the upgradeable contract example

The [upgradeable contract example] demonstrates how to upgrade a Wasm contract.

[![Open in Codespaces](https://github.com/codespaces/badge.svg)][open-in-github-codespaces]

[![Open in Codeanywhere](https://codeanywhere.com/img/open-in-codeanywhere-btn.svg)][open-in-code-anywhere]

[open-in-github-codespaces]: https://github.com/codespaces/new?repo=stellar/soroban-examples&editor=web

[open-in-code-anywhere]: https://app.codeanywhere.com/#https://github.com/stellar/soroban-examples

[upgradeable contract example]: https://github.com/stellar/soroban-examples/tree/main/upgradeable_contract

[Rust programming language]: https://www.rust-lang.org/

### Code

The example contains both an "old" and "new" contract, where we upgrade from "old" to "new". The code below is for the "old" contract.

```rust title="upgradeable_contract/old_contract/src/lib.rs" theme={"theme":{"light":"github-light","dark":"github-dark"}}
#![no_std]

use soroban_sdk::{
    contract, contractimpl, contracttype, Address, BytesN, ContractExecutable, Env,
};

#[contracttype]
#[derive(Clone)]
enum DataKey {
    Admin,
}

#[contract]
pub struct UpgradeableContract;

#[contractimpl]
impl UpgradeableContract {
    pub fn __constructor(env: Env, admin: Address) {
        env.storage().instance().set(&DataKey::Admin, &admin);
    }

    pub fn version() -> u32 {
        1
    }

    pub fn upgrade(env: Env, new_wasm_hash: BytesN<32>) {
        let admin: Address = env.storage().instance().get(&DataKey::Admin).unwrap();
        admin.require_auth();

        env.deployer()
            .update_current_contract(ContractExecutable::Wasm(new_wasm_hash));
    }
}

mod test;
```

Source: [https://github.com/stellar/soroban-examples/blob/main/upgradeable\_contract/old\_contract/src/lib.rs](https://github.com/stellar/soroban-examples/blob/main/upgradeable_contract/old_contract/src/lib.rs)

## How it works

When upgrading a contract, the key function used is `env.deployer().update_current_contract`, which takes a `ContractExecutable` wrapping the Wasm hash of the new contract as a parameter. Here's a step-by-step breakdown of how this process works:

1. **No change in contract address**: The contract's address remains the same after the upgrade. This ensures that all references to the contract stay intact.

2. **The Wasm executable must already be uploaded**: The upgrade depends on the compiled executable (identified by the `new_wasm_hash`) being uploaded and available on the blockchain. This must be done *prior* to invoking the contract's `upgrade(...)` function.

3. **Admin authorization**: Before upgrading, the contract checks if the action is authorized by the `Admin` address. This is crucial to prevent unauthorized upgrades. Only someone with admin rights can perform the upgrade.

4. **The upgrade function**: Below is the function that handles the upgrade process:

   ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
   pub fn upgrade(env: Env, new_wasm_hash: BytesN<32>) {
       let admin: Address = env.storage().instance().get(&DataKey::Admin).unwrap();
       admin.require_auth();

       env.deployer()
           .update_current_contract(ContractExecutable::Wasm(new_wasm_hash));
   }
   ```

   * `env: Env`: The environment object representing the current state of the blockchain.
   * `new_wasm_hash: BytesN<32>`: The hash of the new Wasm code for the contract. The Wasm bytecode must already be installed/present on the ledger.
   * The function first retrieves the admin's address from the contract's storage.
   * It then requires the admin's authorization (`admin.require_auth()`) to proceed.
   * Finally, it updates the contract with the new Wasm bytecode (`env.deployer().update_current_contract(ContractExecutable::Wasm(new_wasm_hash))`).

5. `update_current_contract` will also emit a `SYSTEM` contract [event] that contains the old and new `ContractExecutable`, allowing downstream users to be notified when a contract they use is updated. The event structure will have `topics = ["executable_update", old_executable: ContractExecutable, new_executable: ContractExecutable]` and `data = []`.

[event]: https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/events.md#event-types

## Tests

Open the `upgradeable_contract/old_contract/src/test.rs` file to follow along.

```rust title="upgradeable_contract/old_contract/src/test.rs" theme={"theme":{"light":"github-light","dark":"github-dark"}}
#![cfg(test)]

extern crate std;

use soroban_sdk::{
    symbol_short,
    testutils::{Address as _, AuthorizedFunction, AuthorizedInvocation},
    Address, BytesN, Env, IntoVal,
};

use crate::{UpgradeableContract, UpgradeableContractClient};

mod new_contract {
    soroban_sdk::contractimport!(
        file = "../new_contract/target/wasm32v1-none/release/soroban_upgradeable_contract_new_contract.wasm"
    );
}

fn install_new_wasm(env: &Env) -> BytesN<32> {
    env.deployer().upload_contract_wasm(new_contract::WASM)
}

#[test]
fn test() {
    let env = Env::default();
    env.mock_all_auths();

    let admin = Address::generate(&env);
    let contract_id = env.register(UpgradeableContract, (&admin,));

    let client = UpgradeableContractClient::new(&env, &contract_id);

    assert_eq!(1, client.version());

    let new_wasm_hash = install_new_wasm(&env);

    client.upgrade(&new_wasm_hash);
    assert_eq!(2, client.version());

    // new_v2_fn was added in the new contract, so the existing
    // client is out of date. Generate a new one.
    let client = new_contract::Client::new(&env, &contract_id);
    assert_eq!(1010101, client.new_v2_fn());

    // New contract version requires the `NewAdmin` key to be initialized, but since the constructor
    // hasn't been called, it is not initialized, thus calling try_upgrade won't work.
    let new_update_result = client.try_upgrade(&new_wasm_hash);
    assert!(new_update_result.is_err());

    // `handle_upgrade` sets the `NewAdmin` key properly.
    client.handle_upgrade();

    // Now upgrade should succeed (though we are not actually changing the Wasm).
    client.upgrade(&new_wasm_hash);
    // The new admin is the same as the old admin, so the authorization is still performed for
    // the `admin` address.
    assert_eq!(
        env.auths(),
        std::vec![(
            admin,
            AuthorizedInvocation {
                function: AuthorizedFunction::Contract((
                    contract_id.clone(),
                    symbol_short!("upgrade"),
                    (new_wasm_hash,).into_val(&env),
                )),
                sub_invocations: std::vec![]
            }
        )]
    )
}
```

Source: [https://github.com/stellar/soroban-examples/blob/main/upgradeable\_contract/old\_contract/src/test.rs](https://github.com/stellar/soroban-examples/blob/main/upgradeable_contract/old_contract/src/test.rs)

We first import the compiled Wasm file for the new contract:

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
mod new_contract {
    soroban_sdk::contractimport!(
        file = "../new_contract/target/wasm32v1-none/release/soroban_upgradeable_contract_new_contract.wasm"
    );
}
```

We register the old contract, initialize it with an admin, and verify the version it returns. The note in the code below is important:

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
let admin = Address::generate(&env);
let contract_id = env.register(UpgradeableContract, (&admin,));

let client = UpgradeableContractClient::new(&env, &contract_id);

assert_eq!(1, client.version());
```

We install the new contract's Wasm:

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
let new_wasm_hash = install_new_wasm(&env);
```

Then we run the upgrade, and verify that the upgrade worked:

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
client.upgrade(&new_wasm_hash);
assert_eq!(2, client.version());
```

## Build the contract

To build the contract `.wasm` files, run `stellar contract build` in both `upgradeable_contract/old_contract` and `upgradeable_contract/new_contract` in that order. Both `.wasm` files should be found in both contract `target` directories after building both contracts:

```
target/wasm32v1-none/release/soroban_upgradeable_contract_old_contract.wasm
```

```
target/wasm32v1-none/release/soroban_upgradeable_contract_new_contract.wasm
```

## Run the contract

If you have [`stellar-cli`] installed, you can invoke contract functions. Deploy the old contract and install the Wasm for the new contract.

First, navigate to the `upgradeable_contract/old_contract` directory, and deploy an instance of the old contract. We're providing the `alice` identity to the `__constructor` function, so it will be the contract's `Admin` address. Create and provide your own [identities], where necessary.

This command will output the contract address it was deployed to.

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract deploy \
  --wasm target/wasm32v1-none/release/soroban_upgradeable_contract_old_contract.wasm \
  --source-account alice  \
  --network testnet \
  -- --admin alice
# CAS6FKBXGVXFGU2SPPPJJOIULJNPMPR6NVKWLOQP24SZJPMB76TGH7Y3
```

Then, navigate to `upgradeable_contract/new_contract` and upload the compiled executable file for the new contract. This command will output the Sha256 hash of the executable, which will be used later for the `new_wasm_hash` parameter.

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract upload \
  --source-account alice \
  --wasm target/wasm32v1-none/release/soroban_upgradeable_contract_new_contract.wasm \
  --network testnet
# aa24c81289997ad815489b29db337b53f284cca5aba86e9a8ae5cef7d31842c2
```

Our deployed `old_contract` address is `CAS6FKBXGVXFGU2SPPPJJOIULJNPMPR6NVKWLOQP24SZJPMB76TGH7Y3`. You may need to replace this value with your own. Invoke the `version` function of the contract, to see the current deployed version.

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract invoke \
  --id CAS6FKBXGVXFGU2SPPPJJOIULJNPMPR6NVKWLOQP24SZJPMB76TGH7Y3 \
  --source-account alice \
  --network testnet \
  -- version
# 1
```

Now upgrade the contract. Notice the `--source-account` should be the identity name matching the address passed to the `__constructor` function, when the contract was deployed.

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract invoke \
  --id CAS6FKBXGVXFGU2SPPPJJOIULJNPMPR6NVKWLOQP24SZJPMB76TGH7Y3 \
  --source-account alice \
  --network testnet \
  -- \
  upgrade \
  --new_wasm_hash aa24c81289997ad815489b29db337b53f284cca5aba86e9a8ae5cef7d31842c2
```

Invoke the `version` function again. Now that the contract was upgraded, you'll see a new version.

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract invoke \
  --id CAS6FKBXGVXFGU2SPPPJJOIULJNPMPR6NVKWLOQP24SZJPMB76TGH7Y3 \
  --source-account alice \
  --network testnet \
  -- version
# 2
```

Hooray, our contract has been upgraded!

[`stellar-cli`]: ../../smart-contracts/getting-started/setup#install-the-stellar-cli

[identities]: https://developers.stellar.org/docs/build/smart-contracts/getting-started/setup.md#configure-an-identity
