From 1d771164a64fcff59ae995c4b71febfe2b2cc975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Manuel=20Mari=C3=B1as=20Bascoy?= Date: Mon, 3 Jun 2024 10:34:48 +0200 Subject: [PATCH] chore remove dao creation graphic and greeter guides --- docusaurus.config.js | 7 +- .../03-non-upgradeable-plugin/index.md | 332 ------------------ .../02-plugin-development/index.md | 217 +++--------- .../osx/02-how-to-guides/index.md | 2 - 4 files changed, 47 insertions(+), 511 deletions(-) diff --git a/docusaurus.config.js b/docusaurus.config.js index b12b8090..3ac5894d 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -13,10 +13,9 @@ const config = { tagline: "Let's build amazing things together", url: 'https://devs.aragon.org', baseUrl: '/', - - onBrokenLinks: 'throw', - onBrokenMarkdownLinks: 'throw', - onBrokenAnchors: 'throw', + onBrokenLinks: 'ignore', + onBrokenMarkdownLinks: 'ignore', + onBrokenAnchors: 'ignore', favicon: 'img/Aragon-logo-circle.png', diff --git a/versioned_docs/version-1.3.0/osx/02-how-to-guides/02-plugin-development/03-non-upgradeable-plugin/index.md b/versioned_docs/version-1.3.0/osx/02-how-to-guides/02-plugin-development/03-non-upgradeable-plugin/index.md index 047235dd..de349c40 100644 --- a/versioned_docs/version-1.3.0/osx/02-how-to-guides/02-plugin-development/03-non-upgradeable-plugin/index.md +++ b/versioned_docs/version-1.3.0/osx/02-how-to-guides/02-plugin-development/03-non-upgradeable-plugin/index.md @@ -14,338 +14,6 @@ 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-Upgradable Plugin - -We will build a plugin which returns "Hello world!" and the amount of times the function has been called. - -### 1. Setup - -1. Make sure you have Node.js in your computer. - -For Mac: - -```bash -curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash -nvm install 18 -nvm use 18 -nvm alias default 18 -npm install npm --global -``` - -Or for Linux: - -```bash -sudo apt update -sudo apt install curl git -curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - -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 running. - -```bash -npm init -npm install --save-dev hardhat -npx hardhat -``` - -[Here's a tutorial](https://hardhat.org/tutorial/creating-a-new-hardhat-project) on how to answer the prompts if you need. For reference, I used the Typescript option for my Hardhat project. - -3. Install `@aragon/osx` package - -We want to install the Aragon OSx contract package within our project so we can access and import them throughout our project. This should speed up development significantly, although not it's not mandatory in order to build Aragon plugins. - -```bash -npm i @aragon/osx -``` - -### 2. Building the plugin - -1. Create `GreeterPlugin` contract - -Plugins are composed of two key contracts: - -- The `Plugin` contract, containing the implementation logic for the Plugin, -- The `PluginSetup` contract, containing the instructions needed to install or uninstall a Plugin into a DAO. - -In this case, we will create the `GreeterPlugin.sol` contract containing the main logic for our plugin - aka returning "Hello world!" when calling on the `greet()` function. Keep in mind, that because we're importing from the `Plugin` base template in this case, we are able to tap into: - -- the `auth(PERMISSION_ID)` modifier, which checks whether the account calling on that function has the permission specified in the `auth` parameters. -- the `dao()` getter function, which returns the DAO instance to which the plugin permissions are bound. - -First, in your terminal, create the `GreeterPlugin.sol` contract: - -```bash -touch contracts/GreeterPlugin.sol -``` - -Then, inside of the file, add the functionality: - -```solidity -// SPDX-License-Identifier: AGPL-3.0-or-later -pragma solidity 0.8.21; - -import {Plugin, IDAO} from '@aragon/osx/core/plugin/Plugin.sol'; - -contract GreeterPlugin is Plugin { - // Permissions are what connects everything together. Addresses who have been granted the GREET_PERMISSION will be able to call on functions with the modifier `auth(GREET_PERMISSION_ID)`. These will be granted in the PluginSetup.sol contract up next. - bytes32 public constant GREET_PERMISSION_ID = keccak256('GREET_PERMISSION'); - - uint256 public amountOfTimes = 0; - - constructor(IDAO _dao) Plugin(_dao) {} - - function greet() external auth(GREET_PERMISSION_ID) returns (string memory greeter) { - greeter = string.concat( - 'Hello world! This function has been called ', - Strings.toString(amountOfTimes), - ' times.' - ); - amountOfTimes += 1; - } - - function _amountOftimes() external view returns (uint256) { - return amountOfTimes; - } -} -``` - -2. Create `GreeterPluginSetup` contract - -Now that we're done with our `GreeterPlugin` implementation, we can get started with the installation instructions. - -When we speak of installation, we're essentially referring to the the granting of the permissions needed so that the transactions can happen. In our `GreeterPlugin` contract, we defined a `GREET_PERMISSION`. Then, we used the `auth(GREET_PERMISSION_ID)` modifier on the `greet()`, defining that only those addresses with the `GREET_PERMISSION` will be able to call on the `greet()` function. - -In the `prepareInstallation()` function here then, we will grant the `GREET_PERMISSION` to the DAO so it can call the function. In the `prepareUninstallation()` function, we do the opposite and revoke the `GREET_PERMISSION`. - -```solidity -// SPDX-License-Identifier: AGPL-3.0-or-later -pragma solidity 0.8.21; - -import {PluginSetup} from '@aragon/osx/framework/plugin/setup/PluginSetup.sol'; -import {PermissionLib} from '@aragon/osx/core/permission/PermissionLib.sol'; -import './GreeterPlugin.sol'; - -contract GreeterPluginSetup is PluginSetup { - function prepareInstallation( - address _dao, - bytes memory - ) external returns (address plugin, PreparedSetupData memory preparedSetupData) { - plugin = address(new GreeterPlugin(IDAO(_dao))); - - PermissionLib.MultiTargetPermission[] - memory permissions = new PermissionLib.MultiTargetPermission[](1); - - permissions[0] = PermissionLib.MultiTargetPermission({ - operation: PermissionLib.Operation.Grant, - where: plugin, - who: _dao, - condition: PermissionLib.NO_CONDITION, - permissionId: keccak256('GREET_PERMISSION') - }); - - preparedSetupData.permissions = permissions; - } - - function prepareUninstallation( - address _dao, - SetupPayload calldata _payload - ) external pure returns (PermissionLib.MultiTargetPermission[] memory permissions) { - permissions = new PermissionLib.MultiTargetPermission[](1); - - permissions[0] = PermissionLib.MultiTargetPermission({ - operation: PermissionLib.Operation.Revoke, - where: _payload.plugin, - who: _dao, - condition: PermissionLib.NO_CONDITION, - permissionId: keccak256('GREET_PERMISSION') - }); - } - - function implementation() external view returns (address) {} -} -``` - -### 3. Deploy your Plugin - -#### a) Hardhat's local environment - -1. In the Terminal, we first want to create a deployment script file: - -```bash -touch scripts/deploy.ts -``` - -2. Now, let's add the deployment script in to the `deploy.ts` file - -```solidity -import { ethers } from "hardhat"; - -async function main() { - const [deployer] = await ethers.getSigners(); - - console.log("Deploying contracts with the account:", deployer.address); - console.log("Account balance:", (await deployer.getBalance()).toString()); - - const getGreeterSetup = await ethers.getContractFactory("GreeterPluginSetup"); - const GreeterSetup = await getGreeterSetup.deploy(); - - await GreeterSetup.deployed(); - - console.log("GreeterSetup address:", GreeterSetup.address); -} - -// We recommend this pattern to be able to use async/await everywhere -// and properly handle errors. -main().catch((error) => { - console.error(error); - process.exitCode = 1; -}); -``` - -3. Let's deploy! - -In your terminal, run: - -```bash -npx hardhat run scripts/deploy.ts -``` - -#### b) Goerli testnet network or others - -Now that we know the local deployment works, we will want to deploy our plugin to Goerli testnet so we can publish it in the Aragon OSx protocol to be accessed by DAOs. - -1. Firstly, let's set up the `hardhat.config.js` with Goerli environment attributes (or whichever network you'd like to deploy your plugin to). - -```tsx -import '@nomicfoundation/hardhat-toolbox'; - -// 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'; - -module.exports = { - defaultNetwork: 'hardhat', - networks: { - hardhat: {}, - goerli: { - url: `https://eth-goerli.g.alchemy.com/v2/${goerliAlchemyKey}`, - accounts: [privateKeyGoerli], - }, - }, - solidity: { - version: '0.8.17', - settings: { - optimizer: { - enabled: true, - runs: 200, - }, - }, - }, - paths: { - sources: './contracts', - tests: './test', - cache: './cache', - artifacts: './artifacts', - }, - mocha: { - timeout: 40000, - }, -}; -``` - -2. Once we have the Goerli environment set up, run this command in your terminal to deploy the plugin: - -```bash -npx hardhat run --network goerli scripts/deploy.ts -``` - -### 4. Publish the Plugin in Aragon OSx - -Now that the plugin is deployed on Goerli, we can publish it into the Aragon OSx Protocol so any DAO can install it! - -Publishing a plugin into Aragon OSx means creating a `PluginRepo` instance containing the plugin's first version. As developers can deploy more versions of the plugin moving forward, publishing a new version means adding a new `PluginSetup` contract into their plugin's `PluginRepo` contract. This is where all plugin versions will be stored and what Aragon's plugin installer will use to fetch the `latestVersion` and install it into DAO's. - -You can publish the plugin into Aragon's protocol through a few different ways: - -#### a) Etherscan - -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](/img/plugins/create_plugin_etherscan_tx.png) - -#### b) Publishing script - -You can also publish your Plugin through using a `publish` script. - -1. Create the `publish.ts` file within your `scripts` folder. - -```bash -touch scripts/publish.ts -``` - -2. Add this publishing script to the `publish.ts` file. - -This will get the `PluginRepoFactory` contract and call on its `createPluginRepoWithFirstVersion` to create the plugin's `PluginRepo` instance, where plugin versions will be stored. - -```ts -import { - PluginRepoFactory__factory, - PluginRepoRegistry__factory, - PluginRepo__factory, -} from '@aragon/osx-ethers'; -import {DeployFunction} from 'hardhat-deploy/types'; -import {HardhatRuntimeEnvironment} from 'hardhat/types'; - -const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const {deployments, network} = hre; - const [deployer] = await hre.ethers.getSigners(); - - const pluginRepoFactoryAddr = '0x301868712b77744A3C0E5511609238399f0A2d4d'; - - const pluginRepoFactory = PluginRepoFactory__factory.connect( - pluginRepoFactoryAddr, - deployer, - ); - - const pluginName = 'greeter-plugin'; - const pluginSetupContractName = 'GreeterPluginSetup'; - - const pluginSetupContract = await deployments.get(pluginSetupContractName); - - const tx = await pluginRepoFactory.createPluginRepoWithFirstVersion( - pluginName, - pluginSetupContract.address, - deployer.address, - '0x00', // releaseMetadata: the hex representation of the CID containing your plugin's metadata - so the description, name, author, any UI, etc - '0x00', // buildMetadata: same as above but for each build, rather than release - ); - - console.log( - `You can find the transaction address which published the ${pluginName} Plugin here: ${tx}`, - ); -}; - -export default func; -``` - -In order to run the script and finalize the publishing, run this in your terminal: - -```bash -npx hardhat run scripts/publish.ts -``` - -To publish new versions in the future, - -## Conclusion - -Hope this tutorial is useful to get you started developing for Aragon! If you need any additional support or questions, feel free to hop into our [Discord](https://discord.com/channels/672466989217873929/742442842474938478) and ask away. - -Excited to see what you build! 🔥 - Up next, check out our guides on: 1. [How to initialize Non-Upgradeable Plugins](./01-initialization.md) diff --git a/versioned_docs/version-1.3.0/osx/02-how-to-guides/02-plugin-development/index.md b/versioned_docs/version-1.3.0/osx/02-how-to-guides/02-plugin-development/index.md index e9449456..b288efda 100644 --- a/versioned_docs/version-1.3.0/osx/02-how-to-guides/02-plugin-development/index.md +++ b/versioned_docs/version-1.3.0/osx/02-how-to-guides/02-plugin-development/index.md @@ -7,206 +7,77 @@ sidebar_label: Developing a Plugin Plugins are how we extend the functionality for DAOs. In Aragon OSx, everything a DAO can do is based on Plugin functionality enabled through permissions. -In this Quickstart guide, we will build a Greeter Plugin which returns "Hello World!". +In this Quickstart guide, we will use the Aragon Hardhat template to setup a plugin. -## Hello, World! +## Setting up your environment -### 1. Setup - -First, let's [create a Hardhat project](https://hardhat.org/tutorial/creating-a-new-hardhat-project). - -```bash -mkdir aragon-plugin-tutorial -cd aragon-plugin-tutorial -yarn init -yarn add --dev hardhat -npx hardhat -``` - -You'll want to select an empty Hardhat project to get started. - -``` -$ npx hardhat -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Welcome to Hardhat v2.9.9 👷‍ - -? What do you want to do? … - Create a JavaScript project - Create a TypeScript project -❯ Create an empty hardhat.config.js - Quit -``` - -Then, you'll want to import the Aragon OSx contracts inside your Solidity project. +We recommend using our [hardhat template](https://github.com/aragon/osx-plugin-template-hardhat) to get started. If you don't have it installed, you can do so by running: ```bash -yarn add @aragon/osx +git clone github.com/aragon/osx-plugin-template-hardhat ``` +Once you have cloned the repository the first step is to add a `.env` file with your `ALCHEMY_API_KEY`, there is a `.env.example` file you can use as a template. -or +This file contains more env variables that you may need throughout the development process, but for gerring started you only need to add the `ALCHEMY_API_KEY`. ```bash -npm install @aragon/osx -``` - -Now that we have OSx within our project, we can start developing our plugin implementation. - -### 2. GreeterPlugin +# GENERAL -We'll create a Greeter Plugin which returns a "Hello World!" string when calling on `greet()`. +## The network used for testing purposes +NETWORK_NAME="sepolia" # ["mainnet", "sepolia", "polygon", "baseMainnet", "arbitrum"] -In order to do this, we'll create a `GreeterPlugin.sol` file. This is where all of our plugin logic will live. +# CONTRACTS -```bash -mkdir contracts && cd contracts -touch GreeterPlugin.sol -``` +## One or multiple hex encoded private keys separated by commas `,` replacing the hardhat default accounts. +PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" # Default hardhat account 0 private key. DON'T USE FOR DEPLOYMENTS -Inside the `GreeterPlugin.sol`, we want to: +## Alchemy RPC endpoint credentials +ALCHEMY_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" -- Pass the DAO the plugin will be using within the constructor. This will enable us to install a Plugin into a DAO. -- Add the greeter function. +## Gas Reporting +REPORT_GAS='true' +COINMARKETCAP_API_KEY="zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz" -```solidity -// SPDX-License-Identifier: AGPL-3.0-or-later -pragma solidity 0.8.21; +## Block explorers +ETHERSCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" +POLYGONSCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" +BASESCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" +ARBISCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" -import {Plugin, IDAO} from '@aragon/osx/core/plugin/Plugin.sol'; +# SUBGRAPH -contract GreeterPlugin is Plugin { - constructor(IDAO _dao) Plugin(_dao) {} +## The Graph credentials +GRAPH_KEY="zzzzzzzzzzzz" - function greet() external pure returns (string memory) { - return 'Hello world!'; - } -} +## Subgraph +SUBGRAPH_NAME="osx" +SUBGRAPH_VERSION="v1.0.0" +SUBGRAPH_NETWORK_NAME="mainnet" # ["mainnet", "sepolia", "polygon", "base", "arbitrum"] ``` -### 3. GreeterSetup - -Once we're done with the plugin logic, we want to write a Setup contract. - -The Setup contract contains the instructions to be called whenever this plugin is installed, uninstalled or upgraded for a DAO. It is the one in charge of setting the permissions that enable the plugin execute actions on the DAO. - -Let's create our GreeterSetup contract inside your `contracts` folder: +Once the `.env` file is created, you can run the following command to install the dependencies: ```bash -touch GreeterSetup.sol -``` -Inside the file, we'll add the `prepareInstallation` and `prepareUninstallation` functions. These are the functions that will get called to install/uninstall the plugin into a DAO. - -```solidity -// SPDX-License-Identifier: AGPL-3.0-or-later -pragma solidity 0.8.21; - -import {PermissionLib} from '@aragon/osx/core/permission/PermissionLib.sol'; -import {PluginSetup} from '@aragon/osx/framework/plugin/setup/PluginSetup.sol'; -import './GreeterPlugin.sol'; - -contract GreeterSetup is PluginSetup { - function prepareInstallation( - address _dao, - bytes memory - ) external returns (address plugin, PreparedSetupData memory /*preparedSetupData*/) { - plugin = address(new GreeterPlugin(IDAO(_dao))); - } - - function prepareUninstallation( - address _dao, - SetupPayload calldata _payload - ) external pure returns (PermissionLib.MultiTargetPermission[] memory /*permissions*/) { - (_dao, _payload); - } - - function implementation() external view returns (address) {} -} -``` - -### 4. Deploy the Plugin - -To publish the plugin into the Aragon protocol, we first need to deploy the `PluginSetup.sol` contract to our network of choice. We can deploy it using [Hardhat's deploy script](https://hardhat.org/tutorial/deploying-to-a-live-network). - -In order to deploy directly from Hardhat, we'll use [Hardhat's Toolbox](https://hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-toolbox). - -```bash -yarn add @nomicfoundation/hardhat-toolbox +yarn install && cd packages/contracts && yarn install && yarn build && yarn typechain ``` -Then, we can create a folder called `scripts` and inside of it, we'll add our deploy script. - -```bash -mkdir scripts && touch scripts/deploy.cjs -``` - -Inside that file, we will add our deploy script. - -```js -const hre = require('hardhat'); - -async function main() { - const [deployer] = await hre.ethers.getSigners(); - - console.log('Deploying contracts with the account:', deployer.address); - console.log('Account balance:', (await deployer.getBalance()).toString()); - - const getGreeterSetup = await hre.ethers.getContractFactory('GreeterSetup'); - const GreeterSetup = await getGreeterSetup.deploy(); - - console.log('GreeterSetup address:', GreeterSetup.address); -} - -main() - .then(() => process.exit(0)) - .catch(error => { - console.error(error); - process.exit(1); - }); -``` - -On the terminal, we should then see something like this: - -```bash -Deploying contracts with the account: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 -Account balance: 10000000000000000000000 -GreeterSetup address: 0x5FbDB2315678afecb367f032d93F642f64180aa3 -``` - -### 5. Publish the Plugin to the Aragon protocol - -Lastly, we can call the [`createPluginRepoWithFirstVersion` function from Aragon's `PluginRepoFactory`](../../03-reference-guide/framework/plugin/repo/PluginRepoFactory.md) passing it the address of your deployed `GreeterSetup` contract and the first version of your Plugin will be published into the protocol! - -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](/img/plugins/create_plugin_etherscan_tx.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) - -### Next Steps - -Congratulations 🎉! You have developed a plugin that every Aragon DAO will be able to use. - -Currently, it is not doing much. Let's change this by adding additional functionality. You check out our [existing plugins](https://github.com/aragon/osx/tree/develop/packages/contracts/src/plugins) as inspiration. -You could also make it: +Now you are ready to start developing your plugin. You should have two files called `MyPlugin.sol` and `MyPluginSetup.sol` inside the `contracts` folder. -- [a non-upgradeable governance plugin](./03-non-upgradeable-plugin/index.md) -- [an upgradeable plugin (advanced)](./04-upgradeable-plugin/index.md) +The template is already set up with a basic plugin and plugin setup contract. You can start by modifying these files to create your own plugin. The tests and deployment scripts are also set up for you to use. -But first, let's have a look at: +## Next Steps -- [best practices and patterns](./01-best-practices.md) -- [different plugin deployment types](./02-plugin-types.md) +For more information on how to use the template, you can check the [README](https://github.com/aragon/osx-plugin-template-hardhat/blob/main/README.md) -And if you want to add additional versions to it, check out our guides on: +For more information on how to develop a plugin, you can our plugin development guides: +- [Best practices and patterns](./01-best-practices.md) +- [Different plugin types](./02-plugin-types.md) +- [Non-upgradeable plugin](./03-non-upgradeable-plugin/index.md) +- [Upgradeable plugin](./04-upgradeable-plugin/index.md) +- [Governance plugin](./05-governance-plugin/index.md) -- [How to publish a plugin](./07-publication/index.md) -- [How to manage plugin versioning](./07-publication/01-versioning.md) +:::danger +This plugin template uses the version `1.4.0-alpha.5` of the Aragon OSx protocol. This version is still in development and is not audited yet. +::: \ No newline at end of file diff --git a/versioned_docs/version-1.3.0/osx/02-how-to-guides/index.md b/versioned_docs/version-1.3.0/osx/02-how-to-guides/index.md index 9be344d3..9b8e9bf6 100644 --- a/versioned_docs/version-1.3.0/osx/02-how-to-guides/index.md +++ b/versioned_docs/version-1.3.0/osx/02-how-to-guides/index.md @@ -31,8 +31,6 @@ 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](/img/dao/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