Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: proxy contract cookbook #3253

Merged
merged 52 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
73b1bb1
docs: cookbook for manually deploying and upgrading a proxy
danielbate Oct 5, 2024
191054d
Merge branch 'master' of https://github.com/FuelLabs/fuels-ts into db…
danielbate Oct 9, 2024
0e795f7
chore: add missing test groups
danielbate Oct 9, 2024
36c0e24
chore: changeset
danielbate Oct 9, 2024
238fd5b
chore: update changeset
danielbate Oct 9, 2024
5459232
chore: forc format
danielbate Oct 9, 2024
8a79ee2
Merge branch 'db/chore/manual-proxy-contracts' of https://github.com/…
danielbate Oct 9, 2024
360b704
chore: update doc
danielbate Oct 9, 2024
d7c0b0c
chore: update doc
danielbate Oct 9, 2024
445c93c
chore: update doc
danielbate Oct 9, 2024
914bc01
Merge branch 'master' into db/chore/manual-proxy-contracts
danielbate Oct 9, 2024
67d9433
Merge branch 'master' into db/chore/manual-proxy-contracts
Torres-ssf Oct 11, 2024
d0ff3df
Merge branch 'master' of https://github.com/FuelLabs/fuels-ts into db…
danielbate Oct 15, 2024
8f9c67c
docs: use src 14 commit hash for doc
danielbate Oct 15, 2024
38a125f
chore: migrate to v2 snippet
danielbate Oct 17, 2024
a17bb8e
chore: restore v1 snippets files
danielbate Oct 17, 2024
dea7aea
chore: fix snippet path
danielbate Oct 17, 2024
93b0472
chore: fix test region
danielbate Oct 17, 2024
2290e74
multilning doc comments
Torres-ssf Oct 17, 2024
b966a26
moving snippet to another place
Torres-ssf Oct 17, 2024
e1c676a
Merge branch 'master' into db/chore/manual-proxy-contracts
Torres-ssf Oct 21, 2024
4c5f549
Merge branch 'master' into db/chore/manual-proxy-contracts
Torres-ssf Oct 22, 2024
3eccadc
Merge branch 'master' into db/chore/manual-proxy-contracts
Torres-ssf Oct 29, 2024
3f4b90e
Merge branch 'master' of https://github.com/FuelLabs/fuels-ts into db…
danielbate Nov 19, 2024
6abfd3b
chore: fix toml
danielbate Nov 19, 2024
94ff50b
Merge branch 'master' of https://github.com/FuelLabs/fuels-ts into db…
danielbate Nov 26, 2024
28df5eb
chore: further snippet migration
danielbate Nov 26, 2024
50c2090
feat: add recipe package and import proxy there
danielbate Nov 26, 2024
1eac25b
chore: changeset
danielbate Nov 26, 2024
f0066a5
chore: fix build script
danielbate Nov 26, 2024
fd7885e
chore: changeset
danielbate Nov 26, 2024
b9af2a9
chore: lint
danielbate Nov 26, 2024
eaf5064
chore: lint
danielbate Nov 26, 2024
36037ac
chore: update changeset
danielbate Nov 26, 2024
bcee8b0
chore: update changeset
danielbate Nov 26, 2024
8c50f3d
chore: revert changeset
danielbate Nov 27, 2024
e6327be
chore: lint
danielbate Nov 27, 2024
f6545e6
chore: ignore linters
danielbate Nov 27, 2024
67441b1
Merge branch 'master' into db/chore/manual-proxy-contracts
danielbate Nov 27, 2024
9965c02
chore: cleanup old docs snips
danielbate Nov 27, 2024
970d19f
Merge branch 'db/chore/manual-proxy-contracts' of https://github.com/…
danielbate Nov 27, 2024
8653567
chore: readme updates
danielbate Nov 27, 2024
b24ccef
chore: update doc
danielbate Nov 27, 2024
c32faff
chore: add changelog
danielbate Nov 27, 2024
a0df28b
Merge branch 'db/chore/manual-proxy-contracts' of https://github.com/…
danielbate Nov 27, 2024
29c1e72
chore: make private
danielbate Nov 28, 2024
ea30938
chore: retrieve slots from factory
danielbate Nov 28, 2024
b0029bd
chore: lint
danielbate Nov 28, 2024
50eee30
chore: simplify readme
danielbate Nov 28, 2024
5a9ad21
chore: revert private change
danielbate Nov 28, 2024
dce8677
chore: improve doc
danielbate Nov 28, 2024
f46fc0c
chore: improve doc
danielbate Nov 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/friendly-cooks-appear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@internal/benchmarks": patch
danielbate marked this conversation as resolved.
Show resolved Hide resolved
---

docs: proxy contract cookbook
105 changes: 105 additions & 0 deletions apps/docs-snippets/src/guide/contracts/proxy-contracts.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { Provider, Wallet } from 'fuels';
import { launchTestNode } from 'fuels/test-utils';

import {
Counter,
CounterFactory,
CounterV2,
CounterV2Factory,
ProxyContract,
ProxyContractFactory,
} from '../../../test/typegen';

