From 9b187c6ce0d5ccc71c7934c5366a6a5b4d506f03 Mon Sep 17 00:00:00 2001 From: banasa44 Date: Wed, 8 May 2024 12:29:37 +0200 Subject: [PATCH 1/9] fix: revert deleting step 3 in plugin publishing docs --- .../02-plugin-development/07-publication/index.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/07-publication/index.md b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/07-publication/index.md index 6187a414a..b1edfacdf 100644 --- a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/07-publication/index.md +++ b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/07-publication/index.md @@ -18,6 +18,10 @@ To publish a plugin, we will use Aragon's `PluginRepoFactory` contract - in char You can find all of the addresses of `PluginRepoFactory` contracts by network [here](https://github.com/aragon/osx-commons/tree/develop/configs/src/deployments/json). -To create more versions of your plugin in the future, you'll call on the [`createVersion` function](https://github.com/aragon/osx/blob/develop/packages/contracts/src/framework/plugin/repo/PluginRepo.sol#L128) from the `PluginRepo` instance of your plugin. When you publish your plugin, you'll be able to find the address of your plugin's `PluginRepo` instance within the transaction data. +To create more versions of your plugin in the future, you'll call on the [`createVersion` function](https://github.com/aragon/osx/blob/develop/packages/contracts/src/framework/plugin/repo/PluginRepo.sol#L133) from the `PluginRepo` instance of your plugin. When you publish your plugin, you'll be able to find the address of your plugin's `PluginRepo` instance within the transaction data. + +### 3. Publishing subsequent builds + +When publishing subsequent builds, you want to use the `createVersion` function in the `PluginRepo` contract ([check out the function's source code here](https://github.com/aragon/osx/blob/develop/packages/contracts/src/framework/plugin/repo/PluginRepo.sol#L133)). To deploy your plugin, follow the steps in the [`osx-plugin-template-hardhat` README.md](https://github.com/aragon/osx-plugin-template-hardhat/blob/main/README.md#deployment). From a32ba88be30bd0afeef67eccacc0d187576309ca Mon Sep 17 00:00:00 2001 From: banasa44 Date: Mon, 13 May 2024 13:26:53 +0200 Subject: [PATCH 2/9] chore: move docs images (adapt paths), fix orthographic mistakes --- .../docs/developer-portal/01-get-started.mdx | 10 ++++++++++ .../01-core/03-plugins/index.md | 6 +++--- .../01-how-it-works/01-core/index.md | 5 +++-- .../02-framework/01-dao-creation/index.md | 2 +- .../01-plugin-repo/index.md | 6 +++--- .../01-security-risk-mitigation.md | 2 +- .../02-plugin-setup/index.md | 12 ++++++------ .../02-framework/02-plugin-management/index.md | 2 +- .../01-how-it-works/02-framework/index.md | 3 ++- .../01-how-it-works/_category_.yml | 2 ++ .../developer-portal/01-how-it-works/index.md | 2 +- .../02-how-to-guides/01-dao/index.md | 1 + .../02-plugin-development/02-plugin-types.md | 10 +++++----- .../02-implementation.md | 2 +- .../03-non-upgradeable-plugin/03-setup.md | 4 ++-- .../03-non-upgradeable-plugin/index.md | 6 +++--- .../04-upgradeable-plugin/03-setup.md | 4 ++-- .../04-subsequent-builds.md | 4 ++-- .../05-updating-versions.md | 8 ++++---- .../04-upgradeable-plugin/index.md | 2 +- .../07-publication/02-metadata.md | 4 ++-- .../02-plugin-development/index.md | 3 ++- .../02-how-to-guides/_category_.yml | 2 ++ .../developer-portal/02-how-to-guides/index.md | 7 ++++--- .../04-framework-lifecycle/02-semver.md | 12 ++++++------ .../03-osx-components/07-plugin-setup.md | 4 ++-- .../02-contract-initialization.md | 4 ++-- .../contracts/docs/developer-portal/index.md | 2 +- .../docs/img/docs/Aragon_DAO_Diagram.png | Bin 0 -> 298086 bytes .../aragon-os-framework-overview.drawio.svg | 0 ...-os-infrastructure-core-overview.drawio.svg | 0 .../docs}/aragon-osx.svg | 0 .../img/docs/create_plugin_etherscan_tx.png | Bin 0 -> 830805 bytes .../01-core => img/docs}/dao-plugin.drawio.svg | 0 .../docs}/plugin-installation.drawio.svg | 0 .../docs}/plugin-repo-overview.drawio.svg | 0 .../docs}/plugin-uninstallation.drawio.svg | 0 .../docs}/plugin-update.drawio.svg | 0 .../docs}/plugin-version.drawio.svg | 0 .../docs/img/docs/what_is_a_plugin.png | Bin 0 -> 649599 bytes 40 files changed, 75 insertions(+), 56 deletions(-) create mode 100644 packages/contracts/docs/developer-portal/01-get-started.mdx create mode 100644 packages/contracts/docs/developer-portal/01-how-it-works/_category_.yml create mode 100644 packages/contracts/docs/developer-portal/02-how-to-guides/_category_.yml create mode 100644 packages/contracts/docs/img/docs/Aragon_DAO_Diagram.png rename packages/contracts/docs/{developer-portal/01-how-it-works => img/docs}/aragon-os-framework-overview.drawio.svg (100%) rename packages/contracts/docs/{developer-portal/01-how-it-works/02-framework => img/docs}/aragon-os-infrastructure-core-overview.drawio.svg (100%) rename packages/contracts/docs/{developer-portal/04-framework-lifecycle => img/docs}/aragon-osx.svg (100%) create mode 100644 packages/contracts/docs/img/docs/create_plugin_etherscan_tx.png rename packages/contracts/docs/{developer-portal/01-how-it-works/01-core => img/docs}/dao-plugin.drawio.svg (100%) rename packages/contracts/docs/{developer-portal/01-how-it-works/02-framework/02-plugin-management/02-plugin-setup => img/docs}/plugin-installation.drawio.svg (100%) rename packages/contracts/docs/{developer-portal/01-how-it-works/02-framework/02-plugin-management/01-plugin-repo => img/docs}/plugin-repo-overview.drawio.svg (100%) rename packages/contracts/docs/{developer-portal/01-how-it-works/02-framework/02-plugin-management/02-plugin-setup => img/docs}/plugin-uninstallation.drawio.svg (100%) rename packages/contracts/docs/{developer-portal/01-how-it-works/02-framework/02-plugin-management/02-plugin-setup => img/docs}/plugin-update.drawio.svg (100%) rename packages/contracts/docs/{developer-portal/01-how-it-works/02-framework/02-plugin-management => img/docs}/plugin-version.drawio.svg (100%) create mode 100644 packages/contracts/docs/img/docs/what_is_a_plugin.png diff --git a/packages/contracts/docs/developer-portal/01-get-started.mdx b/packages/contracts/docs/developer-portal/01-get-started.mdx new file mode 100644 index 000000000..f77160cfd --- /dev/null +++ b/packages/contracts/docs/developer-portal/01-get-started.mdx @@ -0,0 +1,10 @@ +--- +title: '' +sidebar_label: Get Started +sidebar_position: 1 +hide_table_of_contents: true +--- + +import GetStarted from '/src/pages/get-started.tsx'; + + diff --git a/packages/contracts/docs/developer-portal/01-how-it-works/01-core/03-plugins/index.md b/packages/contracts/docs/developer-portal/01-how-it-works/01-core/03-plugins/index.md index cfeadcd12..bf1a98ae4 100644 --- a/packages/contracts/docs/developer-portal/01-how-it-works/01-core/03-plugins/index.md +++ b/packages/contracts/docs/developer-portal/01-how-it-works/01-core/03-plugins/index.md @@ -24,7 +24,7 @@ Whenever a DAO installs a plugin, an instance of that plugin's base template is Each instance of a plugin is installed to a DAO through the granting of permissions. :::info -Lern more about the different [plugin types](../../../02-how-to-guides/02-plugin-development/02-plugin-types.md) in our How-to guide. +Learn more about the different [plugin types](../../../02-how-to-guides/02-plugin-development/02-plugin-types.md) in our How-to guide. ::: This raises questions on how the DAO manages plugins and who actually owns plugins. @@ -39,10 +39,10 @@ A DAO manages plugins and interactions between them. In more detail, its permiss
-![Schematic depiction of the interaction between the DAO, the PermissionManager, and a Plugin contract.](../dao-plugin.drawio.svg) +![Schematic depiction of the interaction between the DAO, the PermissionManager, and a Plugin contract.](/img/docs/optimized-svg/dao-plugin.drawio.svg)

- An examplary DAO setup showing interactions between the three core contract pieces triggered by different user groups: The DAO contract in blue containing the PermissionManager in red, respectively, as well as two Plugin contracts in green. + An exemplary DAO setup showing interactions between the three core contract pieces triggered by different user groups: The DAO contract in blue containing the PermissionManager in red, respectively, as well as two Plugin contracts in green. Function calls are visualized as black arrows and require permission checks (red, dashed arrow). In this example, the permission manager determines whether the token voting plugin can execute actions on the DAO, a member can change its settings, or if a DeFi-related plugin is allowed to invest in a certain, external contract.

diff --git a/packages/contracts/docs/developer-portal/01-how-it-works/01-core/index.md b/packages/contracts/docs/developer-portal/01-how-it-works/01-core/index.md index e5d42bef8..a1521cc3a 100644 --- a/packages/contracts/docs/developer-portal/01-how-it-works/01-core/index.md +++ b/packages/contracts/docs/developer-portal/01-how-it-works/01-core/index.md @@ -1,5 +1,6 @@ --- title: The Smart Contracts behind DAOs +sidebar_label: Smart Contracts --- ## The Contracts Constituting Your DAO @@ -28,10 +29,10 @@ The underlying smart contracts constitute **the core contracts** of the Aragon O
-![Schematic depiction of the interaction between the DAO, the PermissionManager, and a Plugin contract.](dao-plugin.drawio.svg) +![Schematic depiction of the interaction between the DAO, the PermissionManager, and a Plugin contract.](/img/docs/optimized-svg/dao-plugin.drawio.svg)

- An examplary DAO setup showing interactions between the three core contract pieces triggered by different user groups: The DAO contract in blue containing the PermissionManager in red, respectively, as well as two Plugin contracts in green. + An exemplary DAO setup showing interactions between the three core contract pieces triggered by different user groups: The DAO contract in blue containing the PermissionManager in red, respectively, as well as two Plugin contracts in green. Function calls are visualized as black arrows and require permission checks (red, dashed arrow). In this example, the permission manager determines whether the token voting plugin can execute actions on the DAO, a member can change its settings, or if a DeFi-related plugin is allowed to invest in a certain, external contract.

diff --git a/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/01-dao-creation/index.md b/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/01-dao-creation/index.md index 8fcbb41d6..32f8dbd6d 100644 --- a/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/01-dao-creation/index.md +++ b/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/01-dao-creation/index.md @@ -24,7 +24,7 @@ as well as an array of `PluginSettings` containing `PluginSetup` contract refere The `DAOFactory` create the `DAO` in four steps and interacts with the `DAORegistry` and being also part of the Aragon OSx framework: -1. Creates a new DAO by deploying an [ERC-1967](https://eips.ethereum.org/EIPS/eip-1967) proxy pointing to the latest Aragon OSx `DAO` impelementation and becomes the initial owner. +1. Creates a new DAO by deploying an [ERC-1967](https://eips.ethereum.org/EIPS/eip-1967) proxy pointing to the latest Aragon OSx `DAO` implementation and becomes the initial owner. 2. Registers the new contract in the [`DAORegistry`](#daoregistry). diff --git a/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/02-plugin-management/01-plugin-repo/index.md b/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/02-plugin-management/01-plugin-repo/index.md index fd58973eb..105b90a3f 100644 --- a/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/02-plugin-management/01-plugin-repo/index.md +++ b/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/02-plugin-management/01-plugin-repo/index.md @@ -4,7 +4,7 @@ title: Plugin Repositories ## What are Plugin Repositories? -Each plugin has its own Plugin Repository, unique ENS name, and on-chain repository contract, the `PluginRepo`, in which different versions of the plugin are stored for reference using verstion tags constituted by a **release** and **build** number. +Each plugin has its own Plugin Repository, unique ENS name, and on-chain repository contract, the `PluginRepo`, in which different versions of the plugin are stored for reference using version tags constituted by a **release** and **build** number. Different versions might contain: @@ -16,10 +16,10 @@ Different versions might contain:
-![Schematic depiction of the versioning taking place in the PluginRepoRegistry.](./plugin-repo-overview.drawio.svg) +![Schematic depiction of the versioning taking place in the PluginRepoRegistry.](/img/docs/optimized-svg/plugin-repo-overview.drawio.svg)

- Overview of the plugin versioning and registry in the Aragon OSx protocol. The `PluginRepoRegistry` contract, which is a curated list of ENS named `PluginRepo` contracts, is shown on the left. Each `PluginRepo` contract maintains a list of versions of the `PluginSetup` contract (internally referencing the `Plugin` implementation contract) and the associated UI building blocks as a URI, examplarily shown on the right. + Overview of the plugin versioning and registry in the Aragon OSx protocol. The `PluginRepoRegistry` contract, which is a curated list of ENS named `PluginRepo` contracts, is shown on the left. Each `PluginRepo` contract maintains a list of versions of the `PluginSetup` contract (internally referencing the `Plugin` implementation contract) and the associated UI building blocks as a URI, exemplarily shown on the right.

diff --git a/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/02-plugin-management/02-plugin-setup/01-security-risk-mitigation.md b/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/02-plugin-management/02-plugin-setup/01-security-risk-mitigation.md index 33015ebe9..1b3433eeb 100644 --- a/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/02-plugin-management/02-plugin-setup/01-security-risk-mitigation.md +++ b/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/02-plugin-management/02-plugin-setup/01-security-risk-mitigation.md @@ -22,7 +22,7 @@ that might be carelessly or intentionally caused, a malicious plugin can hide ** #### Backdoors -- [metamorpic contracts](https://a16zcrypto.com/metamorphic-smart-contract-detector-tool/) (contracts, that can be redeployed with new code to the same address) +- [metamorphic contracts](https://a16zcrypto.com/metamorphic-smart-contract-detector-tool/) (contracts, that can be redeployed with new code to the same address) - malicious repurposing of storage in an update of an upgradeable plugin contract diff --git a/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/02-plugin-management/02-plugin-setup/index.md b/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/02-plugin-management/02-plugin-setup/index.md index 330b81fa3..06942f7e9 100644 --- a/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/02-plugin-management/02-plugin-setup/index.md +++ b/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/02-plugin-management/02-plugin-setup/index.md @@ -9,13 +9,13 @@ A DAO can be set up and customized by the **installation, update, and uninstalla - **Plugin contract:** contains the plugin's implementation logic; everything needed to extend the functionality for DAOs. - **Plugin Setup contract:** contains the instructions needed to install, update, and uninstall the plugin into the DAO. This is done through granting or revoking permissions, enabling plugins to perform actions within the scope of the DAO. -![Aragon OSx Plugins](https://res.cloudinary.com/dacofvu8m/image/upload/v1683225098/Screen_Shot_2023-05-04_at_14.31.25_r0qqut.png) +![Aragon OSx Plugins](/img/docs/what_is_a_plugin.png) How this works: - Although a Plugin is composed by the `Plugin` and `PluginSetup` contracts, the Aragon OSx protocol only knows of the `PluginSetup` contract. - Since the `PluginSetup` contract is the one containing the plugin installation instructions, it is the one in charge of deploying the Plugin instance. Each plugin instance is specific to that DAO, deployed with its own unique parameters. You can review how to build a `PluginSetup` contract [here](../../../../02-how-to-guides/02-plugin-development/index.md). -- The `PluginSetup` contract then interacts with the Aragon OSx framework's `PluginSetupProcessor` contract, which is in charge of applying the installion, update, or uninstallation of a plugin into a DAO. +- The `PluginSetup` contract then interacts with the Aragon OSx framework's `PluginSetupProcessor` contract, which is in charge of applying the installation, update, or uninstallation of a plugin into a DAO. - Publishing a Plugin into the Aragon OSx protocol is done through creating the first version of the plugin's `PluginRepo`. The plugin's `PluginRepo` instance stores all plugin versions. You can read more about that [here](../../../../02-how-to-guides/02-plugin-development/07-publication/index.md). - Except for the gas costs required, plugins are completely free to install, unless decided otherwise by the developer. @@ -44,7 +44,7 @@ The preparation of a `PluginSetup` contract proceeds as follows: - deployment of new contracts - initialization of new storage variables - - deprecating/decomissioning outdated (helper) contracts + - deprecating/decommissioning outdated (helper) contracts - governance settings or other attributes - ... @@ -87,9 +87,9 @@ In the next sections, you will learn about how plugins are curated on Aragon's r
-**a.** ![Schematic depiction of the plugin installation process.](plugin-installation.drawio.svg) -**b.** ![Schematic depiction of the plugin update process.](plugin-update.drawio.svg) -**c.** ![Schematic depiction of the plugin uninstallation process.](plugin-uninstallation.drawio.svg) +**a.** ![Schematic depiction of the plugin installation process.](/img/docs/optimized-svg/plugin-installation.drawio.svg) +**b.** ![Schematic depiction of the plugin update process.](/img/docs/optimized-svg/plugin-update.drawio.svg) +**c.** ![Schematic depiction of the plugin uninstallation process.](/img/docs/optimized-svg/plugin-uninstallation.drawio.svg)

Simplified overview of the two-transaction plugin a. installation, b. update, and c. uninstallation process with the involved contracts as rounded rectangles, interactions between them as arrows, and relations as dashed lines. The first and second transaction are distinguished by numbering as well as solid and dotted lines, respectively. diff --git a/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/02-plugin-management/index.md b/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/02-plugin-management/index.md index e26b10cc2..89877867e 100644 --- a/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/02-plugin-management/index.md +++ b/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/02-plugin-management/index.md @@ -40,7 +40,7 @@ A detailed explanation of the [build and release versioning](../../../02-how-to-

-![](./plugin-version.drawio.svg) +![](/img/docs/optimized-svg/plugin-version.drawio.svg)

A schematic depiction of a plugin bundle consisting of a version tag, the plugin setup contract pointing to the plugin implementation contract, and a metadata URI. diff --git a/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/index.md b/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/index.md index adc424a25..af9a390dd 100644 --- a/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/index.md +++ b/packages/contracts/docs/developer-portal/01-how-it-works/02-framework/index.md @@ -1,5 +1,6 @@ --- title: Framework - How Everything Connects +sidebar_label: Framework --- ## The Infrastructure Running the Aragon OSx Protocol @@ -18,7 +19,7 @@ An overview of the involved contracts and their interactions is shown below:

-![](aragon-os-infrastructure-core-overview.drawio.svg) +![](/img/docs/optimized-svg/aragon-os-infrastructure-core-overview.drawio.svg)

Overview of the framework and core contracts of the Aragon OSx protocol. diff --git a/packages/contracts/docs/developer-portal/01-how-it-works/_category_.yml b/packages/contracts/docs/developer-portal/01-how-it-works/_category_.yml new file mode 100644 index 000000000..93cea945b --- /dev/null +++ b/packages/contracts/docs/developer-portal/01-how-it-works/_category_.yml @@ -0,0 +1,2 @@ +collapsible: true +collapsed: false diff --git a/packages/contracts/docs/developer-portal/01-how-it-works/index.md b/packages/contracts/docs/developer-portal/01-how-it-works/index.md index edd79c1c9..89a97577d 100644 --- a/packages/contracts/docs/developer-portal/01-how-it-works/index.md +++ b/packages/contracts/docs/developer-portal/01-how-it-works/index.md @@ -7,7 +7,7 @@ title: How It Works The Aragon OSx protocol is a DAO framework structured as follows:

- Aragon architecture diagram + ![](/img/docs/optimized-svg/aragon-os-framework-overview.drawio.svg)

Overview of the Aragon OSx protocol with its structural components and their responsibilities: the governance layer constituted by the framework DAO, the code layer including the framework and core contracts, which depends on external libraries and services

diff --git a/packages/contracts/docs/developer-portal/02-how-to-guides/01-dao/index.md b/packages/contracts/docs/developer-portal/02-how-to-guides/01-dao/index.md index e50ec1097..0fbbbaac4 100644 --- a/packages/contracts/docs/developer-portal/02-how-to-guides/01-dao/index.md +++ b/packages/contracts/docs/developer-portal/02-how-to-guides/01-dao/index.md @@ -1,5 +1,6 @@ --- title: How to Operate a DAO +sidebar_title: Operating a DAO --- DAOs are decentralized autonomous organizations. They are a group of people managing on-chain assets through a set of smart contracts. diff --git a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/02-plugin-types.md b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/02-plugin-types.md index eb2d31915..86cd6d8ef 100644 --- a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/02-plugin-types.md +++ b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/02-plugin-types.md @@ -49,11 +49,11 @@ Some key things to keep in mind: The following table compares the different deployment methods with their benefits and drawbacks: -| | `new` Instantiation | Minimal Proxy (Clones) | Transparent Proxy | UUPS Proxy | -| ------------- | --------------------------------------------- | ------------------------------------------------- | ------------------------------------------------ | --------------------------------------------- | -| upgradability | no | no | yes | yes | -| gas costs | high | very low | moderate | low | -| difficulty | low | low | high | high | +| | `new` Instantiation | Minimal Proxy (Clones) | Transparent Proxy | UUPS Proxy | +| -------------- | --------------------------------------------- | ------------------------------------------------- | ------------------------------------------------ | --------------------------------------------- | +| upgradeability | no | no | yes | yes | +| gas costs | high | very low | moderate | low | +| difficulty | low | low | high | high | Accordingly, we recommend to use [minimal proxies (ERC-1167)](https://eips.ethereum.org/EIPS/eip-1167) for non-upgradeable and [UUPS proxies (1822)](https://eips.ethereum.org/EIPS/eip-1822) for upgradeable plugin. To help you with developing and deploying your plugin within the Aragon infrastructure, we provide the following implementation that you can inherit from: diff --git a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/03-non-upgradeable-plugin/02-implementation.md b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/03-non-upgradeable-plugin/02-implementation.md index d0b8af771..f8444bd13 100644 --- a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/03-non-upgradeable-plugin/02-implementation.md +++ b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/03-non-upgradeable-plugin/02-implementation.md @@ -42,7 +42,7 @@ Setting this permission is key because it ensures only signers who have been gra Now that we have created the permission, we will use it to protect the implementation. We want to make sure only the authorized callers holding the `ADMIN_EXECUTE_PERMISSION`, can use the function. -Because we have initialized the [`PluginClonable` base contract](https://github.com/aragon/osx-commons/blob/develop/contracts/src/plugin/PluginCloneable.sol), we can now use its features, i.e., the [`auth` modifier](https://github.com/aragon/osx-commons/blob/1cf46ff15dbda8481f9ee37558e7ea8b257d51f2/contracts/src/permission/auth/DaoAuthorizable.sol#L30-L35) provided through the `DaoAuthorizable` base class. The `auth('ADMIN_EXECUTE_PERMISSION')` returns an error if the address calling on the function has not been granted that permission, effectively protecting from malicious use cases. +Because we have initialized the [`PluginCloneable` base contract](https://github.com/aragon/osx-commons/blob/develop/contracts/src/plugin/PluginCloneable.sol), we can now use its features, i.e., the [`auth` modifier](https://github.com/aragon/osx-commons/blob/1cf46ff15dbda8481f9ee37558e7ea8b257d51f2/contracts/src/permission/auth/DaoAuthorizable.sol#L30-L35) provided through the `DaoAuthorizable` base class. The `auth('ADMIN_EXECUTE_PERMISSION')` returns an error if the address calling on the function has not been granted that permission, effectively protecting from malicious use cases. Later, we will also use the [`dao()` getter function from the base contract](https://github.com/aragon/osx-commons/blob/1cf46ff15dbda8481f9ee37558e7ea8b257d51f2/contracts/src/permission/auth/DaoAuthorizable.sol#L24-L28), which returns the associated DAO for that plugin. diff --git a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/03-non-upgradeable-plugin/03-setup.md b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/03-non-upgradeable-plugin/03-setup.md index 12e45a026..33940074a 100644 --- a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/03-non-upgradeable-plugin/03-setup.md +++ b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/03-non-upgradeable-plugin/03-setup.md @@ -6,7 +6,7 @@ title: Plugin Setup Contract The Plugin Setup contract is the contract defining the instructions for installing, uninstalling, or upgrading plugins into DAOs. This contract prepares the permission granting or revoking that needs to happen in order for plugins to be able to perform actions on behalf of the DAO. -You need it for the plugin to be installed intto the DAO. +You need it for the plugin to be installed into the DAO. ### 1. Finish the Plugin contract @@ -116,7 +116,7 @@ The `prepareInstallation()` function should take in two parameters: 1. the `DAO` it prepares the installation for, and 2. the `_data` parameter containing all the information needed for this function to work properly, in this case, the address we want to set as admin of our DAO. -Hence, the first thing we should do when working on the `prepareInsallation()` function is decode the information from the `_data` parameter. We also want to check that the address is not accidentally set to `address(0)`, which would freeze the DAO forever. +Hence, the first thing we should do when working on the `prepareInstallation()` function is decode the information from the `_data` parameter. We also want to check that the address is not accidentally set to `address(0)`, which would freeze the DAO forever. ```solidity import {Clones} from '@openzeppelin/contracts/proxy/Clones.sol'; diff --git a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/03-non-upgradeable-plugin/index.md b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/03-non-upgradeable-plugin/index.md index bf7da1984..cc88477f3 100644 --- a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/03-non-upgradeable-plugin/index.md +++ b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/03-non-upgradeable-plugin/index.md @@ -14,7 +14,7 @@ Some observations: Before moving on with the Guide, make sure you've read our documentation on [Choosing the Best Type for Your Plugin](../02-plugin-types.md) to make sure you're selecting the right type of contract for your Plugin. -## Building a Non-Upgradeble Plugin +## Building a Non-Upgradable Plugin We will build a plugin which returns "Hello world!" and the amount of times the function has been called. @@ -43,7 +43,7 @@ sudo apt-get install -y nodejs [Here's a tutorial](https://hardhat.org/tutorial/setting-up-the-environment) on installing this if you haven't done so already. -2. Next up, we want to create a Hardhat project in our terminal. This is the Solidity framework we'll use to get our project up and runing. +2. Next up, we want to create a Hardhat project in our terminal. This is the Solidity framework we'll use to get our project up and running. ```bash npm init @@ -275,7 +275,7 @@ You can publish the plugin into Aragon's protocol through a few different ways: Go to the [`PluginFactory`](https://goerli.etherscan.io/address/0x301868712b77744A3C0E5511609238399f0A2d4d#writeContract) contract on Etherscan and deploy the first version of your plugin. -![Register your Plugin through Etherscan](https://res.cloudinary.com/dacofvu8m/image/upload/v1682466427/Screen_Shot_2023-04-25_at_19.46.58_nlo9p1.png) +![Register your Plugin through Etherscan](/img/docs/create_plugin_etherscan.png) #### b) Publishing script diff --git a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/04-upgradeable-plugin/03-setup.md b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/04-upgradeable-plugin/03-setup.md index 4f3fc186e..00956436e 100644 --- a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/04-upgradeable-plugin/03-setup.md +++ b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/04-upgradeable-plugin/03-setup.md @@ -47,7 +47,7 @@ The `prepareInstallation()` function takes in two parameters: 1. the `DAO` it should prepare the installation for, and 2. the `_data` parameter containing all the information needed for this function to work properly, encoded as a `bytes memory`. In this case, we get the number we want to store. -Hence, the first thing we should do when working on the `prepareInsallation()` function is decode the information from the `_data` parameter. +Hence, the first thing we should do when working on the `prepareInstallation()` function is decode the information from the `_data` parameter. Similarly, the `prepareUninstallation()` function takes in a `payload`. ```solidity @@ -131,7 +131,7 @@ Firstly, we'll make sure our preferred network is well setup within our `hardhat ```js import '@nomicfoundation/hardhat-toolbox'; -// To find your Alchemy key, go to https://dashboard.alchemy.com/. Infure or any other provider would work here as well. +// To find your Alchemy key, go to https://dashboard.alchemy.com/. Infura or any other provider would work here as well. const goerliAlchemyKey = 'add-your-own-alchemy-key'; // To find a private key, go to your wallet of choice and export a private key. Remember this must be kept secret at all times. const privateKeyGoerli = 'add-your-account-private-key'; diff --git a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/04-upgradeable-plugin/04-subsequent-builds.md b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/04-upgradeable-plugin/04-subsequent-builds.md index bd2d9bcd8..3568eaaa2 100644 --- a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/04-upgradeable-plugin/04-subsequent-builds.md +++ b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/04-upgradeable-plugin/04-subsequent-builds.md @@ -21,7 +21,7 @@ Make sure you have at least one build already deployed and published into the Ar In this second build implementation we want to update the functionality of our plugin - in this case, we want to update the storage of our plugin with new values. Specifically, we will add a second storage variable `address public account;`. Additional to the `initializeFromBuild2` function, we also want to add a second setter function `storeAccount` that uses the same permission as `storeNumber`. -As you can see, we're still inheritting from the `PluginUUPSUpgradeable` contract and simply overriding some implementation from the previous build. The idea is that when someone upgrades the plugin and calls on these functions, they'll use this new upgraded implementation, rather than the older one. +As you can see, we're still inheriting from the `PluginUUPSUpgradeable` contract and simply overriding some implementation from the previous build. The idea is that when someone upgrades the plugin and calls on these functions, they'll use this new upgraded implementation, rather than the older one. ```solidity import {PluginUUPSUpgradeable, IDAO} '@aragon/osx/core/plugin/PluginUUPSUpgradeable.sol'; @@ -60,7 +60,7 @@ contract SimpleStorageBuild2 is PluginUUPSUpgradeable { } ``` -Builds that you publish don't necessarily need to introduce new storage varaibles of your contracts and don't necessarily need to change the storage. To read more about Upgradeability, check out [OpenZeppelin's UUPSUpgradeability implementation here](https://docs.openzeppelin.com/contracts/4.x/api/proxy#UUPSUpgradeable). +Builds that you publish don't necessarily need to introduce new storage variables of your contracts and don't necessarily need to change the storage. To read more about Upgradeability, check out [OpenZeppelin's UUPSUpgradeability implementation here](https://docs.openzeppelin.com/contracts/4.x/api/proxy#UUPSUpgradeable). :::note Note that because these contracts are Upgradeable, keeping storage gaps `uint256 [50] __gap;` in dependencies is a must in order to avoid storage corruption. To learn more about storage gaps, review OpenZeppelin's documentation [here](https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#storage-gaps). diff --git a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/04-upgradeable-plugin/05-updating-versions.md b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/04-upgradeable-plugin/05-updating-versions.md index e10e3b44b..c21935e69 100644 --- a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/04-upgradeable-plugin/05-updating-versions.md +++ b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/04-upgradeable-plugin/05-updating-versions.md @@ -146,7 +146,7 @@ contract SimpleStorageBuild2Setup is PluginSetup { } ``` -The key thing to review in this new Plugin Setup contract is its `prepareUpdate()` function. The function only contains a condition checking from which build number the update is transitioning to build `2`. Here, it is the build number `1` as this is the only update path we support. Inside, we decode the `address _account` input argument provided with `bytes _date` and pass it to the `initializeFromBuild1` function taking care of intializing the storage that was added in this build. +The key thing to review in this new Plugin Setup contract is its `prepareUpdate()` function. The function only contains a condition checking from which build number the update is transitioning to build `2`. Here, it is the build number `1` as this is the only update path we support. Inside, we decode the `address _account` input argument provided with `bytes _date` and pass it to the `initializeFromBuild1` function taking care of initializing the storage that was added in this build. ### 3. Future builds @@ -226,7 +226,7 @@ contract SimpleStorageBuild3 is PluginUUPSUpgradeable { -With each new build implementation, we will need to udate the Plugin Setup contract to be able to update to that new version. We do this through updating the `prepareUpdate()` function to support any new features that need to be set up. +With each new build implementation, we will need to update the Plugin Setup contract to be able to update to that new version. We do this through updating the `prepareUpdate()` function to support any new features that need to be set up.
Third plugin setup example, modifying prepareUpdate function @@ -353,8 +353,8 @@ contract SimpleStorageBuild3Setup is PluginSetup { In this case, the `prepareUpdate()` function only contains a condition checking from which build number the update is transitioning to build 2. Here, we can update from build 0 or build 1 and different operations must happen for each case to transition to `SimpleAdminBuild3`. -In the first case, `initializeFromBuild1` is called taking care of intializing `address _account` that was added in build 1 and emitting the events added in build 2. +In the first case, `initializeFromBuild1` is called taking care of initializing `address _account` that was added in build 1 and emitting the events added in build 2. -In the second case, `initializeFromBuild2` is called taking care of intializing the build. Here, only the two events will be emitted. +In the second case, `initializeFromBuild2` is called taking care of initializing the build. Here, only the two events will be emitted. Lastly, the `prepareUpdate()` function takes care of modifying the permissions by revoking the `STORE_PERMISSION_ID` and granting the more specific `STORE_NUMBER_PERMISSION_ID` and `STORE_ACCOUNT)PERMISSION_ID` permissions, that are also granted if build 2 is freshly installed. This must happen for both update paths so this code is outside the `if` statements. diff --git a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/04-upgradeable-plugin/index.md b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/04-upgradeable-plugin/index.md index 37ca2ad33..7c8ba89d2 100644 --- a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/04-upgradeable-plugin/index.md +++ b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/04-upgradeable-plugin/index.md @@ -18,7 +18,7 @@ Although we've abstracted away most of the complications of the upgrade process - You have read about the different [plugin types](../02-plugin-types.md) and decided to develop an upgradeable plugin being deployed via the [UUPS pattern (ERC-1822)](https://eips.ethereum.org/EIPS/eip-1822). - You know how to write a [non-upgradeable plugin](../03-non-upgradeable-plugin/index.md). - You know about the difficulties and pitfalls of ["Writing Upgradeable Contracts"](https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable) that come with - - modifiying the storage layout + - modifying the storage layout - initialization - inheritance - leaving storage gaps diff --git a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/07-publication/02-metadata.md b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/07-publication/02-metadata.md index bfe6d57c1..2c574b79d 100644 --- a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/07-publication/02-metadata.md +++ b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/07-publication/02-metadata.md @@ -67,7 +67,7 @@ Each `"prepare..."` object contains: | description | `string` | The description of what this particular setup step is doing and what it requires the input for. | | inputs | `object[]` | A description of the inputs required for this setup step following the [Solidity JSON ABI](https://docs.ethers.org/v5/api/utils/abi/formats/#abi-formats--solidity) format enriched with an additional `"description"` field for each element. | -By following the Solidity JSON ABI format for the inputs, we followed an establishd standard, have support for complex types (tuples, arrays, nested versions of the prior) and allow for future extensibility (such as the human readable description texts that we have added). +By following the Solidity JSON ABI format for the inputs, we followed an establish standard, have support for complex types (tuples, arrays, nested versions of the prior) and allow for future extensibility (such as the human readable description texts that we have added). #### Example @@ -103,7 +103,7 @@ By following the Solidity JSON ABI format for the inputs, we followed an establi "internalType": "struct Multisig.MultisigSettings", "name": "multisigSettings", "type": "tuple", - "description": "The inital multisig settings." + "description": "The initial multisig settings." } ], "prepareUpdate": { diff --git a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/index.md b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/index.md index 869b37a71..9c474c9bc 100644 --- a/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/index.md +++ b/packages/contracts/docs/developer-portal/02-how-to-guides/02-plugin-development/index.md @@ -1,5 +1,6 @@ --- title: How to build a DAO Plugin +sidebar_title: Developing a Plugin --- ## Plugin Development Quickstart Guide @@ -185,7 +186,7 @@ Lastly, we can call the [`createPluginRepoWithFirstVersion` function from Aragon We can do this directly by calling the function on Etherscan ([make sure to get the right scan and contract address based on your network](https://github.com/aragon/osx-commons/tree/develop/configs/src/deployments/json)) or through locally calling on the method from your project using Ethers. -![Etherscan](https://res.cloudinary.com/dacofvu8m/image/upload/v1682466427/Screen_Shot_2023-04-25_at_19.46.58_nlo9p1.png) +![Etherscan](/img/docs/create_plugin_etherscan.png) If you want to review how to publish your plugin in more depth, review our [How to Publish a Plugin in Aragon OSx guide here](./07-publication//index.md) diff --git a/packages/contracts/docs/developer-portal/02-how-to-guides/_category_.yml b/packages/contracts/docs/developer-portal/02-how-to-guides/_category_.yml new file mode 100644 index 000000000..93cea945b --- /dev/null +++ b/packages/contracts/docs/developer-portal/02-how-to-guides/_category_.yml @@ -0,0 +1,2 @@ +collapsible: true +collapsed: false diff --git a/packages/contracts/docs/developer-portal/02-how-to-guides/index.md b/packages/contracts/docs/developer-portal/02-how-to-guides/index.md index 2bf688431..f3ca919f2 100644 --- a/packages/contracts/docs/developer-portal/02-how-to-guides/index.md +++ b/packages/contracts/docs/developer-portal/02-how-to-guides/index.md @@ -1,5 +1,6 @@ --- -title: How-to Guides +title: Tutorials +sidebar_label: Tutorials --- ## Welcome to our How To Guides on Using the Aragon OSx Protocol! @@ -30,14 +31,14 @@ Technically speaking, Aragon DAOs are: All other functionality is enabled through plugins. This allows DAOs to be extremely flexible and modular as they mature, through installing and uninstalling these plugins as needs arise. -![Aragon DAO](https://res.cloudinary.com/dacofvu8m/image/upload/v1683224604/Screen_Shot_2023-05-04_at_14.21.52_uuogzr.png) +![Aragon DAO](/img/docs/Aragon_DAO_Diagram.png) On the technical level, plugins are composed of two key contracts: - ⚑️ The Plugin implementation contract: containing all of the logic and functionality for your DAO, and - πŸ‘©πŸ»β€πŸ« The Plugin Setup contract: containing the installation, uninstallation and upgrade instructions for your plugin. -![Aragon OSx Plugins](https://res.cloudinary.com/dacofvu8m/image/upload/v1683225098/Screen_Shot_2023-05-04_at_14.31.25_r0qqut.png) +![Aragon OSx Plugins](/img/docs/what_is_a_plugin.png) Through plugins, we provide a secure, flexible way for on-chain organizations to iterate as they grow. diff --git a/packages/contracts/docs/developer-portal/04-framework-lifecycle/02-semver.md b/packages/contracts/docs/developer-portal/04-framework-lifecycle/02-semver.md index 7f549bca7..49135f3a0 100644 --- a/packages/contracts/docs/developer-portal/04-framework-lifecycle/02-semver.md +++ b/packages/contracts/docs/developer-portal/04-framework-lifecycle/02-semver.md @@ -38,7 +38,7 @@ We now classify [smart contract changes](01-systems.md#smart-contracts) accordin ### Storage - Addition - Be aware that public constatns/immutables affect the `interfaceId`. + Be aware that public constants/immutables affect the `interfaceId`. Implementation - **IF** contract is **NOT** upgradeable @@ -108,7 +108,7 @@ See the [OpenZeppelin article on multiple inheritance](https://docs.openzeppelin - Change - Body - A change to a function body can change the behaviour of the function requiring dependent contracts or software systems to change + A change to a function body can change the behavior of the function requiring dependent contracts or software systems to change - **IF** used by SDK @@ -117,17 +117,17 @@ See the [OpenZeppelin article on multiple inheritance](https://docs.openzeppelin - **IF** used by App - [ ] adapt App - Behavioural changes that can be **major** / breaking + Behavioral changes that can be **major** / breaking - additional checks that result in external contracts reverting - making different internal or external calls - different execution or storing logic - Behavioural changes that can be **minor** + Behavioral changes that can be **minor** - storing new values - Non-behavioural changes that classify as **patch** + Non-behavioral changes that classify as **patch** - gas optimizations @@ -212,7 +212,7 @@ Inheriting contracts or depending software systems must adapt. Logic using the constants / immutable variables must be adapted -Be aware that public constatns/immutables change the `interfaceId`. +Be aware that public constants/immutables change the `interfaceId`. ### Compiler Version diff --git a/packages/contracts/docs/developer-portal/04-framework-lifecycle/03-osx-components/07-plugin-setup.md b/packages/contracts/docs/developer-portal/04-framework-lifecycle/03-osx-components/07-plugin-setup.md index f5059cc71..1581239fd 100644 --- a/packages/contracts/docs/developer-portal/04-framework-lifecycle/03-osx-components/07-plugin-setup.md +++ b/packages/contracts/docs/developer-portal/04-framework-lifecycle/03-osx-components/07-plugin-setup.md @@ -58,7 +58,7 @@ Conduct all necessary actions to prepare the installation of a plugin. ## Implement `prepareUninstallation` -Conduct all necessary actions to prepare the uninstallation of a plugin and to decomission it. +Conduct all necessary actions to prepare the uninstallation of a plugin and to decommission it. - decode `_payload._data` if required @@ -76,7 +76,7 @@ Conduct all necessary actions to prepare the uninstallation of a plugin and to d over from the `_currentBuild` to the new build by - - deploying / decomissioning helpers return the addresses of the prevailing ones via the `preparedSetupData.helpers` array of addresses. + - deploying / decommissioning helpers return the addresses of the prevailing ones via the `preparedSetupData.helpers` array of addresses. - requesting to grant new / revoke existing permissions and returning them via the `preparedSetupData.permissions` array of permission structs. ## Update Metadata diff --git a/packages/contracts/docs/developer-portal/04-framework-lifecycle/04-sub-processes/02-contract-initialization.md b/packages/contracts/docs/developer-portal/04-framework-lifecycle/04-sub-processes/02-contract-initialization.md index ad82efbc9..12c90b31b 100644 --- a/packages/contracts/docs/developer-portal/04-framework-lifecycle/04-sub-processes/02-contract-initialization.md +++ b/packages/contracts/docs/developer-portal/04-framework-lifecycle/04-sub-processes/02-contract-initialization.md @@ -58,7 +58,7 @@ Accordingly, `v1.2.0` is the 5th version and our `reinitializer()` number is `5` First, change the `reinitializer(5)` and make sure that there is a test for it. -Then do all the initialzation changes and write a note, in which version they have been introduced (for easier traceability). +Then do all the initialization changes and write a note, in which version they have been introduced (for easier traceability). ```solidity function initialize(uint256 calldata _a, address calldata _c) external reinitializer(5) { @@ -89,7 +89,7 @@ function initializeFrom( uint8[3] calldata _previousProtocolVersion, bytes calldata _initData ) external reinitializer(5) { - // Ensure that the previous and current protocol MAJOR version numbers match. If not, revert because the upgrade is incompatible since breaking changes occured. + // Ensure that the previous and current protocol MAJOR version numbers match. If not, revert because the upgrade is incompatible since breaking changes occurred. if (_previousProtocolVersion[0] != protocolVersion()[0]) { revert('Incompatible upgrade'); } diff --git a/packages/contracts/docs/developer-portal/index.md b/packages/contracts/docs/developer-portal/index.md index e3e43afbf..8fb02e364 100644 --- a/packages/contracts/docs/developer-portal/index.md +++ b/packages/contracts/docs/developer-portal/index.md @@ -1,6 +1,6 @@ --- title: Aragon OSx -sidebar_label: Introduction to Aragon OSx +sidebar_label: Introduction sidebar_position: 0 --- diff --git a/packages/contracts/docs/img/docs/Aragon_DAO_Diagram.png b/packages/contracts/docs/img/docs/Aragon_DAO_Diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..0b955cd459f4779a3f2bb0a59f1ab9b25fb5c2f2 GIT binary patch literal 298086 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