Skip to main content
Version: 3.2.0

Proxy

This example shows how you can use the implementation of proxy to to implement proxy pattern for upgradeable contracts.

Disclaimer

Delegate calls were marked as a possible attack vector in ink! Therefore the Proxy pattern will not work within OpenBrush until this is reimplemented in ink! 4. You can use this tutorial for general understanding of Proxy pattern.

Step 1: Import default implementation

With default Cargo.toml, you need to enable corresponding features, embed modules data structures and implement them via #[openbrush::implementation] macro as described in that section.

The main traits are Ownable and Proxy.

Step 2: Define constructor

Define the constructor where you initialize the owner with the contract initiator and passing code hash of the logic layer.

impl Contract {
#[ink(constructor)]
pub fn new(forward_to: Hash) -> Self {
let mut instance = Self::default();

let caller = Self::env().caller();
instance._init_with_forward_to(forward_to);
instance._init_with_owner(caller);

instance
}
}

Step 3: Define forward function

Define the forward function to make delegate calls of upgradeable contract through proxy contract.

#![cfg_attr(not(feature = "std"), no_std, no_main)]

#[openbrush::implementation(Proxy, Ownable)]
#[openbrush::contract]
pub mod proxy {
use openbrush::traits::Storage;

#[ink(storage)]
#[derive(Default, Storage)]
pub struct Contract {
#[storage_field]
proxy: proxy::Data,
#[storage_field]
ownable: ownable::Data,
}

impl Contract {
#[ink(constructor)]
pub fn new(forward_to: Hash) -> Self {
let mut instance = Self::default();
proxy::Internal::_init_with_forward_to(&mut instance, forward_to);
ownable::Internal::_init_with_owner(&mut instance, Self::env().caller());

instance
}
#[ink(message, payable, selector = _)]
pub fn forward(&self) {
proxy::Internal::_fallback(self)
}
}
}

You can check an example of the usage of Proxy.