-
Notifications
You must be signed in to change notification settings - Fork 12
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
Upgradeable contracts using proxies. #39
Open
JoshuaBatty
wants to merge
2
commits into
master
Choose a base branch
from
josh/proxies
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
- Feature Name: `contract_proxies` | ||
- Start Date: 2024-05-21 | ||
- RFC PR: [FuelLabs/sway-rfcs#0013](https://github.com/FuelLabs/sway-rfcs/pull/39) | ||
|
||
# Summary | ||
|
||
[summary]: #summary | ||
|
||
This proposal introduces a feature to simplify the creation of upgradeable contracts in Sway by enhancing the Forc.toml manifest file. | ||
|
||
# Motivation | ||
|
||
[motivation]: #motivation | ||
|
||
Sway developers want to upgrade their smart contract code post-deployment and need tooling support to facilitate this process. They seek a straightforward method, such as adding a configuration to the Forc.toml file, to enable and manage contract upgradeability seamlessly. | ||
|
||
# Guide-level explanation | ||
|
||
[guide-level-explanation]: #guide-level-explanation | ||
|
||
### Use of the Forc.toml for an upgradeable contact. | ||
This proposal enhances the Forc.toml file to simplify creating upgradeable contracts. A new `[proxy]` table indicates to `forc-deploy` that this contract is upgradable. During the initial deployment, `forc-deploy` stores the proxy contract's address in the `address` field, streamlining future updates and ensuring the address is stored safely with the project. | ||
|
||
```toml | ||
[project] | ||
authors = ["Fuel Labs <[email protected]>"] | ||
entry = "main.sw" | ||
license = "Apache-2.0" | ||
name = "implementation" | ||
|
||
[proxy] | ||
enabled = true # Undecided if we really need this flag yet. | ||
address = # this field gets automatically added and filled in during deployment | ||
``` | ||
|
||
## Workflow | ||
|
||
The deployment process takes care of generating proxy bytecode, deploying contracts, and updating addresses automatically. The workflow from forc’s perspective could look something like the following: | ||
|
||
1. **Forc Deploy**: | ||
- Forc deploy checks if the **`proxy.enabled`** field is set to **`true`** in **`Forc.toml`**. | ||
- If enabled, it checks the **`proxy.address`** field. | ||
- If **`proxy.address`** is empty, it deploys a new proxy contract, updates the **`proxy.address`** field with the deployed proxy's address, and deploys the implementation contract. | ||
- If **`proxy.address`** is not empty, it skips deploying a new proxy and proceeds to update the existing proxy's storage to point to the new implementation contract. | ||
2. **Initial Deployment**: | ||
- Generate the proxy contract bytecode. | ||
- Deploy the implementation contract. | ||
- Deploy the proxy contract. | ||
- Update the proxy contract's storage to point to the implementation contract's address. | ||
- Store the proxy contract's address in **`Forc.toml`**. | ||
3. **Subsequent Deployments**: | ||
- Check if a proxy address already exists. | ||
- Check storage layout consistency between the proxy and the new implementation contract. | ||
- Check for breaking changes in the ABI. | ||
- If storage layout is consistent and no breaking changes are found in the ABI, deploy the new implementation contract. | ||
- Update the existing proxy contract to point to the new implementation contract's address. | ||
|
||
```mermaid | ||
graph TD | ||
A[Check Forc.toml] --> B{Proxy Enabled?} | ||
B -- No --> C[Deploy Main Contract Normally] | ||
B -- Yes --> D{Proxy Address Exists?} | ||
D -- No --> E[Generate Proxy Contract Bytecode] | ||
E --> F[Deploy Implementation Contract] | ||
F --> G[Deploy Proxy Contract] | ||
G --> H[Update Proxy Storage with Implementation Address] | ||
H --> I[Store Proxy Address in Forc.toml] | ||
D -- Yes --> J[Check Storage Layout Consistency] | ||
J -- Inconsistent --> X[Abort Deployment] | ||
J -- Consistent --> K[Check for ABI Breaking Changes] | ||
K -- Breaking Changes --> Y[Abort Deployment] | ||
K -- No Breaking Changes --> L[Deploy New Implementation Contract] | ||
L --> M[Update Existing Proxy Storage with New Implementation Address] | ||
``` | ||
|
||
### **Usability Features** | ||
|
||
- **Simplicity**: The system is simple for developers to use. They only need to enable the proxy in **`Forc.toml`**, and the rest is handled automatically. | ||
- **Automation**: Automatically managing the proxy address in **`Forc.toml`** reduces the risk of errors and ensures consistency. | ||
- **Deployment Flexibility**: The system handles both initial deployments and subsequent updates seamlessly. | ||
|
||
### **Security Considerations** | ||
|
||
- **Address Verification**: Ensure the address stored in **`Forc.toml`** is accurate and not tampered with. Use checksums or other verification methods if needed. | ||
- **State Management**: Ensure the proxy contract's storage is correctly updated to point to the new implementation contract to prevent any potential issues with state consistency. | ||
- **Access Control**: Implement proper access control in the proxy contract to restrict who can update the implementation address to prevent unauthorized changes. | ||
- **Storage Layout Consistency**: Ensure that the storage layout between the proxy and the implementation contracts is identical. | ||
|
||
### **Example Contract Syntax** | ||
@IGI-111 to fill out. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we fill this in? |
||
|
||
|
||
### **Compiler Features** | ||
* A function that generates the smallest possible byte code for the proxy contract that can be used by `forc-deploy` |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think removing this makes sense, as absence or existence of
[proxy]
table can be used to deduce thisThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess setting this to false would allow you to deploy the contract for testing purposes before generating and committing to the proxy contract.
Users could always comment out
[proxy]
but this might make that more explicit?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm you mean to test the implementation contract right? if so sounds good to me. Another option to infer the
enabled = true
if the table is there, and for testing users can useenabled = false
or we can explicitly require the field to be there.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fwiw I think having them comment it out for that behavior (or run a specific flag) looks more correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if
address = #
is valid TOML.Some blockchains make things like this explicit by pointing to well-known values like
addresss = 0x0000000000000000000000000000000000000000
. I personally don't like this because you have to count the number of0
for no good reason and is also error-prone.Maybe an enum here or a shorter value as a placeholder could make sense:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the proxy will only ever be a single value, would it make sense to move this to the
project
table?