The Upgradability Library provides functions that can be used to implement contract upgrades via simple upgradable proxies. The Upgradability Library implements the required and optional functionality from SRC-14 as well as additional functionality for ownership of the proxy contract.
For implementation details on the Upgradability Library please see the Sway Libs Docs .
In order to use the Upgradability library, Sway Libs and Sway Standards must be added to the Forc.toml
file and then imported into your Sway project. To add Sway Libs as a dependency to the Forc.toml
file in your project please see the Getting Started . To add Sway Standards as a dependency please see the Sway Standards Book .
To import the Upgradability Library and SRC-14 Standard to your Sway Smart Contract, add the following to your Sway file:
use sway_libs::upgradability::*;
use standards::{src14::*, src5::*};
To implement the SRC-14 standard with the Upgradability library, be sure to add the Sway Standards dependency to your contract. The following demonstrates the integration of the Ownership library with the SRC-14 standard.
use sway_libs::upgradability::{_proxy_owner, _proxy_target, _set_proxy_target};
use standards::{src14::{SRC14, SRC14Extension}, src5::State};
#[namespace(SRC14)]
storage {
// target is at sha256("storage_SRC14_0")
target: Option<ContractId> = None,
proxy_owner: State = State::Uninitialized,
}
impl SRC14 for Contract {
#[storage(read, write)]
fn set_proxy_target(new_target: ContractId) {
_set_proxy_target(new_target);
}
#[storage(read)]
fn proxy_target() -> Option<ContractId> {
_proxy_target()
}
}
impl SRC14Extension for Contract {
#[storage(read)]
fn proxy_owner() -> State {
_proxy_owner(storage.proxy_owner)
}
}
NOTE An initialization method must be implemented to initialize the proxy target or proxy owner.
Once imported, the Upgradability Library's functions will be available. Use them to change the proxy target for your contract by calling the set_proxy_target()
function.
#[storage(read, write)]
fn set_proxy_target(new_target: ContractId) {
_set_proxy_target(new_target);
}
Use the proxy_target()
method to get the current proxy target.
#[storage(read)]
fn proxy_target() -> Option<ContractId> {
_proxy_target()
}
To change the proxy target for your contract use the set_proxy_owner()
function.
#[storage(write)]
fn set_proxy_owner(new_proxy_owner: State) {
_set_proxy_owner(new_proxy_owner, storage.proxy_owner);
}
Use the proxy_owner()
method to get the current proxy owner.
#[storage(read)]
fn proxy_owner() -> State {
_proxy_owner(storage.proxy_owner)
}
To restrict a function to only be callable by the proxy's owner, call the only_proxy_owner()
function.
#[storage(read)]
fn only_proxy_owner_may_call() {
only_proxy_owner(storage.proxy_owner);
// Only the proxy's owner may reach this line.
}