An Aragon OSx governance plugin that gives a single account (the admin) the power to execute actions on the DAO directly, without voting. Proposals execute when they are created.
Documentation: protocol-doc, Admin Plugin.
Halborn: audit report
- Commit ID: 546cfa243a5d0726d75158db646573ca2237f570
- Started: 2024-11-18
- Finished: 2025-02-13
| Contract | Purpose |
|---|---|
src/Admin.sol |
The plugin, deployed as an EIP-1167 minimal clone. |
src/AdminSetup.sol |
Plugin setup: installs and uninstalls the plugin through the PluginSetupProcessor. |
src/zkSync/AdminZkSync.sol |
Same plugin for zkSync Era, initialized in its constructor (minimal clones do not work on zkSync). |
src/zkSync/AdminSetupZkSync.sol |
Plugin setup for zkSync Era (deploys AdminZkSync with new). |
The plugin is not upgradeable: installations cannot be updated to a newer build. To move to a new build, a DAO uninstalls the plugin and installs the new one.
Deployed addresses and ABIs are published in artifacts-hub.
Requirements: Foundry and just.
git clone https://github.com/aragon/admin-plugin.git
cd admin-plugin
just init <network> # fetch the git submodules (lib/), create .env from .env.example, select the network (default: mainnet)
just help # list every recipe (available once the submodules are fetched)just init runs git submodule update --init --recursive. Run that command yourself if you prefer not to use just.
Network settings (RPC, chain ID, OSx and management DAO addresses) come from just-foundry (lib/just-foundry/networks/<network>.env). Switch networks with just switch <network> and inspect the resolved values with just env. Secrets go in .env (see .env.example) or in vars (see .vars.yaml).
forge buildjust test # unit, integration and fuzz tests
just test-fork # fork tests against the active network (requires RPC_URL)
just test-coverage # HTML coverage report under ./reportLayout:
test/
├── unit/admin/concrete/<function>/ one folder per function, run for both Admin and AdminZkSync
├── unit/admin/fuzz/
├── unit/adminSetup/concrete/<function>/ run for both AdminSetup and AdminSetupZkSync
├── unit/metadata/ build metadata vs what the setups decode
├── unit/script/ deployment scripts
├── integration/concrete/pluginSetup/ install, use and uninstall through a local PluginSetupProcessor
├── fork/ live networks
└── utils/ constants, mocks, harnesses
just predeploy # simulate Deploy.s.sol
just deploy # new network: creates the plugin repo and publishes VERSION_BUILD
just pre-new-version # simulate NewVersion.s.sol
just new-version # existing repo: deploys the setup, prints the management DAO proposal- Both scripts deploy
AdminSetupZkSyncon zkSync Era (chains 324 and 300) andAdminSetupeverywhere else. Deploy.s.solcreates the plugin repo (ENS subdomainADMIN_ENS_SUBDOMAIN:adminin production; no ENS name when unset), publishesPlaceholderSetupbuilds belowVERSION_BUILDso that build numbers match every other network, publishes the setup asVERSION_BUILD, and hands ROOT, MAINTAINER and UPGRADE_REPO over to the management DAO.NewVersion.s.soldeploys the setup and prints thecreateVersionaction(s) forADMIN_PLUGIN_REPO_ADDRESS, wrapped in acreateProposalcall forMANAGEMENT_DAO_MULTISIG_ADDRESS. Any member of the management DAO multisig submits it.
Both scripts write artifacts/artifacts-<network>-<timestamp>.json for artifacts-hub (just import-plugin <file> there). On zkSync the setup has no implementation and the artifact omits it. For NewVersion, import the artifact only after the proposal has executed.
- Bump
VERSION_BUILDinscript/PluginSettings.sol(andVERSION_RELEASEfor a new release). - Update the files in
script/metadata/:build-metadata.json,new-version-proposal-metadata.json, andrelease-metadata.jsonon a new release. - Pin each file with
just ipfs-pin <file>and paste theipfs://URIs intoscript/PluginSettings.sol. The scripts refuse to run while any of them is empty.
- I have checked out the official repository on the
mainbranch, andgit statusreports no local changes - The rest of the ceremony reports the same
git log -n 1commit hash - I have run
just init <network>andjust envshows the right network, addresses and deployer -
DEPLOYER_KEYis a fresh wallet that only I operate -
ETHERSCAN_API_KEYis set (when the network uses Etherscan) -
VERSION_BUILDand every metadata URI inscript/PluginSettings.solare final -
ADMIN_ENS_SUBDOMAIN=admin(new network only) -
just testruns clean, andjust test-forkruns clean on the target network -
just predeploy(orjust pre-new-version) completes without errors -
just balanceshows at least 15% more funds than the simulation estimated - My machine is on a trusted network and exposes no services
- I run
just deploy(orjust new-version)
- The script completed without errors and every contract is verified on the network's explorer
- The log under
logs/matches the console output -
artifacts/artifacts-<network>-<timestamp>.jsonmatches the logged addresses, and it was imported into artifacts-hub (after the proposal executed, forNewVersion) - The plugin repo's ROOT, MAINTAINER and UPGRADE_REPO permissions belong to the management DAO only (
Deploy) - The log, the artifact and
broadcast/<script>/<chain-id>/run-latest.jsonare uploaded to the shared location
just-foundry selects forge-zksync automatically on zkSync networks (just switch zksync or zksync-sepolia). The scripts pick AdminSetupZkSync there on their own.
AGPL-3.0-or-later, see LICENSE.md.