/**
* @group node
* @group browser
*/
describe('Proxy Contracts', () => {
it('deploys and upgrades a contracts using a proxy', async () => {
using launched = await launchTestNode();

const {
provider: testProvider,
wallets: [testWallet],
} = launched;
const providerUrl = testProvider.url;
const WALLET_PVT_KEY = testWallet.privateKey;

// #region proxy-2
// #import { Provider, Wallet };
// #context import { WALLET_PVT_KEY } from 'path/to/my/env/file';
// #context import { CounterFactory, Counter, ProxyFactory, CounterV2Factory } from 'path/to/typegen/outputs';

const provider = await Provider.create(providerUrl);
const wallet = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider);

const counterContractFactory = new CounterFactory(wallet);
const { waitForResult: waitForCounterContract } = await counterContractFactory.deploy();
const { contract: counterContract } = await waitForCounterContract();
// #endregion proxy-2

// #region proxy-3
// It is important to pass the pass all storage slots to the proxy in order to initialize the storage slots.
danielbate marked this conversation as resolved.
Show resolved Hide resolved
const storageSlots = Counter.storageSlots.concat(ProxyContract.storageSlots);

// These configurables are specific to our recommended SRC14 compliant contract. They must be passed on deploy
// and then `initialize_proxy` must be called to setup the proxy contract.
const configurableConstants = {
INITIAL_TARGET: { bits: counterContract.id.toB256() },
INITIAL_OWNER: { Initialized: { Address: { bits: wallet.address.toB256() } } },
};

const proxyContractFactory = new ProxyContractFactory(wallet);
const { waitForResult: waitForProxyContract } = await proxyContractFactory.deploy({
storageSlots,
configurableConstants,
});
const { contract: proxyContract } = await waitForProxyContract();

const { waitForResult: waitForProxyInit } = await proxyContract.functions
.initialize_proxy()
.call();
await waitForProxyInit();
// #endregion proxy-3

// #region proxy-4
// Make sure to use only the contract ID of the proxy when instantiating the contract
// as this will remain static even with future upgrades.
const initialContract = new Counter(proxyContract.id, wallet);

const { waitForResult: waitForIncrement } = await initialContract.functions
.increment_counter(1)
.call();
await waitForIncrement();

const { value: count } = await initialContract.functions.get_count().get();
// #endregion proxy-4

// #region proxy-6
const { waitForResult: waitForCounterContractV2 } = await CounterV2Factory.deploy(wallet);
const { contract: counterContractV2 } = await waitForCounterContractV2();

const { waitForResult: waitForUpdateTarget } = await proxyContract.functions
.set_proxy_target({ bits: counterContractV2.id.toB256() })
.call();

await waitForUpdateTarget();
// #endregion proxy-6

// #region proxy-7
// Again, we are instantiating the contract with the same proxy ID but using a new contract instance.
const upgradedContract = new CounterV2(proxyContract.id, wallet);
const { waitForResult: waitForSecondIncrement } = await upgradedContract.functions
.increment_counter(1)
.call();
await waitForSecondIncrement();

const { value: increments } = await upgradedContract.functions.get_increments().get();
const { value: secondCount } = await upgradedContract.functions.get_count().get();
// #endregion proxy-7

expect(count.toNumber()).toBe(1);
expect(secondCount.toNumber()).toBe(2);
expect(increments.toNumber()).toBe(1);
});
});
2 changes: 2 additions & 0 deletions apps/docs-snippets/test/fixtures/forc-projects/Forc.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[workspace]
members = [
"counter",
"counter-v2",
"echo-enum",
"liquidity-pool",
"log-values",
Expand Down Expand Up @@ -34,4 +35,5 @@ members = [
"input-output-types",
"bytecode-input",
"configurable-pin",
"proxy-contract",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[project]
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "main.sw"
license = "Apache-2.0"
name = "counter-v2"

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// #region proxy-5
contract;

abi Counter {
#[storage(read)]
fn get_count() -> u64;

#[storage(read)]
fn get_increments() -> u64;

#[storage(write, read)]
fn increment_counter(amount: u64) -> u64;

#[storage(write, read)]
fn decrement_counter(amount: u64) -> u64;
}

storage {
counter: u64 = 0,
increments: u64 = 0,
}

impl Counter for Contract {
#[storage(read)]
fn get_count() -> u64 {
storage.counter.try_read().unwrap_or(0)
}

#[storage(read)]
fn get_increments() -> u64 {
storage.increments.try_read().unwrap_or(0)
}

#[storage(write, read)]
fn increment_counter(amount: u64) -> u64 {
let current = storage.counter.try_read().unwrap_or(0);
storage.counter.write(current + amount);

let current_iteration: u64 = storage.increments.try_read().unwrap_or(0);
storage.increments.write(current_iteration + 1);

storage.counter.read()
}

#[storage(write, read)]
fn decrement_counter(amount: u64) -> u64 {
let current = storage.counter.read();
storage.counter.write(current - amount);
storage.counter.read()
}
}
// #endregion proxy-5
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// #region proxy-1
contract;

abi Counter {
Expand All @@ -18,20 +19,21 @@ storage {
impl Counter for Contract {
#[storage(read)]
fn get_count() -> u64 {
storage.counter.read()
storage.counter.try_read().unwrap_or(0)
}

#[storage(write, read)]
fn increment_counter(amount: u64) -> u64 {
let current = storage.counter.read();
let current = storage.counter.try_read().unwrap_or(0);
storage.counter.write(current + amount);
storage.counter.read()
}

#[storage(write, read)]
fn decrement_counter(amount: u64) -> u64 {
let current = storage.counter.read();
let current = storage.counter.try_read().unwrap_or(0);
storage.counter.write(current - amount);
storage.counter.read()
}
}
// #endregion proxy-1
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[project]
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "main.sw"
license = "Apache-2.0"
name = "proxy-contract"

[dependencies]
standards = { git = "https://github.com/FuelLabs/sway-standards", tag = "v0.6.0" }
sway_libs = { git = "https://github.com/FuelLabs/sway-libs", tag = "v0.24.0" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
library;

use standards::src5::State;

abi OwnedProxy {
#[storage(write)]
fn initialize_proxy();

#[storage(write)]
fn set_proxy_owner(new_proxy_owner: State);
}
Loading
Loading