diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e9ff3655..cdfbb9d8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -74,7 +74,6 @@ content/ ├── contracts-compact/ # Compact contract implementations ├── contracts-stylus/ # Stylus contracts for Arbitrum ├── ui-builder/ # UI Builder documentation -├── defender/ # Defender platform documentation ├── monitor/ # Monitoring tools documentation ├── relayer/ # Relayer service documentation ├── stellar-contracts/ # Stellar blockchain contracts @@ -266,7 +265,7 @@ To add or modify navigation: Product-specific icons located in `src/components/icons/`: - **Blockchain Icons**: Ethereum, Arbitrum, Starknet, Stellar, Polkadot, Midnight, Zama -- **Product Icons**: Contracts, Defender, Monitor, Relayer +- **Product Icons**: Contracts, Monitor, Relayer - **Tool Icons**: Wizard, Ethernaut, and others Icons are React components that accept className props for styling. diff --git a/content/contracts/4.x/governance.mdx b/content/contracts/4.x/governance.mdx index 96050587..9b5f2167 100644 --- a/content/contracts/4.x/governance.mdx +++ b/content/contracts/4.x/governance.mdx @@ -36,7 +36,7 @@ When using a timelock with your Governor contract, you can use either OpenZeppel [Tally](https://www.tally.xyz) is a full-fledged application for user owned on-chain governance. It comprises a voting dashboard, proposal creation wizard, real time research and analysis, and educational content. -For all of these options, the Governor will be compatible with Tally: users will be able to create proposals, visualize voting power and advocates, navigate proposals, and cast votes. For proposal creation in particular, projects can also use Defender Admin as an alternative interface. +For all of these options, the Governor will be compatible with Tally: users will be able to create proposals, visualize voting power and advocates, navigate proposals, and cast votes. In the rest of this guide, we will focus on a fresh deploy of the vanilla OpenZeppelin Governor features without concern for compatibility with GovernorAlpha or Bravo. @@ -106,7 +106,7 @@ A proposal is a sequence of actions that the Governor contract will perform if i Let’s say we want to create a proposal to give a team a grant, in the form of ERC20 tokens from the governance treasury. This proposal will consist of a single action where the target is the ERC20 token, calldata is the encoded function call `transfer(, )`, and with 0 ETH attached. -Generally a proposal will be created with the help of an interface such as Tally or Defender. Here we will show how to create the proposal using Ethers.js. +Generally a proposal will be created with the help of an interface such as Tally. Here we will show how to create the proposal using Ethers.js. First we get all the parameters necessary for the proposal action. diff --git a/content/contracts/5.x/governance.mdx b/content/contracts/5.x/governance.mdx index e45ccfa3..23839454 100644 --- a/content/contracts/5.x/governance.mdx +++ b/content/contracts/5.x/governance.mdx @@ -36,7 +36,7 @@ When using a timelock with your Governor contract, you can use either OpenZeppel [Tally](https://www.tally.xyz) is a full-fledged application for user owned on-chain governance. It comprises a voting dashboard, proposal creation wizard, real time research and analysis, and educational content. -For all of these options, the Governor will be compatible with Tally: users will be able to create proposals, see voting periods and delays following [IERC6372](/contracts/5.x/api/interfaces#IERC6372), visualize voting power and advocates, navigate proposals, and cast votes. For proposal creation in particular, projects can also use [Defender Transaction Proposals](https://docs.openzeppelin.com/defender/module/actions#transaction-proposals-reference) as an alternative interface. +For all of these options, the Governor will be compatible with Tally: users will be able to create proposals, see voting periods and delays following [IERC6372](/contracts/5.x/api/interfaces#IERC6372), visualize voting power and advocates, navigate proposals, and cast votes. In the rest of this guide, we will focus on a fresh deploy of the vanilla OpenZeppelin Governor features without concern for compatibility with GovernorAlpha or Bravo. @@ -111,7 +111,7 @@ A proposal is a sequence of actions that the Governor contract will perform if i Let’s say we want to create a proposal to give a team a grant, in the form of ERC-20 tokens from the governance treasury. This proposal will consist of a single action where the target is the ERC-20 token, calldata is the encoded function call `transfer(, )`, and with 0 ETH attached. -Generally a proposal will be created with the help of an interface such as Tally or [Defender Proposals](https://docs.openzeppelin.com/defender/module/actions#transaction-proposals-reference). Here we will show how to create the proposal using Ethers.js. +Generally a proposal will be created with the help of an interface such as Tally. Here we will show how to create the proposal using Ethers.js. First we get all the parameters necessary for the proposal action. diff --git a/content/defender/changelog.mdx b/content/defender/changelog.mdx deleted file mode 100644 index 5460b6ee..00000000 --- a/content/defender/changelog.mdx +++ /dev/null @@ -1,224 +0,0 @@ ---- -title: Changelog ---- - - -# [v1.54.0](https://github.com/OpenZeppelin/defender-client/releases/tag/v1.54.0) - 2023-12-07 - -## What's Changed -* Fix the lerna publish for the npm packages by [@collins-w](https://github.com/collins-w) in [#439](https://github.com/OpenZeppelin/defender-client/pull/439) -* add arbitrum sepolia support by [@MCarlomagno](https://github.com/MCarlomagno) in [#438](https://github.com/OpenZeppelin/defender-client/pull/438) -* Release preminor versions for RC by [@collins-w](https://github.com/collins-w) in [#445](https://github.com/OpenZeppelin/defender-client/pull/445) -* Remove the GPG key by [@collins-w](https://github.com/collins-w) in [#451](https://github.com/OpenZeppelin/defender-client/pull/451) -* Revert "Remove the GPG key" by [@collins-w](https://github.com/collins-w) in [#452](https://github.com/OpenZeppelin/defender-client/pull/452) -* Run the deploy steps only when lerna detects changes by [@collins-w](https://github.com/collins-w) in [#456](https://github.com/OpenZeppelin/defender-client/pull/456) -* Bump actions/upload-artifact from 3.1.2 to 3.1.3 by [@dependabot](https://github.com/dependabot) in [#376](https://github.com/OpenZeppelin/defender-client/pull/376) -* defender-client-deps: bump nx-cloud from 16.0.5 to 16.5.2 by [@dependabot](https://github.com/dependabot) in [#397](https://github.com/OpenZeppelin/defender-client/pull/397) -* Bump actions/checkout from 4.1.0 to 4.1.1 by [@dependabot](https://github.com/dependabot) in [#435](https://github.com/OpenZeppelin/defender-client/pull/435) -* defender-client-deps: bump axios from 1.4.0 to 1.6.2 by [@dependabot](https://github.com/dependabot) in [#440](https://github.com/OpenZeppelin/defender-client/pull/440) -* Bump actions/dependency-review-action from 3.1.0 to 3.1.4 by [@dependabot](https://github.com/dependabot) in [#457](https://github.com/OpenZeppelin/defender-client/pull/457) -* Add support for optimism sepolia by [@MCarlomagno](https://github.com/MCarlomagno) in [#454](https://github.com/OpenZeppelin/defender-client/pull/454) -* Add base sepolia by [@MCarlomagno](https://github.com/MCarlomagno) in [#455](https://github.com/OpenZeppelin/defender-client/pull/455) -* Increase the dependabot interval and examples from being watched by [@collins-w](https://github.com/collins-w) in [#461](https://github.com/OpenZeppelin/defender-client/pull/461) - - -**Full Changelog**: https://github.com/OpenZeppelin/defender-client/compare/v1.52.0...v1.54.0 - -[Changes][v1.54.0] - - - -# [v1.52.0](https://github.com/OpenZeppelin/defender-client/releases/tag/v1.52.0) - 2023-11-10 - -## What's Changed -* Add environment variable endpoints for autotasks by [@shahnami](https://github.com/shahnami) in [#414](https://github.com/OpenZeppelin/defender-client/pull/414) -* Add Meld network by [@shahnami](https://github.com/shahnami) in [#419](https://github.com/OpenZeppelin/defender-client/pull/419) - - -**Full Changelog**: https://github.com/OpenZeppelin/defender-client/compare/v1.51.0...v1.52.0 - -[Changes][v1.52.0] - - - -# [v1.51.0](https://github.com/OpenZeppelin/defender-client/releases/tag/v1.51.0) - 2023-11-07 - -## What's Changed -* Add support to scroll mainnet by [@MCarlomagno](https://github.com/MCarlomagno) in [#406](https://github.com/OpenZeppelin/defender-client/pull/406) -* Support proposals pagination by [@MCarlomagno](https://github.com/MCarlomagno) in [#422](https://github.com/OpenZeppelin/defender-client/pull/422) -* defender-client-deps: bump @babel/traverse from 7.22.8 to 7.23.2 by [@dependabot](https://github.com/dependabot) in [#398](https://github.com/OpenZeppelin/defender-client/pull/398) -* Bump ossf/scorecard-action from 2.2.0 to 2.3.1 by [@dependabot](https://github.com/dependabot) in [#412](https://github.com/OpenZeppelin/defender-client/pull/412) -* defender-client-deps: bump aws-sdk from 2.1414.0 to 2.1488.0 by [@dependabot](https://github.com/dependabot) in [#423](https://github.com/OpenZeppelin/defender-client/pull/423) -* Bump crazy-max/ghaction-import-gpg from 5.3.0 to 6.0.0 by [@dependabot](https://github.com/dependabot) in [#377](https://github.com/OpenZeppelin/defender-client/pull/377) -* Bump actions/setup-node from 3.6.0 to 4.0.0 by [@dependabot](https://github.com/dependabot) in [#407](https://github.com/OpenZeppelin/defender-client/pull/407) - - -**Full Changelog**: https://github.com/OpenZeppelin/defender-client/compare/v1.50.0...v1.51.0 - -[Changes][v1.51.0] - - - -# [v1.50.0](https://github.com/OpenZeppelin/defender-client/releases/tag/v1.50.0) - 2023-10-25 - -## What's Changed -* Add support to scroll sepolia network by [@MCarlomagno](https://github.com/MCarlomagno) in [#379](https://github.com/OpenZeppelin/defender-client/pull/379) -* Add support for relayer status endpoint by [@zeljkoX](https://github.com/zeljkoX) in [#381](https://github.com/OpenZeppelin/defender-client/pull/381) -* Add Account client and support to retrieve quotas usage by [@zeljkoX](https://github.com/zeljkoX) in [#404](https://github.com/OpenZeppelin/defender-client/pull/404) - - -**Full Changelog**: https://github.com/OpenZeppelin/defender-client/compare/v1.49.0...v1.50.0 - -[Changes][v1.50.0] - - - -# [v1.49.0](https://github.com/OpenZeppelin/defender-client/releases/tag/v1.49.0) - 2023-10-09 - -## What's Changed -* Support api versioning by [@MCarlomagno](https://github.com/MCarlomagno) in [#312](https://github.com/OpenZeppelin/defender-client/pull/312) -* add defender v2 env var to readme by [@MCarlomagno](https://github.com/MCarlomagno) in [#316](https://github.com/OpenZeppelin/defender-client/pull/316) -* defender-client-deps: bump eslint from 8.44.0 to 8.50.0 by [@dependabot](https://github.com/dependabot) in [#323](https://github.com/OpenZeppelin/defender-client/pull/323) -* defender-client-deps: bump nx from 16.5.1 to 16.9.0 by [@dependabot](https://github.com/dependabot) in [#322](https://github.com/OpenZeppelin/defender-client/pull/322) -* Bump step-security/harden-runner from 2.4.0 to 2.5.1 by [@dependabot](https://github.com/dependabot) in [#306](https://github.com/OpenZeppelin/defender-client/pull/306) -* defender-client-deps: bump code-style from `0c7b307` to `a6cd128` by [@dependabot](https://github.com/dependabot) in [#315](https://github.com/OpenZeppelin/defender-client/pull/315) -* defender-client-deps: bump nx from 16.9.0 to 16.9.1 by [@dependabot](https://github.com/dependabot) in [#327](https://github.com/OpenZeppelin/defender-client/pull/327) -* Add Safe support as viaType by [@MCarlomagno](https://github.com/MCarlomagno) in [#320](https://github.com/OpenZeppelin/defender-client/pull/320) -* Bump release-drafter/release-drafter from 5.23.0 to 5.24.0 by [@dependabot](https://github.com/dependabot) in [#285](https://github.com/OpenZeppelin/defender-client/pull/285) -* Bump anchore/sbom-action from 0.14.2 to 0.14.3 by [@dependabot](https://github.com/dependabot) in [#282](https://github.com/OpenZeppelin/defender-client/pull/282) -* Bump ossf/scorecard-action from 2.1.3 to 2.2.0 by [@dependabot](https://github.com/dependabot) in [#284](https://github.com/OpenZeppelin/defender-client/pull/284) -* fix deploy readme imports by [@MCarlomagno](https://github.com/MCarlomagno) in [#313](https://github.com/OpenZeppelin/defender-client/pull/313) -* defender-client-deps: bump lerna from 7.1.3 to 7.3.0 by [@dependabot](https://github.com/dependabot) in [#319](https://github.com/OpenZeppelin/defender-client/pull/319) -* defender-client-deps: bump prettier from 2.6.2 to 2.8.8 by [@dependabot](https://github.com/dependabot) in [#278](https://github.com/OpenZeppelin/defender-client/pull/278) -* [StepSecurity] Apply security best practices by [@step-security-bot](https://github.com/step-security-bot) in [#257](https://github.com/OpenZeppelin/defender-client/pull/257) -* Bump ncipollo/release-action from 1.12.0 to 1.13.0 by [@dependabot](https://github.com/dependabot) in [#328](https://github.com/OpenZeppelin/defender-client/pull/328) -* Bump actions/checkout from 3.5.2 to 4.1.0 by [@dependabot](https://github.com/dependabot) in [#329](https://github.com/OpenZeppelin/defender-client/pull/329) -* Bump actions/dependency-review-action from 2.5.1 to 3.1.0 by [@dependabot](https://github.com/dependabot) in [#330](https://github.com/OpenZeppelin/defender-client/pull/330) -* Bump step-security/harden-runner from 2.4.0 to 2.5.1 by [@dependabot](https://github.com/dependabot) in [#331](https://github.com/OpenZeppelin/defender-client/pull/331) -* Bump dotenv from 8.6.0 to 16.3.1 in /examples/pause-proposal by [@dependabot](https://github.com/dependabot) in [#332](https://github.com/OpenZeppelin/defender-client/pull/332) -* Bump @openzeppelin/defender-sentinel-client from 1.22.0 to 1.48.0 in /examples/create-sentinel by [@dependabot](https://github.com/dependabot) in [#333](https://github.com/OpenZeppelin/defender-client/pull/333) -* Bump dotenv from 8.6.0 to 16.3.1 in /examples/action-proposal by [@dependabot](https://github.com/dependabot) in [#334](https://github.com/OpenZeppelin/defender-client/pull/334) -* Bump dotenv from 8.6.0 to 16.3.1 in /examples/batch-proposal by [@dependabot](https://github.com/dependabot) in [#335](https://github.com/OpenZeppelin/defender-client/pull/335) -* Feature/paginated relayer list by [@zeljkoX](https://github.com/zeljkoX) in [#326](https://github.com/OpenZeppelin/defender-client/pull/326) -* Add support to Mantle by [@MCarlomagno](https://github.com/MCarlomagno) in [#321](https://github.com/OpenZeppelin/defender-client/pull/321) - -## New Contributors -* [@step-security-bot](https://github.com/step-security-bot) made their first contribution in [#257](https://github.com/OpenZeppelin/defender-client/pull/257) - -**Full Changelog**: https://github.com/OpenZeppelin/defender-client/compare/v1.48.0...v1.49.0 - -[Changes][v1.49.0] - - - -# [v1.48.0](https://github.com/OpenZeppelin/defender-client/releases/tag/v1.48.0) - 2023-08-10 - -## What's Changed -* Add new matchedChecksumAddresses field to types by [@shahnami](https://github.com/shahnami) in [#293](https://github.com/OpenZeppelin/defender-client/pull/293) -* Remove provenance by [@tirumerla](https://github.com/tirumerla) in [#295](https://github.com/OpenZeppelin/defender-client/pull/295) -* PLAT-2112 Export SentinelBaseConditionSummary interface and sub interfaces by [@emnul](https://github.com/emnul) in [#297](https://github.com/OpenZeppelin/defender-client/pull/297) -* Expose network list endpoint by [@shahnami](https://github.com/shahnami) in [#292](https://github.com/OpenZeppelin/defender-client/pull/292) -* add support for base mainnet by [@mok0230](https://github.com/mok0230) in [#294](https://github.com/OpenZeppelin/defender-client/pull/294) -* add support for linea mainnet by [@mok0230](https://github.com/mok0230) in [#302](https://github.com/OpenZeppelin/defender-client/pull/302) - -## New Contributors -* [@emnul](https://github.com/emnul) made their first contribution in [#297](https://github.com/OpenZeppelin/defender-client/pull/297) - -**Full Changelog**: https://github.com/OpenZeppelin/defender-client/compare/v1.47.0...v1.48.0 - -[Changes][v1.48.0] - - - -# [v1.47.1](https://github.com/OpenZeppelin/defender-client/releases/tag/v1.47.1) - 2023-07-28 - -**Full Changelog**: https://github.com/OpenZeppelin/defender-client/compare/v1.47.0...v1.47.1 - -[Changes][v1.47.1] - - - -# [v1.47.0](https://github.com/OpenZeppelin/defender-client/releases/tag/v1.47.0) - 2023-07-12 - -## What's Changed -* Add scenario trigger type by [@dylankilkenny](https://github.com/dylankilkenny) in [#212](https://github.com/OpenZeppelin/defender-client/pull/212) -* remove git+ from repository field in package.json by [@mok0230](https://github.com/mok0230) in [#281](https://github.com/OpenZeppelin/defender-client/pull/281) -* Upgrade axios & fix tests by [@tirumerla](https://github.com/tirumerla) in [#286](https://github.com/OpenZeppelin/defender-client/pull/286) - - -**Full Changelog**: https://github.com/OpenZeppelin/defender-client/compare/v1.46.0...v1.47.0 - -[Changes][v1.47.0] - - - -# [v1.46.0](https://github.com/OpenZeppelin/defender-client/releases/tag/v1.46.0) - 2023-06-14 - -## What's Changed -* Fix lerna positionals by [@tirumerla](https://github.com/tirumerla) in [#275](https://github.com/OpenZeppelin/defender-client/pull/275) -* defender-client-deps: bump @types/async-retry from 1.4.4 to 1.4.5 by [@dependabot](https://github.com/dependabot) in [#272](https://github.com/OpenZeppelin/defender-client/pull/272) -* Bump github/codeql-action from 2.3.6 to 2.13.4 by [@dependabot](https://github.com/dependabot) in [#267](https://github.com/OpenZeppelin/defender-client/pull/267) -* Bump actions/checkout from 3.5.2 to 3.5.3 by [@dependabot](https://github.com/dependabot) in [#269](https://github.com/OpenZeppelin/defender-client/pull/269) -* defender-client-deps: bump aws-sdk from 2.1390.0 to 2.1395.0 by [@dependabot](https://github.com/dependabot) in [#273](https://github.com/OpenZeppelin/defender-client/pull/273) -* Reference new [@openzeppelin](https://github.com/openzeppelin) scope by [@shahnami](https://github.com/shahnami) in [#276](https://github.com/OpenZeppelin/defender-client/pull/276) - - -**Full Changelog**: https://github.com/OpenZeppelin/defender-client/compare/v1.45.0...v1.46.0 - -[Changes][v1.46.0] - - - -# [v1.45.0](https://github.com/OpenZeppelin/defender-client/releases/tag/v1.45.0) - 2023-06-12 - -## What's Changed -* Bump defender-base-client version to the latest one - 1.44.0 by [@collins-w](https://github.com/collins-w) in [#234](https://github.com/OpenZeppelin/defender-client/pull/234) -* fix: add base goerli to valid list by [@0xsambugs](https://github.com/0xsambugs) in [#235](https://github.com/OpenZeppelin/defender-client/pull/235) -* Improve CI/CD & format fixes by [@tirumerla](https://github.com/tirumerla) in [#233](https://github.com/OpenZeppelin/defender-client/pull/233) -* Fix workflow patches & yq download url by [@tirumerla](https://github.com/tirumerla) in [#244](https://github.com/OpenZeppelin/defender-client/pull/244) -* Add license & fix wf permissions by [@tirumerla](https://github.com/tirumerla) in [#246](https://github.com/OpenZeppelin/defender-client/pull/246) -* Fix permissions to release by [@tirumerla](https://github.com/tirumerla) in [#247](https://github.com/OpenZeppelin/defender-client/pull/247) -* Fix RC workflow by [@tirumerla](https://github.com/tirumerla) in [#248](https://github.com/OpenZeppelin/defender-client/pull/248) -* Add conditions to rc workflow by [@tirumerla](https://github.com/tirumerla) in [#252](https://github.com/OpenZeppelin/defender-client/pull/252) -* Fix rc workflow bug by [@tirumerla](https://github.com/tirumerla) in [#253](https://github.com/OpenZeppelin/defender-client/pull/253) -* Fix condition on release job by [@tirumerla](https://github.com/tirumerla) in [#254](https://github.com/OpenZeppelin/defender-client/pull/254) -* Bump actions/upload-artifact from 3.1.0 to 3.1.2 by [@dependabot](https://github.com/dependabot) in [#239](https://github.com/OpenZeppelin/defender-client/pull/239) -* Bump ossf/scorecard-action from 2.1.2 to 2.1.3 by [@dependabot](https://github.com/dependabot) in [#238](https://github.com/OpenZeppelin/defender-client/pull/238) -* Bump actions/checkout from 3.1.0 to 3.5.2 by [@dependabot](https://github.com/dependabot) in [#236](https://github.com/OpenZeppelin/defender-client/pull/236) -* Bump github/codeql-action from 2.2.4 to 2.3.5 by [@dependabot](https://github.com/dependabot) in [#250](https://github.com/OpenZeppelin/defender-client/pull/250) -* Add Linea Goerli by [@ernestognw](https://github.com/ernestognw) in [#249](https://github.com/OpenZeppelin/defender-client/pull/249) -* Fix rc bug 3 by [@tirumerla](https://github.com/tirumerla) in [#255](https://github.com/OpenZeppelin/defender-client/pull/255) -* rename walletId to relayerId (deployments) by [@MCarlomagno](https://github.com/MCarlomagno) in [#251](https://github.com/OpenZeppelin/defender-client/pull/251) -* defender-client-deps: bump @types/node from 12.20.54 to 12.20.55 by [@dependabot](https://github.com/dependabot) in [#245](https://github.com/OpenZeppelin/defender-client/pull/245) -* defender-client-deps: bump web3-core-helpers from 1.9.0 to 1.10.0 by [@dependabot](https://github.com/dependabot) in [#243](https://github.com/OpenZeppelin/defender-client/pull/243) -* Generate SBOM for every release by [@tirumerla](https://github.com/tirumerla) in [#256](https://github.com/OpenZeppelin/defender-client/pull/256) -* defender-client-deps: bump @ethersproject/hash from 5.6.1 to 5.7.0 by [@dependabot](https://github.com/dependabot) in [#242](https://github.com/OpenZeppelin/defender-client/pull/242) -* defender-client-deps: bump @ethersproject/providers from 5.6.8 to 5.7.2 by [@dependabot](https://github.com/dependabot) in [#241](https://github.com/OpenZeppelin/defender-client/pull/241) -* Bump github/codeql-action from 2.3.3 to 2.3.6 by [@dependabot](https://github.com/dependabot) in [#258](https://github.com/OpenZeppelin/defender-client/pull/258) -* defender-client-deps: bump aws-sdk from 2.1367.0 to 2.1390.0 by [@dependabot](https://github.com/dependabot) in [#259](https://github.com/OpenZeppelin/defender-client/pull/259) -* defender-client-deps: bump jszip from 3.10.0 to 3.10.1 by [@dependabot](https://github.com/dependabot) in [#260](https://github.com/OpenZeppelin/defender-client/pull/260) -* defender-client-deps: bump web3-core from 1.9.0 to 1.10.0 by [@dependabot](https://github.com/dependabot) in [#261](https://github.com/OpenZeppelin/defender-client/pull/261) -* defender-client-deps: bump platform-deploy-client from 0.3.3 to 0.6.0 by [@dependabot](https://github.com/dependabot) in [#262](https://github.com/OpenZeppelin/defender-client/pull/262) -* Better deploy release docs by [@mok0230](https://github.com/mok0230) in [#265](https://github.com/OpenZeppelin/defender-client/pull/265) -* Fix: bugs in stable workflow by [@tirumerla](https://github.com/tirumerla) in [#266](https://github.com/OpenZeppelin/defender-client/pull/266) -* Test publishing by [@tirumerla](https://github.com/tirumerla) in [#274](https://github.com/OpenZeppelin/defender-client/pull/274) - -## New Contributors -* [@collins-w](https://github.com/collins-w) made their first contribution in [#234](https://github.com/OpenZeppelin/defender-client/pull/234) -* [@MCarlomagno](https://github.com/MCarlomagno) made their first contribution in [#251](https://github.com/OpenZeppelin/defender-client/pull/251) - -**Full Changelog**: https://github.com/OpenZeppelin/defender-client/compare/v1.44.0...v1.45.0 - -[Changes][v1.45.0] - - -[v1.54.0]: https://github.com/OpenZeppelin/defender-client/compare/v1.52.0...v1.54.0 -[v1.52.0]: https://github.com/OpenZeppelin/defender-client/compare/v1.51.0...v1.52.0 -[v1.51.0]: https://github.com/OpenZeppelin/defender-client/compare/v1.50.0...v1.51.0 -[v1.50.0]: https://github.com/OpenZeppelin/defender-client/compare/v1.49.0...v1.50.0 -[v1.49.0]: https://github.com/OpenZeppelin/defender-client/compare/v1.48.0...v1.49.0 -[v1.48.0]: https://github.com/OpenZeppelin/defender-client/compare/v1.47.1...v1.48.0 -[v1.47.1]: https://github.com/OpenZeppelin/defender-client/compare/v1.47.0...v1.47.1 -[v1.47.0]: https://github.com/OpenZeppelin/defender-client/compare/v1.46.0...v1.47.0 -[v1.46.0]: https://github.com/OpenZeppelin/defender-client/compare/v1.45.0...v1.46.0 -[v1.45.0]: https://github.com/OpenZeppelin/defender-client/tree/v1.45.0 diff --git a/content/defender/dac.mdx b/content/defender/dac.mdx deleted file mode 100644 index f323b02b..00000000 --- a/content/defender/dac.mdx +++ /dev/null @@ -1,228 +0,0 @@ ---- -title: Defender as Code Plugin ---- - -Defender as Code (DaC) is a Serverless Framework plugin for automated resource management and configuration as code. - - -This plugin is under development and behavior might change. Handle with care. - - -## Prerequisites - -Serverless Framework: https://www.serverless.com/framework/docs/getting-started/ - -## Installation - -You can initialise your Serverless project directly using our pre-configured template: - -``` -sls install --url https://github.com/OpenZeppelin/defender-as-code/tree/main/template -n my-service -``` - - -For the command above to work correctly you need access to this repo. - - -Alternatively, you can install it directly into an existing project with: - -`yarn add @openzeppelin/defender-as-code` - -## Setup - -There are a few ways you can set up the `serverless.yml` configuration: - -* Create it from scratch; -* Use Defender’s 2.0 Serverless export capability; -* Leverage the example [template](https://github.com/OpenZeppelin/defender-as-code/blob/main/template/serverless.yml) provided in the `defender-as-code` repository. - -If you already have resources such as contracts, notifications, relayers, actions, etc. in Defender, you can export a `serverless.yml` configuration file containing these resources from the manage → advanced page. - -![Defender Export Serverless](/defender/manage-advanced-export-serverless.png) - - -If you have previously deployed with `defender-as-code` to the same account and subsequently created new resources through the Defender user interface, the export function will automatically assign a `stackResourceId` to the new resources based on the name of your latest deployment stack. If you have not deployed using `defender-as-code` before, a default stack name of `mystack` will be used. - - -This plugin allows you to define Actions, Monitors, Notifications, Block Explorer API Keys, Relayers, Contracts, Policies, and Secrets declaratively from a `serverless.yml` and provision them via the CLI using `serverless deploy`. An example template below with an action, a relayer, a policy and a single relayer API key defined: - -```yaml -service: defender-as-code-template -configValidationMode: error -frameworkVersion: '3' - -provider: - name: defender - stage: $opt:stage, 'dev' - stackName: 'mystack' - ssot: false - -defender: - key: '$env:TEAM_API_KEY' - secret: '$env:TEAM_API_SECRET' - -resources: - actions: - action-example-1: - name: 'Hello world from serverless' - path: './actions/hello-world' - relayer: $self:resources.relayers.relayer-1 - trigger: - type: 'schedule' - frequency: 1500 - paused: false - # optional - unencrypted and scoped to the individual action - environment-variables: - hello: 'world!' - action-example-2: 2cbc3f58-d962-4be8-a158-1035be4b661c - - policies: - policy-1: - gas-price-cap: 1000 - whitelist-receivers: - - '0x0f06aB75c7DD497981b75CD82F6566e3a5CAd8f2' - eip1559-pricing: true - - relayers: - relayer-1: - name: 'Test Relayer 1' - network: 'sepolia' - min-balance: 1000 - policy: $self:resources.policies.policy-1 - api-keys: - - key1 - -plugins: - - '@openzeppelin/defender-as-code' -``` - -This requires setting the `key` and `secret` under the `defender` property of the YAML file. We recommend using environment variables or a secure (gitignored) configuration file to retrieve these values. Modify the `serverless.yml` accordingly. - -Ensure the Defender Team API Keys are setup with all appropriate API capabilities. - -The `stackName` (e.g. mystack) is combined with the resource key (e.g. relayer-1) to uniquely identify each resource. This identifier is called the `stackResourceId` (e.g. mystack.relayer-1) and allows you to manage multiple deployments within the same tenant. - -You may also reference existing Defender resources directly by their unique ID (e.g. `2cbc3f58-d962-4be8-a158-1035be4b661c`). These resources will not be managed by the plugin and will be ignored during the deploy process. However, you may reference them in other resources to update their configuration accordingly. -A list of properties that support direct referencing: - -* `relayer` may reference a `relayerId` in Actions -* `action-trigger` may reference an `actionid` in Monitor -* `action-condition` may reference an `actionId` in Monitor -* `address-from-relayer` may reference a `relayerId` in Relayer -* `notify-config.channels` may reference multiple `notificationId` in Monitor -* `contracts` may be used over `addresses` and reference multiple `contractId` in Monitor - The following is an example of how a direct reference to a Defender contract and relayer can be used in monitor and action respectively: - -```yaml -... -contracts: - contract-1: 'sepolia-0xd70d6A0480420b4C788AF91d0E1b0ca6141A9De8' # contractId of an existing resource in Defender -relayers: - relayer-2: 'bcb659c6-7e11-4d37-a15b-0fa9f3d3442c' # relayerId of an existing relayer in Defender -actions: - action-example-1: - name: 'Hello world from serverless' - path: './actions/hello-world' - relayer: $self:resources.relayers.relayer-2 - trigger: - type: 'schedule' - frequency: 1500 - paused: false -monitors: - block-example: - name: 'Block Example' - type: 'BLOCK' - network: 'sepolia' - risk-category: 'TECHNICAL' - # optional - either contracts OR addresses should be defined - contracts: - - $self:resources.contracts.contract-1 - ... -... -``` - -### SSOT mode - -Under the `provider` property in the `serverless.yml` file, you can optionally add a `ssot` boolean. SSOT or Single Source of Truth, ensures that the state of your stack in Defender is perfectly in sync with the `serverless.yml` template. -This means that all resources, that are not defined in your current template file, are removed from Defender, with the exception of Relayers, upon deployment. If SSOT is not defined in the template, it will default to `false`. - -Any resource removed from the `serverless.yml` file does _not_ get automatically deleted in order to prevent inadvertent resource deletion. For this behaviour to be anticipated, SSOT mode must be enabled. - -### Secrets (Actions) - -Action secrets can be defined both globally and per stack. Secrets defined under `global` are not affected by changes to the `stackName` and will retain when redeployed under a new stack. Secrets defined under `stack` will be removed (on the condition that [SSOT mode](#ssot-mode) is enabled) when the stack is redeployed under a new `stackName`. To reference secrets defined under `stack`, use the following format: `_`, for example `mystack_test`. - -```yaml -secrets: - # optional - global secrets are not affected by stackName changes - global: - foo: $self:custom.config.secrets.foo - hello: $self:custom.config.secrets.hello - # optional - stack secrets (formatted as _) - stack: - test: $self:custom.config.secrets.test -``` - -### Types and Schema validation - -We provide auto-generated documentation based on the JSON schemas: - -* [Defender Property](https://github.com/OpenZeppelin/defender-as-code/blob/main/src/types/docs/defender.md) -* [Provider Property](https://github.com/OpenZeppelin/defender-as-code/blob/main/src/types/docs/provider.md) -* [Resources Property](https://github.com/OpenZeppelin/defender-as-code/blob/main/src/types/docs/resources.md) - -More information on types can be found [here](https://github.com/OpenZeppelin/defender-as-code/blob/main/src/types/index.ts). Specifically, the types preceded with `Y` (e.g. YRelayer). For the schemas, you can check out the [docs-schema](https://github.com/OpenZeppelin/defender-as-code/blob/main/src/types/docs-schemas) folder. - -Additionally, an [example project](https://github.com/OpenZeppelin/defender-as-code/blob/main/examples/defender-test-project/serverless.yml) is available which provides majority of properties that can be defined in the `serverless.yml` file. - -## Commands - -### Deploy - -You can use `sls deploy` to deploy your current stack to Defender. - -The deploy takes in an optional `--stage` flag, which is defaulted to `dev` when installed from the template above. - -Moreover, the `serverless.yml` may contain an `ssot` property. More information can be found in the [SSOT mode](#ssot-mode) section. - -This command will append a log entry in the `.defender` folder of the current working directory. Additionally, if any new relayer keys are created, these will be stored as JSON objects in the `.defender/relayer-keys` folder. - - -When installed from the template, we ensure the `.defender` folder is ignored from any git commits. However, when installing directly, make sure to add this folder in your `.gitignore` file. - - -### Info - -You can use `sls info` to retrieve information on every resource defined in the `serverless.yml` file, including unique identifiers, and properties unique to each component. - -### Remove - -You can use `sls remove` to remove all resources defined in the `serverless.yml` file from Defender. - - -To avoid potential loss of funds, Relayers can only be deleted from the Defender UI directly. - - -### Logs - -You can use `sls logs --function ` to retrieve the latest action logs for a given action identifier (e.g. mystack.action-example-1). This command will run continiously and retrieve logs every 2 seconds. - -### Invoke - -You can use `sls invoke --function ` to manually run an action, given its identifier (e.g. mystack.action-example-1). - - -Each command has a standard output to a JSON object. - - -## Caveats - -Errors thrown during the `deploy` process, will not revert any prior changes. Common errors are: - -* Not having set the API key and secret -* Insufficient permissions for the API key -* Validation error of the `serverless.yml` file (see [Types and Schema Validation](#types-and-schema-validation)) - -Usually, fixing the error and retrying the deploy should suffice as any existing resources will fall within the `update` clause of the deployment. However, if unsure, you can always call `sls remove` to remove the entire stack, and retry. - -Action secrets are encrypted key-value pairs and injected at runtime into the lambda environment. Secrets are scoped to all actions automatically. Alternatively, you may use environment-variables to define key-value pairs that are scoped to the individual action, and available at runtime through `process.env`. Note that these values are not encrypted. diff --git a/content/defender/faq.mdx b/content/defender/faq.mdx deleted file mode 100644 index 55c840ef..00000000 --- a/content/defender/faq.mdx +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Frequently Asked Questions (FAQ) ---- - -OpenZeppelin Defender is the evolution of Defender, with an improved user experience, a cleaner interface, and new features that offer a more cohesive experience across the DevSecOps lifecycle. - -## How can I sign up to Defender? - -New sign-ups were disabled on June 30, 2025. Until the final shutdown on July 1, 2026, Defender will remain fully operational while we focus on the open source versions of tools like Relayers and Monitor. Detailed migration guides are coming soon to help you transition seamlessly to open source. - -[Read more](https://blog.openzeppelin.com/doubling-down-on-open-source-and-phasing-out-defender) - -## Once I migrate to Defender, can I continue using Defender legacy? - -No, once you migrate to Defender, you will no longer have access to Defender 1.0 UI and API. - -## Are there any breaking changes when migrating? - -Yes, there are multiple changes to the API endpoints that will require you to update your integrations. You can find the API docs [here](https://www.api-docs.defender.openzeppelin.com/#defender-sdk). - -## What are the pricing options for Defender? - -You can find the pricing for Defender [here](https://www.openzeppelin.com/pricing). - -## Does Defender offer support? - -We offer a Service Level and Support Agreement (SLA) for paid subscriptions. Learn more [here](#sla). - -## How can I get an upgrade my tenant account? - -You can use the billing page to upgrade your tenant account to a higher tier [here](https://defender.openzeppelin.com/v2/#/billing/). - -## Where can I see my tier quota usage? - -You can see your tier quota usage in the billing page [here](https://defender.openzeppelin.com/v2/#/billing/usage). diff --git a/content/defender/guide/factory-monitor.mdx b/content/defender/guide/factory-monitor.mdx deleted file mode 100644 index d0176880..00000000 --- a/content/defender/guide/factory-monitor.mdx +++ /dev/null @@ -1,243 +0,0 @@ ---- -title: Automatic monitoring for factory clones ---- - -The factory-clone pattern can be advantageous for minimizing gas costs. However, since each clone gets deployed to a new address, it may be a challenge to efficiently track and monitor each of these contracts. - -This guide shows how to use Defender to monitor a factory contract as well as the clone contracts created by it. Monitor automation is achieved through the following structure of Defender modules: - -* A Monitor watches for successful event emitted by the factory contract that creates a clone. If detected, it triggers an [Action](/defender/module/actions) and [passes along information](/defender/module/actions#monitor-invocations) about the transaction. -* The Action makes use of the [`defender-sdk`](https://www.npmjs.com/package/@openzeppelin/defender-sdk) to add the address of the newly created contract to the [address book](/defender/module/address-book) for easier monitoring. -* Aditionally, the Action uses the [`defender-sdk`](https://www.npmjs.com/package/@openzeppelin/defender-sdk) to add the clone address to the list of addresses watched by a Monitor. - -In this case, the contract ABI can be pre-supplied since clone contracts will have identical ABIs. Alternatively, you may be able to dynamically retrieve the ABI from a verified contract at a given address using [Etherscan’s API](https://docs.etherscan.io/api-endpoints/contracts). - -## Generate API Key - -To programmatically add a contract to the address book, the [`sdk`](https://www.npmjs.com/package/@openzeppelin/defender-sdk) requires credentials in the form of an API key and secret. Create and copy the credentials in the [API keys page](https://defender.openzeppelin.com/v2/#/settings/api-keys/new). - -![Create API credentials](/defender/guide-factory-api.png) - -Now, navigate to the [Secrets](https://defender.openzeppelin.com/v2/#/settings/secrets) page in Defender and create a new secret with the name `API_KEY` and paste in the API key. Create another secret with the name `API_SECRET` and paste in the API secret. These secrets will be used by the Action securely. - -![Save API credentials](/defender/guide-factory-secrets.png) - -## Create the Action - -Navigate to the [Action creation page](https://defender.openzeppelin.com/v2/#/actions/automatic/new?), enter a name, and select `Webhook` as trigger. Then, paste the following Action code and save it: - -```jsx -const Defender = require('@openzeppelin/defender-sdk'); - -exports.handler = async function (event) - const creds = { - apiKey: event.secrets.API_KEY, - apiSecret: event.secrets.API_SECRET, - - const client = new Defender(creds); - - const payload = event.request.body - const matchReasons = payload.matchReasons - const newCloneAddress = matchReasons[0].params._clone - const newCloneAbi = `[ - - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - - ], - "name": "ValueChanged", - "type": "event" - }, - - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - - "inputs": [], - "name": "retrieve", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - - ], - "stateMutability": "view", - "type": "function" - }, - - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - - ], - "name": "store", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ]` - // Add new clone contract - await client.proposal.addContract( - network: 'sepolia', - address: newCloneAddress, - name: `Clone ${newCloneAddress`, - abi: newCloneAbi, - }) -} -``` - -![Create Action](/defender/guide-factory-create-action.png) - -The Action is now ready to be triggered by a Monitor. - - -Manually triggering this Action will be raise an error, since the Action relies on data supplied by a Monitor (such as the address of the newly deployed clone contract address). - - -## Create the Monitor - -This Monitor will watch for an event emitted by the factory contract signaling that a new clone has been created. Navigate to the [Monitor creation page](https://defender.openzeppelin.com/v2/#/monitor/new/custom), choose a name, risk category, and select the Factory contract (add the factory if it’s not already added). - -![Monitor General Information](/defender/guide-factory-monitor-general-information.png) - -Leave `Transaction Filters` as it is, and continue to the `Events` tab. Here, select the event name for clone creation and leave the event parameters blank to catch all emitted events. - -![Monitor Events](/defender/guide-factory-monitor-events.png) - -Lastly, open the `Alerts` section and select the Action created in the previous step within the `Execute an Action` dropdown. Feel free to add any other setting, like notifications, and save the Monitor. - -![Monitor Alerts](/defender/guide-factory-monitor-alerts.png) - -As with any action, the triggering of this Monitor will be recorded in the [Logs](/defender/logs). - -## Test run - -To test the set up, navigate to [Transaction Proposals](https://defender.openzeppelin.com/v2/#/transaction-proposals/new?) to manually create a clone through the factory. Select the factory contract, and call the function that creates a clone with any parameters needed. - -![Transaction Proposal to create clone](/defender/guide-factory-create-clone.png) - -Then, execute this this transaction with your preferred approval process, like a Relayer or EOA wallet. Head over to run history of the Action to verify it was triggered by the Monitor, adding the clone contract address to Defender. - -![Action Run History](/defender/guide-factory-action-run-history.png) - -## Create Monitor for clones - -Now that you have a clone contract to serve as a template for all future clone contracts, it’s time to create a Monitor for them. Navigate to the [Monitor creation page](https://defender.openzeppelin.com/v2/#/monitor/new/custom), choose a name, risk category, and select the clone contract. - -Aditionally, feel free to add any other filters for transactions, events, and functions, or notifications. Save the Monitor and observe the logs/notifications to verify that the Monitor is working as expected. - -![Monitor Clones](/defender/guide-factory-monitor-clones.png) - -## Automatically add clones to Monitor - -With the last Monitor, you can update the Action to add any newly created contract to the list of addresses being monitored by the Monitor. Update the Action code with the following code, replacing `monitorId` with the ID of the Monitor created in the previous step: - -```jsx -const Defender = require('@openzeppelin/defender-sdk'); - -exports.handler = async function (event) - const creds = { - apiKey: event.secrets.API_KEY, - apiSecret: event.secrets.API_SECRET, - - const client = new Defender(creds); - - const payload = event.request.body - const matchReasons = payload.matchReasons - const newCloneAddress = matchReasons[0].params._clone - const newCloneAbi = `[ - - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - - ], - "name": "ValueChanged", - "type": "event" - }, - - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - - "inputs": [], - "name": "retrieve", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - - ], - "stateMutability": "view", - "type": "function" - }, - - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - - ], - "name": "store", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ]` - // Add new clone contract - await client.proposal.addContract( - network: 'sepolia', - address: newCloneAddress, - name: `Clone ${newCloneAddress`, - abi: newCloneAbi, - }) - - // Add clone contract to Monitor - const monitorId = 'REPLACE' - const monitor = await client.monitor.get(monitorId) - const subscribedAddresses = monitor.addressRules[0].addresses - subscribedAddresses.push(newCloneAddress) - await client.action.update(monitorId, addresses: subscribedAddresses ) -} -``` - -Now when the Action runs, not only will it add the contract to Defender, it will also add it to the Monitor. - -To verify, execute another test run! - -## References - -* [Actions Documentation](/defender/module/actions) -* [Monitor Documentation](/defender/module/monitor) diff --git a/content/defender/guide/fireblock-defender-integration.mdx b/content/defender/guide/fireblock-defender-integration.mdx deleted file mode 100644 index 194d0897..00000000 --- a/content/defender/guide/fireblock-defender-integration.mdx +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Fireblocks integration within Defender ---- - -You can directly submit transactions to Fireblocks from Defender. Fireblocks is a robust asset management solution that utilizes multi-party computation to secure all treasury operations, ensuring enhanced security and efficiency. - -## Pre-requisites - -* If you want leverage Fireblocks within Defender you can contact the OZ team to enable to Fireblocks integration for your account. - -## 1. Generate CSR file -1. To use this feature, navigate to the **Settings** page and click on **Approval Process** in the sidebar. If the Fireblocks integration is enabled for your account, go to the **Integrations** tab, which is located next to the **All Approval Process** tab. - - ![Integration tab](/defender/guide-fireblocks-integration-tab.png) - -2. Click on **Generate new API Key for Fireblocks**. Here, you will need to generate a Certificate Signing Request (CSR), which will be used within the Fireblocks platform to enable this feature and create API keys. - - ![CSR Generation Modal](/defender/guide-fireblocks-csr-modal.png) - This will trigger Defender to generate a public/private key-pair. The CSR is then generated and signed with the private key and securely stored to prevent leakage. - -## 2. Create Fireblocks API user -1. First, you will need to import the CSR within the Fireblocks UI when creating a new API user. Note that the API user will require any role that can _at least_ initiate transactions, e.g. Signer. - - ![Create API user](/defender/guide-fireblocks-add-user.png) - -2. Once the API user has been created and approved by the Fireblocks workspace owner, copy the Fireblocks API key and navigate to the Fireblocks API Keys page. You should see an incomplete API key setup, which you can then edit and complete with the Fireblocks API key. Note that you will not be able to generate a new CSR file unless you complete the setup or delete the previous incomplete one. - - ![API Key generated](/defender/guide-fireblocks-api-key.png) - -## 3. Connect Fireblocks with Defender -1. First, navigate to the **Settings** page subsequently click **Approval Process** in the sidebar, the navigate to the **Integrations** tab. Over here click on the **Paste API Key from Fireblocks**. - - ![Insert API Key Defender](/defender/guide-fireblock-paste-api-key.png) - -2. Insert the Fireblocks API key. - - ![Insert API key](/defender/guide-fireblocks-edit-api-key.png) - - - To submit a transaction to Fireblocks via Defender, ensure the correct permissions are set in Fireblocks, such as the relevant whitelisted addresses and the Transaction Access Policy (TAP). For example, you might need to whitelist the contract address you wish to interact with, as well as ensure that the newly created API user is allowed to interact with the relevant account and vaults (defined in the TAP). - - -## 4. Create Approval Process - -### Pick a Fireblocks Wallet from the List -You can pick a Fireblocks wallet from the list of available wallets by just providing the Fireblocks API key. We will attempt to fetch the list of available vaults and wallets from Fireblocks. - -![Create Defender Approval Process](/defender/guide-fireblocks-approval-process-automatic.png) - -### Manually Add a Fireblocks Wallet -In some rare cases you might not see your wallets in the list that is automatically fetched from Fireblocks. In that case you can select the `Manual` option and type in the required information manually. - -![Create Defender Approval Process](/defender/guide-fireblocks-approval-process-manual.png) - -To get your ***Vault ID***, head to Fireblocks console, click on the vault you are interested in and copy the ID (last number) from the URL. - -![Vault ID](/defender/guide-fireblocks-vault-id.png) - -To get your ***Asset Wallet Address***, head to Fireblocks console, click on the asset you are interested in and copy the address (starts with 0x). - -![Asset Wallet Address](/defender/guide-fireblocks-asset-wallet-address.png) - -## 5. Approve or Reject a Transaction -Note, Defender will not allow you to approve or reject a transaction from the UI. This is only possible via the Fireblocks mobile app or console. diff --git a/content/defender/guide/forked-network.mdx b/content/defender/guide/forked-network.mdx deleted file mode 100644 index 3db962ff..00000000 --- a/content/defender/guide/forked-network.mdx +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Deploy a smart contract on a forked network ---- - -Defender empowers you to harness your customized network forks for deploying and testing smart contracts, along with associated configurations of, for example, actions, monitors, and workflows. This guide will lead you through the steps of deploying a smart contract on a forked network and interacting with it. - -## Pre-requisites - -* OpenZeppelin Defender account. - -## 1. Configure your forked network - -You will setup a forked network on [Phalcon](https://phalcon.xyz) and add this network to Defender. To configure a forked network, follow these steps: - -1. Register an account on [Phalcon](https://phalcon.xyz) and create a new fork using Ethereum mainnet as the source network. -2. Ensure anti-replay protection is activated to use a distinct chain ID for your fork, preventing conflicts with public chain IDs. - - ![Phalcon create a fork](/defender/tutorial-forked-network-phalcon-create.png) -3. Copy the RPC URL and Explorer URL (this can be found under 'Scan') of your forked network. You will need it to add the network to Defender. - - ![Phalcon dashboard](/defender/tutorial-forked-networks-phalcon-dashboard.png) -4. Open [Defender Forked Networks](https://defender.openzeppelin.com/v2/#/settings/networks/forks) in a web browser. -5. Click on **Add Forked Network**. - - ![Forked Networks landing page](/defender/tutorial-forked-networks-intro.png) -6. Enter the details of your forked network which can be found in your Phalcon dashboard. -7. Click on **Save**. - - ![Forked Networks added network](/defender/tutorial-forked-networks-create.png) - - -You may use any provider to fork a network, such as [Conduit](https://conduit.xyz). However, we recommend using Phalcon as it is free and easy to use. - - -## 2. Configure the deploy environment - -You will setup a deploy environment for the forked network you just added to Defender. To configure a deploy environment, follow these steps: - -1. Open [Defender Deploy](https://defender.openzeppelin.com/v2/#/deploy) in a web browser. -2. Click on **Setup** for your production environment (or setup a test environment if your network is forked from a testnet). - - ![Deploy landing page](/defender/tutorial-forked-networks-deploy-intro.png) -3. From the network dropdown, select the forked network you just added. - - ![Delpoy wizard step 1](/defender/tutorial-forked-networks-deploy-wizard-step1.png) -4. Click on **Next** to continue. -5. When asked to provide a block explorer API key, click on **Skip this step** as it’s **not possible to use block explorer API keys for forked networks**. - - ![Delpoy wizard step 2](/defender/tutorial-forked-networks-deploy-wizard-step2.png) -6. On step 3 of the deploy wizard, create a new Relayer from which your deploy transaction will originate by clicking on **Create Relayer** from the dropdown menu. - - ![Delpoy wizard step 3](/defender/tutorial-forked-networks-deploy-wizard-step3.png) -7. Lastly, click on **Skip this step** when asked to select an upgrade approval process. **Currently, upgrades are not supported for forked networks**. -8. Make sure to copy the generated team API keys and store them in a safe place. You will need them to interact with your deploy environment. - -Your deploy environment is now setup! - - -You should fund the relayer account with enough ETH to cover the gas costs of your deploy transaction. Most providers have a faucet that you can use to fund your relayer account. For Phalcon, you can find this on the dashboard. - - -## 3. Deploy a smart contract on a forked network - -You will deploy a smart contract on the forked network you just added to Defender. To deploy a smart contract, follow these steps: - -1. Setup a JavaScript project and install the [defender-sdk-deploy-client](https://www.npmjs.com/package/@openzeppelin/defender-sdk-deploy-client) NPM package. Alternatively, you can use the [defender-sdk delpoy example script](https://github.com/OpenZeppelin/defender-sdk/blob/main/examples/deploy-contract/index.js) provided in the OpenZeppelin Defender SDK repository. -2. The deployment code will look something like this: - - ```js - const config = await client.deploy.getDeployApprovalProcess('mainnet-fork'); - console.log(config); - -const deployment = await client.deploy.deployContract( - contractName: 'Box', - contractPath: 'contracts/Box.sol', - network: 'mainnet-fork', - artifactPayload: JSON.stringify(artifactFile), - licenseType: 'MIT', - verifySourceCode: true, - // Only provide the `salt` if you wish to use `CREATE2`. Otherwise, omit this field to use `CREATE`. - salt: "a-unique-salt" -); - -const deploymentStatus = await client.deploy.getDeployedContract(deployment.deploymentId); -console.log(deploymentStatus); -``` -. Run the script to deploy the contract. **Note** that providing a `salt` will deploy the contract using `CREATE2`. Otherwise, the contract will be deployed using the `CREATE` opcode. Visit the documentation for more information on the [caveats of deployment](https://docs.openzeppelin.com/defender/tutorial/deploy#deploy-caveat). -. Once deployed, you can track the deployment status on the [Defender Deploy dashboard](https://defender.openzeppelin.com/v2/#/deploy/environment/production). - -## Next steps - -Congratulations! You have successfully deployed a smart contract on a forked network. If you have provided a `blockExplorerUrl`, you can verify the transaction on the block explorer of your forked network. - - -After deploying a contract, we recommend creating a Monitor and setting up Actions on Defender. Learn how to setup a Monitor [here](/defender/tutorial/monitor), and use Actions with its tutorial [here](/defender/tutorial/actions). - - -## References - -* [Deploy Documentation](/defender/module/deploy) -* [Actions Documentation](/defender/module/actions) -* [Monitor Documentation](/defender/module/monitor) -* [Phalcon](https://phalcon.xyz) -* [Conduit](https://conduit.xyz) diff --git a/content/defender/guide/meta-tx.mdx b/content/defender/guide/meta-tx.mdx deleted file mode 100644 index f248a4b6..00000000 --- a/content/defender/guide/meta-tx.mdx +++ /dev/null @@ -1,518 +0,0 @@ ---- -title: Relaying gasless meta-transactions with a web app ---- - -Gasless meta-transactions offer users a more seamless experience on the blockchain, potentially eliminating the need to spend money on gas fees for every interaction. This method allows users to sign a transaction for free and have it securely executed by a third party, with that party paying the gas to complete the transaction. - -Defender provides a seamless experience and secure way to implement gasless meta-transactions using Relayers. These Relayers handle sending transactions on behalf of users, eliminating the need for users to manage private keys, transaction signing, nonce management, gas estimation, and transaction inclusion. - -This demo app showcases how to implement meta-transactions using not just ERC-2771, but also explores other gasless transaction standards: - -* ERC-2771: Secure Native Meta Transactions: This [demo app](https://github.com/OpenZeppelin/workshops/tree/master/25-defender-metatx-api) implements meta-transactions using [ERC2771Forwarder](https://docs.openzeppelin.com/contracts/api/metatx#ERC2771Forwarder) and [ERC2771Context](https://docs.openzeppelin.com/contracts/api/metatx#ERC2771Context) to separate `msg.sender` from the Relayer’s address. All the user needs to do is sign a message using the account they would like to issue the transaction from. The signature is formed for the target contract and the data of the desired transaction, using the user’s private key. This signing happens off-chain and costs no gas. The signature is passed to the Relayer so it can execute the transaction for the user (and pay the gas). -* ERC-2612: Permit Function: This standard introduces a method for enabling gasless token approvals in ERC-20 tokens. Users can grant spending permission to a relayer service by signing a message instead of directly paying gas fees for the traditional "approve" function. This allows the relayer to handle token approvals on the user’s behalf. -* ERC-3009: Transfer with Authorization: This standard facilitates gasless token transfers through off-chain authorizations. Users sign messages authorizing specific token transfers, which can then be submitted to the blockchain by anyone, including a relayer service. - -A gasless meta-transaction relay can be easily and securely implemented using Defender with [Relayers](/defender/module/relayers), which allow you to send transactions easily without needing to manage private keys, transaction signing, nonce management, gas estimation, and transaction inclusion. - -## Pre-requisites - -* OpenZeppelin Defender account. -* [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) and [Yarn](https://classic.yarnpkg.com/lang/en/docs/install/#mac-stable) installed - -## 1. ERC-2771: Secure Native Meta Transactions - -You can view the live [demo app](https://defender-metatx-workshop-demo.openzeppelin.com/) here. It accepts registrations directly if the user has the available funds to pay for the transaction, otherwise the data is sent as a meta-transaction. - -In the example code, the functionality of the [`SimpleRegistry` contract](https://github.com/OpenZeppelin/workshops/blob/master/25-defender-metatx-api/contracts/SimpleRegistry.sol) is to take a string and store it. The contract’s [meta-transaction implementation](https://github.com/OpenZeppelin/workshops/blob/master/25-defender-metatx-api/contracts/Registry.sol) achieves the same result by decoupling the signer from the sender of the transaction. - -When comparing the code, note the meta-transaction’s use of `_msgSender()` as opposed to the SimpleRegistry’s use of `msg.sender`. By extending from `ERC2771Context` and `ERC2771Forwarder`, the contract becomes meta-transaction capable. - - -All OpenZeppelin contracts are compatible with the use of `_msgSender()`. - - -The second fundamental change between the two contracts is the need for the meta-transaction contract ([Registry](https://github.com/OpenZeppelin/workshops/blob/master/25-defender-metatx-api/contracts/Registry.sol)) to specify the address of the trusted forwarder, which in this case is the address of the `ERC2771Forwarder` contract. - -### 1.1 Configure the project - -First, fork the repository and navigate to the directory for this guide. There, install the dependencies with `yarn`: - -``` -$ git clone https://github.com/openzeppelin/workshops.git -$ cd workshops/25-defender-metatx-api/ -$ yarn -``` - -Create a `.env` file in the project root and supply an API key and secret from the [API keys page](https://defender.openzeppelin.com/v2/#/settings/api-keys/new). A private key will be used for local testing but the Relayer is used for actual contract deployment. - -``` -PRIVATE_KEY="0xabc" -API_KEY="abc" -API_SECRET="abc" -``` - -### 1.2 Create Relayer - -Run the Relayer creation script, which will use the Defender API parameters in the `.env` file: - -``` -$ yarn create-relay -``` - -The Relayer is created using the `defender-sdk` package: - -```jsx -// ... -const client = new Defender(creds); - -// Create Relayer using Defender SDK client. -const requestParams = - name: 'MetaTxRelayer', - network: 'sepolia', - minBalance: BigInt(1e17).toString(), -; - -const relayer = await client.relay.create(requestParams); -// ... -``` - -After creating it, the script will fetch the Relayer ID and create an API key and secret set to send transacitons via it. The Relayer ID is automatically stored in the `relayer.json` file, and its API paramteres in the `.env` file. - -### 1.3 Compile the Contract Using Hardhat - -Within the `contracts` directory, you can find the both the `SimpleRegistry.sol` and `Registry.sol` contracts. The former contract contains the meta-transaction functionality, as you can see here: - -```jsx -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "@openzeppelin/contracts/metatx/ERC2771Context.sol"; -import "@openzeppelin/contracts/metatx/ERC2771Forwarder.sol"; - -contract Registry is ERC2771Context - event Registered(address indexed who, string name); - - mapping(address => string) public names; - mapping(string => address) public owners; - - constructor(ERC2771Forwarder forwarder) // Initialize trusted forwarder - ERC2771Context(address(forwarder)) { - - - function register(string memory name) external - require(owners[name] == address(0), "Name taken"); - address owner = _msgSender(); // Changed from msg.sender - owners[name] = owner; - names[owner] = name; - emit Registered(owner, name); - -} -``` - -Run `npx hardhat compile` to compile it for deployment. - -### 1.4 Deploy Using Relayer - -You can easily deploy a compiled smart contract without handling a private key by using the Relayer client from the [`defender-sdk`](https://www.npmjs.com/package/@openzeppelin/defender-sdk) package. - -The `deploy.js` script pulls the Relayer’s credentials from the local `.env` file along with the artifacts for the `Registry` and `ERC2771Forwarder` contracts and uses ethers.js to deploy. The relevant addresses of these contracts are saved to the local file `deploy.json`. - -```jsx -// ... -const creds = - relayerApiKey: process.env.RELAYER_API_KEY, - relayerApiSecret: process.env.RELAYER_API_SECRET, -; -const client = new Defender(creds); - -const provider = client.relaySigner.getProvider(); -const signer = client.relaySigner.getSigner(provider, speed: 'fast' ); - -const forwarderFactory = await ethers.getContractFactory('ERC2771Forwarder', signer) -const forwarder = await forwarderFactory.deploy('ERC2771Forwarder') - .then((f) => f.deployed()) - -const registryFactory = await ethers.getContractFactory('Registry', signer) -const registry = await registryFactory.deploy(forwarder.address) - .then((f) => f.deployed()) -// ... -``` - -Run this script with `yarn deploy`. - -After the contracts are deployed, the Relayer key and secret can be safely deleted; they are not needed unless additional local testing is desired. The contract addresses will be saved in the `deploy.json` file. - -### 1.5 Create Action via API - -The demo app uses an [Action](/defender/module/actions) to supply the necessary logic for telling the Relayer to send a transaction to the `Forwarder` contract, supplying the signer’s address. The Action will get triggered by each call to its webhook from the app. - -Due to the tight relationship between components, the Relayer credentials are securely available to the Action simply by instantiating a new provider and signer. - -The position of the Action here is crucial -- only the Action’s webhook is exposed to the frontend. The Action’s role is to execute the transaction according to the logic assigned to it: if the user has funds, they pay for the transaction. If not, the Relayer pays for the transaction. - -It’s important that the Relayer’s API key and secret are insulated from the frontend. If the Relayer keys were exposed, anyone could potentially use the Relayer to send any transaction they wanted. - -Here is the code for the Action, found in `action/index.js`: - -```jsx -const Defender = require('@openzeppelin/defender-sdk'); -const ethers = require('hardhat') - -const ForwarderAbi = require('../../src/forwarder'); -const ForwarderAddress = require('../../deploy.json').ERC2771Forwarder; - -async function relay(forwarder, request, signature, whitelist) - // Decide if we want to relay this request based on a whitelist - const accepts = !whitelist || whitelist.includes(request.to); - if (!accepts) throw new Error(`Rejected request to ${request.to`); - - // Validate request on the forwarder contract - const valid = await forwarder.verify(request, signature); - if (!valid) throw new Error(`Invalid request`); - - // Send meta-tx through relayer to the forwarder contract - const gasLimit = (parseInt(request.gas) + 50000).toString(); - return await forwarder.execute(request, signature, gasLimit ); -} - -async function handler(event) - // Parse webhook payload - if (!event.request || !event.request.body) throw new Error(`Missing payload`); - const { request, signature = event.request.body; - console.log(`Relaying`, request); - - // Initialize Relayer provider and signer, and forwarder contract - const creds = ... event ; - - const client = new Defender(creds); - - const provider = client.relaySigner.getProvider(); - const signer = client.relaySigner.getSigner(provider, speed: 'fast' ); - const forwarder = new ethers.Contract(ForwarderAddress, ForwarderAbi, signer); - - // Relay transaction! - const tx = await relay(forwarder, request, signature); - console.log(`Sent meta-tx: $tx.hash`); - return txHash: tx.hash ; -} - -module.exports = - handler, - relay, - -``` - -Note that the Action code must include an `index.js` file that exports a handler entrypoint. If the code relies on any external dependencies (such as an imported ABI) it’s necessary to bundle the Action using webpack, rollup, etc. You can create an Action via [Defender](https://defender.openzeppelin.com/v2/#/actions/automatic/new?) or with the [`defender-sdk`](https://www.npmjs.com/package/@openzeppelin/defender-sdk) package. - -Run `yarn create-action` to compile the code and create the Action with the bundled code via the SDK’s `action.create()` method: - -```jsx -// ... -const actionId = await client.action.create( - name: "Relay MetaTx", - encodedZippedCode: await client.action.getEncodedZippedCodeFromFolder('./build/action'), - relayerId: relayerId, - trigger: { - type: 'webhook' - , - paused: false -}); -// ... -``` - -Head to [Defender Actions](https://defender.openzeppelin.com/v2/#/actions/automatic) and copy the Actions’s webhook so that you can test functionality and connect the app to the Action for relaying meta-transactions. - -![Copy Webhook](/defender/guide-meta-tx-copy-webhook.png) - -Save the Action webhook in your `.env` file as `WEBHOOK_URL` and in the /app `.env` file as the `REACT_APP_WEBHOOK_URL`. - -Test the meta-transaction’s functionality with `yarn sign` followed by `yarn invoke`. - -### 1.6 Create Web App - -The key building blocks have been laid, so next it is a matter of crafting a web application that makes use of these components. - -You can see the details of this relationship in the [`register.js`](https://github.com/OpenZeppelin/workshops/blob/master/25-defender-metatx-api/app/src/eth/register.js) file. The user’s transaction request is sent to the Relayer by way of the Action’s webhook, and this executes the Actions’s logic given the parameters supplied by the application. Note that the signer’s nonce is incremented from the transaction. - -```jsx -import ethers from 'ethers'; -import createInstance from './forwarder'; -import signMetaTxRequest from './signer'; - -async function sendTx(registry, name) - console.log(`Sending register tx to set name=${name`); - return registry.register(name); -} - -async function sendMetaTx(registry, provider, signer, name) - console.log(`Sending register meta-tx to set name=${name`); - const url = process.env.REACT_APP_WEBHOOK_URL; - if (!url) throw new Error(`Missing relayer url`); - - const forwarder = createInstance(provider); - const from = await signer.getAddress(); - const data = registry.interface.encodeFunctionData('register', [name]); - const to = registry.address; - - const request = await signMetaTxRequest(signer.provider, forwarder, to, from, data ); - - return fetch(url, - method: 'POST', - body: JSON.stringify(request), - headers: { 'Content-Type': 'application/json' , - }); -} - -export async function registerName(registry, provider, name) - if (!name) throw new Error(`Name cannot be empty`); - if (!window.ethereum) throw new Error(`User wallet not found`); - - await window.ethereum.enable(); - const userProvider = new ethers.BrowserProvider(window.ethereum); - const userNetwork = await userProvider.getNetwork(); - console.log(userNetwork) - if (userNetwork.chainId !== 11155111) throw new Error(`Please switch to Sepolia for signing`); - - const signer = userProvider.getSigner(); - const from = await signer.getAddress(); - const balance = await provider.getBalance(from); - - const canSendTx = balance.gt(1e15); - if (canSendTx) return sendTx(registry.connect(signer), name); - else return sendMetaTx(registry, provider, signer, name); - -``` - -## 2. ERC-2612: Permit Function -EIP-2612 introduces the [permit](https://docs.openzeppelin.com/contracts/4.x/api/token/erc20#ERC20Permit) function, a tool for enabling gasless transactions in ERC-20 tokens. By extending the ERC-20 interface with a method allowing users to modify their allowance via a signed message instead of the approve function, this standard empowers users to approve tokens without directly paying gas fees. This standard enables relayer services to execute transactions on behalf of users by paying gas fees, while the user only needs to sign a message. -``` -function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external -``` -This function modifies the `allowance` of the spender for the owner’s tokens, based on a signed approval. The signature is split into `v`, `r`, and `s` components for verification. - -### 2.1 EIP-712 signing front-end -How it uses EIP-712 for structured data signing: EIP-2612 leverages EIP-712 for creating and signing structured data. This provides a human-readable representation of the data being signed, enhancing security and user experience. Example code: - -```jsx -// ... - const domain = - name: name, - version: '1', - chainId: chainId, - verifyingContract: ERC20_ADDRESS, - ; - - const types = - Permit: [ - { name: 'owner', type: 'address' , - name: 'spender', type: 'address' , - name: 'value', type: 'uint256' , - name: 'nonce', type: 'uint256' , - name: 'deadline', type: 'uint256' , - ] - }; - - const value = - owner: OWNER_ADDRESS, - spender: SPENDER_ADDRESS, - value: amount, - nonce: nonce, - deadline: deadline, - ; - - - const signature = await wallet.signTypedData(domain, types, value); - const sig = ethers.Signature.from(signature); - const recoveredAddress = ethers.verifyTypedData(domain, types, value, signature); - - const request = - owner: OWNER_ADDRESS, - spender: SPENDER_ADDRESS, - amount, - deadline, - v: sig.v, - r: sig.r, - s: sig.s - ; - - return fetch(`$url/relayerForwardMessage`, - method: 'POST', - body: JSON.stringify(request), - headers: { 'Content-Type': 'application/json' , - }); -``` -### 2.2 Relayer service -Create a back-end service to interact with Defender Relayers. The service will initially require the setup of [Defender Relayers](https://docs.openzeppelin.com/defender/manage/relayers). Once configured, it will handle incoming requests from the front-end and forward the signed EIP-712 message to the contract. The service will utilize the Relayers to execute the contract’s permit function, allowing the Relayer to cover gas fees. The service will facilitate token approvals for end-users, enabling subsequent operations with the Relayers, such as transferring tokens to different wallets. -```jsx -import ethers, defender from "hardhat"; - -// ... -const creds = - relayerApiKey: process.env.RELAYER_API_KEY, - relayerApiSecret: process.env.RELAYER_API_SECRET, -; -const client = new Defender(creds); - -const provider = client.relaySigner.getProvider(); -const signer = client.relaySigner.getSigner(provider, speed: 'fast' ); - -const erc20 = await ethers.getContractAt("ERC20Token", CONTRACT_ADDRESS); - -// You can now use these values to call the permit function -// permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) -const tx = await erc20.permit( - request.owner, - request.spender, - request.amount, - request.deadline, - request.v, - request.r, - request.s -); - -await tx.wait(); -console.log("Permit executed!"); - -// Example subsequent operation -const transferTx = await erc20.transferFrom(request.owner, to, request.amount); -await transferTx.wait(); -// ... -``` - -## 3. ERC-3009: Transfer with Authorization -ERC-3009 introduces a standard for gasless token transfers through off-chain authorizations. This standard allows users to sign messages authorizing token transfers, which can then be submitted to on-chain by anyone, through the [Defender Relayers](https://docs.openzeppelin.com/defender/manage/relayers) service. Comparison with EIP-2612 (signing differences): -While EIP-2612 focuses on approvals, ERC-3009 directly authorizes transfers. The key differences are: - -* Purpose: ERC-3009 authorizes specific transfers, while EIP-2612 approves an allowance. -* Flexibility: ERC-3009 doesn’t require EIP-712 for structured data signing, offering more flexibility in message formatting. -* Time Window: ERC-3009 includes validAfter and validBefore parameters, allowing for more precise control over when the authorization can be executed. - -The function definition: -``` -function transferWithAuthorization( - address from, - address to, - uint256 value, - uint256 validAfter, - uint256 validBefore, - bytes32 nonce, - uint8 v, - bytes32 r, - bytes32 s -) external -``` - -### 3.1 EIP-712 signing front-end -Similar to ERC-2612, you can use the EIP-712 format to sign messages on the front-end as the end user. While ERC-3009 offers more flexibility for front-end message signing, this example adheres to the EIP-712 standard. Example code: - -```jsx - //... - - const validAfter = Math.floor(Date.now() / 1000); // Now - const validBefore = validAfter + 3600; // 1 hour from validAfter - const value = ethers.parseEther("10"); // Amount to transfer - const nonce = ethers.randomBytes(32); - - const domain = - name: name, - version: '1', - chainId: chainId, - verifyingContract: ERC20_ADDRESS, - ; - - const types = - TransferWithAuthorization: [ - { name: 'from', type: 'address' , - name: 'to', type: 'address' , - name: 'value', type: 'uint256' , - name: 'validAfter', type: 'uint256' , - name: 'validBefore', type: 'uint256' , - name: 'nonce', type: 'bytes32' , - ] - }; - - const valueToSign = - from: FROM_ADDRESS, - to: TO_ADDRESS, - value: value, - validAfter: validAfter, - validBefore: validBefore, - nonce: nonce, - ; - - - const signature = await wallet.signTypedData(domain, types, valueToSign); - const sig = ethers.Signature.from(signature); - const request = - from: FROM_ADDRESS, - to: TO_ADDRESS, - value, - validAfter, - validBefore, - nonce, - v: sig.v, - r: sig.r, - s: sig.s - ; - - return fetch(`$url/relayerForwardMessage`, - method: 'POST', - body: JSON.stringify(request), - headers: { 'Content-Type': 'application/json' , - }); -``` -### 3.2 Relayer service -Create a back-end service to interact with Defender Relayers. The service will initially require the setup of Defender Relayers. Once configured, it will handle incoming requests from the front-end and forward the signed messages to the contract. The service will utilize the Relayers to execute the contract’s `transferWithAuthorization` function, allowing the Relayer to cover gas fees. The service will facilitate the transfer of tokens for the end-users. -```jsx -import ethers, defender from "hardhat"; - -// ... -const creds = - relayerApiKey: process.env.RELAYER_API_KEY, - relayerApiSecret: process.env.RELAYER_API_SECRET, -; -const client = new Defender(creds); - -const provider = client.relaySigner.getProvider(); -const signer = client.relaySigner.getSigner(provider, speed: 'fast' ); - -const erc20 = await ethers.getContractAt("ERC20Token", CONTRACT_ADDRESS); - -const tx = await erc20.transferWithAuthorization( - request.from, - request.to, - request.value, - request.validAfter, - request.validBefore, - request.nonce, - request.v, - request.r, - request.s -); - -await tx.wait(); -console.log("TransferWithAuthorization executed!"); -// ... -``` - -## Try the app - -Install the necessary dependencies and run the app. - -``` -$ cd app -$ yarn -$ yarn start -``` - -1. Open app: [http://localhost:3000/](http://localhost:3000/) -2. Change to Sepolia network in Metamask -3. Enter a name to register and sign the meta-transaction in Metamask -4. Your name will be registered, showing the address that created the meta-transaction and the name. - -Use the frontend to see it working for yourself! Compare what happens when you sign the registry with an account that has funds, and then try it with an account that has a zero ETH balance. - -## References - -* [Demo repo - Meta-Transaction Name Registry](https://github.com/OpenZeppelin/workshops/tree/master/25-defender-metatx-api) -* [Documentation - Meta Transactions](https://docs.openzeppelin.com/contracts/api/metatx) diff --git a/content/defender/guide/private-network.mdx b/content/defender/guide/private-network.mdx deleted file mode 100644 index be4e769f..00000000 --- a/content/defender/guide/private-network.mdx +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: Adding a complete Private Network ---- - -Private Networks allow you to customize your account by adding compatible mainnets and testnets. You can then use them as any other supported network to deploy, monitor, and manage smart contracts on those networks. This guide will lead you through the steps of adding a Private Network with a subgraph and Safe contracts. - -## Pre-requisites - -* OpenZeppelin Defender account. - -## 1. Configure Private Network - -As an example, this guide uses [Tenderly](https://tenderly.co/) to create a network to use. Follow these steps: - -1. Regsiter an account on Tenderly and create a fork network from Ethereum mainnet. Toggle the custom chain ID and set it to a unique value to prevent conflicts with public chain IDs. - - ![Tenderly create network](/defender/guide-tenderly-private-network.png) -2. Copy the network RPC and go to the [Private Network page on Defender](https://defender.openzeppelin.com/v2/#/settings/networks/private/new). Fill and submit the form with the network information, leaving the optional fields on blank (which will be configured in the next steps): - - ![Configure network on Defender](/defender/guide-configure-private-network.png) - -## 2. Deploy Safe contracts - -With the Private Network created, you can now deploy the Safe contracts, which can be used for multisigs or CREATE2 deployments. Follow these steps: - -1. Clone the `safe-smart-account` repository and install the dependencies: - - ``` - git clone https://github.com/safe-global/safe-smart-account && cd safe-smart-account && npm install - ``` -2. Create a new wallet, copy its mnemonic, and paste it in the `.env` file alongside the RPC url of the Private Network in the `NODE_URL` parameter. For example, with [Foundry](https://book.getfoundry.sh/): - - ``` - cast wallet new-mnemonic - ``` -3. Fund the wallet with native tokens (like Ether) via Tenderly. - - ![Fund wallet on Private Network](/defender/guide-fund-private-network-relayer.png) -4. Paste the private key of the wallet and network RPC in the following command to deploy the CREATE2 Deployer contract. Copy the contract address in `contractAddress` for the next step. - - ``` - cast send --rpc-url NETWORK_RPC --private-key PRIVATE_KEY --create 0x604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3 - ``` -5. Replace the `deterministicDeployment` function in `hardhat.config.ts` with the following code, replacing `YOUR_CONTRACT_ADDRESS` and `YOUR_WALLET_ADDRESS`: - - ```jsx - const deterministicDeployment = (): DeterministicDeploymentInfo => - return { - factory: "YOUR_CONTRACT_ADDRESS", - deployer: "YOUR_WALLET_ADDRESS", - funding: BigNumber.from(100000).mul(BigNumber.from(100000000000)).toString(), - signedTx: "0xf8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf326a0b1fd9f4102283a663738983f1aac789e979e220a1b649faa74033f507b911af5a061dd0f2f6f2341ee95913cf94b3b8a49cac9fdd7be6310da7acd7a96e31958d7", - ; - }; - ``` -6. Run the following command to deploy the Safe contracts (don’t worry about the verification errors): -+ -``` -npm run deploy-all custom -``` -7. Navigate to the [`Private Networks` page on Defender](https://defender.openzeppelin.com/v2/#/settings/networks/private) and click on the edit button of the network you created. - - ![Edit Private Network on Defender](/defender/guide-edit-private-network.png) -8. Copy the following addreses from the Safe contracts deployment output and paste them on Defender: - * Safe Master Address: `Safe` - * Safe Proxy Factory Address: `SafeProxyFactory` - * Safe Multi-Send Call-Only Address: `MultiSendCallOnly` - * Safe Create Call Address: `CreateCall` - -## 3. Create subgraph - -Subgraphs on Defender are powered by [TheGraph](https://thegraph.com). In order to create one for a Private Network, the network must be first supported by the TheGraph. [Here’s](https://github.com/graphprotocol/graph-tooling/blob/121843e982c69ffb31aae911431a68a2349ea062/packages/cli/src/protocols/index.ts#L91) the list of supported networks as data sources. Follow these steps to create a subgraph: - -1. Clone the Defender subgraph toolkit repository and install the dependencies: - - ``` - git clone https://github.com/OpenZeppelin/defender-subgraphs && cd defender-subgraphs && yarn - ``` -2. Follow the steps in the [README](https://github.com/OpenZeppelin/defender-subgraphs/blob/main/README.md). -3. Copy the subgraph URL and paste it in the `Subgraph URL` field on the Defender Private Network configuration. - -![Subgraph URL on Defender](/defender/guide-subgraph-private-network.png) - -## Next steps - -Congratulations! You have successfully added a complete Private Network. You can now use it to deploy and test your smart contracts with the Safe contracts and subgraph. - -## References - -* [Safe contracts deployments](https://github.com/safe-global/safe-smart-account#deployments) -* [Defender subgraph toolkit](https://github.com/OpenZeppelin/defender-subgraphs) diff --git a/content/defender/guide/timelock-roles.mdx b/content/defender/guide/timelock-roles.mdx deleted file mode 100644 index 50109d58..00000000 --- a/content/defender/guide/timelock-roles.mdx +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: How to manage roles of a TimelockController ---- - -Defender allows you to oversee and command contract permissions of any smart contract that uses [AccessControl from OpenZeppelin Contracts](https://docs.openzeppelin.com/contracts/api/access#AccessControl). This guide will lead you through the steps of importing a TimelockController contract, creating a proposal, and managing its roles. A `TimelockController` is a smart contract that enforces a delay between when an operation is queued and when it can be executed. This mechanism is commonly used in decentralized governance to increase security and provide transparency, allowing stakeholders to observe and react to changes before they are executed. TimelockController uses the following `AccessControl`` setup: - -* The **Proposer** role is in charge of queueing operations: this is the role the Governor instance should be granted, and it should likely be the only proposer in the system. -* The **Executor** role is in charge of executing already available operations: we can assign this role to the special zero address to allow anyone to execute (if operations can be particularly time sensitive, the Governor should be made Executor instead). -* Lastly, there is the **Admin** role, which can grant and revoke the two previous roles: this is a very sensitive role that will be granted automatically to the timelock itself, and optionally to a second account, which can be used for ease of setup but should promptly renounce the role. - -## Pre-requisites - -* OpenZeppelin Defender account. - -## 1. Creating TimelockController - -First, you need to deploy a contract that implements `TimelockController`. For example, using OpenZeppelin Contracts 5.0: - -```solidity -//SPDX-License-Identifier: Unlicense -pragma solidity ^0.8.18; - -import "@openzeppelin/contracts/governance/TimelockController.sol"; - -contract Timelock is TimelockController - constructor(uint256 minDelay, address[] memory proposers, address[] memory executors) TimelockController(minDelay, proposers, executors, msg.sender) { -} -``` - -This contract will grant the **Admin** role to the deployer, and the **Proposer** and **Executor** roles to the accounts passed as arguments. If you want to grant the **Proposer** and **Executor** roles to the same account, you can pass the same address twice. After deploying the contract, copy its address and proceed to the next step. - -## 2. Importing to Defender - -Navigate to the [Address Book on Defender](https://defender.openzeppelin.com/v2/#/address-book/new) and add your contract with its address and network. If the contract is verified, Defender will automatically pick up the ABI. Otherwise, you need to [paste the ABI](https://gist.github.com/mverzilli/a35ab1b5bd7039167cc9270e9fd60632) manually. - -## 3. Creating a proposal - -[Defender Transaction Proposals](/defender/module/transaction-proposals) allows you to create and manage proposals. Proposals in turn can directly execute actions on schedule delayed execution of functions through the TimelockController contract. In order to create a new proposal, navigate to the [Transaction Proposal creation page](https://defender.openzeppelin.com/v2/#/transaction-proposals/new?) and select your imported `TimelockController`. - -Then, select the `schedule` function from the functions dropdown and fill the information about the proposal you want to execute. For example: - -![Proposal Data](/defender/guide-timelock-roles-schedule.png) - -Finally, select the approval process to send this proposal. This depends on who is the proposal of your `TimelockController` contract. For this guide, the proposer is an EOA wallet. With Defender, you can create an approval process that is connected to your EOA and send this proposal with it. - -![Proposer](/defender/guide-timelock-proposer.png) - -You can then execute the proposal by creating another Transaction Proposal and selecting the `execute` function with the previous proposal data. - -## 4. Granting a role - -Now, you can use [Defender Access Control](/defender/module/access-control) to grant or revoke roles of your `TimelockController` contract. Navigate to [Access Control](https://defender.openzeppelin.com/v2/#/access-control/contracts) and select your imported `TimelockController` contract. - -![Timelock Controller Roles](/defender/guide-timelock-roles.png) - -In order to grant someone a role, you need to have access to the address that holds admin power over the role. For example, with the DEFAULT_ADMIN_ROLE, you can grant or revoke any role. In this case, you can use an EOA that holds the DEFAULT_ADMIN_ROLE to grant the PROPOSER_ROLE to another address. - -First, expand the dropdown of `PROPOSER_ROLE` and paste the address to grant the role to. - -![Receiver of role](/defender/guide-timelock-role-receiver.png) - -Then, scroll down and use an approval process that holds the DEFAULT_ADMIN_ROLE to send the transaction, like an EOA wallet. Click on `Save Changes`, which will send the transaction to your wallet. - -![Grant a role](/defender/guide-timelock-roles-grant.png) - -On the right side of the page, you will see that the transaction was executed and the role was granted to the address you selected. - -![Granted a role](/defender/guide-timelock-roles-granted.png) - -## Revoking a role - -To revoke a role, you need do the same steps but unselect the address to revoke the role from in the dropdown. - -![Remover of role](/defender/guide-timelock-role-remover.png) - -Then, use the same approval process and save the changes. The transaction should be executed and the role revoked, as confirmed on the right side of the page. - -![Revoked role](/defender/guide-timelock-role-revoked.png) - -## References - -* [Transaction Proposals Documentation](/defender/module/transaction-proposals) -* [Access Control Documentation](/defender/module/access-control) -* [TimelockController Documentation](https://docs.openzeppelin.com/contracts/governance#timelock) diff --git a/content/defender/guide/upgrade-actions-dependencies.mdx b/content/defender/guide/upgrade-actions-dependencies.mdx deleted file mode 100644 index 470be4c3..00000000 --- a/content/defender/guide/upgrade-actions-dependencies.mdx +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: Upgrading Actions Dependencies ---- - -Actions must be kept updated with the latest Node.js runtime and dependencies versions to ensure they run in an up-to-date and secure environment. Occasionally, Node.js and dependencies versions get deprecated on Defender, which means that the Actions running on those Node.js versions (and related dependencies) must be upgraded to the latest ones to ensure they continue to function as expected. - -## Upgrade Process - -When there is a major Node.js version deprecation, the Defender team notifies users about this event and sets a deadline for upgrading actions to the latest dependency versions. If no action is taken by the deadline, Defender automatically upgrades the actions on behalf of users. - - -We encourage users to make the upgrade process by themselves as the automatic upgrade might introduce breaking changes in dependencies. - - -## How to Upgrade Actions Runtimes - -1. Check the Action [dependencies latest versions](https://docs.openzeppelin.com/defender/module/actions#environment) and search for any breaking changes in your Action code. -2. Make any necessary code changes. -3. Test the Action code. A safe approach to do this: - a. Create a new Action with the same code using the target dependencies version and run it to verify that it works as expected. - b. If your action sends relayer transactions using [defender-sdk](https://docs.openzeppelin.com/defender/sdk) (or any other Defender legacy package), validate that it works by connecting a testnet relayer with your action. -4. Once you have verified that the code and dependencies are compatible, upgrade the Action dependencies to the latest version. diff --git a/content/defender/guide/usage-notification.mdx b/content/defender/guide/usage-notification.mdx deleted file mode 100644 index 59ffee2d..00000000 --- a/content/defender/guide/usage-notification.mdx +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Manage custom and system usage notifications ---- - -Defender enables you to receive notifications when your usage exceeds a certain threshold. This guide will walk you through the steps of setting up custom usage notifications and managing system usage notifications. Defender currently tracks usage metrics such as: - -* Monitor Alerts: The number of times your monitors have triggered an alert. -* Action Runs: The number of times your actions have been executed. -* Relayer Transactions: The number of transactions your relayers have processed. -* Code Inspector Reports: The number of reports generated by Code Inspector. -* Transaction Proposals: The number of proposals created. - -In addition, Defender provides default system usage notifications triggered when your usage exceeds 90% and 100%, respectively. For users with overages or metered billing enabled, only system usage notifications are triggered when usage surpasses 200%. These notifications are sent to the email addresses of all tenant administrator users. - -## Pre-requisites - -* OpenZeppelin Defender account. - -## 1. Configure a custom usage notification - -You will configure a custom usage notification for when your Action Runs usage exceeds 75% of your quota. You will set up an alert to be sent to all tenant administrators when this happens. To configure a custom usage notification, follow these steps: - -1. Open [Defender Billing Settings](https://defender.openzeppelin.com/v2/#/billing/settings) in a web browser. -2. Click on **Create Notification** in the top-right corner of the Notifications section. - - ![Billing Settings](/defender/guide-usage-notifications-all.png) - -3. In the **Create Notification** dialog: - * Enter a name for the notification. For example, `Action Runs Usage 75%`. - * Select the usage metric you want to monitor. In this case, select `Action Runs`. - * Set the threshold to 75. Below, you will see the current usage and the absolute value of the threshold for the selected metric. - * Select the "All Tenant Administrators" notification channel. For now, your selection is limited to ***Slack*** and ***Email***. - - ![Usage Notification Create Dialog](/defender/guide-usage-notifications-create.png) - -At any time, you may pause or unpause usage notifications. You can do this by toggling the switch next to the notification name. You can also manage your notifications by clicking on the three dots next to the notification threshold. From the dropdown menu, you can edit or delete the notification. System usage notifications can only be paused. - -![Manage Notification](/defender/guide-usage-notifications-edit-menu.png) - -## 2. Pause a system usage notification - -You will pause a system usage notification for when Monitor Alerts usage exceeds 90% (or 200% for users with overages enabled) of your quota. If overages are enabled for your account, you will see the **Surpassing** notifications. Otherwise, you will only see the **Nearing** and **Exceeding** notifications. - -To pause a system usage notification, follow these steps: - -1. Open [Defender Billing Settings](https://defender.openzeppelin.com/v2/#/billing/settings) in a web browser. -2. Filter the notifications table by selecting the "System" tab. -3. Locate the **Nearing Monitor Alerts** or **Surpassing Monitor Alerts** notification. -4. Toggle the switch to pause the notification. - -![Nearing Monitor Alerts](/defender/guide-usage-notifications-system-unmetered.png) - -![Surpassing Monitor Alerts](/defender/guide-usage-notifications-system.png) - - -If a user disabled system notifications from their profile, they will also be opted out of all system notifications, regardless of their individual paused state. - - -![Disable System Notifications](/defender/guide-profile-disable-system-notifications.png) - -## Next steps - -Congratulations! You have successfully set up a custom usage notification. Once your Action Runs usage exceeds the 75% threshold, all your tenant administrators will receive an email notification. In addition, you have paused the default system usage notification for when Monitor Alert exceeds the 90% (or 200% for users with overages enabled) threshold. Therefore, your tenant administrators will no longer receive a system email notification when this happens. diff --git a/content/defender/index.mdx b/content/defender/index.mdx deleted file mode 100644 index 2078733c..00000000 --- a/content/defender/index.mdx +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: Defender ---- - - - - -New sign-ups were disabled on June 30, 2025. Until the final shutdown on July 1, 2026, Defender will remain fully operational while we focus on the open source versions of tools like Relayers and Monitor. Detailed migration guides are coming soon to help you transition seamlessly to open source. - -[Read more](https://blog.openzeppelin.com/doubling-down-on-open-source-and-phasing-out-defender) - - - - - -- **[Migrate from Defender Monitor to OpenZeppelin Monitor](/defender/migration#monitor-migration)** - Export configurations, set up infrastructure, and test your monitors -- **[Migrate from Defender Relayer to OpenZeppelin Relayer](/defender/migration#relayer-migration)** - Transfer relayers, update SDK integration, and migrate transaction handling - -View the complete [Migration Guide](/defender/migration) for detailed instructions. - - - -OpenZeppelin Defender is a mission-critical developer security platform to **code**, **audit**, **deploy**, **monitor**, and **operate** blockchain applications with confidence. - -Integrating directly into the developer workflow, Defender makes it easy and fast for developers and operators to prevent and fix security issues pre and post-deployment. - -## Subscriptions -Defender offers flexible subscriptions to match your team’s needs and support your project at any scale. - -* **Builder (Free)** - Suitable for individuals and small projects that are getting started on testnets and need access to all basic features with limited quotas. -* **Professional** - For mature projects running on mainnets that need access to premium features, higher quotas and metered billing, as well as access to OpenZeppelin support and SLA. -* **Enterprise** - For large projects with higher volumes that need a custom plan to meet their project needs, with higher quotas, access to all premium and security features, and a dedicated support channel. - -## Modules - -Defender modules work seamlessly together, providing users powerful features and a superior, integrated experience. Learn more about each module by clicking on its card. - - - - Automatic code analysis powered by AI models and tools developed by our security experts. - - - Manage the smart contract audit process and track issues and resolutions. - - - Manage deployments and upgrades to ensure secure releases. - - - Send transactions to the blockchain via Defender automatically. - - - Detect smart contract activity and anomalies through trigger actions and alerts. - - - Create transactions to be executed on-chain. - - - Create automated actions to perform on-chain and off-chain operations. - - - Create a shared repository of user-friendly names for your accounts or contracts. - - - Manage smart contract accounts, roles, and permissions easily. - - -## Available networks -Defender works with most mainnet and testnet networks, as well as local mainnet forks. - -* [**Arbitrum One**](https://arbitrum.io/), [**Arbitrum Nova**](https://nova.arbitrum.io/), **Arbitrum Sepolia**. -* [**Aurora**](https://aurora.dev/) and **Aurora Testnet**. -* [**Avalanche C**](https://docs.avax.network/dapps) and **FUJI C-Chain**. -* [**Base Mainnet**](https://www.base.org/) and **Base Sepolia**. -* [**Binance Smart Chain**](https://docs.binance.org/smart-chain/guides/bsc-intro.html) and **BSC testnet**. -* [**Celo**](https://celo.org/) and **Alfajores**. -* [**Ethereum Mainnet**](https://ethereum.org/en/), **Sepolia** testnet and **Holesky** testnet. -* [**Fantom**](https://fantom.foundation/what-is-fantom-opera/) and **Fantom Testnet**. -* [**Fuse**](https://fuse.io/). -* [**Gnosis Chain**](https://www.gnosis.io/) -* [**Hedera**](https://hedera.com/) and **Hedera Testnet**. -* [**Japan Open Chain**](https://www.japanopenchain.org/en/docs/developer/mainnet) and **Japan Open Chain Testnet**. -* [**Linea Mainnet**](https://linea.build/) and **Linea Sepolia**. -* [**Scroll Mainnet**](https://scroll.io/) and **Scroll Sepolia**. -* [**Mantle Mainnet**](https://www.mantle.xyz/) and **Mantle Sepolia**. -* [**Meld Mainnet**](https://www.meld.com/) and **Meld Testnet**. -* [**Moonbeam**](https://moonbeam.network/), **Moonriver**, and **Moonbase Alpha (Testnet)**. -* [**OP Mainnet**](https://optimism.io/), **OP Sepolia**. -* [**Polygon** (POL)](https://www.polygon.technology/), **Amoy**, [**zkEVM**](https://polygon.technology/polygon-zkevm) and **Polygon Cardona zkEVM testnet** -* [**Scroll Mainnet**](https://scroll.io/) and **Scroll Sepolia**. -* [**Unichain**](https://www.unichain.org/) and **Unichain Sepolia**. -* [**zkSync Era Mainnet**](https://zksync.io/) and **zkSync Era Sepolia**. -* [**Geist Mainnet**](https://www.playongeist.com//) and **Polter Testnet**. -* [**Abstract Mainnet**](https://docs.abs.xyz/overview) and **Abstract Sepolia**. -* [**Peaq Mainnet**](https://www.peaq.network/) and **Peaq Agung**. -* [**Sei**](https://www.sei.io/) and **Sei Testnet (Atlantic-2)**. - -If there is any other network or layer-2 solution you would like to use from Defender, please [reach out to us via the form on Defender](#feedback)! - -### Status -You can check the status of Defender and the supported networks on our [status page](https://status.defender.openzeppelin.com/), where you can also subscribe to receive notifications. If a supported network experiences issues, some features in Defender for that network may not work properly. - -## Integrations -Integrations throughout Defender allow users to connect with other services and tools. Find the list of integrations and more information [here](/defender/integrations). - -## Service Level and Support Agreement -For our [paid subscriptions](https://www.openzeppelin.com/pricing), we’re offering enhanced service reliability, guaranteed uptime, and priority support. You can learn more on our [Service Level and Support Agreement (SLA) page](https://www.openzeppelin.com/service-level-agreement). - -## Feedback - -As a Defender user, your feedback is important! Please provide us feedback by accesing the form on the bottom-right corner of your screen. - -![Feedback form button bottom-right corner](/defender/feedback-button.png) diff --git a/content/defender/integrations.mdx b/content/defender/integrations.mdx deleted file mode 100644 index f736daa6..00000000 --- a/content/defender/integrations.mdx +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Integrations ---- - -Defender seamlessly integrates with your existing tools and workflows, so you can easily secure your project throughout the secure development lifecycle. - -## SDK Plugins -* [**Hardhat**](https://hardhat.org/): Code, deploy and upgrade your Hardhat projects through Defender. -* [**Foundry**](https://getfoundry.sh/): Code your Foundry projects with support of Defender. - -## IDEs -* [**Remix**](https://remix.ethereum.org/): Deploy your Remix contracts using Defender deployment environments through the Defender Remix Plugin. - -## Libraries -* [**OpenZeppelin Contracts**](https://www.openzeppelin.com/contracts): Speed up your smart contract development with security and performance baked in. - -## Continuous Integration -* [**GitHub**](/defender/module/code): Install Code Inspector to maximize security in every project PR. -* [**Defender as Code (DaC)**](/defender/dac): Serverless Framework plugin for automated resource management. - -## Key Management & Transaction Execution -* [**Safe**](https://app.safe.global/): Use Safe multisigs to approve Defender operations. -* [**Fireblocks**](https://www.fireblocks.com/): Use Fireblocks assets to approve Defender operations. -* [**Flashbots**](https://www.flashbots.net/): Send private transactions to prevent MEV and other attack vectors. - -## Notification & Logging -* [**Datadog**](https://www.datadoghq.com/): Push notifications and logs to your Datadog system. -* [**PagerDuty**](https://www.pagerduty.com/): Configure PagerDuty to receive notifications and trigger operations. -* [**Opsgenie**](https://www.atlassian.com/software/opsgenie): Configure Opsgenie to receive notifications for their alert management services. -* [**Slack**](https://slack.com/): Configure Slack channels to receive notifications. -* [**Telegram**](https://telegram.org/): Configure Telegram bots to receive notifications. -* [**Discord**](https://discord.com/): Configure Discord channels to receive notifications. -* **Webhooks**: Configure any Webhook to manage any type of alert with complete flexibility. -* **Email**: Receive alerts via any Email. - -## Threat Detection & Transaction Data -* [**Etherscan**](https://etherscan.io/): Visualize transactions from Defender using Etherscan-based explorers. -* [**Blockscout**](https://www.blockscout.com/): Visualize transactions from Defender using Blockscout-based explorers. - -## Source Code -* [**Github**, window=_black](https://github.com/): Install our [Code Github application](/defender/module/code) to scan your project with every pull request to identify potential vulnerabilities and suggest improvements to enhance your code quality. - -If there is any other integration you would like, please [reach out to us via the form on Defender](#feedback)! diff --git a/content/defender/logs.mdx b/content/defender/logs.mdx deleted file mode 100644 index 8e6c8a06..00000000 --- a/content/defender/logs.mdx +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: Logs ---- - -Defender generates log trails of every potentially relevant event in the system. This includes manual actions, such as modifying an Action or Monitor, as well as automated activity, such as sending a transaction or firing a notification. Logs can be optionally forwarded to Datadog and Splunk for aggregation or exported. - -## Use cases - -* Track user actions on your team by monitoring sign ins and activity across the application -* Detect potential attacks on your infrastructure from failed sign in attempts -* Follow relayer activity to understand the transactions being sent from your accounts -* Keep an audit trail of all module configuration changes -* Filter by severity, type, user, module, time, and more - -## Log Entries - -Every log entry is structured with the following format: - -* `Module`: The origin of the log entry, such as Monitor, Actions, Workflows, Deploy, etc. -* `Date and Time`: The day and time the log entry was generated with the format `Day Month Year` and 12-hour clock format in the browser local timezone -* `Severity`: The severity level of the log entry, ranging from `trace` to `error` -* `Subject`: The trigger/cause that generated the log. If contract related, the contract name is displayed -* `Event`: Type of acitivty logged. For example, `Created`, `Added`, `Deledated`, `Updated`, etc. -* `Description`: Details on the event. For example, `Contract was updated`, `Address book entry was updated`, etc. -* `User`: Team user that generated the log entry, directly or indirectly - -![Logs Page](/defender/logs.png) - -You can click on each log entry to get a detailed view, which includes the tenant id, user id, activity response, request, log id, timestamp, and more. - -![Logs Detailed View](/defender/logs-detailed.png) - -## Log Forwarding - -Generated logs can be forwarded to Datadog and Splunk, or any other service that supports API Key authentication. You can use this to aggregate all logs across your infrastructure in a single place. - -## Setup Log Forwarding Destination - -To set up a log forwarding destination, open the Logs page and click the 'Send Logs to an External Service' button. - -Form fields: - -* **URL** field is a required field. All logs are forwarded to this URL address using HTTP POSTs. -* **API Header Name** is optional. This is the name of the request header that contains the API Key value. Most log management services require it. Please refer to your log management service documentation to determine if you need it. -* **API Key** is an optional field. API Key is sent with every request for authentication purposes. Most log management services require it. Please refer to your log management service documentation to determine if you need it. -* **Log Types** lets you specify which subset of Defender generated logs you want to have forwarded based on Defender components. -* **Log Levels** lets you specify which subset of Defender generated logs you want to have forwarded based on the log levels. For example debug logs can be used for Autotasks debugging purposes and they can contain data that should not be exported to external systems. - - -In the next section we will cover how to setup Log Forwarding with Splunk and Datadog but it is worth noting that Log Forwarding works with any other service that supports API Key authentication. - - -### Splunk - -Forwarding logs to Splunk is done by using Splunk HEC(HTTP Event Collector). -Documentation for setting up logging with Splunk HEC can be found [here](https://docs.splunk.com/Documentation/Splunk/latest/Data/UsetheHTTPEventCollector). - - -Log Forwarding does not work with Splunk trial accounts because of Splunk internals. - - -Example: - -* **URL**: `https://username.splunkcloud.com/services/collector/raw` -* **API Header Name**: `Authorization` -* **API Key**: `Splunk xxxxxxxxxxxxxxxxxxxxxxxxxxx` - - -`URL` value is dynamic as URL includes account username. - - - -`API Key` should contain `Splunk` prefix. - - -### Datadog - -Documentation for setting up logging on Datadog can be found [here](https://docs.datadoghq.com/logs/). - -Example: - -* **URL**: `https://http-intake.logs.datadoghq.com/api/v2/logs` -* **API Header Name**: `DD-API-KEY` -* **API Key**: `xxxxxxxxxxxxxxxxxxxxxxxxxxx` - - -Datadog uses different sites around the world. For example, if you are relying on an EU server the `URL` field value should be https://http-intake.logs.datadoghq.eu/api/v2/logs - - - -`API Key` value can be obtained from Datadog site by opening `Logs` section from the left menu. -Go to `Cloud` section and select `AWS` provider. -After following those steps, the `API Key` value is displayed in the bottom section of the page. - diff --git a/content/defender/migration.mdx b/content/defender/migration.mdx deleted file mode 100644 index 0c3b488b..00000000 --- a/content/defender/migration.mdx +++ /dev/null @@ -1,480 +0,0 @@ ---- -title: Migrating from Defender to Open Source ---- - -## Overview - -Defender is now in maintenance mode. To continue using monitoring and relaying capabilities with the latest features and updates, we recommend migrating to OpenZeppelin's open source tools. - -This guide covers: - -- Migrating from **Defender Monitor** to [OpenZeppelin Monitor](/monitor) -- Migrating from **Defender Relayer** to [OpenZeppelin Relayer](/relayer) - -Both tools are designed to be self-hosted, giving you full control over your infrastructure while maintaining the functionality you rely on. - -## Migration Strategy - -### Planning Your Migration - -1. **Review your current usage**: Identify which Defender modules you're actively using -2. **Export configurations**: Use Defender UI to export Monitors and Relayers configuration -3. **Set up infrastructure**: Configure the open source tools on your own infrastructure -4. **Test thoroughly**: Run both systems in parallel during the transition period -5. **Migrate traffic gradually**: Switch over when you're confident everything works correctly - -### Timeline Considerations - -- Plan for adequate testing time before fully switching over -- Consider running both systems in parallel during migration -- Schedule migration during low-traffic periods if possible - ---- - -## Monitor Migration - -### From Defender Monitor to OpenZeppelin Monitor - -OpenZeppelin Monitor offers similar functionality to Defender Monitor: - -- **Event and function monitoring**: Monitor smart contract events and function calls -- **Custom filtering**: Write custom JavaScript, Python or Bash filters to match specific conditions -- **Multiple notification channels**: Integrate with Slack, Telegram, Discord, webhooks and emails - -### Getting Started - -To begin your Monitor migration: - -1. **Review your existing monitors**: Export your Defender Monitor configurations using the "Download OpenZeppelin Monitor Configurations" button -2. **Import your configurations**: Use the exported configurations to recreate your monitors in OpenZeppelin Monitor -3. **Set up OpenZeppelin Monitor**: Follow the [installation guide](/monitor) to set up the Monitor. - -Defender Monitor Migration Button - -The "OpenZeppelin Monitor Configurations" button will download a .zip file containing configuration files for every monitor in your Defender account (If for any reason you don't want a specific monitor to be migrated, we recommend you delete the monitor before clicking on the OpenZeppelin Monitor Configurations button ). These configurations are ready to copy and paste directly into OpenZeppelin Monitor. Before running the monitors, make sure to review and update any placeholder values in the configuration files, such as: - -- API keys and secrets -- RPC URLs and endpoint addresses -- Webhook URLs for notifications -- Service integration credentials (Slack, Telegram, Discord, etc.) - - - Custom Actions attached to your Defender monitors will not be automatically - migrated. You will need to manually recreate any custom action logic following - the [OpenZeppelin Monitor documentation](/monitor) for trigger handlers and - custom notifications. - - -Alternatively, if you don't want to download all the monitors configurations at once, you can navigate to each individual monitor and download its configuration separately. This gives you more control over which monitors to migrate and when. - -Download Individual Monitor Config - -Here's a video with the process step by step: https://www.loom.com/share/6de3d269f92c4df6abe951af69c64feb - -4. **Test your monitors**: Verify that alerts trigger correctly before decommissioning Defender monitors - -For detailed migration instructions and support, visit the [OpenZeppelin Monitor documentation](/monitor). - ---- - -## Relayer Migration - -### From Defender Relayer to OpenZeppelin Relayer - -[OpenZeppelin Relayer](/relayer) is an open-source transaction relaying service that provides secure, reliable transaction submission to blockchain networks. With **Defender shutting down on July 1, 2026**, migrating to OpenZeppelin Relayer ensures continuity of your relaying infrastructure while giving you full control over your deployment. - -OpenZeppelin Relayer offers similar functionality to Defender Relayer: - -- **Transaction relaying**: Submit transactions to supported blockchain networks efficiently -- **Transaction signing**: Securely sign transactions using configurable key management -- **Nonce management**: Handle nonce management to ensure transaction order -- **Gas pricing**: Automatic gas price estimation and configuration -- **Multi-chain support**: Interact with EVM, Solana, and Stellar networks -- **SDK integration**: Easily interact with the relayer through a companion JavaScript/TypeScript SDK -- **Configurable policies**: Define and enforce network-specific policies for transaction processing - -### Getting Started - -Follow these steps to migrate your Defender Relayers to OpenZeppelin Relayer: - -#### Step 1: Download Configuration from Defender - -Export your Defender Relayer configurations using the "OpenZeppelin Relayer Configurations" button in the Defender UI. - -Defender Relayer Migration Button - - - If you don't want a specific relayer to be migrated, delete that relayer - before clicking the download button. - - -**What you'll download:** - -A **ZIP file** containing: - -- `config.json` - Your relayer configurations -- `networks/` folder - Custom network definitions (if you have relayers on forked or private networks) - -#### Step 2: Set Up OpenZeppelin Relayer - -Before importing your configurations, set up the OpenZeppelin Relayer infrastructure by following the [OpenZeppelin Relayer Quick Start Guide](/relayer/quickstart). - -#### Step 3: Place Configuration Files - -1. Extract the downloaded ZIP file -2. Copy `config.json` to the `config/` directory in your OpenZeppelin Relayer project -3. If you have custom networks, copy the `networks/` folder contents to `config/networks/` - -Your directory structure should look like: - -``` -openzeppelin-relayer/ -├── config/ -│ ├── config.json -│ └── networks/ # Only if you had forked/private networks -│ ├── my-network.json -│ └── ... -``` - -#### Step 4: Adjust Configuration - -After placing the files, you need to update several configuration values: - -**For custom networks:** - -If you have forked or private networks, update the RPC URLs in each network definition file under `config/networks/`. Replace placeholder values with your actual RPC endpoint URLs: - -```json -{ - "network": "my-custom-network", - "rpc_urls": ["https://your-rpc-endpoint.com"] -} -``` - -**For all relayers:** - -Edit `config/config.json` to update: - -1. **Signer configuration**: Each relayer needs a signer configured. See [Choosing a Signer Type](#choosing-a-signer-type) below for options and setup instructions. - -2. **Notification webhooks**: Update the `notifications` section with your webhook URLs: - -```json -"notifications": [ - { - "id": "my-webhook", - "type": "webhook", - "url": "https://your-webhook-endpoint.com/notifications", - "signing_key": { - "type": "env", - "value": "WEBHOOK_SIGNING_KEY" - } - } -] -``` - -3. **Network-specific policies**: Review and adjust policies for each relayer as needed (gas price caps, minimum balance thresholds, whitelist receivers, etc.). - - - For detailed configuration options, see the [OpenZeppelin Relayer - Configuration documentation](/relayer/configuration). - - -#### Step 5: Verify OpenZeppelin Relayer Works - -After configuring, start the relayer and verify it's working correctly: - -1. **Start the relayer** using one of the methods described in the [Quick Start Guide](/relayer/quickstart) (either running locally with Cargo or using Docker Compose). - -2. **Check the startup logs** for any configuration errors or warnings. - -3. **Test the API endpoints** to verify your relayers are configured correctly: - -```bash -# Get relayer details -curl -X GET http://localhost:8080/api/v1/relayers/{relayer_id} \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer YOUR_API_KEY" - -# Check relayer balance -curl -X GET http://localhost:8080/api/v1/relayers/{relayer_id}/balance \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer YOUR_API_KEY" -``` - -Replace `{relayer_id}` with your relayer's ID and `YOUR_API_KEY` with the API key from your `.env` file. - -A successful response confirms your relayer is properly configured and connected to the network. - -#### Step 6: Transfer Funds - -Once OpenZeppelin Relayer is running correctly: - -1. Go to **Defender Relayers** in the Defender UI -2. Select the relayer you want to migrate -3. Go to settings -4. Click the **Withdraw** button - -Defender Relayer Withdraw Button - -5. **Recommended**: Transfer a small amount first and test with a transaction -6. If the test transaction succeeds, transfer the remaining funds - - - Since you're creating new relayer addresses (see [Understanding Signer - Migration](#understanding-signer-migration)), make sure to update any smart - contract permissions, whitelists, or access control lists to include the new - addresses before transferring all funds. - - -#### Step 7: Gradually Move Traffic - -After successful testing: - -1. Run both Defender and OpenZeppelin Relayer in parallel -2. Shift traffic incrementally from Defender to OpenZeppelin Relayer -3. Monitor for any issues -4. Once confident, fully switch over to OpenZeppelin Relayer - -Here's a video with the process step by step: https://www.loom.com/share/cb5e0f5d8c064a71abc8c18fac273cf0 - -### Understanding Signer Migration - - -**Relayer recreation is required due to AWS KMS security constraints** - -Defender Relayers use AWS Key Management Service (AWS KMS) to secure private keys. Due to AWS KMS's security model, **private keys cannot be exported** outside AWS. This means: - -- You cannot export existing Defender Relayer private keys -- You cannot import Defender Relayer keys into OpenZeppelin Relayer -- You **must create new relayers with new addresses** when migrating to OpenZeppelin Relayer - -This is a fundamental security feature of AWS KMS that protects your keys from unauthorized access. - - - -### Choosing a Signer Type - -OpenZeppelin Relayer supports multiple signer types to accommodate different security requirements and infrastructure setups. Each relayer must be configured with a signer that manages the private key for transaction signing. - -#### Available Signer Options - -| Signer Type | Description | -| ------------------------------------- | ------------------------------------------------ | -| **Local** | Encrypted keystore file stored on the filesystem | -| **AWS KMS** | Amazon Web Services Key Management Service | -| **Google Cloud KMS** | Google Cloud Key Management Service | -| **HashiCorp Vault** | Vault secret engine for private key storage | -| **HashiCorp Vault Transit** | Vault Transit encryption engine | -| **Turnkey** | Third-party key management service | -| **Coinbase Developer Platform (CDP)** | Coinbase's managed key solution | - -#### Migration Steps for Signers - -1. **Select a signer type** that matches your security and infrastructure requirements -2. **Generate new keys** using your chosen signer service (refer to the [Signer Configuration documentation](/relayer/configuration/signers) for detailed setup instructions) -3. **Configure your relayers** to use the new signers in your OpenZeppelin Relayer configuration -4. **Update smart contract permissions**: Since you'll have new addresses, update any: - - Access control lists - - Whitelist entries - - Role assignments - - Trusted forwarder configurations -5. **Transfer funds** from old Defender Relayer addresses to new OpenZeppelin Relayer addresses -6. **Test thoroughly** before switching production traffic - - - For detailed configuration instructions for each signer type, see the - [OpenZeppelin Relayer Signer Configuration - documentation](/relayer/configuration/signers). - - -### SDK Migration - -If you are using the [Defender SDK](https://github.com/OpenZeppelin/defender-sdk) (`@openzeppelin/defender-sdk`) to interact with Defender Relayers programmatically, you will need to migrate to the [OpenZeppelin Relayer SDK](https://github.com/OpenZeppelin/openzeppelin-relayer-sdk) (`@openzeppelin/relayer-sdk`). - -#### Installation - -Replace the Defender SDK with the OpenZeppelin Relayer SDK: - -```bash -# Remove Defender SDK -npm uninstall @openzeppelin/defender-sdk @openzeppelin/defender-sdk-relay-client @openzeppelin/defender-sdk-relay-signer-client - -# Install OpenZeppelin Relayer SDK -npm install @openzeppelin/relayer-sdk -``` - -#### Code Migration Examples - -**Sending a Transaction** - -Before (Defender SDK): - -```jsx -const { Defender } = require("@openzeppelin/defender-sdk"); -const client = new Defender({ - relayerApiKey: "YOUR_API_KEY", - relayerApiSecret: "YOUR_API_SECRET", -}); - -const tx = await client.relaySigner.sendTransaction({ - to: "0x...", - value: "1000000000000000000", - data: "0x", - gasLimit: 21000, - speed: "fast", -}); -``` - -After (OpenZeppelin Relayer SDK): - -```typescript -import { RelayerApi, Configuration } from "@openzeppelin/relayer-sdk"; - -const config = new Configuration({ - basePath: "http://localhost:8080/api/v1", - accessToken: "YOUR_API_KEY", -}); - -const relayerApi = new RelayerApi(config); - -const tx = await relayerApi.sendTransaction("your-relayer-id", { - to: "0x...", - value: "1000000000000000000", - data: "0x", - gas_limit: 21000, - speed: "fast", -}); -``` - -**Getting Transaction Status** - -Before (Defender SDK): - -```jsx -import { Relayer } from "@openzeppelin/defender-sdk-relay-signer-client"; -const relayer = new Relayer({ apiKey: API_KEY, apiSecret: API_SECRET }); -const tx = await relayer.getTransaction(transactionId); -``` - -After (OpenZeppelin Relayer SDK): - -```typescript -import { RelayerApi, Configuration } from "@openzeppelin/relayer-sdk"; - -const config = new Configuration({ - basePath: "http://localhost:8080/api/v1", - accessToken: "YOUR_API_KEY", -}); - -const relayerApi = new RelayerApi(config); -const tx = await relayerApi.getTransactionById( - "your-relayer-id", - transactionId -); -``` - -**Listing Relayers** - -Before (Defender SDK): - -```jsx -const { Defender } = require("@openzeppelin/defender-sdk"); -const client = new Defender({ - apiKey: "YOUR_API_KEY", - apiSecret: "YOUR_API_SECRET", -}); - -const relayers = await client.relay.list(); -``` - -After (OpenZeppelin Relayer SDK): - -```typescript -import { RelayerApi, Configuration } from "@openzeppelin/relayer-sdk"; - -const config = new Configuration({ - basePath: "http://localhost:8080/api/v1", - accessToken: "YOUR_API_KEY", -}); - -const relayerApi = new RelayerApi(config); -const relayers = await relayerApi.listRelayers(); -``` - -#### API Method Mapping - -| Defender SDK Method | OpenZeppelin Relayer SDK Method | -| -------------------------------------- | --------------------------------- | -| `client.relaySigner.sendTransaction()` | `relayerApi.sendTransaction()` | -| `relayer.getTransaction()` | `relayerApi.getTransactionById()` | -| `relayer.list()` | `relayerApi.listTransactions()` | -| `relayer.replaceTransactionById()` | `relayerApi.replaceTransaction()` | -| `relayer.cancelTransactionById()` | `relayerApi.cancelTransaction()` | -| `relayer.sign()` | `relayerApi.sign()` | -| `relayer.signTypedData()` | `relayerApi.signTypedData()` | -| `relayer.getRelayer()` | `relayerApi.getRelayer()` | -| `relayer.getRelayerStatus()` | `relayerApi.getRelayerStatus()` | - -For detailed migration instructions and support, visit the [OpenZeppelin Relayer documentation](/relayer). - ---- - -## Support and Resources - -### Documentation - -- [OpenZeppelin Monitor Documentation](/monitor) -- [OpenZeppelin Relayer Documentation](/relayer) - -### Getting Help - -If you encounter issues during migration or have questions: - -- Review the respective documentation for each tool -- Check GitHub repositories for issues and discussions -- Reach out to the OpenZeppelin community - -### Migration Checklist - -Use this checklist to track your migration progress: - -#### Monitor Migration - -- [ ] Export Monitor configurations from Defender -- [ ] Review and update placeholder values (API keys, RPC URLs, etc.) -- [ ] Set up OpenZeppelin Monitor infrastructure -- [ ] Import and configure monitors -- [ ] Recreate custom action logic -- [ ] Test alert triggers -- [ ] Run in parallel with Defender Monitor -- [ ] Switch over and decommission Defender monitors - -#### Relayer Migration - -- [ ] Export Relayer configurations from Defender -- [ ] Review and update placeholder values (signers, RPC URLs, policies) -- [ ] Set up OpenZeppelin Relayer infrastructure -- [ ] Import and configure relayers -- [ ] Update SDK integration code (if applicable) -- [ ] Test transaction processing -- [ ] Run in parallel with Defender Relayers -- [ ] Transfer funds from Defender Relayers -- [ ] Gradually move traffic to OpenZeppelin Relayers -- [ ] Decommission Defender Relayers diff --git a/content/defender/module/access-control.mdx b/content/defender/module/access-control.mdx deleted file mode 100644 index 7fecf7f3..00000000 --- a/content/defender/module/access-control.mdx +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: Access Control ---- - -Access control allows you to seamlessly oversee and command contract permissions on a grand scale, with the power to view and control access at a granular level. Currently supports [ownable](https://docs.openzeppelin.com/contracts/4.x/access-control#ownership-and-ownable) and [role-based](https://docs.openzeppelin.com/contracts/4.x/access-control#role-based-access-control) access control. - - -At this time, access control is supported across all networks except **Hedera**, **Fantom Testnet** and **Arbitrum Nova**. - - -## Use cases - -* Manage ownership of contracts and proxies, including the ability to transfer ownership to a multisig or DAO -* Identify roles, and remove or give permissions to addresses through multisigs or wallets -* Import contracts from the supported networks, or use contracts deployed through Defender. - -## Contracts - -The main page shows all your contracts from the [Address Book](/defender/module/address-book) that have an access control interface supported. You can also add an existing contract to the Address Book by clicking on the "Add new contract" button. This is a one-time form where you specify the network, address and name. The contract’s ABI will be automatically pulled from the respective block explorers if available. If not, you will have to enter the ABI manually. When a contract is added, the main page will update and show it if applicable. - -![Access control main page](/defender/access-control.png) - -* Not Ownable: contract has no ownership interface -* Ownable: current owner address -* Roles: number of roles found in the contract - -## Contract - -The contract page contains all the information about the contract selected, including the name, environment, network, address, and roles found. Defender performs on-chain syncs with the contract every minute, with the last sync time found on the top right of the page. - -Access control automatically tries to fetch all roles within a contract, but there’s the possibility of missing some. In this case, you can add a role manually by clicking on the "Add new role" button and specifying the name of it. - -When modifying a role, you have to choose which admin address to use. In the case of a multisig as admin, the transaction to modify the role will be wrapped into a proposal, which will be pending until approved by the other signers (if any) and executed. You can see the pending proposals on the right side of the page. - -![Access control contract page](/defender/access-control-contract.png) - - -We provide a quickstart tutorial to change access control roles using Defender. Check it out [here](/defender/tutorial/access-control)! - diff --git a/content/defender/module/actions.mdx b/content/defender/module/actions.mdx deleted file mode 100644 index 012493e8..00000000 --- a/content/defender/module/actions.mdx +++ /dev/null @@ -1,499 +0,0 @@ ---- -title: Actions ---- - -Actions allow you to implement custom app logic for on-chain and off-chain operations. You can enable automated responses to threats detected by the [Monitor](/defender/module/monitor) and [Workflows](/defender/module/actions#workflows) modules. - -## Use cases - -* Automate smart contract operations -* Execute actions as response to a [Monitor](/defender/module/monitor) alert -* Automate [Workflow](/defender/module/actions#workflows) steps with Actions -* Call external APIs and interact with other smart contracts - -## Actions - -Actions are automated Javascript pieces of code that can be executed via triggers. - -![Automatic Action](/defender/auto-action-general-info.png) - -### Triggers - -The following triggers are supported: - -* **Schedule**: Choose a frequency, and Defender will invoke the function at the specified interval. Note that the specified interval is between two consecutive execution starts, _not_ between the end of one run and the beginning of the next one. Alternatively, it’s possible to specify when the action should run using [cron expressions](https://crontab.cronhub.io/). -* **Webhook**: Defender will create a webhook URL for the action, which will be executed whenever an HTTP POST request is sent to that endpoint. The URL can be regenerated at any time. When invoked, the HTTP request information will be injected into the action, and the HTTP response will include the action run info along with any data returned from the action. - - -When sending requests to the webhook, make sure to include the `Content-Type: application/json` header. We have a strict requirement for this header to be present in the request. Otherwise you will see `415 Unsupported Media Type` error. - - -* **Monitor**: Triggered by a Defender [Monitor](/defender/module/monitor). It will contain a body property with the details for the triggering event that you can use to run custom logic. - -### Environment - -Actions run in a [node 20 environment](https://nodejs.org/dist/latest-v20.x/docs/api/) with 256mb RAM and a 5-minute timeout. The code for each action must be smaller than 5mb in size. For ease-of-use, a set of common dependencies are pre-installed in the environment. The latest action dependenacy version `v2025-01-16` has the following dependencies: - -```jsx -"@datadog/datadog-api-client": "^1.0.0-beta.5", -"@fireblocks/fireblocks-web3-provider": "^1.3.1", -"@gnosis.pm/safe-core-sdk": "^0.3.1", -"@gnosis.pm/safe-ethers-adapters": "^0.1.0-alpha.3", -"@openzeppelin/defender-admin-client": "1.54.6", -"@openzeppelin/defender-autotask-client": "1.54.6", -"@openzeppelin/defender-autotask-utils": "1.54.6", -"@openzeppelin/defender-kvstore-client": "1.54.6", -"@openzeppelin/defender-relay-client": "1.54.6", -"@openzeppelin/defender-sdk": "1.15.2", -"@openzeppelin/defender-sentinel-client": "1.54.6", -"axios": "^1.7.4", -"axios-retry": "3.5.0", -"ethers": "5.5.3", -"fireblocks-sdk": "^2.5.4", -"graphql": "^15.5.1", -"graphql-request": "3.4.0", -"web3": "1.9.0" -``` - - -Defender dependencies that are not under the `@openzeppelin` namespace are now deprecated. Impacted dependencies are defender-admin-client, defender-autotask-client, defender-autotask-utils, defender-kvstore-client, defender-relay-client, defender-sentinel-client - - - -If other dependencies are needed, a JavaScript module bundler, such as rollup or webpack, can be used. Refer to [this sample project](https://github.com/OpenZeppelin/defender-sdk/tree/main/examples/custom-ethers-pkg) to learn how. Contact us to add a dependacy you think other users would find useful! - - - -We love [Typescript](https://www.typescriptlang.org/) in the OpenZeppelin development team, and we hope you do too! If you want to write your actions in TypeScript, you’ll need to first compile them using `tsc` or via your bundler of choice, and then upload the resulting JavaScript code. Unfortunately, we don’t support coding directly in TypeScript in the user interface. All `defender-sdk` packages are coded in TypeScript and are packaged with their type declarations. You can also use the [openzeppelin/defender-sdk-action-client](https://www.npmjs.com/package/@openzeppelin/defender-sdk-action-client) package for type definitions for the event payload. - - -### Runtime Upgrades - -Actions must be kept updated with recent Node.js runtime versions to ensure they run in an up-to-date and secure environment. Occasionally, we enforce runtime upgrades to all Actions to a minimum runtime version. The process consists of: - -1. Sending email notifications before the automatic upgrade. -2. Displaying a UI banner under the actions page to warn about the upcoming automatic upgrade. -3. Making a forum announcement. -4. On the automatic upgrade day, Defender automatically upgrades all action runtimes to the minimum required version. - - -we suggest checking your Actions, making necessary changes, and upgrading in advance to prevent any breaking changes. - - -### Defining code - -#### Handler function - -Your code must export an async `handler` function that will be invoked on each execution of the action. - -```jsx -exports.handler = async function(event) - // Your code here - -``` - -The following interface contains the `event` types injected by Defender when invoking an Action: - -```typescript -export interface ActionEvent - /** - * Internal identifier of the relayer function used by the relay-client - */ - relayerARN?: string; - - /** - * Internal identifier of the key-value store function used by the kvstore-client - */ - kvstoreARN?: string; - - /** - * Internal credentials generated by Defender for communicating with other services - */ - credentials?: string; - - /** - * Read-only key-value secrets defined in the Action secrets vault - */ - secrets?: ActionSecretsMap; - - /** - * Contains a Webhook request, Monitor match information, or Monitor match request - */ - request?: ActionRequestData; - /** - * actionId is the unique identifier of the Action - */ - actionId: string; - /** - * Name assigned to the Action - */ - actionName: string; - /** - * Id of the the current Action run - */ - actionRunId: string; - /** - * Previous Action run information - */ - previousRun?: PreviousActionRunInfo; - -``` - -#### Relayer integration - -If you connect your automatic action to a relayer, then Defender will automatically inject temporary credentials to access the relayer from the action code. Simply pass the event object to the relayer client in place of the credentials: - -```jsx -const Defender = require('@openzeppelin/defender-sdk'); - -exports.handler = async function(event) - const client = new Defender(event); - - // Use relayer for sending txs or querying the network... - -``` - -This allows you to send transactions using the relayer from actions without having to set up any API keys or secrets. Furthermore, you can also use the relayer’s JSON RPC endpoint for making queries to any Ethereum network without having to configure API keys for external network providers. - -We also support [`ethers.js`](https://www.npmjs.com/package/@openzeppelin/defender-relay-client#ethersjs) for making queries or sending transactions via the relayer. To use ethers.js replace the above snippet with this: - -```jsx -const DefenderRelaySigner, DefenderRelayProvider = require('defender-relay-client/lib/ethers'); -const ethers = require('ethers'); - -exports.handler = async function(event) - const provider = new DefenderRelayProvider(event); - const signer = new DefenderRelaySigner(event, provider, { speed: 'fast' ); - // Use provider and signer for querying or sending txs from ethers, for example... - const contract = new ethers.Contract(ADDRESS, ABI, signer); - await contract.ping(); -} -``` - -If you prefer [`web3.js`](https://www.npmjs.com/package/@openzeppelin/defender-relay-client#web3js): - -```jsx -const DefenderRelayProvider = require('defender-relay-client/lib/web3'); -const Web3 = require('web3'); - -exports.handler = async function(event) - const provider = new DefenderRelayProvider(event, { speed: 'fast' ); - const web3 = new Web3(provider); - // Use web3 instance for querying or sending txs, for example... - const [from] = await web3.eth.getAccounts(); - const contract = new web3.eth.Contract(ABI, ADDRESS, from ); - await contract.methods.ping().send(); -} -``` - -#### Monitor invocations - -Actions triggered from a Monitor can have two types of body properties and scheme, depending what type of Monitor triggered the action: - -* In the case of a Defender monitor, the body will contain the [monitor event schema](/defender/module/monitor#monitor-event-schema). - -If the action is written in TypeScript, `BlockTriggerEvent` type from the [defender-sdk-action-client](https://www.npmjs.com/package/@openzeppelin/defender-sdk-action-client) package can be used. - -```jsx -exports.handler = async function(params) - const payload = params.request.body; - const matchReasons = payload.matchReasons; - const sentinel = payload.sentinel; - - // if contract monitor - const transaction = payload.transaction; - const abi = sentinel.abi; - - // custom logic... - -``` - -#### Webhook invocations - -When an action is invoked via a webhook, it can access the HTTP request info as part of the `event` parameter injected in the handler. Likewise, the return value will be included in the `result` field of the HTTP response payload. - -```jsx -exports.handler = async function(event) - const { - body, // Object with JSON-parsed POST body - headers, // Object with key-values from HTTP headers - queryParameters, // Object with key-values from query parameters - = event.request; - - return - hello: 'world' // JSON-serialized and included in the `result` field of the response - ; -} -``` - -At the moment only JSON payloads are supported, and only non-standard headers with the `X-` or `Stripe-` prefix are provided to the action. - -A sample response from the webhook endpoint looks like the following, where `status` is one of `success` or `error`, `encodedLogs` has the base64-encoded logs from the run, and `result` has the JSON-encoded value returned from the execution. - -```json - - "autotaskRunId": "37a91eba-9a6a-4404-95e4-38d178ba69ed", - "autotaskId": "19ef0257-bba4-4723-a18f-67d96726213e", - "trigger": "webhook", - "status": "success", - "createdAt": "2021-02-23T18:49:14.812Z", - "encodedLogs": "U1RBU...cwkK", - "result": "{\"hello\":\"world\"", - "requestId": "e7979150-44d3-4021-926c-9d9679788eb8" -} -``` - - -Actions that take longer than 25 seconds to complete will return a response with a pending state. Nevertheless, the action will continue to run in the background and eventually complete (in less than 5 minutes). - - - -If `"message":"Missing Authentication Token"` is the response to a Webhook HTTP request, double check that the request was actually a POST. This response occurs when issuing a GET. - - - -Webhook requests have strict content-type requirements. If the request does not have a `Content-Type: application/json` header, the action invocation will return a `415 Unsupported Media Type` error. Please make sure to include this header in your requests. - - -#### Secrets -Defender secrets allow you to store sensitive information, such as API keys and secrets that can be accessed securely from actions.\ -Action secrets are key-value case-sensitive pairs of strings, that can be accessed from action code using the `event.secrets` object. There is no limit to the number of secrets used by an action. Secrets are shared across all actions, and not specific to a single one. - -```jsx -exports.handler = async function(event) - const { mySecret, anApiKey = event.secrets; -} -``` - -Secrets are encrypted and stored in a secure vault, only decrypted for injection when the action runs. Once written, a secret can only be deleted or overwritten from the user interface, but not read. - - -An action may log the value of a secret, accidentally leaking it. - - - -While it’s possible to use secrets to store private keys for signing messages or transactions, we recommend to use a Defender relayer instead. Signing operations for Defender relayers provide an extra level of security over loading the private key in action code and signing there. - - -#### Key-value data store - -The action key-value data store allows to persist simple data across action runs and between different actions. It can be used to store transaction identifiers, hashed user emails, or even small serialized objects. - -You can interact with your key-value store through an instance of `Defender`, which is initialized with the payload injected in the your Action `handler` function. Once initialized, you can call `kvstore.get`, `kvstore.put`, or `kvstore.del`. - -```jsx -const Defender = require('@openzeppelin/defender-sdk'); - -exports.handler = async function (event) - const client = new Defender(event); - - await client.keyValueStore.put('myKey', 'myValue'); - const value = await client.keyValueStore.get('myKey'); - await client.keyValueStore.del('myKey'); -; -``` - -The key-value store allows to get, put, and delete key-value pairs, which must be strings that are limited to 1 KB and values to 300 KB. - - -Data stored is shared across all actions. To isolate the records managed by each action, prefixing the keys with a namespace unique to each action is recommended. - - - -Each item expires 90 days after its last update. If long-lived data store is needed, we recommend setting up an external database and use action secrets to store the credentials for connecting to it. - - -#### Notifications - -Actions can send notifications through various channels already defined in the Defender Notifications settings. This integration allows you to quickly inform other connected systems about changes detected or made by actions. - -To send a notification, you should use `notificationClient.send()`, as shown in the following example: -```js -exports.handler = async function(credentials, context) - const { notificationClient = context; - - try - notificationClient.send({ - channelAlias: 'example-email-notification-channel-alias', - subject: 'Action notification example', - message: 'This is an example of a email notification sent from an action', - ); - } catch (error) - console.error('Failed to send notification', error); - -} -``` - -For email notifications, basic HTML tags are supported. Here’s an example of how to generate an HTML message: -```js - -function generateHtmlMessage(actionName, txHash) - return ` -

Transaction sent from Action ${actionName

-

Transaction with hash $txHash was sent.

-`; -} - -exports.handler = async function(event, context) - const { notificationClient = context; - - const relayer = new Relayer(credentials); - - const txRes = await relayer.sendTransaction( - to: '0xc7464dbcA260A8faF033460622B23467Df5AEA42', - value: 100, - speed: 'fast', - gasLimit: '21000', - ); - - try - notificationClient.send({ - channelAlias: 'example-email-notification-channel-alias', - subject: `Transaction sent from Action ${event.actionName`, - message: generateHtmlMessage(event.actionName, txRes.hash), - }); - } catch (error) - console.error('Failed to send notification', error); - -} -``` - -To send a metric notification, use the `notificationClient.sendMetric()` method instead, as shown in the following example: - -```js -exports.handler = async function(credentials, context) - const { notificationClient = context; - - try - notificationClient.sendMetric({ - channelAlias: 'example-email-notification-channel-alias', - name: 'datadog-test-metric', - value: 1, - ); - } catch (error) - console.error('Failed to send notification', error); - -} -``` - - -If an invalid or paused notification channelAlias is passed, an error will be thrown. - - - -If a notification cannot be sent for any other reason, no error will be thrown, but a status message will be added to the action logs. For example, if a notification to a webhook channel that has an inactive URL is sent, a log entry will be added but no error will be thrown. - - - -If multiple notification channels are using the same alias, the notification will be sent to all of them. - - -#### Error handling - -Automatic action invocations that result in an error contain an `errorType` field in the action run response that will be set to an [ActionErrorType as defined in defender-sdk](https://github.com/OpenZeppelin/defender-sdk/blob/340fce19e35cfed420c94369630ee8f70254c9ac/packages/action/src/models/action-run.res.ts#L6). A user readable error will also appear in the Run History view. - -### Local development - -If you want to reproduce the behavior of an action locally for debugging or testing, follow these steps: - -* Initialize a new npm project (`npm init`) -* Set the `dependencies` key in `package.json` to the packages indicated in the [Environment](#environment) section above -* Download `yarn.lock`: 📎 [yarn.lock]() -* Run `yarn install --frozen-lockfile`. - -You can also use the following template for local development, which will run the action code when invoked using `node`. It will load the relayer credentials from environment variables, or use the injected credentials when run by Defender. - -```jsx -const Defender = require('@openzeppelin/defender-sdk'); - - -// Entrypoint for the action -exports.handler = async function(event) - const client = new Defender(credentials); - // Use client.relaySigner for sending txs - - -// To run locally (this code will not be executed in actions) -if (require.main === module) - const { RELAYER_API_KEY: apiKey, RELAYER_API_SECRET: apiSecret = process.env; - exports.handler( apiKey, apiSecret ) - .then(() => process.exit(0)) - .catch(error => console.error(error); process.exit(1); ); -} -``` - -Remember to send any other value that your action expects in the `event` object, such as secrets or monitor events. - -### Updating code - -You can edit an action’s code via the Defender interface, or programmatically via API using the [`defender-sdk`](https://www.npmjs.com/package/@openzeppelin/defender-sdk) npm package. The latter allows to upload a code bundle with more than a single file: - - -The code bundle must not exceed 5MB in size after being compressed and base64-encoded, and it must always include an `index.js` at the root of the zip file to act as the entrypoint. - - -## Workflows - -Workflows allow you to instantly detect, respond, and resolve threats and attacks with pre-defined actions and scenarios. You can conduct attack simulations and test real-world scenarios on forked networks too. - -Workflows are processes that combine automatic actions and transaction templates. Actions can be run in parallel or connected sequentially. Workflows can be triggered manually or via a [Monitor](/defender/module/monitor). - -Creating workflows is a seamless experience guided through a form that allows you to organize actions in the workflow process easily. - -![Create Workflow](/defender/actions-start-workflow.png) - -To populate a workflow, you have to drag existing actions from the list on the right onto the form. Actions are executed vertically, meaning the previous actions must finish successfully to begin the execution of the new row. Parallel actions are executed at the same time. However, the workflow stops completely if an action exits with an error. - -![Edit Workflow](/defender/actions-workflow.png) - -To run multiple actions in parallel, click "Add Parallel Sequence" and drag actions into the available side-by-side boxes. - -![Parallel Workflow](/defender/actions-parallel-workflow.png) - -You can drag actions back off the workflow to remove them or click the visible minus icon in the upper right to remove an empty step. The "Save" button on the top right saves the workflow with its configuration and name. - - -We provide a quickstart tutorial to create and use Workflows. Check it out [here](/defender/tutorial/workflows)! - - -## A complete example - -The following example uses ethers.js and the relayer integration to send a transaction calling `execute` on a given contract. Before sending the transaction, it checks a `canExecute` view function and validates if a parameter received via a webhook matches a local secret. If the transaction is sent, it returns the hash in the response, which is sent back to the webhook caller. - -```jsx -const ethers = require("ethers"); -const DefenderRelaySigner, DefenderRelayProvider = require('defender-relay-client/lib/ethers'); - -// Entrypoint for the action -exports.handler = async function(event) - // Load value provided in the webhook payload (not available in schedule or sentinel invocations) - const { value = event.request.body; - - // Compare it with a local secret - if (value !== event.secrets.expectedValue) return; - - // Initialize relayer provider and signer - const provider = new DefenderRelayProvider(event); - const signer = new DefenderRelaySigner(event, provider, speed: 'fast' ); - - // Create contract instance from the signer and use it to send a tx - const contract = new ethers.Contract(ADDRESS, ABI, signer); - if (await contract.canExecute()) - const tx = await contract.execute(); - console.log(`Called execute in ${tx.hash`); - return tx: tx.hash ; - } -} -``` - - -The code does not need to wait for the transaction to be mined. Defender will take care of monitoring the transaction and resubmitting if needed. The action only needs to send the request and exit. - - -## Security considerations - -The code for each action is isolated in Defender, and actions are restricted via strict access controls to have zero access to other Defender internal infrastructure. The only exception is that an action may access its linked relayer, which is negotiated via temporary credentials injected by the action service upon each execution. Still, the action can only call the relayer’s exposed methods and has no direct access to the backing private key or any other services. - - -We provide a quickstart tutorial to create an automatic action for a smart contract using Defender. Check it out [here](/defender/tutorial/actions)! - diff --git a/content/defender/module/address-book.mdx b/content/defender/module/address-book.mdx deleted file mode 100644 index 6ecdc667..00000000 --- a/content/defender/module/address-book.mdx +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Address Book ---- - -The Address Book allows you to create a shared repository of user-friendly names for your accounts or contracts. You can set up these names anywhere you see an address in Defender just by clicking on it, or you can manage your entire Address Book in the dedicated section. Defender automatically creates Address Book entries for you when you import accounts and contracts in other modules. - -When working with products in Defender, account and contract information will be directly sourced from the Address Book whenever you are required to enter an address, so you can easily fetch addresses from your Address Book when configuring monitors and actions. - -![Manage Address Book](/defender/manage-address-book.png) diff --git a/content/defender/module/audit.mdx b/content/defender/module/audit.mdx deleted file mode 100644 index 8bded02c..00000000 --- a/content/defender/module/audit.mdx +++ /dev/null @@ -1,82 +0,0 @@ ---- -title: Audit ---- - -Audit allows you to summon our team of security experts to verify your system works as intended with the highest level of scrutiny. You can track issues and resolutions, and interact directly with auditors for faster and more efficient communication. - -## Use cases - -* Maintain a searchable repository of all smart contract audits and issues. -* Streamline the interactions between auditors and developers. -* Automate the fix-review process for all identified issues. -* Track all issues identified in an audit to completion. - -## Auditors and Reports - -Auditors have special roles in Defender. Audit Managers are able to sync audit reports to Defender from GitHub and add the Auditors, which are able to read and track issues and questions. Audit Manager can also identify which members of your team have permission to read or comment on audits. - -Once an Audit Manager syncs and delivers an audit report to Defender, it will be visible to any team members who have been assigned the Audit Read or Audit Comment role. All active and historic audit reports will be visible, and team members can click on any audit report to view the details. - -![Audit Status Header](/defender/audit-status.png) - -The Audit page initially includes the project’s name, status, and date of report. Below this, you can find the executive summary of the audit, which provides an overview of the audit’s findings and the overall security posture of the smart contract or project. It also includes links and information on the scope, timeline, and Auditors. - -Below the executive summary, you can find the differente sections of the audit. - -### Overview - -The "Overview" section provides context and background information about the project or smart contract being audited. This section typically starts with a brief introduction to the project, including the project’s name, purpose, and a general description of what it aims to achieve. It’s followed by an overview of the architecture and key components of the project, supported by a high-level description of how the smart contract or blockchain application is structured and how different modules or components interact with each other. Information about the technology stack used in the project may be included. This can encompass the programming languages, libraries, frameworks, and blockchain platforms employed in the development. - -Depending on the audit, this section may also contain additional information about the smart contract’s privileged roles to explain its purpose and responsibilities within the project. This helps auditors and readers understand who has control over critical functions and what actions they can perform. Similarly, trust assumptions are commonly mentioned to outline implicit or explicit assumptions made by the project’s developers about the security and reliability of external components, services, or entities that the project relies on. Lastly, the "Overview" section may include client-found vulnerabilities if provided by the client. These are vulnerabilities or issues that have been identified by the project’s users or clients before the audit, helping the auditors understand the context and history of security concerns related to the project. - -### Issues - -The "Issues" section provides an in-depth examination of security vulnerabilities, bugs, or concerns discovered during the audit process. Within this section, you can filter the issues by content, severity, or status. Filtering by content allows you to look for issues with specific titles or descriptions. Filtering by severity allows you to look for issues with a specific severity level, like Critical, High, Medium, Low, Note, or Client Reported. Filtering by status allows you to look for issues with a specific status, like Unresolved, No Response, Responded, Resolved, Partially Resolved, Acknowledged Not Resolved, or Acknowledged Will Resolve. - -![Audit Issue Filters](/defender/audit-filter.png) - -Each issue within this section contains a title, description, date, and status. You can click on one to expand the information and be able to respond to it. - -![Audit Side Page](/defender/audit-side.png) - -The description explains the nature of the issue, its potential impact, and any technical details necessary for understanding the problem. The issue is also tagged with a severity assessment, helping to describe the impact, likelihood, and difficulty of an issue for prioritization and transparency. - -### Recommendations - -The "Recommendations" section offers actionable guidance to improve the security posture of the project based on the audit results. This section is often composed of mitigation strategies, monitor recommendations, incident response plans, potential pitfalls, and other technical and non-technical advice. - -Monitoring and incident response recommendations included in this section are crucial for ensuring the ongoing security and resilience of your blockchain project or smart contract. These recommendations focus on proactive measures to detect and respond to security incidents, breaches, or anomalies effectively. The information given will provide details on how to apply these recommendations with Defender [Monitors](/defender/module/monitor), [Actions](/defender/module/actions), and [Workflows](/defender/module/actions#workflows). We recommend following the tutorials found in this documentation to learn how to use the Defender modules, like the [Monitor](/defender/tutorial/monitor), [Actions](/defender/tutorial/actions), and [Workflow](/defender/tutorial/workflows) tutorials. - -Recommendations often include: - -* **Event Monitoring**: event monitoring to track and analyze events emitted by your smart contracts. This is essential for identifying unusual or unexpected behavior that may indicate a security issue. -* **Custom Alerts**: Custom alerts based on specific conditions or events. This aligns with the incident response recommendation to have alerting mechanisms in place. -* **Automated Response**: Automated responses to specific events or conditions, enabling rapid incident mitigation. Combined with [Actions](/defender/module/actions) and [Workflows](/defender/module/actions#workflows). -* **Threshold Monitoring**: Monitoring for unusual deviations from established thresholds is a common incident response practice. Defender can assist in setting up threshold-based monitoring with [Monitors](/defender/module/monitor) and to react with automatic [Workflows](/defender/module/actions#workflows). -* **Deployment Considerations**: Minimize risk while avoiding unnecessary delays and post-deployment using Defender [Deploy](/defender/module/deploy). Employ automatic analysis to avoid storage collisions or other issues and benefit from features like cross-chain deterministic deployments, bytecode verification, and more. - -### Conclusion - -The "Conclusion" section summarizes the audit’s findings and provides an overall assessment of the project’s security posture. This section begins with a concise summary of the key findings from the audit, including a recap of critical security vulnerabilities, issues, or concerns discovered during the assessment with the security levels assigned to each identified issue, helping stakeholders understand which issues posed the highest risks. Depending on the issues found, the "Conclusion" section may also restate the high-priority recommendations for addressing issues, emphasizing the immediate actions needed to enhance security. - -This section will also communicate the risks associated with the project’s current security status to help project owners, investors, and users make informed decisions. Additional valuable insights may be provided to support certain decisions by stakeholders, such as deployment, further development, and improvements. If recommendations were provided, these will be restated in this section as a high-level overview. - -## Fix-Review process - -After an audit report is delivered, the individual issues within a report are open to response and comment until they are each finalized by an Audit Manager. Auditors and team members assigned the Audit Comment role are allowed to respond and comment. Team members may ask questions to Auditors or supply information. - -In order to initiate a response on an issue, click on the issue within the "Issues" section of the audit page and then click on "Reply to this issue". - -![Audit Issue Response](/defender/audit-new-issue.png) - -Team members may leave comments for auditors. Specifically, team members can supply links to pull requests (PRs) or commits in their GitHub repository, which represent fixes associated with a specific issue. Multiple links may be added. - -![Audit Issue Reply](/defender/audit-reply-issue.png) - -Defender will keep and display a trail of all communications between the auditors and team members on each issue. - -![Audit Trail](/defender/audit-trail.png) - -Depending on the outcome of fixes and reviews, auditors may update the status of issues to Partially Resolved or Resolved. Once the fix-review process is complete for all issues, the Audit Manager will finalize the audit, after which the full trail of activity is visible, but no more responses or comments are allowed. At the end of the audit, the Audit Manager can also provide a PDF report of the audit, including the fix-review process. - -For any questions regarding your audit process, please get in touch with your assigned Audit Manager. You can provide Defender feedback via [its feedback form](#feedback) — your comments and suggestions will be instrumental in helping us shape the future of the Audit module! diff --git a/content/defender/module/code.mdx b/content/defender/module/code.mdx deleted file mode 100644 index d1e39301..00000000 --- a/content/defender/module/code.mdx +++ /dev/null @@ -1,286 +0,0 @@ ---- -title: Code Inspector ---- - -Code Inspector seamlessly integrates with Github to maximize security with every step of your development process via automatic code analysis powered by machine learning intelligence and state-of-the-art tools developed by our security experts. - -For every push to your code, the OpenZeppelin Code Inspector dives into a detailed examination, identifying potential vulnerabilities and suggesting improvements to enhance your code quality. It generates a succinct report, summarizable in your PR comments for quick and immediate access, while a more detailed report is made available on Defender. - -## Use cases - -* Automatically conduct security analysis on pull requests, identifying vulnerabilities and suggesting improvements. -* Utilize summarized reports in the pull request for immediate insights into your code’s health and security. -* Access comprehensive, detailed reports on Defender for an in-depth understanding of potential vulnerabilities and code optimization areas. -* Use OpenZeppelin’s Dependency Checker to identify reused contracts and match them against a database of known vulnerabilities. -* Apply static analysis rules to Solidity files, identifying potential issues and their severity for high-quality code maintenance. - -## Features - -Some issues found by Code Inspector are detected by our AI models. Keep in mind that while we provide confidence levels, the models may occasionally generate incorrect or misleading information. Make sure to verify the information accordingly and we’d love to hear your feedback. - -Code Inspector has a wide range of functionalities designed to enhance security, efficiency, and code quality. These processes are powered by machine learning models and state-of-the-art tools developed by our security experts. - -* **Reused Code**: Identifies vulnerabilities in reused smart contract code by generating a unique fingerprint for each contract and matching it against a database of known issues. -* **Vulnerable Dependencies**: Notify when a OpenZeppelin Contracts dependency with a known vulnerability is used, providing you with the necessary information to address the issue. -* **Test Suggestions**: Opportunities to apply fuzzing tests to functions, providing you with areas where further testing could prove beneficial. -* **External Call Safety**: Safety of external calls, highlighting any instances that might pose a severity concern. -* **Standard Compatibility**: Compatibility of your contracts with established standards, flagging potential compatibility issues. -* **Reentrancy Attack Vectors**: Potential reentrancy attack vectors at both the file and function level, assigning these threats high-severity labels. -* **Code Readability**: Missing docstrings in functions and misspelled words throughout the codebase, ensuring your code is as legible and understandable as possible. -* **Code Efficiency and Security Practices**: Areas in your code where improvements can be made for better performance and highlights potential security risks, enabling you to optimize and secure your contracts more effectively. - -## Installation - -Installation must be initiated from Defender. Installing the app directly from GitHub will not correctly set up the integration. - -The installation process connects your Defender account and your GitHub repositories. Follow the following steps: - -1. Navigate to the [Code Inspector page](https://defender.openzeppelin.com/v2/#/code) on Defender. -2. Click on the Install Code Inspector button, which redirects you to Github. -3. Select and approve the repositories to install the app. -4. Generate your first report by creating or updating a pull request on a repository that has the app installed. - -The installation is currently done solely through Defender, ensuring a seamless connection for the reports. Following the installation, no additional setup is required. If you encounter installation issues, refer to our [Troubleshooting](#installation-issues) section for guidance. - -## Usage - -Code Inspector is designed to streamline your code analysis workflow. Once installed, the app is triggered whenever a pull request (PR) is opened or a new commit is pushed to an existing PR in your GitHub repository. To avoid skipping the report, the PR must contain at least a modification to any Solidity file or the `package.json` file. - -The app automatically generates a summary report for each new commit, which is posted as a comment in your PR. This summary report is continuously updated with the latest issues discovered in the most recent commit, and the commit hash is directly viewable in the report. - -Along with the summary reports in PR comments, a detailed report for each commit is created and can be accessed on Defender, offering in-depth information on the identified issues and how to fix them. - -If you wish to stop receiving reports for a specific repository, it’s as simple as navigating to the Code Inspector settings and removing the respective repository from the list. - -### Statuses -These are the possible statuses of reports: - -* `Running`: The report has been triggered, and it’s running. -* `Succeeded`: The report has been successfully generated, and it’s available in Defender and Github. -* `Failed`: The report has failed. Make sure that your repository contains valid Solidity files. If this issue persists, please get in touch. -* `Throttled`: The report has been throttled as your tenant exceeded the Code Inpsector quota limit. If you would like to increase your quota, please get in touch. -* `Skipped`: The report has been skipped. Check that the PR and/or commit contains at least one modification to a Solidity file or the `package.json` file. - -## Reports - -### Summary Report - -The summary report provides a clear overview of potential vulnerabilities detected in the code during the review process. The report is conveniently categorized by process and severity level, making it easier to identify areas that need attention. You can navigate to the complete report on Defender via the provided link. Each report is tied to a specific commit, ensuring accurate tracking of changes and issues over time. - -image::code-report-summary.png[Summary Report] - -In this example, you can see the number of issues detected by Code Inspector, along with their respective severity levels. By clicking the link at the bottom of the report, you can view the full details of these vulnerabilities on Defender. - -### Issues - -Full reports identify issues within your smart contracts using a broad range of rules. The rules cover many aspects, such as known vulnerabilities, best practices, code efficiency, and secure coding principles. - -![Full Report 1](/defender/contract-inspector-detailed-report.png) - -Each issue is assigned a severity level based on the potential impact on the contract’s functionality and security. An explanation accompanies each flagged issue, articulating the reason for the concern. - -Every issue has a suggested resolution tailored to improving your code quality and overall security. This might include recommendations to refine your code, modify visibility scopes, apply necessary mathematical checks, enhance documentation, or adhere to a specific Ethereum standard. - -Depicted below is an example of a vulnerability detected in a dependency with a brief description of its potential impact. The specific dependency and its version are outlined, pinpointing where the problem exists. - -![Dependency Checker Report](/defender/dependency-checker-detailed-report.png) - -To help you resolve these issues, recommendations on updates or patches that can address the vulnerabilities are provided along with the relevant advisory links for a more detailed understanding of the issue. - -By reviewing and applying the proposed solutions in this report, you can enhance the robustness and reliability of your smart contracts, ensuring adherence to best practices and industry standards. This makes the audit process smoother and improves the preparedness of your contracts for successful deployment. - -### Standards - -This feature introduces a new section in the report called ***Standards***. This section provides insights into your contracts that implement interfaces from the OpenZeppelin Contracts library. For example, if you are using an `IERC20`, Code Inspector will check the implementation details and properties to ensure you are using this ERC correctly. - -## Detailed Checks - -For each function and event defined in an interface, Code Inspector performs comprehensive checks to verify compliance with the standard. These checks include: - -* ***Signature:*** Ensures that the function or event signature matches the standard’s specification. Example: `transfer(address,uint256)` -* ***Visibility:*** Checks that the visibility of functions and events adheres to the standard’s requirements. Example: `external`, `public` -* ***Mutability:*** For functions, ensures that the mutability is correctly specified as per the standard. Example: `view`, `pure` -* ***Return Type:*** Verifies that the return types of functions align with the expected types defined in the standard. Example `returns (bool)` -* ***Parameter Names:*** Confirms that the parameter names are consistent with those defined in the standard, enhancing code readability and maintainability. Example: `transfer(address recipient, uint256 amount)` -* ***Return Names:*** Ensures that the return variable names, where used, are consistent with the standard. Example: `returns (bool success)` - -If any attribute of a function or event fails, the entire function or event is marked as failed. Additionally, if any function or event within an implementation fails, the entire implementation is considered non-compliant. - -## Configuration - -You can configure repository-specific parameters for Code Inspector using a file called `defender.config.json` in the root directory. The structure of the file is separated into processes run by Code Inspector. Each process has a list of parameters that you can adjust to your needs. For example, you can specify which directories to scan, which is useful to prevent Code Inspector from analyzing test or script files written in Solidity. - -### Contract Inspector -Contract Inspector runs a [set of rules](#rules) to detect potential issues in your code. You can configure the following parameters: - -* `enabled`: ability to turn off the Contract Inspector. False meaning not to run, and true to run. (default: `true`) -* `scan_directories`: list of directories to scan with paths starting from the root directory. default: `["."]` -* `include_rules`: list of rules to run. default: [all rules](#rules). -* `exclude_rules`: list of rules to not run. default: none. - -### Dependency Checker -Dependency Checker verifies that your dependencies are not vulnerable to known issues. You can configure the following parameters: - -* `enabled`: ability to turn off Dependency Checker. False meaning not to run, and true to run. (default: `true`) - -#### Example - -The following `defender.config.json` configuration file will disable Dependency Checker and run Contract Inspector on the `src/contracts1` and `src/contracts2` directories, excluding two rules (`naming-convention` and `unused-state`). - -```json - - "contract_inspector": { - "enabled": true, - "scan_directories": ["src/contracts1", "src/contracts2"], - "exclude_rules": ["naming-convention", "unusued-state"] - , - "dependency_checker": - "enabled": false - -} -``` - -## Assets - -The Assets page allows you to manage your Code Inspector assets, supporting two types: Smart Contracts and GitHub repositories. When you install the Code Inspector GitHub app and select repositories, they will appear on this page. Additionally, you can create Smart Contract assets from addresses in your address book. Note that Smart Contract assets must be verified on Etherscan for this feature to work. - -Smart Contract assets can be manually triggered for reports on the report page. GitHub assets can be triggered manually and automatically from new pull requests (PRs) and commits. - -![Code Assets](/defender/code-assets.png) - -### Settings - -The Asset Settings page offers two main settings to manage how Defender handles asset security: Automatically Generate Report and Vulnerability Detection. - -#### Automatically Trigger Report for Pull Requests - -Automatically Generate Report, is specifically for GitHub repositories. When enabled, this setting ensures continuous monitoring by generating new reports automatically whenever a new pull request (PR) is opened or a new commit is pushed to a PR. - -#### Active Vulnerability Detection and Notification - -Active Vulnerability Detection and Notification provides a robust security measure by automatically scanning your assets for new vulnerabilities. -This setting is applicable to both GitHub repositories and smart contracts. To enable this feature for Github repositories assets, you must activate the setting and select a specific branch to be monitored. - -* **Automated Scanning**: Leveraging Defender’s advanced smart contracts scanning capabilities, when our team becomes aware of a new vulnerability, whether disclosed or undisclosed, we promptly update our scanning algorithms to detect it. We then scan all assets configured to be monitored -* **Automated Notification**: Once the automatic scanning is completed an automated system notification email will be sent to inform you whether the vulnerability was detected in your monitored assets. If detected, the notifications include relevant information tailored to the nature of the vulnerability. -* **Risk Mitigation**: When detected, to aid in addressing and mitigating detected vulnerabilities, notifications may include suggestions for risk mitigation, providing actionable steps for administrators to protect their smart contracts and associated assets. - -By enabling Active Vulnerability Detection and Notification for your assets, you can benefit from continuous, automated scanning and timely notifications, empowering you to respond quickly to new threats and maintain the security of your smart contracts and GitHub repositories. This proactive approach ensures that you can stay ahead of potential vulnerabilities and safeguard your code effectively. - -## Settings - -The Settings page allows you to manage the permissions and access level of the Code Inspector. If you need to make changes to the repositories that the app has access to, a convenient link takes you directly to the GitHub settings page of the app, facilitating effortless repository management. - -In the Github tab, you can globally suspend or uninstall the app, giving you complete control over its operation within your projects. - -![Code Inspector Github](/defender/code-settings-advanced.png) - -## Troubleshooting - -### Installation Issues - -* **Installing the app outside Defender**: Code Inspector must be installed via Defender. If you attempt to install it from elsewhere, the installation will not succeed. Ensure you’re logged in to your OpenZeppelin account and navigate to Code Inspector from Defender for a successful installation. -* **Code Inspector Access**: Access to Code Inspector is required for a successful installation. If you find that you don’t have access and you think this is a mistake, contact OpenZeppelin support to get the necessary permissions. - -### Repository Size Issues - -Errors related to analysis timeouts are often caused by large codebases. To mitigate this issue, it is recommended to use the `scan_directories` option in the defender configuration file to scope the analysis to relevant files only. By specifying which directories to include in the scan, the configuration file can significantly reduce processing times and prevent timeouts. For detailed instructions on setting up the configuration file, please refer to the [Configuration](/defender/module/code#configuration) section. - -## Rules - -| ID | Description | Severity | -| --- | --- | --- | -| `alert-uniswap-v2-router-liquidity-considerations` | Identifies any instance of a Uniswap Router V2 addLiquidity call. | note | -| `array-length-to-stack` | Identifies when the length of an array can be written to the stack to save gas. | note | -| `call-with-arbitrary-address-bytes` | Identifies a potentially unsafe external call. | medium | -| `chainlink-deprecated-functions` | Identifies usage of chainlink’s deprecated functions. | medium | -| `check-consistent-usage-of-msgsender-msgdata` | Identifies usage of `msg.sender` or `msg.data` when `_msgSender()` or/and `_msgData()` are present | note | -| `check-effect-interact` | Identifies a possible violation of the check, effect and interact pattern. | ethtrust | -| `check-erc4337-compatibility` | Identifies if the contract may not be compatible with ERC-4337. | note | -| `check-return-data-from-external-call` | Identifies when the external call return data check is missing. | note | -| `constants-not-using-proper-format` | Identifies when a constant is not using the proper format. | note | -| `dangerous-strict-equality` | Identifies the use of strict equalities that can cause a Gridlock. | medium | -| `default-values-assigned` | Identifies an instance of a variable initialized to its default value. | note | -| `delegatecall-to-arbitrary-address` | Identifies when an there is a delegatecall or call code to an arbitrary address. | high | -| `delegatecall-usage` | Identifies an instance of delegatecall. | ethtrust | -| `different-pragma-directives` | Identifies whether different Solidity versions are used. | low | -| `disableinitializers-not-called-in-implementation-constructor` | Identifies if `_disableInitializers()` is not being called in the constructor of an Initializable contract | note | -| `doc-code-mismatch-model` | Identifies a possible docstrings and code mismatch. | low | -| `duplicated-import` | Identifies duplicated imports. | note | -| `exact-balance` | Identifies whether a balance is compared to an exact value. | ethtrust | -| `external-call-reentrancy-attack-vector` | Identifies external calls as a possible vector for a reentrancy attacks. | note | -| `fallback-with-return-value` | Identifies if there are fallback functions with return values. | note | -| `floating-pragma` | Identifies pragma directives that do not specify a particular, fixed version of Solidity. | low | -| `function-init-state-variable` | Identifies when a state variable is initialized by a function. | note | -| `function-level-access-control-model` | Identifies a possible access control attack vector on a function. | high | -| `function-level-reentrancy-model` | Identifies a possible reentrancy attack vector on a function. | high | -| `function-visibility-too-broad` | Identifies if function visibility is unnecessarily broad. | note | -| `gas-limit-on-call` | Identifies when an external call has a hard-coded gas limit. | low | -| `hashing-dynamic-values` | Identifies a hashing of a packed encoded dynamic value. | ethtrust | -| `identify-hardhat-console-import` | Identifies a hardhat console import. | note | -| `identify-to-do-comments` | Identifies todo comments in the code. | note | -| `inconsistent-order-contract` | Identifies when a contract has a inconsistent order. | note | -| `inconsistent-use-named-returns` | Identifies inconsistent usage of named returns within a codebase. | note | -| `incorrect-format-onERC721Received` | Identifies when a contract includes the `onERC721Received` function and it has an incorrect format. | note | -| `incorrect-modifier` | Identifies an incorrect definition of a modifier. | medium | -| `incremental-update-optimization` | Identifies the use of `i`` (rather than ``i`) to save gas in for loop headers. | note | -| `indecisive-license` | Identifies when a file has multiple SPDX licenses. | note | -| `int-negative-evaluation-overflow` | Identifies when additive inverse of an int variable is evaluated. | note | -| `lack-of-gap-variable` | Identifies when an upgradeable contract does not have a gap variable. | low | -| `lack-of-indexed-event-parameters` | Identifies when a lack of indexed event parameter. | note | -| `lack-of-security-contact` | Identifies when a contract does not have a security contact. | note | -| `lack-of-spdx-license-identifier` | Identifies when a lack of SPDX license identifier. | note | -| `lock-ether` | Identifies any instance of locked ETH within a contract. | high | -| `memory-side-effect-assembly` | Identifies when some code may be vulnerable to a Solidity compiler vulnerability. | medium | -| `missing-docstrings` | Identifies when a function is missing docstrings. | low | -| `missing-initializer-modifier` | Identifies when a function is missing the initializer modifier. | low | -| `missing-mapping-named-parameters` | identifies when a mapping is missing named parameters | note | -| `missing-return` | Identifies when a function is missing the return statement. | low | -| `misuse-boolean-literal` | Detects the misuse of a Boolean literal (used in complex expressions or as conditionals). | medium | -| `msg-value-loop` | Identifies usage of msg.value inside a loop. | note | -| `multiple-contracts-per-file` | Identifies multiple contract declarations per file. | note | -| `name-reused` | Identifies in a codebase when two or more contracts have the same name. | note | -| `non-explicit-imports` | Identifies a non-explicit import. | note | -| `not-operator-assembly` | Identifies usage of the `not` operator inside assembly code because it functions differently than in other languages. | note | -| `outdated-solidity-version` | Identifies a Solidity file with an outdated Solidity version. | note | -| `overriding-state-values-in-constructor` | Identifies cases where state variables are explicitly set to values within a contract but are overwritten by the constructor. | note | -| `possible-incorrect-abi-decode` | Identifies the potential for incorrect ABI decoding. | note | -| `possible-return-bomb` | Identifies a possible vector for a return bomb attack. | note | -| `pragma-spans-breaking-changes` | Identifies a Solidity file with pragma that spans versions of solidity where breaking changes may have been introduced. | low | -| `precision-loss-div-before-mul` | Identifies possible precision loss due to division before multiplication | note | -| `redundant-safemath-library` | Identifies a redundant use of SafeMath library. | note | -| `replace-revert-strings-custom-errors` | Identifies when a revert string could be replaced by a custom error. | note | -| `require-instead-of-revert` | Identifies when a require statement does not check for any conditions. | low | -| `require-missing-message` | Identifies when an error message is missing from the require statement. | low | -| `require-multiple-conditions` | Identifies a require statement with multiple conditions. | low | -| `revert-missing-message` | Identifies when a revert statement is missing the error message. | low | -| `selfdestruct-usage` | Identifies an instance of selfdestruct. | ethtrust | -| `state-updated-without-event` | Identifies if a function is updating the state without an event emission. | note | -| `state-var-visibility-not-explicitly-declared` | Identifies when the visibility of a state variable that has not been explicitly declared. | note | -| `sushiswap-callback-attack` | Identifies possible attacks on sushiswap callback where a fake pool address can pass authorization check. | note | -| `swapped-arguments-function-call` | Identifies when the arguments of function call have been swapped. | note | -| `too-many-digits` | Identifies a literal number with many digits. | note | -| `transferfrom-dangerous-from` | Identifies usage of `transferFrom` with `from` parameter not being a `msg.sender`. | high | -| `unchecked-call-success` | Identifies when the external call fail check is missing. | ethtrust | -| `unchecked-increment` | Identifies that an incremental update is not wrapped in an unchecked block. | note | -| `unchecked-keyword` | Identifies unchecked code inside a function. | note | -| `unchecked-math` | Identifies a potentially unsafe usage of unchecked math. | high | -| `unicode-direction-control` | Identifies the use of unicode direction control character. | ethtrust | -| `unnecessary-assignment` | Identifies an unnecessary assignment of a variable. | note | -| `unnecessary-cast` | Identifies an unnecessary cast. | note | -| `unsafe-abi-encoding` | Identifies any use of unsafe ABI encoding. | low | -| `unsafe-mint-ERC721` | Identifies if a `_mint` function is used instead of `_safeMint` in ERC721 context. | note | -| `unused-arguments` | Identifies an unused function argument. | note | -| `unused-enum` | Identifies an unused enum. | note | -| `unused-error` | Identifies an unused error. | note | -| `unused-event` | Identifies an unused event. | note | -| `unused-function` | Identifies an unused function with internal or private visibility. | note | -| `unused-imports` | Identifies an unused import. | note | -| `unused-named-returns` | Identifies an unused named return variable. | note | -| `unused-state-variable` | Identifies an unused state variable. | note | -| `unused-struct` | Identifies an unused struct. | note | -| `use-of-transfer-send` | Identifies instance of transfer or send. | low | -| `use-of-uint-instead-of-uint256` | Identifies if an `int/uint` is used instead of `int256/uint256`. | note | -| `variable-could-be-constant` | Identifies variables that could be declared as `constant`. | note | -| `variable-could-be-immutable` | Identifies variables that are only ever set in the constructor and could be `immutable`. | note | -| `void-constructor-call` | Identifies the call to a constructor that is not implemented. | low | diff --git a/content/defender/module/deploy.mdx b/content/defender/module/deploy.mdx deleted file mode 100644 index 6b313bda..00000000 --- a/content/defender/module/deploy.mdx +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: Deploy ---- - -Deploy allows you to deploy and upgrade smart contracts across chains securely. You can prove that the code running on-chain matches the audited implementation and minimize crucial mistakes that can lead to losses or issues. - -## Use cases - -* Configure production and test environments with granularity over deployer addresses. -* Pay gas for deployments automatically. -* Ensure all smart contract deployments are verified on block explorers. -* Manage deployments to multiple chains from a single place. -* Automate multisig approval process for upgrades. -* Fully compatible with CI/CD for automated releases. -* Track the details and history for every deployment or upgrade. - -## Environments - -Deploy is divided into production and test environments, with mainnet networks for the former and testnet networks for the latter. Each environment is associated with one or more networks according to its type of environment, which allows to separate test contracts from production safely. To facilitate the onboarding process, the setup for each environment is configured through a wizard, which swiftly walks you through the following steps. - -### Wizard - -#### Step 1: Networks - -In the first step, you select the networks to use. Deploy supports multi-chain deployments, allowing users to deploy contracts to the same addresses across multiple networks. You can add or remove networks at any time through the environment page. - - -To maintain the best security practices, the wizard will only show networks according to the type of environment chosen to prevent mixing networks. - - -#### Step 2: Deploying - -In this step, users choose the default approval process for each network. The resource associated to this approval process is the one that will be used to pay and execute the deployment transactions. If you don’t have an approval process for a network, the wizard will allow you to create one of either type Relayer, Safe or EOA ("Externally Owned Account"). You can learn more about approval processes [here](/defender/settings#approval-processes). - -#### Step 3: Upgrading - -This last step is optional but recommended if you plan to deploy upgradeable contracts. Here you choose the approval process for upgrades for each network. You can find a list of supported processes [here](/defender/settings#approval-processes). - -## Environment Page - -Once inside an environment, you can see the configuration and activity of deployments within it. - -### Configuration - -You can edit the configuration of any network within the environment. To do so, click the edit button to reach the configuration page, where you can add or remove a network and change the default approval processes. We use system block explorer API keys to automatically verify contracts on Etherscan. You can manage your own keys in the configuration page. - -### History - -The history table shows the activity within the environment, allowing you to check the status of deployments or upgrades. There are three possible statuses: - -* `COMPLETE`: The deployment has been successfully executed in the network. -* `PENDING`: The upgrade is waiting for approval. -* `FAILED`: The deployment has failed. Make sure the relayer or EOA associated to the approval process has enough funds and that the smart contract is valid. - -## Deploying and Upgrading - -After an environment is configured, you can use it for deployments and upgrades. To do so, we provide an [API](https://www.npmjs.com/package/@openzeppelin/defender-sdk-deploy-client), and [Hardhat](https://www.npmjs.com/package/@openzeppelin/hardhat-upgrades) and [Foundry](https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades) plugins. The Deploy API is recommended for custom projects that don’t use Hardhat or Foundry. On the other hand, the plugins are extremely easy to use as they only require a few lines of code to implement. - -Defender will use the default approve process for deployments and upgrades. However, the Hardhat and Foundry plugins allow you to specify a different approval process for upgrades. If a block explorer API key is not provided, Defender will try to verify the contracts with the default key. Otherwise, it will use the one provided. - - -We provide a quickstart tutorial to deploy and upgrade a smart contract using Defender with Hardhat and Foundry. Check it out [here](/defender/tutorial/deploy)! - - - -Using `CREATE2` may affect `msg.sender` behavior; see documentation for details [here](/defender/tutorial/deploy#caveats)! - - -## Metadata - -To identify, tag, or classify deployments, you can use the `metadata` field, which includes properties like `commitHash`, `tag`, or any custom property that suits your use case. - -```js - const client = new Defender( - apiKey: process.env.API_KEY, - apiSecret: process.env.API_SECRET, - ); - - const deployment = await client.deploy.deployContract( - contractName: 'Example', - ... - metadata: { - commitHash: '4ae3e0d', - tag: 'v1.0.0', - anyOtherField: 'anyValue', - , - }); -``` - -Once the deployment is submitted, these metadata fields will be displayed in the Defender UI under _Metadata_, formatted in JSON. - -![Deploy Metadata](/defender/deploy-metadata-1.0.png) diff --git a/content/defender/module/monitor.mdx b/content/defender/module/monitor.mdx deleted file mode 100644 index b1eba1b0..00000000 --- a/content/defender/module/monitor.mdx +++ /dev/null @@ -1,453 +0,0 @@ ---- -title: Monitor ---- - - - -Defender is now in maintenance mode. To continue monitoring your smart contracts/any other on-chain events with the latest features and updates, we recommend migrating to [OpenZeppelin Monitor](/monitor). - -See the complete [Migration Guide](/defender/migration#monitor-migration) for detailed instructions on exporting your configurations. - - - -Monitors allow you to gain full visibility into your smart contracts' risks and behaviors. You can detect threats, get alerts on threats and anomalies, and automatically respond and resolve issues. - -## Use cases - -* Monitor crucial events and authorized functions like ownership transfers, pauses, or mints. -* Alert on potentially dangerous transactions or operational issues. -* Integrate notifications to Slack, Telegram, Discord, email, PagerDuty, Opsgenie or custom APIs. -* Use pre-built templates to setup monitoring quickly and easily. -* Combine with other Defender modules to execute on-chain transactions with monitor triggers. - -## Monitors - -Monitors can be created from scratch or from templates, which are designed for common use cases. Templates automatically pre-populate a monitor, so you can easily modify and re-adapt them. - -![Monitor Templates](/defender/monitor-templates.png) - -Monitors are organized into five categories, according to the type of risk they monitor: - -* Governance -* Access Control -* Suspicious Activity -* Financial -* Technical - -You can also specify a severity level, which your team can use to group or filter monitors by. - -* High Severity -* Medium Severity -* Low Severity - -## Configuring a Monitor - -A monitor watches all on-chain contract transactions and notifies when one matches the parameters, filters, or events. - - -At this time, Monitors are supported across all [networks](#networks) except Fantom. - - -### General Information -* **Name**: The name assigned to the monitor. -* **Risk Category**: The risk category of the monitor, useful for filtering or grouping. -* **Contracts**: The smart contracts to monitor. Monitoring relies on the underlying ABI, so you may only have 1 ABI per monitor. In case of multiple smart contracts, the monitor must adhere to the same ABI/Interface. -* **Confirmation Blocks**: If you want to be notified only after a certain level of confidence that the transaction is accepted, a higher confirmation block level is recommended, but if you want to be notified as soon as possible with tolerance to reorganizations, a lower confirmation block level is better. In chains where safe and finalized block tags are accepted, you can also select them as confirmation block level. - -### Matching Rules - -For a transaction to trigger a notification, it must satisfy **ALL** of the following: - -* Transaction **MUST** have a To, From, or Address (from the log) that matches the configured address. -* If a **Transaction Filter** is specified - * The Transaction **MUST** match the **Transaction Filter**. -* If **Events** are selected - * The Transaction **MUST** emit any of the selected Events and match the **Event Condition** (if any) -* If **Functions** are selected - * The Transaction **MUST** directly invoke any of the selected Functions (contract calls are not detected at the moment) and match the **Function Condition** (if any) - -### Transaction Filters - -Transaction filters allows to narrow the transactions being monitored. These are entered as property expressions or Javascript code, offering great flexibility. To accommodate comparisons for checksum and non-checksum addresses, comparisons are case-insensitive. - - -To receive ALL transactions that involve the selected events/functions, transaction conditions should not be specified. - - -* Conditions can use `AND`, `OR`, `NOT` and `()` -* Conditions can use `==`, `<`, `>`, `>=`, `<=` to compare -* Number values can be referred to by Hex (0xabc123) or Decimal (10000000000) -* String values can only be compared via `==` -* Includes basic math operators: `+`, `-`, `*`, `/`, `^` - - -If a transaction filter condition is specified, then a transaction MUST meet this condition in order to trigger a notification. - - -Transaction Conditions can refer to the following properties - -* `to` is the _to_ address for the transaction -* `from` is the _from_ address for the transaction -* `gasPrice` is the price of gas sent in the transaction. In EIP1559 transactions, it's equal to or below the `maxFeePerGas`. -* `maxFeePerGas` is the maximum price the transaction was willing to pay for the transaction. Only existent in EIP1559 transactions. -* `maxPriorityFeePerGas` is the maximum amount of wei over the `BASE_FEE` the transaction is willing to pay to the miner for inclusion. Only existent in EIP1559 transactions. -* `gasLimit` is the gas limit sent in the transaction -* `gasUsed` is the amount of gas used in the transaction -* `value` is the value sent in the transaction -* `nonce` is the nonce for the specific transaction -* `status` is a derived value and can be compared with `"success"` or `"failed"` - -#### Example Conditions - -Transactions that are reverted - -```jsx -status == "failed" -``` - -Transactions excluding those from 0xd5180d374b6d1961ba24d0a4dbf26d696fda4cad - -```jsx -from != "0xd5180d374b6d1961ba24d0a4dbf26d696fda4cad" -``` - -Transactions that have BOTH a gasPrice higher than 50 gwei AND a gasUsed higher than 20000 - -```jsx -gasPrice > 50000000000 and gasUsed > 20000 -``` - -### Custom Filters - -Custom filters supports custom code for filtering transactions. If a custom filter is specified, it will be called with a list of matches found for a given block. This allows the monitor to use other datasources and custom logic to evaluate whether a transaction matches. - - -Only transactions that match other conditions (event, function, transaction) will invoke the custom filter. - - - -Each invocation can contain up to 25 transactions. - - -#### Request Schema - -The request body will contain the following structure. The `MonitorConditionRequest` type from the [defender-sdk-action-client](https://www.npmjs.com/package/@openzeppelin/defender-sdk-action-client) package can be used for custom filters in Typescript. - -```jsx - - "events": [ - { - "hash": "0xab..123", // the transaction hash - "timestamp": "1699857792", // the timestamp of the transaction (block) - "blockNumber": 18561272, // the block number of the transaction - "blockHash": "0xab..123", // block hash from where this transaction was seen - "transaction": { // eth_getTransactionReceipt response body - ... // see https://eips.ethereum.org/EIPS/eip-1474 - "cumulativeGasUsed": "0xc3614", - "effectiveGasPrice": "0x6e214d78", - "gasUsed": "0x6075", - "logs": [ - { ... - ], - "logsBloom": "0x4..0", - "status": "0x1", - "from": "0xab..123", - "to": "0xab..123", - "transactionHash": "0xab..123", - "transactionIndex": "0x9", - "type": "0x2" - }, - "matchReasons": [ // the reasons why monitor triggered - - "type": "event", // event, function, or transaction - "address": "0x123..abc", // address of the event emitting contract - "signature": "...", // signature of your event/function - "condition": "value > 5", // condition expression (if any) - "args": ["5"], // parameters by index (unnamed are present) - "params": { "value": "5" // parameters by name (unnamed are not present) - } - ], - "matchedAddresses": ["0xabc..123"], // the addresses from this transaction your are monitoring - "matchedChecksumAddresses": ["0xAbC..123"], // the checksummed addresses from this transaction your are monitoring - "monitor": - "id": "44a7d5...31df5", // internal ID of your monitor - "name": "Monitor Name", // name of your monitor - "abi": [...], // abi of your addresses (or undefined) - "addresses": ["0x000..000"], // addresses your monitor is watching - "confirmBlocks": 0, // number of blocks monitor waits (can be 'safe' or 'finalized' on PoS clients) - "network": "rinkeby" // network of your addresses - "chainId": 4 // chain Id of the network - , - "metadata": "..." // metadata (if available) - } - ] -} -``` - -#### Response Schema - -The custom filter must return a structure containing all matches. Returning an empty object indicates no match occurred. The type for this object is `MonitorConditionResponse`. - - -Errors will be treated as a non-match. - - -```jsx - - "matches": [ - { - "hash": "0xabc...123", // transaction hash - "metadata": { - "foo": true // any object to be shared with notifications - - }, - - "hash": "0xabc...123" // example with no metadata specified - - ] -} -``` - -#### Example Custom Filters - -```jsx -exports.handler = async function(payload) - const conditionRequest = payload.request.body; - const matches = []; - const events = conditionRequest.events; - for(const evt of events) { - - // add custom logic for matching here - - // metadata can be any JSON-marshalable object (or undefined) - matches.push({ - hash: evt.hash, - metadata: { - "id": "customId", - "timestamp": new Date().getTime(), - "numberVal": 5, - "nested": { "example": { "here": true } - } - }); - } - return matches -} -``` - -### Events and Functions - -Events and functions can be selected as filters. Selecting multiple events acts as an OR clause (triggered for ANY selected events). The same applies for functions. - -Conditions for events or functions can further narrow the monitor. These can refer to arguments in the signature either by name (if the argument is named) or by index (e.g., $0, $1...). The variables must match the types shown in the interface. If left empty, the condition will be ignored. - - -If no events or functions are specified, then ALL transactions to or from the contracts will be in scope. - - - -Monitors seamlessly supports notifications for events emitted by a smart contract on all networks, regardless of whether they are triggered directly or through internal calls from a third contract. However, the capability to track and provide notifications for internal function calls within a contract is currently limited to the Ethereum mainnet. - - -#### Example Conditions - -Transactions that emit a `Transfer(...)` event with a value between 1 and 100 ETH (in hex) - -```jsx -// Event Signature: Transfer(address to, address from, uint256 value) -value > 0xde0b6b3a7640000 and value < 0x56bc75e2d63100000 -``` - -Transactions that emit a `ValsEvent(...)` event with an array with a first element equal to 5 - -```jsx -// Event Signature: ValsEvent(uint256[3] vals) -vals[0] == 5 -``` - -Transactions that invoke a `greet(...)` function with an unnamed string of "hello" - -```jsx -// Function Signature: greet(address, string) -$1 == "hello" -``` - -## Alerts - -A monitor can use any supported notification channel for alerting. It’s also possible to connect an Action or a Workflow that should run with the monitor. - -To prevent repeated alerts from individual monitors and control the notification rate, you can use the Alert Threshold and Minimum time between consecutive notifications fields. - -* Alert Threshold: Define the number of times a monitor must trigger per unit of time before a notification is sent or an action is fired. The unit of time is defined by the Minimum time between consecutive notifications field. -* Minimum time between consecutive notifications: Set the the minimum wait time between sending notifications. - -![Configure Defender Monitor alerts](/defender/monitor-alert-v2.png) - -### Notifications - -You can create **Notifications** attached to the Monitor alerts for getting notified about the on-chain events across many channels, see more about how to create and configure them in [this section](/defender/settings/notifications). - -#### Customizing Notification - -You can also modify the message body content and formatting using the Customize notification checkbox below the notification channel selector. - -##### Template - -```md -**Monitor Name** - -{ monitor.name } - -**Network** - -{ monitor.network } - -**Block Hash** - -{ blockHash } - -**Transaction Hash** - -{ transaction.transactionHash } - -**Transaction Link** - -[Block Explorer]({ transaction.link }) - -{ matchReasonsFormatted } - -**value** - -{ value } -``` - -#### Preview - -```md -*Monitor Name* - -Monitor - -*Network* - -rinkeby - -*Block Hash* - -0x22407d00e953e5f8dabea57673b9109dad31acfc15d07126b9dc22c33521af52 - -*Transaction Hash* - -0x1dc91b98249fa9f2c5c37486a2427a3a7825be240c1c84961dfb3063d9c04d50 - -https://rinkeby.etherscan.io/tx/0x1dc91b98249fa9f2c5c37486a2427a3a7825be240c1c84961dfb3063d9c04d50[Block Explorer] - -*Match Reason 1* - -_Type:_ Function - -_Matched Address_:_ 0x1bb1b73c4f0bda4f67dca266ce6ef42f520fbb98 - -_Signature:_ greet(name) - -_Condition:_ name == 'test' - -_Params:_ - -name: test - -*Match Reason 2* - -_Type:_ Transaction - -_Condition:_ gasPrice > 10 - -*Value* - -0x16345785D8A0000 -``` - -##### Message Syntax - -Custom notifications support a limited set of markdown syntax: - -* Bold (`***this text is bold***`) -* Italic (`*this text*` and `_this text_` are italic) -* Links (this is a `[link](https://example.com)`) - -There is partial support for additional markdown syntax, but rendering behavior varies by platform. Email supports full HTML and has the richest feature set, but other messaging platforms have limitations, including support for standard markdown features such as headings, block quotes, and tables. Combinations of the supported features (e.g., bold and italicized text) also have mixed support. A warning message will appear directly below the editor if the markdown contains any syntax with mixed platform support. - -#### Monitor Event Schema -You can access the following schema when using custom notification templates. This schema is also passed to the Action if you configure your monitor to execute one. -```jsx - - "transaction": { // eth_getTransactionReceipt response body - ... // see https://eips.ethereum.org/EIPS/eip-1474 - "cumulativeGasUsed": "0xc3614", - "effectiveGasPrice": "0x6e214d78", - "gasUsed": "0x6075", - "logs": [ - { ... - ], - "logsBloom": "0x4..0", - "status": "0x1", - "from": "0xab..123", - "to": "0xab..123", - "transactionHash": "0xab..123", - "transactionIndex": "0x9", - "type": "0x2" - }, - "blockHash": "0xab..123", // block hash from where this transaction was seen - "matchReasons": [ // the reasons why monitor triggered - - "type": "event", // event, function, or transaction - "address": "0x123..abc", // address of the event emitting contract - "signature": "...", // signature of event/function - "condition": "value > 5", // condition expression (if any) - "args": ["5"], // parameters by index (unnamed are present) - "params": { "value": "5" // parameters by name (unnamed are not present) - } - ], - "matchedAddresses":["0x000..000"] // the addresses from this transaction monitored - "monitor": - "id": "44a7d5...31df5", // internal ID of monitor - "name": "Monitor Name", // name of monitor - "abi": [...], // abi of address (or undefined) - "addresses": ["0x000..000"], // addresses monitored - "confirmBlocks": 0, // number of blocks monitor waits (can be 'safe' or 'finalized' on PoS clients) - "network": "rinkeby" // network of address - "chainId": 4 // chain Id of the network - , - "value": "0x16345785D8A0000" // value of the transaction - "metadata": ... // metadata injected by action condition (if applicable) -} -``` - -##### Dynamic Content - -Custom notification templates render dynamic content using inline templating. Any string surrounded by double curly braces will be resolved against the Event Schema. Deeply nested items (including those in arrays) can be accessed using dot notation. - -In addition to the standard event schema, the following parameters are injected for usage in custom notification messages: - -* `transaction.link` -* `matchReasonsFormatted` - -#### Character Limit - -Messages will be truncated if they exceed a platform’s character limit. The best practice is to limit messages to 1900 characters. - -## Settings - -In the settings tab, you can specify the default notification channel associated with the different severities: High, Medium, or Low. - -![Monitor Settings](/defender/monitor-settings.png) - -## Pausing and Deleting - -From the monitor page, you can pause created monitors that are active. By clicking on the dotted button on the card, you can delete or save the monitor as a template. - -Saving a monitor as a template stores its configuration and parameters, which can be found by clicking the template gallery tab. - - -We provide a quickstart tutorial to monitor a smart contract using Defender. Check it out [here](/defender/tutorial/monitor)! - - diff --git a/content/defender/module/relayers.mdx b/content/defender/module/relayers.mdx deleted file mode 100644 index 6f12d83e..00000000 --- a/content/defender/module/relayers.mdx +++ /dev/null @@ -1,735 +0,0 @@ ---- -title: Relayers ---- - - - -Defender is now in maintenance mode. To continue relaying transactions with the latest features and updates, we recommend migrating to [OpenZeppelin Relayer](/relayer). - -See the complete [Migration Guide](/defender/migration#relayer-migration) for detailed instructions on exporting your configurations. - - - -Relayers allow you to send on-chain transactions via regular API requests or through other Defender modules, like Actions, Workflows, and Deploy. Relayers also automate the payment of gas fees and take care of private key secure storage, transaction signing, nonce management, gas pricing estimation, and resubmissions. With Relayers, you don't have to worry about storing private keys on your back-end servers or monitoring gas prices and transactions to ensure they get confirmed. - -## Use cases - -* Execute transactions on smart contracts automatically to trigger a state transition. -* Update an on-chain oracle with external data. -* Send meta-transactions to build a gasless experience. -* React to sign-ups in your app by airdropping tokens to your new users. -* Sweep funds from protocol contracts to secure wallets, -* Build bots with complete custom logic and flexibility. - -## What's a Relayer? - -A Relayer is an Ethereum-based externally-owned account (EOA) assigned exclusively to your team. Every time you create a new Relayer, Defender will create a new private key in a secure vault. Whenever you request Defender to send a transaction through that Relayer, the corresponding private key will be used for signing. - -You can think of each Relayer as a queue for sending transactions, where all transactions sent through the same Relayer will be sent in order and from the same account, controlled exclusively by your team. Learn more about the technical implemention [here](#under-the-hood). - -![Manage Relayers](/defender/manage-relayers.png) - -To create a Relayer, simply click the ***Create Relayer*** button on the top-right section of the page, specify a name and select the network. - -![Manage Relayers Detail](/defender/manage-relayers-detail.png) - - -Keep in mind that you’ll need to fund each Relayer individually with ETH (or the native chain token) to ensure they have enough funds to pay for the gas of the transactions you send. Defender will send you an email notification if a Relayer’s funds drop below 0.1 ETH. - - - -Testnet Relayers created through the Deploy wizard will be automatically funded if possible. Read more [here](/defender/module/deploy#step-3-upgrading). - - -### API Keys - -Each Relayer can have one or more **API keys** associated with it. In order to send a transaction through a Relayer, you will need to authenticate the request with one an API key/secret pair. You can create or delete API keys as you see fit, and this will not change the sending address or Relayer balance. - -To create an API key for a Relayer, click on the Relayer and then on the **More** button to expand the dropdown and select **Create API Key**. - -![Manage Relayers Create API Key](/defender/manage-relayers-create-api-key.png) - -Once the API Key is created, make sure to write down the secret key. The API secret is only visible once during the creation — if you don’t write it down, it’s lost forever. - -![Manage Relayer API Key](/defender/manage-relayer-api-key.png) - - -The API key of a Relayer is ***not*** related to its private key. The private key is always kept within a secure key vault and never exposed (see the [Security considerations](#security-considerations) section for more info). This decoupling allows you to freely rotate API keys while keeping the same address for your Relayer. - - -### Addresses - -Whenever you create a Relayer, a fresh EOA will be created to back it. For security reasons, it’s not possible to import an existing private key into a Relayer nor export the private key of a Relayer created by Defender. If you grant a privileged role to a Relayer address in your system to avoid lock-in, consider having an administrative method for switching it to a different one if needed. - -### Policies - -You can limit a Relayer’s behavior by specifying policies. - -To configure a Relayer’s policies, go to the [Relayer page](https://defender.openzeppelin.com/v2/#/relayers), select the Relayer, and then go to the **Policies** tab. You will then see a form where you can opt to enable policies and tweak their parameters. - -![Manage Relayer Policies](/defender/manage-relayer-policies.png) - -#### Gas price cap -Specify a maximum gas price for every transaction sent with the Relayer. When this policy is enabled, Defender will overwrite the `gasPrice` or `maxFeePerGas` of any transaction that goes beyond the specified cap. Take into account that the gas price for a transaction is specified based on gas price oracles at the moment the Relayer actually sends the transaction to be mined, so this policy can be used as a protection on gas price surges. - - -In addition to the maximum gas price policy you can specify here, Defender implements a minimum gas price policy for networks that have minimum gas requirements. Check requirements with the individual networks you use. - - -#### Receiver whitelist -Specify a list of authorized contracts for every transaction sent using the Relayer. Defender will reject and discard any transaction whose destination address is not in the list. - - -The whitelist applies only to the `to` field of a transaction. It doesn’t filter ERC20 or other assets receivers. - - -#### EIP1559 Pricing -Specify if the transactions the Relayer sends should be EIP1559 by default or not. This applies whenever the Relayer sends a transaction with dynamic gas pricing or a non specified `gasPrice` or `maxFeePerGas`/`maxPriorityFeePerGas`. Note that this policy option is only shown for EIP1559 compatible networks. - - -EIP1559 Pricing policy is enabled by default for new Relayers. If you have a Relayer that was created without the default opt-in, you can always enable this flag. - - -#### Private transactions -Specify if the transactions should be sent via private mempool. This means that a transaction will not be publicly seen until it’s included in a block. - -The parameter can be toggled between the following states: `true` to enable private mempool transactions, `false` to opt for public visibility. Alternatively, users can specify the transaction speed by setting the value to either `flashbots-normal` or `flashbots-fast`. By default, when the policy is set to `true`, the speed defaults to `flashbots-normal`, allowing for seamless inclusion while maintaining transaction privacy. This configuration empowers users to tailor their transaction strategy to suit their specific privacy and speed requirements effectively. You can read about faster transactions with Flashbots [here](https://docs.flashbots.net/flashbots-protect/quick-start#faster-transactions). - - -Private transactions are only enabled for _mainnet_ by using the [Flashbots Protect RPC](https://docs.flashbots.net/flashbots-protect/rpc/quick-start). So, the same [key considerations](https://docs.flashbots.net/flashbots-protect/rpc/quick-start#key-considerations) might apply while sending private transactions through Defender. - - -## Relayer Groups - -Relayer Groups are collections of individual relayers that work together to submit transactions. By grouping relayers, you can increase the overall transaction throughput and redundancy, which enhances the reliability of the transaction submission process. Relayer Groups are designed to distribute the workload across multiple relayers, ensuring that no single relayer becomes a bottleneck. - -### Benefits of Relayer Groups - -* ***Increased Throughput:*** Relayer Groups can handle a higher volume of transactions because the workload is spread across multiple relayers. -* ***Redundancy:*** If one relayer in the group fails or becomes slow, others can take over, reducing the risk of delays. -* ***Efficiency:*** By coordinating multiple relayers, you can optimize transaction submission and ensure that transactions are processed as quickly as possible. -* ***Centralised Management:*** The ability to manage multiple relayers under a single API key simplifies administration, making it easier to maintain control over a complex system. - -### Drawbacks of Relayer Groups - -* ***Unified Configuration:*** Policies and configurations apply uniformly across all relayers in the group, making it difficult to manage individual relayer settings. -* ***Limited Functionality:*** Certain functionalities, like message signing, are not available for relayers that are part of a group. -* ***Group-Restricted Operation:*** Relayers within a group cannot be used independently; they must function collectively as part of the group. -* ***Potential Transaction Order Issues:*** Since transactions are distributed among different relayers based on their condition, they may not be processed in the order they were received, leading to some transactions being mined out of sequence. - -### Health Monitoring -Relayer groups rely on regular health checks to ensure that transactions are distributed efficiently among the relayers in the group. These health checks assess the performance and availability of each relayer, helping the system decide which relayers are best suited to handle new transactions. - -The system regularly evaluates each relayer in the group. It calculates a "weight" for each relayer based on several key factors. These weights are then used to determine how transactions should be distributed within the group, with priority given to the most reliable and responsive relayers. - -* ***Speed of First Transaction Processing (Highest Priority):*** The most important factor is how quickly a relayer starts processing transactions. The system looks at the time it takes for the first pending transaction to be sent and processed. A faster relayer is considered healthier and is given a higher priority. -* ***Number of Pending Transactions:*** The system checks how many transactions are waiting in each relayer’s queue. If a relayer has a lot of pending transactions, it might indicate that it’s overloaded and could struggle to process new transactions quickly. -* ***Remaining Balance:*** The relayer’s available balance is also considered. A relayer needs enough balance to cover transaction fees. If a relayer’s balance is low, it may have difficulty processing transactions, which affects its health score. - -Users can manually adjust the weight of individual relayers. For example, setting a weight of 0 would prevent a relayer from being used, offering precise control over which relayers are active. - -## Sending transactions - -The easiest way to send a transaction via a Relayer is using the [`Defender SDK`](https://www.npmjs.com/package/@openzeppelin/defender-sdk) package. The client is initialized with an API key/secret and exposes a simple API for sending transactions through the corresponding Relayer. - -```jsx -const Defender = require('@openzeppelin/defender-sdk'); -const client = new Defender( - relayerApiKey: 'YOUR_API_KEY', - relayerApiSecret: 'YOUR_API_SECRET' -); - -const tx = await client.relayerSigner.sendTransaction( - to, value, data, gasLimit, speed: 'fast' -); - -const mined = await tx.wait(); -``` - - - -For better reliability of the relayers, we recommend sending no more than **50 transactions/min** on a single relayer especially on fast moving chains like Polygon, Optimism, Arbitrum etc.. For example, if you want 250 transactions/min throughput, you would need to load balance across 5 relayers. These 5 relayers can be part of the same account. - - - -You don’t need to enter a private key when initializing a Relayer client, since the private key is kept secure in the Defender vault. - - - -Currently, _zkSync_ doesn’t have a way to precisely calculate `gasLimit` other than using the `eth_estimateGas` endpoint. Therefore, Defender can’t do any gasLimit and overrides the user input with the RPC estimation. - - -### Using ethers.js - -The Relayer client integrates with [ethers.js](https://docs.ethers.io/v6/) via a custom [signer](https://docs.ethers.org/v6/api/providers/#Signer). This allows you switch to a Relayer and send transactions with minimal changes in your codebase. - -```jsx -const Defender = require('@openzeppelin/defender-sdk'); -const ethers = require('ethers'); - -const credentials = relayerApiKey: YOUR_RELAYER_API_KEY, relayerApiSecret: YOUR_RELAYER_API_SECRET ; -const client = new Defender(credentials); - -const provider = client.relaySigner.getProvider(); -const signer = client.relaySigner.getSigner(provider, speed: 'fast', validUntil ); - -const erc20 = new ethers.Contract(ERC20_ADDRESS, ERC20_ABI, signer); -const tx = await erc20.transfer(beneficiary, 1e18.toString()); -const mined = await tx.wait(); -``` - -In the example above, we are also using a `DefenderRelayProvider` for making calls to the network. The signer can work with any provider, such as `ethers.getDefaultProvider()`, but you can rely on Defender as a network provider as well. - -You can read more about the ethers integration [here](https://www.npmjs.com/package/@openzeppelin/defender-sdk-relay-client). - -### Using web3.js - -The Relayer client integrates with [web3.js](https://web3js.readthedocs.io/) as well as via a custom [provider](https://web3js.readthedocs.io/en/v1.3.4/web3-eth.html#providers). This allows you to send transactions with a Relayer and query the network using the familiar web3 interface. - -```jsx -const Defender = require('@openzeppelin/defender-sdk'); -const Web3 = require('web3'); - -const credentials = relayerApiKey: YOUR_RELAYER_API_KEY, relayerApiSecret: YOUR_RELAYER_API_SECRET ; -const client = new Defender(credentials); - -const provider = client.relaySigner.getProvider(); - -const web3 = new Web3(provider); - -const [from] = await web3.eth.getAccounts(); -const erc20 = new web3.eth.Contract(ERC20_ABI, ERC20_ADDRESS, from ); -const tx = await erc20.methods.transfer(beneficiary, (1e18).toString()).send(); -``` - -In the example above, the `transfer` transaction is signed and broadcasted by the Relayer, and any additional JSON RPC calls are routed via Defender private endpoint. - -You can read more about the web3 integration [here](https://www.npmjs.com/package/@openzeppelin/defender-sdk-relay-client). - -### Intents Support with Relay Signer - -When using the Defender SDK’s relay signer to send transactions from the context of an ethers/web3 contract, it is important to note that transactions in [intent mode](#the-intent-mechanism) are not supported. If the API returns an [intent response](#intent-response), an error will be thrown due to the current implementation expecting certain fields that are absent in the intent response. - -To avoid this issue, it is recommended to fallback to using the default SDK `sendTransaction` method for transaction submissions. This ensures that the transaction can be processed without errors. - -Additionally, the current implementation does not track transactions that are resubmitted, which can lead to complications when multiple hashes are generated due to retries. It is crucial to implement logic that can handle these scenarios effectively, ensuring that the process completes even when transaction hashes change in the background. - -### EIP1559 support - -Since not all of the supported networks are EIP1559 compatible, the EIP1559 transaction support is only enabled for those ***networks identified as compatible*** and enabled by the team. - -A Relayer can send EIP1559 transactions in the following ways: - -* Sending a transaction via UI with the [`EIP1559Pricing`](#eip1559-pricing) policy ***enabled*** -* Sending a transaction via API with both `maxFeePerGas` and `maxPriorityFeePerGas` specified -* Sending a transaction via API with `speed` and with the [`EIP1559Pricing`](#eip1559-pricing) policy ***enabled*** - -Once any transaction is sent, ***it will have the same type*** on every stage of its lifecycle (such as replacement and repricing), so it’s currently not possible to change the type if it’s already been submitted. - - -Any attempt to send `maxFeePerGas` or `maxPriorityFeePerGas` to non-EIP1559 compatible networks will be rejected and discarded by the Relayer. - - -You can tell if a network supports EIP1559 by looking at the Relayer [policies](#policies). If the EIP1559Pricing policy doesn’t show up, it means that we haven’t added EIP1559 support for that network. - - -If you notice an EIP1559 compatible network that we already support but doens’t have the EIP enabled, please don’t hesitate to reach out via [https://www.openzeppelin.com/defender2-feedback](https://www.openzeppelin.com/defender2-feedback). - - -### Private transactions - -Private transaction allows a Relayer to send transactions without being visible on the public mempool, and instead, the transaction is relayed via a private mempool using a special `eth_sendRawTransaction` provider, which will vary depending on the network and current support (such as Flashbots network coverage). - -A Relayer may send a private transaction in any of the following ways: - -* Sending a transaction via API with the [`privateTransactions`](#private-transactions) policy ***enabled*** or set to `flashbots-normal` or `flashbots-fast` -* Sending a transaction via API with `isPrivate` parameter set to `true` -* Sending a transaction via UI and checking the Mempool Visibility checkbox - -![Mempool visibility checkbox on Relayer's send transaction view](/defender/relayer-mempool-visibility-check.png) - - -Sending a transaction with the `isPrivate` flag set to `true` to a network that doesn’t support private transactions will be rejected and discarded by the Relayer. - - -Currently, only the following network is supported - -* **Mainnet**: Via [Flashbots Protect RPC](https://docs.flashbots.net/flashbots-protect/rpc/quick-start) - -### Speed - -Instead of the usual `gasPrice` or `maxFeePerGas`/`maxPriorityFeePerGas`, the Relayer may also accept a speed parameter, which can be `safeLow`, `average`, `fast`, or `fastest`. These values are mapped to actual gas prices when the transaction is sent or resubmitted and vary depending on the state of the network. - -If speed is provided, the transaction would be priced according to the `EIP1559Pricing` Relayer policy. - - -Mainnet gas prices and priority fees are calculated based on the values reported by [EthGasStation](https://ethgasstation.info/), [EtherChain](https://etherchain.org/tools/gasPriceOracle), [GasNow](https://www.gasnow.org/), [Blockative](https://docs.blocknative.com/gas-platform), and [Etherscan](https://etherscan.io/gastracker). In Polygon and its testnet, the [gas station](https://gasstation-mainnet.matic.network/v2) is used. In other networks, gas prices are obtained from a call to `eth_gasPrice` or `eth_feeHistory` to the network. - - -### Fixed Gas Pricing - -Alternatively, you may specify a ***fixed gasPrice*** or a ***fixed combination of maxFeePerGas and maxPriorityFeePerGas*** for a transaction, by setting either the `gasPrice` parameter or `maxFeePerGas` and `maxPriorityFeePerGas` parameters. Transactions with a fixed pricing are either mined with the specified pricing or replaced with a NOOP transaction if they couldn’t be mined before [validUntil](#valid-until) time. - -Keep in mind that you have to provide either `speed`, `gasPrice`, `maxFeePerGas`/`maxPriorityFeePerGas` or none, but not a mix between them in a send transaction request. - - -Whenever a send transaction request is sent without any pricing parameter, it will be priced with a `fast` default speed. - - - -If you’re providing both fixed `maxFeePerGas` and `maxPriorityFeePerGas`, make sure that `maxFeePerGas` is greater or equal than `maxPriorityFeePerGas`. Otherwise, it’ll be rejected. - - -### Valid Until - -Every transaction via a Relayer is valid for submission to the network until `validUntil` time. After `validUntil` time the transaction is replaced by a NOOP transaction in order to prevent Relayers from getting stuck at the transaction’s nonce. A NOOP transaction does nothing except advancing the Relayer’s nonce. - -`validUntil` defaults to 8 hours after the transaction creation. Note that you can combine validUntil with a [fixed pricing](#fixed-gas-pricing) to achieve extremely fast mining times and beating other transactions on `gasPrice` or `maxFeePerGas`. - -If you’re using `ethers.js`, you may set a `validForSeconds` option instead of `validUntil`. In the example below, we configure a `DefenderRelaySigner` to issue a transaction which will be valid for 120 seconds after its creation. - -```jsx -const DefenderRelayProvider, DefenderRelaySigner = require('@openzeppelin/defender-sdk-relay-signer-client/ethers'); -const ethers = require('ethers'); - -const credentials = apiKey: API_KEY, apiSecret: API_SECRET ; -const provider = new DefenderRelayProvider(credentials); -const signer = new DefenderRelaySigner(credentials, provider, speed: 'fast', validForSeconds: 120 ); -``` - - -`validUntil` is a UTC timestamp. Make sure to use a UTC timezone and not a local one. - - -### Transaction IDs - -Since a Relayer may resubmit a transaction with an updated gas pricing if it does’t get confirmed in the expected time frame, the `hash` of a given transaction may change over time. To track the status of a given transaction, the Relayer API returns a `transactionId` identifier you can use to [query](https://www.npmjs.com/package/@openzeppelin/defender-sdk-relay-signer-client) it. - -```jsx -import Relayer from '@openzeppelin/defender-sdk-relay-signer-client'; -const relayer = new Relayer( apiKey: API_KEY, apiSecret: API_SECRET ); -const latestTx = await relayer.getTransaction(tx.transactionId); -``` - -The returned transaction object `latestTx` will have the following shape: - -```jsx -interface RelayerTransactionBase - transactionId: string; // Defender transaction identifier - hash: string; // Ethereum transaction hash - to: string; - from: string; - value?: string; - data?: string; - speed: 'safeLow' | 'average' | 'fast' | 'fastest'; - gasLimit: number; - nonce: number; - status: 'pending' | 'sent' | 'submitted' | 'inmempool' | 'mined' | 'confirmed' | 'failed'; - chainId: number; - validUntil: string; - -``` - - -The `getTransaction` function will return the latest view of the transaction from the Defender service, which gets updated every minute. - - -### Replace Transactions - -While a Relayer will automatically resubmit transactions with increased gas pricing if they are not confirmed, and will automatically cancel them after their valid-until timestamp, you can still manually replace or cancel your transaction if it has not been mined yet. This allows you to cancel a transaction if it is no longer valid, tweak its TTL, or bump its speed or gas pricing. - -To do this, use the `replaceByNonce` or `replaceById` of the `@openzeppelin/defender-sdk-relay-client`: - -```jsx -// Cancel tx payload (tx to a random address with zero value and data) -replacement = - to: '0x6b175474e89094c44da98b954eedeac495271d0f', - value: '0x00', - data: '0x', - speed: 'fastest', - gasLimit: 21000 -; - -// Replace a tx by nonce -tx = await relayer.replaceTransactionByNonce(42, replacement); - -// Or by transactionId -tx = await relayer.replaceTransactionById('5fcb8a6d-8d3e-403a-b33d-ade27ce0f85a', replacement); -``` - -You can also replace a pending transaction by setting the `nonce` when sending a transaction using the `ethers` or `web3.js` adapters: - -```jsx -// Using ethers -erc20 = new ethers.Contract(ERC20_ADDRESS, ERC20_ABI, signer); -replaced = await erc20.functions.transfer(beneficiary, 1e18.toString(), - nonce: 42 -); - -// Using web3.js -erc20 = new web3.eth.Contract(ERC20_ABI, ERC20_ADDRESS, from ); -replaced = await erc20.methods.transfer(beneficiary, (1e18).toString()).send( - nonce: 42 -); -``` - - -You can ***only*** replace transactions of the same type. For example, if you’re trying to replace an EIP1559 transaction, it ***can’t be replaced*** with a legacy transaction. Also, if `speed` is provided instead, the transaction will be repriced as its original type requires with the given speed. - - -### Webhooks Notifications - -Listening to transaction status changes can be efficiently achieved using a push-based approach through webhooks. This method allows your application to receive real-time notifications whenever there are updates to the status of a transaction. - -***Steps to Configure Webhook Notifications***: - -1. ***Access the Relayers Page*** -2. ***Select Transaction Statuses***: - On the Relayers page, you will find options to select the specific transaction statuses for which you want to receive notifications. Available statuses: - * ***Pending***: Transaction received by the Defender. - * ***Sent***: Transaction prepared for sending(priced and signed). - * ***Submitted***: Transaction submitted to the network. - * ***InMemPool***: Transaction found in the mempool. - * ***Mined***: Transaction mined. - * ***Confirmed***: Transaction confirmed(a minimum of 12 confirmations). -3. ***Choose Notification Channel***: - After selecting the desired statuses, you need to choose webhook notification channels. This is where the webhook notifications will be sent. -4. ***Save Your Configuration***: - Once you have selected the statuses and configured the notification channel, save your settings. This will register your webhook and start the process of receiving notifications for the selected events. - -Example of Webhook Notification: -```json - - "event": "transaction_status_change", - "timestamp": "2024-06-13T12:29:41.254Z", - "transaction": { - "signature": { - "r": "0xee81d58c53c1d3432c95847c71a525417bad6e8fa711007137b2e11155ba8f94", - "s": "0x362ce1f75d660504e22590f678c243bc24954ccfbf17864f4aab05fd8b1d6ca3", - "v": "0x1b" - , - "maxPriorityFeePerGas": 7556907973, - "maxFeePerGas": 39004490874, - "chainId": 11155111, - "hash": "0xea04c34422295ef60b57fea50790b4f9396d852274fa46ee5cf8d0407d7cc32b", - "transactionId": "1eece8bb-05d6-493f-903a-12c750700b81", - "value": "0x5af3107a4000", - "gasLimit": 25200, - "to": "0x5e87fD270D40C47266B7E3c822f4a9d21043012D", - "from": "0xf87921a0999d522383afa2b41db2538231a647f0", - "data": "0x", - "nonce": 19, - "status": "mined", - "speed": "fast", - "validUntil": "2024-06-13T20:29:01.051Z", - "createdAt": "2024-06-13T12:29:01.546Z", - "sentAt": "2024-06-13T12:29:01.546Z", - "pricedAt": "2024-06-13T12:29:01.546Z", - "isPrivate": false - } -} -``` - -### List Transactions - -You can also list the latest transactions sent via your Relayer, optionally filtering by status (pending, mined, or failed). This can be particularly useful to prevent your Actions scripts from re-sending a transaction already in-flight: before sending a transaction, you can use the list method filtered by `pending` status to see if there is a transaction in the queue with the same destination and calldata as the one you are about to send. - -```jsx -const txs = await relayer.list( - since: new Date(Date.now() - 60 * 1000), - status: 'pending', // can be 'pending', 'mined', or 'failed' - limit: 5, // newest txs will be returned first - usePagination: true, - next: '' // optional next cursor for pagination - sort: 'desc' -) -``` - -### Delete Pending Transaction - -In situations where a relayer is stuck and unable to process transactions, the system provides a functionality to delete pending transactions. This action is designed as a last resort to address issues with transactions that have not been mined for at least 30 minutes. This feature can be activated from the Relayer Drawer, under the Pending Transactions tab, when the relayer has pending transactions. - -Key Points: - -* ***Intended Use***: This feature is specifically aimed at resolving issues with relayers that are stuck due to unmined transactions. It is recommended to use this only after confirming that there have been no transactions mined for at least 30 minutes. -* ***Operation Overview***: Upon initiating the delete operation, the relayer will enter a paused state. During this pause, the system will either send NOOPs (No-Operation Instructions) to clear certain transactions or remove them entirely from the database. This distinction is made based on the specific characteristics of each pending transaction. -* ***Duration***: The entire process of deleting pending transactions and resuming normal operations can take up to 30 minutes. This includes the time taken to assess each transaction, apply the necessary actions, and ensure the relayer is ready to resume its functions. -* ***Resumption of Operations***: After the completion of the delete operation, the relayer will automatically resume its standard activities. Users do not need to take any further action to reactivate the relayer. -* ***Notification***: Users will receive an email notification once the process is complete and the relayer has resumed its operations. - -### The Intent Mechanism - -An "intent" is a concept introduced to improve the efficiency and reliability of transaction submissions. Instead of immediately submitting a transaction, an intent is a placeholder that indicates a transaction is ready to be sent but is temporarily held back. This mechanism helps manage situations where the transaction queue becomes too large or when the network or relayer is processing transactions slowly. - -Intents are used to maintain the order of transactions and prevent overloading the system. There are two primary scenarios where intents come into play: - -* ***High Transaction Volume:*** When the number of pending transactions exceeds the maximum allowed in-flight, new transactions are stored as intents. This prevents the system from being overwhelmed and ensures that transactions are submitted in the correct order. -* ***Slow Processing:*** If the network or relayer is processing transactions slowly (e.g., no transaction has been mined in the last 30 minutes), new transactions are stored as intents to avoid adding to the congestion. - -#### Intent Response - -Intent response is similar to the response of a normal transaction, but with the following differences: - -* `hash` is `null` -* `isIntent` is `true` and indicates the transaction was sent as an intent, this will not be set for normal transactions. This field will not be removed or changed when the intent is processed. -* `pendingIntentSince` is the timestamp when the intent was created and indicates the intent is still pending. This field will be removed once the intent is processed. -* `relayerId` is the same ID of the relayer group upon creation. This will change to the ID of the relayer that will process the intent once the assignment is made. -* No gas-related fields are set, the transaction will be priced when it is processed. - -```json - - "hash": null, - "transactionId": "transaction123", - "value": "0x1", - "gasLimit": 21000, - "to": "0x123...", - "data": "0x", - "status": "pending", - "speed": "fast", - "validUntil": "2000-01-01T20:00:00.000Z" - "isIntent": true, - "relayerId": "relayer123", - "tenantRelayerGroupId": "tenant123|relayerGroup123", - "createdAt": "2000-01-01T12:00:00.000Z" - -``` - -#### Cancel Intents - -Relayer transaction intents can be canceled and permanently removed from our end. This feature is particularly useful when you need to prevent a specific intent from being submitted or want to free up space in the queue for other, more urgent transactions. - -To do this, use the `cancelTransactionById` method of the `@openzeppelin/defender-sdk-relay-client`: - -```jsx -tx = await relayer.cancelTransactionById('5fcb8a6d-8d3e-403a-b33d-ade27ce0f85a'); -``` - -## Signing - -In addition to sending transactions, a Relayer can also sign arbitrary messages according to the [EIP-191 Standard](https://eips.ethereum.org/EIPS/eip-191) (prefixed by `\x19Ethereum Signed Message:\n`) using its private key. You can access this feature via the `sign` method of the client or the equivalent ethers.js method. - -```jsx -const signResponse = await relayer.sign( message ); -``` - - -As opposed to most libraries, Relayers use non-deterministic ECDSA signatures. This means that if you request a Relayer to sign the same message multiple times, you will get multiple different signatures, which may differ to the result you get by signing using ethersjs or web3js. All those different signatures are valid. See [RFC6979](https://datatracker.ietf.org/doc/html/rfc6979#section-3) more information. - - - -For relayers that are part of a relayer group this method is not available. - - -## Signing Typed Data - -Along with the sign api method, Relayers also implement a `signTypedData`, which you can use to sign messages according to the [EIP712 Standard](https://eips.ethereum.org/EIPS/eip-712) for typed data signatures. -You can either provide the `domainSeparator` and `hashStruct(message)` or use the equivalent ethers.js method - -```jsx -const signTypedDataResponse = await relayer.signTypedData( - domainSeparator, - hashStructMessage -); -``` - - -For relayers that are part of a relayer group this method is not available. - - -## Relayer Info - -A relayer’s address can be retrieved using the `getAddress` method of the `DefenderRelaySigner` class. - -```jsx -const address = await signer.getAddress(); -``` - -If you need more info about a Relayer then checkout the `getRelayer` method of the client. It returns the following data: - -```jsx -const info = await relayer.getRelayer(); -console.log('Relayer info', info); - -export interface RelayerModel - relayerId: string; - name: string; - address: string; - network: string; - paused: boolean; - createdAt: string; - pendingTxCost: string; - -``` - - -For relayers that are part of a relayer group this method will return the relayer group information. - - -## Relayer Status - -To gain better insight into the current status of a relayer, one can use the `getRelayerStatus` method from the `DefenderRelaySigner` class. This method provides real-time information about a relayer, such as its nonce, transaction quota, and the number of pending transactions. -```jsx -const address = await signer.getRelayerStatus(); -``` - -If you need info about a Relayer then checkout the `getRelayer` method of the client. It returns the following data: - -```jsx -export interface RelayerStatus - relayerId: string; - name: string; - nonce: number; - address: string; - numberOfPendingTransactions: number; - paused: boolean; - pendingTxCost?: string; - txsQuotaUsage: number; - rpcQuotaUsage: number; - lastConfirmedTransaction?: { - hash: string; - status: string; - minedAt: string; - sentAt: string; - nonce: number; - ; -} -``` - - -For relayers that are part of a relayer group this method will return an array of status responses for the group. - - -## Network calls - -Defender also provides an easy way to make arbitrary JSON RPC calls to the network. You can use the low-level `relayer.call` method to send any JSON RPC HTTP request: - -```jsx -const balance = await relayer.call('eth_getBalance', ['0x6b175474e89094c44da98b954eedeac495271d0f', 'latest']); -``` - -If you are using ethers.js, this is supported via a custom `DefenderRelayProvider` [provider](https://docs.ethers.org/v6/api/providers/) object: - -```jsx -const provider = new DefenderRelayProvider(credentials); -const balance = await provider.getBalance('0x6b175474e89094c44da98b954eedeac495271d0f'); -``` - -## Withdrawing funds - -You can withdraw funds from a Relayer on the [Relayers page](https://defender.openzeppelin.com/v2/#/relayers), selecting the Relayer, and clicking on **Withdraw**. - -![Relayer Withdraw Button](/defender/relayer-withdraw.png) - -At the **Withdraw** screen, you can choose to send funds in ETH or pick from a built-in list of ERC20 tokens. - -![Relayer Withdraw Funds Screen](/defender/relayer-withdraw-screen.png) - -## Under the hood - -Each Relayer is associated to a private key. When a request to send a transaction is received, the Relayer validates the request, atomically assigns it a nonce, reserves balance for paying for its gas fees, resolves its speed to a `gasPrice` or `maxFeePerGas`/`maxPriorityFeePerGas` depending on its EIP1559 pricing policy, signs it with its private key, and enqueues it for submission to the blockchain. The response is sent back to the client only after this process has finished. Then, the transaction is broadcasted through multiple node providers for redundancy and retried up to three times in case APIs are down. - -Every minute, all in-flight transactions are checked by the system. If they have not been mined and more than a certain time has passed (which depends on the transaction speed), they are resubmitted with a 10% increase in their respective transaction type pricing (or the latest pricing for their speed, if it’s greater), which could be up to a **150% of the reported gas pricing for their speed**. This process causes the transaction hash to change, but their ID is preserved. On the other hand, if the transaction has been mined, it is still monitored for several blocks until we consider it to be confirmed. - -### Insufficient Funds - -Defender carefully tracks the costs of transactions sent to a relayer. In instances where the relayer cannot immediately process a transaction, Defender accumulates the costs of all pending transactions. Before allowing any new transactions to be submitted, Defender will ensure that the balance of the relayer is sufficient to cover the costs of all pending transactions including the new one. Consequently, you may encounter an "insufficient funds" error for a particular transaction during such occurrences. - -* The cost of a transaction is calculated as: `txCost = gasLimit * maxFeePerGas + value`. -* The balance of a relayer is calculated as: `predictedBalance = balance - pendingTxCosts`. - -An "insufficient funds" error will throw when: `txCost > predictedBalance`. - -## Transaction Throughput and Load Balancing - - -We recommend using relayer groups for increased throughput and redundancy. However, if that is not an option, you could use the method below to optimize your setup. - - -Relayers assign nonces atomically which allows them to handle many concurrent transactions. However, there do exist limits to optimize the infrastructure (all numbers below are cumulative of all Relayers in an account) - -By default, when you create an api key for a specific relayer it’s automatically assigned with the following rate limits. - -* 100 requests/second with a burst of 300 requests. - -These rate limits are for both reads ( e.g. - getting transaction status ) and writes ( e.g. - sending transactions ). - -If you need additional throughput for your use case please reach out `defender-support@openzeppelin.com`. You need to be on **enterprise tier** for throughput increases. - -For better reliability of the relayers, we recommend sending no more than **50 transactions/min** on a single relayer especially on fast moving chains like Polygon, Optimism, Arbitrum etc.. For example, if you want 250 transactions/min throughput, you would need to load balance across 5 relayers. These 5 relayers can be part of the same account. - -You may use the [`Defender SDK`](https://www.npmjs.com/package/@openzeppelin/defender-sdk) package to load balance across multiple relayers. Here is a simple example on how you can do this: - -```ts -require('dotenv').config(); - -const Defender = require('@openzeppelin/defender-sdk'); - -async function loadbalance() - const LOAD_BALANCE_THRESHOLD = 50; - const relayerCredsForMainNet = [ - { - relayerApiKey: process.env.RELAYER_API_KEY_1, - relayerApiSecret: process.env.RELAYER_API_SECRET_1, - , - - relayerApiKey: process.env.RELAYER_API_KEY_2, - relayerApiSecret: process.env.RELAYER_API_SECRET_2, - , - ]; - const relayerClientsForMainNet = relayerCredsForMainNet.map((creds) => new Defender(creds)); - - const getNextAvailableRelayer = async () => - for (const client of relayerClientsForMainNet) { - const relayerStatus = await client.relaySigner.getRelayerStatus(); - if (relayerStatus.numberOfPendingTransactions < LOAD_BALANCE_THRESHOLD) { - return client; - - console.log( - `$relayerStatus.relayerId is busy. Pending transactions: $relayerStatus.numberOfPendingTransactions/$LOAD_BALANCE_THRESHOLD`, - ); - } - return undefined; - }; - - const executeTransaction = async () => - const client = await getNextAvailableRelayer(); - if (!client) throw new Error('Unable to load balance. All relayers are operating above the suggested threshold.'); - - const txResponse = await client.relaySigner.sendTransaction({ - to: '0x179810822f56b0e79469189741a3fa5f2f9a7631', - value: 1, - speed: 'fast', - gasLimit: '21000', - ); - console.log('txResponse', JSON.stringify(txResponse, null, 2)); - - await executeTransaction(); -} - -async function main() - try { - return await loadbalance(); - catch (e) - console.log(`Unexpected error:`, e); - process.exit(1); - -} - -if (require.main === module) - main().catch(console.error); - -``` - -## Security considerations - -All private keys are stored in the AWS Key Management Service. Keys are generated within the KMS and never leave it, i.e., all sign operations are executed within the KMS. Furthermore, we rely on dynamically generated AWS Identity and Access Management policies to isolate access to the private keys among tenants. - -As for API secrets, these are only kept in memory during creation when they are sent to the client. After that, they are hashed and stored securely in AWS Cognito, which is used behind the scenes for authenticating Relayer requests. This makes API keys easy to rotate while preserving the same private key on the KMS. - -### Rollups - -When sending transactions to a rollup chain, such as Arbitrum or Optimism, Relayers currently depend on the chain’s sequencer/aggregator. This means that, if the sequencer goes down or censors transactions, Relayers will not bypass it and commit directly to layer 1. - -## Inactivity - -Testnet relayers are considered inactive if they haven’t sent any transactions in more than 60 days. When a testnet relayer is inactive, we provide a 14-day grace period to mark the relayer as active. If users don’t take any action, the relayer will be automatically deleted once the period is over. diff --git a/content/defender/module/transaction-proposals.mdx b/content/defender/module/transaction-proposals.mdx deleted file mode 100644 index 54f5717f..00000000 --- a/content/defender/module/transaction-proposals.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Transaction Proposals ---- - -Transaction Proposals are very similar to actions, but instead of having to write the javascript code, you can use a form-based editor to define the transaction parameters.\ -This low-code format is very useful for non technical users and simple scenarios, but lacks the flexibility of the Actions. If you need to invoke external APIs or contracts, or perform more complex logic, you should use the [Actions](/defender/module/actions) instead. - -## General Information -To create a Transaction Proposal from Defender, you need to define a few parameters: - -* Title: A descriptive name for the proposal. This will be latter shown in the proposal list. -* Description(optional): A longer description of the proposal. This will be shown in the proposal details. -* Target Contract: The smart contract that you want to run the transaction on. - - -If you have trouble connecting your wallet to Defender, there may be a conflict between wallet extensions if multiple are installed. - - -## Function -Define the function that you want to call on the target contract. You can select from a list of functions that are available on the contract interface. If the function has parameters, you can define them here. - -## Approval Process -Define how you want the transaction to be executed. You can choose from any of the [transaction approval processes](/defender/settings#approval-processes) available in Defender that you have previously configured or you can optionally create a new one. diff --git a/content/defender/remix-plugin.mdx b/content/defender/remix-plugin.mdx deleted file mode 100644 index 498cf024..00000000 --- a/content/defender/remix-plugin.mdx +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: Remix Plugin ---- - -When coding and compiling contracts from [Remix IDE](https://remix.ethereum.org/), you can use Defender Plugin to deploy your contracts by configuring a [Deployment Environment](/defender/module/deploy) and using an Approval Process as deployer. - -## Installation - -1. Go to [Remix IDE](https://remix.ethereum.org/) and click on Plugin manager (bottom left corner). -2. Search **Defender Deploy** from the Modules list, and click "Activate". -3. A new tab in the left nav bar with the OpenZeppelin icon should be displayed. - -![Install Defender Remix Plugin](/defender/remix-plugin-install.png) - -## Usage - -### API Key generation -In your Defender dashboard, go to **Settings -> API Keys** and click **Create API Key**, you only need _Manage Deployments_ permission. - - -We also recommend to set an expiration for the API Key, considering that is going to be used from an external site. - - -![Defender Remix Plugin Api Key](/defender/remix-plugin-api-key.png) - -### Deployment from Remix - -Go to Remix IDE site, and open Defender plugin (see Installation step). - -#### Setup -Set your **API Key** and **API Secret** and press "Authenticate". If the keys are valid, you should see a green tick in at the right indicating that you were succesfully authenticated, also a message in the Remix terminal. - -![Defender Remix Plugin Setup](/defender/remix-plugin-setup.png) - -#### Network -Select any of the supported networks. This also includes private and fork networks configured in your tenant. - -![Defender Remix Plugin Network](/defender/remix-plugin-network.png) - -#### Approval Process -Here you have 3 options: - -* Select an existing approval process from your **Deployment Environment** configured for the selected network. - - -If you have an existing deployment environment in the selected network, this is the only option allowed. - - -* If the **Deployment Envoronment** does not exist for the selected network, then you can create a new one. - - -If the Approval Process to be created is a Relayer, the API Key must include _Manage Relayers_ permission. - - -* Additionally, you can use the **injected provider** from Remix (a browser wallet) to deploy the contract, this will create a Defender **Deployment Environment** under the hood after deploying the contract. - -![Defender Remix Plugin Approval Process](/defender/remix-plugin-approval-process.png) - -#### Deploy -You should see the latest compiled contract along with the constructor inputs. - - -In case you don’t see it, compile the target contract again, the Defender plug-in should detect the compilation and display the contructor inputs. - - - -Upgradable contracts are not yet fully supported. This action will only deploy the implementation contract without initializing. For safe upgrades, we strongly recommend usign [Upgrades Package](https://github.com/OpenZeppelin/openzeppelin-upgrades). - - -![Defender Remix Plugin Deploy](/defender/remix-plugin-deploy.png) - -#### Deterministic Deployments - -Defender Deploy supports a `salt` value to create deployments to deterministic addresses using `create2`. Click on `Deterministic` checkbox and set the salt field to any arbitrary value. - -![Defender Remix Plugin Deploy Deterministic](/defender/remix-plugin-deploy-deterministic.png) - -#### Further Steps - -Once the contract deployment was submitted to Defender, in some cases you will need to complete the deployment from Defender Dashboard, you should see a green banner indicating that the contract was submitted and a link to your Deployment in Defender. - -![Defender Remix Plugin Deploy Completed](/defender/remix-plugin-deploy-completed.png) - -## Feedback - -The Defender Remix Plugin is open source, for feedback related to the plugin, please submit an issue in the [Github Repository](https://github.com/OpenZeppelin/defender-deploy-plugin) or send an email to `defender-support@openzeppelin.com`. diff --git a/content/defender/sdk.mdx b/content/defender/sdk.mdx deleted file mode 100644 index 2104ca76..00000000 --- a/content/defender/sdk.mdx +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: Defender SDK and API ---- - -[Defender SDK](https://www.npmjs.com/package/@openzeppelin/defender-sdk) (Formerly defender-client packages) is a node package that allows developers to interact with Defender programatically using Javascript/Typescript. - -See [sdk repository](https://github.com/OpenZeppelin/defender-sdk) or [SDK and API documentation](https://www.api-docs.defender.openzeppelin.com/) for more detailed information. - -## Installation - -You can install the whole package using NPM or any of your favorite package managers - -``` -npm install @openzeppelin/defender-sdk -``` - -or you can install single subpackages - -``` -npm install @openzeppelin/defender-sdk-deploy-client -``` - - -For more information about setup, examples and usage, please visit [Defender SDK](https://github.com/OpenZeppelin/defender-sdk) README file in Github. - - -## API Keys - -In order to operate your Defender account using the SDK or API, Defender requires API keys and secrets generated in the dashboard to authenticate requests. - -When creating API keys, you can also specify the expiration in days, hours and minutes. - -![API Key expiration configuration in Defender](/defender/api-key-expiration-config.png) - -Defender notifies ***3 days*** before and ***at expiration time*** about the API keys expiration. - - -Once the key is expired, any request sent to Defender API will throw `API Key is either expired or invalid` error. - - -### Relayer API Keys - -Relayers API Keys are generated in Relayer details page, and are exclusively used for managing the signer operations for that Relayer, e.g. send or query transactions, get the nonce or sign data. - -```js -const creds = - relayerApiKey: , - relayerApiSecret: , -; -const client = new Defender(creds); - -const txResponse = await client.relaySigner.sendTransaction( - to: '0x179810822f56b0e79469189741a3fa5f2f9a7631', - value: 1, - speed: 'fast', - gasLimit: '21000', -); -``` - - -Only `client.relaySigner` package is available when authenticating using `relayerApiKey` and `relayerApiSecret`. - - -### Admin API Keys - -Admin API Keys are generated in ***Manage -> API Keys***, and they are used to operate all other resources in Defender, including relayers CRUD operations. -```js -const creds = - apiKey: , - apiSecret: , -; -const client = new Defender(creds); - -const proposals = await client.proposal.list( - limit: 10, - next: undefined, -); -``` diff --git a/content/defender/settings.mdx b/content/defender/settings.mdx deleted file mode 100644 index 01fdbfdd..00000000 --- a/content/defender/settings.mdx +++ /dev/null @@ -1,311 +0,0 @@ ---- -title: Settings ---- - -Manage everything related to the configuration of Defender, including notifications, addresses, team members, API keys, and more. - -## Approval Processes - -Approval processes act as a wrapper for transactions to be executed on-chain. They currently wrap the following: - -* Multisigs -* EOAs (outside Defender) -* Relayers (inside Defender) -* Governor contracts -* Timelock contracts -* Fireblocks - -They are defined per network, and are used throughout Defender to execute transactions, such as in the [Deploy](/defender/module/deploy) wizard, [Actions](/defender/module/actions) and [Workflows](/defender/module/actions#workflows). - -![Manage Approval Processes](/defender/manage-approvals.png) - -## Notifications - -When triggered, Defender can deliver notifications to one or more configured notification channels which can include any of Slack, email, Telegram, Discord, Datadog, PagerDuty, OpsGenie, or custom webhooks. These notification channels can be used in monitors, actions, and workflows. - -![Manage Notifications](/defender/manage-notify-channels.png) - -### Slack Configuration - -Please see [Slack webhook documentation](https://api.slack.com/messaging/webhooks) to configure a Slack webhook. Once Slack is configured, enter the webhook URL in Defender. - -* **Alias** is the name for this Slack configuration. For instance, you might name it after the name of the channel. -* **Webhook URL** is the URL from your Slack management console to use for notification. - -### Email Configuration - -* **Alias** is the name for this email list. (e.g., Developers) -* **Emails** is the list of emails you wish to notify. These can be comma or semicolon-delimited. - -### Discord Configuration - -Please see [Discord webhook documentation](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) to configure a webhook for your Discord channel. - -* **Alias** is the name for this Discord configuration. -* **Webhook URL** is the URL from your Discord channel to use for notification. - -### Telegram Configuration - -Please see [Telegram bot documentation](https://core.telegram.org/bots#6-botfather) to configure a Telegram Bot using the BotFather. - - -The Telegram Bot must be added to your channel and have the rights to post messages. - - -To find the Chat ID of the channel, execute the following curl (with your bot token value) and extract the `id` value of the chat. If you do not receive any entries in the response, send a test message to your chat first. - -```shell -$ curl https://api.telegram.org/bot$BOT_TOKEN/getUpdates - - "ok": true, - "result": [ - { - "update_id": 98xxxx98, - "channel_post": { - "message_id": 26, - "sender_chat": { - "id": -100xxxxxx5976, - "title": "Monitor Test", - "type": "channel" - , - "chat": - "id": -100xxxxxx5976, // <--- This is your chat ID - "title": "Monitor Test", - "type": "channel" - , - "date": 1612809138, - "text": "test" - } - } - ] -} -``` - -* **Alias** is the name for this Telegram configuration. -* **Chat ID** is the ID of the Telegram Chat. -* **Bot Token** is the token you receive from the BotFather when creating the Telegram Bot. - -### Datadog Configuration - -Datadog configurations let Defender forward custom metrics to your Datadog account. For more information about custom metrics, please see [Datadog metrics documentation](https://docs.datadoghq.com/developers/metrics/) - -The metric we send is a COUNT metric, which represents the number of transactions that triggered the notification. We do not send zeros, so a lack of data should be expected if there is no trigger. With each metric, we send two tags: `network` (rinkeby, mainnet,...) and when a monitor has triggered the notification then `monitor` (name of the monitor) - - -It can take several minutes for a new custom metric to show up in the Datadog console - - -* **Alias** is the name for this Datadog configuration. -* **Api Key** is the API key from your Datadog management. -* **Metric Prefix** will precede all metric names. For instance, with a prefix of `openzeppelin.`, monitors will send a metric called `openzeppelin.monitor`. - -### Webhook Configuration - -To configure a custom webhook notification channel, you just need to provide the webhook endpoint URL and an alias for display purposes. - -* **Alias** is the name for this webhook endpoint. -* **Webhook URL** is the URL where notifications will be sent. - -To avoid overwhelming the receiving webhook with many concurrent requests under a high number of matches, Defender sends a JSON object with an `events` containing an array with all the matching events found in a block. - -```js - - events: [...] // See Event Schema info in Action or Monitor docs - -``` - -For more information on the event schema see the documentation on [Monitor](/defender/module/monitor) or [Actions](/defender/module/actions). - -### OpsGenie Configuration - -Please see [OpsGenie integration documentation](https://support.atlassian.com/opsgenie/docs/create-a-default-api-integration/) to configure an OpsGenie API integration that can create alerts. - -* **API Key** Integration API key that can be found in the integration settings -* **Instance Location** Location where the OpsGenie instance server is located -* **Responders** Teams, users, escalations and schedules that the alert will be routed to send notifications. The type field is mandatory for each item, where possible values are team, user, escalation and schedule. If the API Key belongs to a team integration, this field will be overwritten with the owner team. Either id or name of each responder should be provided. You can refer below for example values (50 teams, users, escalations or schedules) -* **Visible To** Teams and users that the alert will become visible to without sending any notification. The type field is mandatory for each item, where possible values are team and user. In addition to the type field, either id or name should be given for teams and either id or username should be given for users. Please note: that alert will be visible to the teams that are specified within responders field by default, so there is no need to re-specify them within visibleTo field. You can refer below for example values (50 teams or users in total) -* **Alias** Client-defined identifier of the alert, that is also the key element of [Alert De-Duplication](https://support.atlassian.com/opsgenie/docs/what-is-alert-de-duplication/) (512 max characters) -* **Priority** Priority level of the alert. Possible values are P1, P2, P3, P4 and P5. Default value is P3 -* **Entity** Entity field of the alert that is generally used to specify which domain alert is related to (512 max characters) -* **Actions** Custom actions that will be available for the alert (10 x 50 max characters) -* **Note** Additional note that will be added while creating the alert (25000 max characters) -* **Details** Map of key-value pairs to use as custom properties of the alert (8000 max characters) -* **Tags** Tags of the alert (20 x 50 max characters) - -### PagerDuty Configuration - -Please see [PagerDuty integration documentation](https://support.pagerduty.com/docs/services-and-integrations) to configure an PagerDuty API v2 integration that can create change and alert events. - -* **Event Type** Event type for PagerDuty categorization (alert or change) -* **Routing Key** Integration Key for an integration on a service or on a global ruleset (32 characters) -* **Event Action** The action type of event (trigger, acknowledge or resolve) -* **Dedup Key** Deduplication key for correlating triggers and resolves (255 max characters) -* **Severity** The perceived severity of the status the event is describing with respect to the affected system (critical, error, warning or info) -* **Component** Component of the source machine that is responsible for the event -* **Group** Logical grouping of components of a service -* **Class** The class/type of the event -* **Custom_detail** Map of key-value pairs to provide additional details about the event and affected system - -## Team Members - -You can invite, manage access for, and remove team members from your Defender account under the _Team Members_ section. - -![Manage Team Members](/defender/manage-team-invite.png) - - -If you want to add a user to your team, make sure to invite them from the _Team Members_ section. If they sign up directly to the application, they will be added to a new team of their own instead. If this happens, consider having your teammate delete their account, so you can re-send the invitation for your team. Alternatively, they can join your team using a different email address. - - -### Roles - -Every team member has an assigned role. You can manage authorization to access, modify and execute across all Defender products through the role-based access control system. - -When you invite a new user to your team, you will assign a role to them, determining their access permissions. - -To create a new role, click on the _Create Role_ button. You will be asked to enter a role name and description, and to specify the level of access users in that role will get for each product. You can also specify which administrative powers the role will give access to: manage users and roles, manage team API keys, manage Fireblocks API keys, manage Address Book, and configure log forwarding. - -![Manage Role Creation](/defender/manage-role-create.png) - -After saving, the new role will be available to assign to new or existing team members. Naturally, if in the future you decide to modify the access level of a given role, all users who have that role will as a consequence see their access level change. - - -Be careful when granting administrative permissions. A user with the rights to modify roles but not to access any other component can modify their own role to grant them access to any other parts of the application. - - -### Two factor authentication (2FA) - -We strongly suggest that you enable 2FA to improve your Defender account security. As a second authentication factor, Defender relies on the [Time-based One-Time Password standard (TOTP)](https://en.wikipedia.org/wiki/Time-based_One-time_Password_algorithm). To enable 2FA on Defender, you need a TOTP compliant application, such as [Authy](https://authy.com/) or Google Authenticator. Each user can enable 2FA under their profile, accessible from the top-right user menu. Defender will guide users through the necessary steps. - -#### Enforcing 2FA - -As an admin user, you can enforce 2FA for all users in your team. To do so, go to the settings under _Team Members_ section, and click on the _Enforce 2FA_ toggle. This will require all users to setup 2FA before they can access Defender again. - - -If you have users that are still accessing Defender 1.0, they will have to setup 2FA as well. - - -### Password reset - -To change your user password for Defender, follow the steps below. - -* If you are logged in, sign out by opening the upper right corner menu and clicking on **Sign out**. You will be redirected to the landing page. -* From Defender landing page, click on **Sign in**. You will be redirected to the sign in page. -* From Defender sign in page, click on **Forgot your password?**. -* Enter your email address and click on **Reset my password**. You will shortly receive an email with instructions on how to continue with the password reset process. - -## Secrets -Secrets are key-value case-sensitive pairs of strings, that can be accessed from any Action using the `event.secrets` object. You can define as many secrets as you need to be used by your Actions. Secrets are shared across all your Actions, and not specific to a single one. - -```jsx -exports.handler = async function(event) - const { mySecret, anApiKey = event.secrets; -} -``` - -Secrets are encrypted and stored in a secure vault, only decrypted for injection in your actions runs. Once written, a secret can only be deleted or overwritten from the user interface, but not read. - - -An action may log the value of a secret, accidentally leaking it. - - -![Defender Secrets](/defender/manage-secrets.png) - -You can use secrets for storing secure keys to access external APIs, or any other secret value that you do not want to expose in the Actions code. - - -While you can also use actions secrets to store private keys for signing messages or transactions, we recommend you use [Relayers](#Relayers) instead. Signing operations for relayers are executed within a secure vault, providing an extra level of security than loading the private key in an action run and signing there. - - -## API Keys - -In API Keys you can manage the keys used by clients to access the Defender API for your account, and also enter integration API keys if you are using Fireblocks for approvals. Note that relayers have their own API keys that are separate from these API keys and are configured directly in Manage Relayers. - -To add an API key, click on the Create API Key button. - -![Manage Create Team API Key](/defender/manage-new-api-key-v2.png) - -Select the API capabilities that you want associated with the API key: - -* **Manage Transaciton Proposals and Contract** for creating and issuing actions and managing contracts. -* **Manage Relayers** for creating relayers and changing relayer policies. -* **Manage Automatic Actions** for creating and modifying automatic actions and their configurations. -* **Manage Monitors** for creating and managing monitors and their configurations. - -Optionally, select the API Key expiration. You can specify the expiration time in minutes, hours or days. - -Once the API key is created, Defender will show you the details. - -![Manage Team API Key](/defender/manage-api-key-v2.png) - -Be sure to copy the secret key, it will be required for access and it will not be accessible again after the form is dismissed. - -## Custom Networks - -### Forked Networks - -In the "Forked Networks" section, you can manage and oversee your forked networks. These networks let you test the efficiency of your security setup and offer a vital chance to identify and fix any problems before launching on testnets and mainnets. - -![Manage Forked Networks](/defender/manage-forked-networks-create.png) - -Setting up a forked network is accomplished by clicking the "Create Forked Network" button. This action prompts you to provide a name for the forked network and select the base network you intend to fork from. Your choice of forking can be made from any of the networks supported by Defender. The network’s currency symbol will be automatically populated based on the network you select. Additionally, you will need to input the RPC URL for the forked network and, optionally, an API key if it is required for access. - -For an improved user experience, you also have the option to include the block explorer URL. - -Once created, the network becomes accessible for utilization in any Defender module that necessitates network selection. This is particularly valuable when engaging in tasks such as establishing an approval process, configuring a relayer, or deploying a contract. - -![Select Forked Network](/defender/manage-forked-networks-selection.png) - - -Once you have created a Forked Network you cannot edit its name or RPC URL. If you need to change these settings you will need to delete and recreate the Forked Network. When a forked network is deleted, **all** associated resources will also be deleted. This includes approval processes, relayers, contracts, address book entries, etc. - - -### Private Networks - -Navigate through the "Private Networks" section to effectively manage and oversee your private networks. These networks establish a restricted and controlled environment tailored for testing and validating network configurations. This controlled space empowers users to identify and resolve potential issues before deploying configurations to production environments, providing a secure venue to evaluate system functionality and security measures in isolation. - -![Manage Private Networks](/defender/manage-private-networks-create.png) - -To set up a private network, simply click the "Create Private Network" button. This action prompts you to define a name for the private network and select the currency symbol ("ETH") for your network. Additionally, provide the RPC URL, and optionally, an API key if access requires it. - - -The chain ID of a private network must not conflict with the chain ID of an [officially supported Defender network](#networks). - - -For an enhanced user experience, customize your setup by including the block explorer URL, Safe contract deployment addresses, and a subgraph URL. - -[Safe Contracts](https://github.com/safe-global/safe-contracts) form a comprehensive collection of smart contracts designed for deploying, managing, and interacting with multi-signature wallets. Defender utilizes the following Safe contract deployments to enrich the user experience: - -* ***Master***: Facilitates a Safe multisignature wallet deployment with support for confirmations using signed messages based on EIP-712. -* ***Proxy Factory***: Enables a Safe smart contract deployment to create a new proxy contract and execute a message call to the new proxy within a single transaction. -* ***Multi Send Call Only***: Allows a Safe smart contract deployment to batch multiple transactions into one, specifically for calls. -* ***Create Call***: Facilitates a Safe smart contract deployment to utilize different create opcodes for deploying a contract. - -You can [deploy these contracts](https://github.com/safe-global/safe-deployments) on your private network, providing the contract addresses in the creation form to leverage them in Defender, especially when deploying using `CREATE2`. - -Defender utilizes Subgraph for GraphQL-based querying of blockchain data, primarily for the Access Control module. Create your own [Subgraph](https://thegraph.com/docs/en/developing/creating-a-subgraph/), and input the endpoint in the creation form to activate this functionality in Defender. You can find an example configuration for the Access Control subgraph [here](). - -Once created, the network becomes accessible for utilization in any Defender module requiring network selection. This proves invaluable when engaging in tasks such as establishing an approval process, configuring a relayer, or deploying a contract. - -![Select Private Network](/defender/manage-private-networks-selection.png) - - -After creating a Private Network, you cannot edit its name, RPC URL, or symbol. To make changes, you must delete and recreate the Private Network. Deleting a private network will also delete **all** associated resources, including approval processes, relayers, contracts, address book entries, etc. - - -### Limitations - -While custom networks serve as a great way to integrate EVM compatible networks into Defender or to test unique network conditions, they come with a some notable drawbacks that set them apart from officially supported Defender networks: - -* ***RPC Bottlenecks***: Custom networks can only have a single RPC provider which becomes a single point of failure during periods of high traffic. -* ***Limited Reliability***: Custom networks may return non-standard or unexpected responses which will not be handled by Defender. Thus, some services may not behave as expected. -* ***Slower Transaction Processing***: Custom networks require more RPC calls with every transaction request leading to slower transaction processing. - - -High transaction volumes are only advised for custom networks with highly reliable RPC endpoints. - - -## Advanced - -In the Advanced tab, you can export the serverless configuration file from the current configuration for your Defender account. - -This can be used to setup automated resource management for your account with configuration as code. Also, in Advanced, you can delete your Defender account. This action is non-reversible, all Defender configurations will be deleted, and all product functions will be canceled and removed. diff --git a/content/defender/settings/notifications.mdx b/content/defender/settings/notifications.mdx deleted file mode 100644 index c90dd6ee..00000000 --- a/content/defender/settings/notifications.mdx +++ /dev/null @@ -1,120 +0,0 @@ ---- -title: Notification Channels ---- - -Use Notification Channels to get notified about events across different Defender Modules, like Monitor Triggers, Workflows or Relayer Transactions lifecycle events. - -## Supported Channels - -### From Defender -* **Email**: Receive emails from the Defender trusted address: noreply@defender.openzeppelin.com -* **Webhooks**: Configure your own endpoints to receive signed notifications. - -### Third Party Services -* [**Slack**](https://slack.com/). -* [**Telegram**](https://telegram.org/). -* [**Discord**](https://discord.com/). -* [**Datadog**](https://www.datadoghq.com/). -* [**PagerDuty**](https://www.pagerduty.com/). -* [**Opsgenie**](https://www.atlassian.com/software/opsgenie). - -## Setup - -Go to **Settings -> Notification Channels** section and select and configure your preferred channel. - -![Notification channel creation in Defender](/defender/notification-channel-setup-1.0.png) - -## Usage -The Notification Channel can be linked to any Defender module to get notified about events. - -![Use notification channel in Defender module](/defender/notification-channel-setup-2.0.png) - -Also, it is possible to customize the notification template, [see how](/defender/module/monitor#customizing-notification). - -## Additional configurations - -### Webhook Secrets - -As an additional security measure, Defender implements a Hash-based Message Authentication Code ([HMAC](https://en.wikipedia.org/wiki/HMAC)), by adding a `Defender-Signature` and `Defender-Timestamp` request headers to the notification sent to webhook endpoints. Therefore, the endpoint receiving the notification can verify the authenticity of the request. - -Each webhook notification has a secret key associated that can be accessed under **Settings -> Notification Channnels -> Webhook details**. - -The `Defender-Signature` is generated using [SHA256 algorithm](https://en.wikipedia.org/wiki/SHA-2) and `webhook secret` to sign the payload and the timestamp. - - -Only Admin users in the Account have permission to see the webhook secret. - - -#### Signature Validation - -##### Using Defender SDK - -The authenticity of the signature can be validated using `verifySignature` utility function in [Defender SDK](/defender/sdk). - -```js -function webhookHandler(req, res) - const signature = req.headers['Defender-Signature']; - const timestamp = req.headers['Defender-Timestamp']; - - const defender = new Defender({ - apiKey: process.env.API_KEY, - apiSecret: process.env.API_SECRET, - ); - - const result = client.notificationChannel.verifySignature( - body: req.body, - signature, - timestamp, - secret: process.env.WEBHOOK_SECRET, - validityInMs: 1000 * 60 * 10, // 10 mins - ); - - if (!result.valid) throw new Error(result.error); - - // your handler code -} -``` - -##### Manual Verification - -The signature is generated using HMAC with `SHA256` algorithm, so it can be verified in any programming language using the right `Webhook Secret`. - -##### Python example - - -This code example was tested in Python 3.12. For different versions, the code might be slightly different. - - -```py -from datetime import datetime, timedelta, UTC -import hmac -import hashlib - -def verify_signature(body_object: dict, timestamp: str, signature: str secret: str) -> bool: - # Parse the timestamp - try: - timestamp_dt = datetime.fromisoformat(timestamp) - except ValueError: - return False # Invalid timestamp format - - # Get the current time and calculate the time difference - current_time = datetime.now(UTC) - time_difference = current_time - timestamp_dt - - # Check if the time difference is within the allowed range (10 minutes) - if time_difference > timedelta(minutes=10): - return False - - # Merge timestamp with body_object - payload_to_verify = **body_object, 'timestamp': timestamp - payload_to_verify_str = json.dumps(payload_to_verify, separators=(',', ':')) - - # Create a new HMAC object using the secret and the SHA256 hash algorithm - hmac_obj = hmac.new(secret.encode(), payload_to_verify_str.encode(), hashlib.sha256) - - # Generate signature - generated_signature = hmac_obj.hexdigest() - - # Compare the generated signature with the provided signature - return hmac.compare_digest(generated_signature, signature) -``` diff --git a/content/defender/tutorial/access-control.mdx b/content/defender/tutorial/access-control.mdx deleted file mode 100644 index 47893b79..00000000 --- a/content/defender/tutorial/access-control.mdx +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Modify and assign roles in a role-based access control smart contract ---- - -Defender allows you to seamlessly oversee and command contract permissions on a grand scale, with the power to view and control access at a granular level. This tutorial shows how to add a smart contract to see and manage its roles, including assigning and removing roles. - -## Pre-requisites - -* OpenZeppelin Defender account. -* Any external wallet (like Metamask) with an EOA that holds funds in Sepolia. - -## 1. Add contract - - -For this tutorial, you will create a contract that implements the role-based Access Control library using [this](https://sepolia.etherscan.io/address/0xF909B3dBB525fDe7C3e8cd59FbECF3D42c217454) factory deployed to Sepolia. Your created contract will automatically assign you the admin role to manage its roles. - - -1. Open the Defender [Address Book](https://defender.openzeppelin.com/v2/#/address-book/new) in a web browser. -2. Fill the form with the following values and click `Create`: - - * Name: `Access Control Factory` - * Network: `Sepolia` - * Address: `0xF909B3dBB525fDe7C3e8cd59FbECF3D42c217454` - -+ -image::tutorial-access-control-factory.png[Address Book for factory] - -1. Navigate to [Transaction Proposals](https://defender.openzeppelin.com/v2/#/transaction-proposals/new?). -2. Fill the ***General Information*** section with the following values: - - * Name: `Create Access Control contract` - * Target contract: `Access Control Factory` - -+ -image::tutorial-access-control-tx-general.png[Transaction Proposal general information] - -1. For the ***Function*** section, select the `create` function. -2. Open the ***Approval Process*** section, click the input field and select `Create Approval Process`. -3. Fill the approval process form with the following values and click `Save Changes`: - - * Name: `Access Control Admin` - * Type: `EOA` - * Address: _Your wallet EOA address_ -4. Connect your wallet with the EOA address of the approval process created and click `Submit Transaction Proposal`. - - ![Transaction Proposal submit proposal](/defender/tutorial-access-control-submit-proposal.gif) -5. Click on the `Create Access Control contract` transaction proposal. -6. Click the top-right button `Approve and Execute` and confirm the transaction on your wallet. - - ![Transaction Proposal submit tx](/defender/tutorial-access-control-submit-tx.gif) -7. Scroll down and under ***Execution Result***, hover over the first contract to copy its address. - - ![Transaction Proposal copy address](/defender/tutorial-access-control-copy-address.png) -8. Navigate to the Defender https://defender.openzeppelin.com/v2/#/address-book/new Address Book] to add your newly created contract. -9. Fill the form with the following values and click `Create`: - - * Name: `Access Control Contract` - * Network: `Sepolia` - * Address: _Contract address copied from the previous steps_ - * ABI: _Copy and paste the following_ - -+ -```json -["inputs": [],"stateMutability": "nonpayable","type": "constructor","inputs": [],"name": "AccessControlBadConfirmation","type": "error","inputs": [{"internalType": "address","name": "account","type": "address","internalType": "bytes32","name": "neededRole","type": "bytes32"],"name": "AccessControlUnauthorizedAccount","type": "error"},"anonymous": false,"inputs": [{"indexed": true,"internalType": "bytes32","name": "role","type": "bytes32","indexed": true,"internalType": "bytes32","name": "previousAdminRole","type": "bytes32","indexed": true,"internalType": "bytes32","name": "newAdminRole","type": "bytes32"],"name": "RoleAdminChanged","type": "event"},"anonymous": false,"inputs": [{"indexed": true,"internalType": "bytes32","name": "role","type": "bytes32","indexed": true,"internalType": "address","name": "account","type": "address","indexed": true,"internalType": "address","name": "sender","type": "address"],"name": "RoleGranted","type": "event"},"anonymous": false,"inputs": [{"indexed": true,"internalType": "bytes32","name": "role","type": "bytes32","indexed": true,"internalType": "address","name": "account","type": "address","indexed": true,"internalType": "address","name": "sender","type": "address"],"name": "RoleRevoked","type": "event"},"inputs": [],"name": "DEFAULT_ADMIN_ROLE","outputs": [{"internalType": "bytes32","name": "","type": "bytes32"],"stateMutability": "view","type": "function"},"inputs": [],"name": "RANDOM_ROLE","outputs": [{"internalType": "bytes32","name": "","type": "bytes32"],"stateMutability": "view","type": "function"},"inputs": [{"internalType": "bytes32","name": "role","type": "bytes32"],"name": "getRoleAdmin","outputs": ["internalType": "bytes32","name": "","type": "bytes32"],"stateMutability": "view","type": "function"},"inputs": [{"internalType": "bytes32","name": "role","type": "bytes32","internalType": "address","name": "account","type": "address"],"name": "grantRole","outputs": [],"stateMutability": "nonpayable","type": "function"},"inputs": [{"internalType": "bytes32","name": "role","type": "bytes32","internalType": "address","name": "account","type": "address"],"name": "hasRole","outputs": ["internalType": "bool","name": "","type": "bool"],"stateMutability": "view","type": "function"},"inputs": [{"internalType": "bytes32","name": "role","type": "bytes32","internalType": "address","name": "callerConfirmation","type": "address"],"name": "renounceRole","outputs": [],"stateMutability": "nonpayable","type": "function"},"inputs": [{"internalType": "bytes32","name": "role","type": "bytes32","internalType": "address","name": "account","type": "address"],"name": "revokeRole","outputs": [],"stateMutability": "nonpayable","type": "function"},"inputs": [{"internalType": "bytes4","name": "interfaceId","type": "bytes4"],"name": "supportsInterface","outputs": ["internalType": "bool","name": "","type": "bool"],"stateMutability": "view","type": "function"}] -``` - -1. Navigate to the [Access Control page](https://defender.openzeppelin.com/v2/#/access-control/contracts). -2. Observe your newly added contract with the number addresses that hold the admin role. - - ![Access Control page with contract](/defender/tutorial-access-control-page.gif) -3. Click on the contract card. - -## 2. View and modify roles - -In your contract-specific page, you can see the addresses that hold the `DEFAULT_ADMIN_ROLE` role, which is the EOA address from the approval process you used to deploy the contract. To make a change, click on the role and input the new address (or remove one address if you want to remove it from the role). Follow these steps to add a new address to the `DEFAULT_ADMIN_ROLE`: - -1. Click on the `DEFAULT_ADMIN_ROLE` role. -2. Select any address from the dropdown menu or add a new one. -3. Scroll down and click on `Select an Approval Process`. -4. Select your `Access Control Admin` approval process. -5. Check that your wallet is connected with the right EOA address. If not, click on the button below the field to connect your wallet. -6. Click on `Save Changes` and confirm the transaction on your wallet. -7. Wait for the transaction to get executed and check that the new address holds the `DEFAULT_ADMIN_ROLE` role. - -+ -image::tutorial-access-control-add.gif[Access Control page of contract add role] - -For ownable contracts, you can only make changes to the `Owner` role using an approval process that matches the current owner’s address. When using a multisig as approval process, you will see the pending proposals on the right side of the page. - -The page sync every minute, and updates when modifying a role. - -## Next steps - -Congratulations! You can import other contracts and modify their roles. - - -After configuring Access Control, we recommend seting up Workflows. Learn how to use Workflows with its tutorial [here](/defender/tutorial/workflows). - - -## References - -* [Access Control Documentation](/defender/module/access-control) -* [Access Control Factory](https://sepolia.etherscan.io/address/0xF909B3dBB525fDe7C3e8cd59FbECF3D42c217454) -* [Access Control Contract](https://sepolia.etherscan.io/address/0x1b073085c60ace585c4179984b3be5bf9ef53176) diff --git a/content/defender/tutorial/actions.mdx b/content/defender/tutorial/actions.mdx deleted file mode 100644 index 8b190c52..00000000 --- a/content/defender/tutorial/actions.mdx +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: Automate smart contract transaction for hourly activity ---- - -Defender allows you to automate smart contract operational tasks with easy integration with the rest of Defender. This tutorial shows how to build an action that sends an on-chain transaction every hour that adds an object to a box and increases the number of objects inside. - -## Pre-requisites - -* OpenZeppelin Defender account. - - -Learn to [deploy](/defender/tutorial/deploy) and [monitor](/defender/tutorial/monitor) contracts through Defender! - - -## 1. Set up action - -You will configure an action that sends an hourly transaction with the `addObject()` function to the `0xC64f7ace6127bc7B0bAb23bD1871aC81e6AEC074` contract in Sepolia, which is an example of a Box contract deployed in the [Deploy](/defender/tutorial/deploy) tutorial. To do so, follow these steps: - -1. Run the following command in your terminal: -2. Open [Defender Relayers](https://defender.openzeppelin.com/v2/#/relayers) in a web browser. -3. Click on **Create Relayer** with the name `Actions Relayer` and Sepolia network. -4. Fund it with some Sepolia ETH. This relayer will send and pay for the automated transactions. -5. Open [Defender Actions](https://defender.openzeppelin.com/v2/#/actions). -6. Click on **Create Action**. -7. Name the action `Hourly object add`. -8. Select **Schedule** as trigger, and a **Timespan** of 1 hour as schedule. -9. Select the **Actions Relayer** as the connected relayer. -10. Paste the following code in the **Code** field: - - ```jsx - const Defender = require('@openzeppelin/defender-sdk'); - - exports.handler = async function(credentials) - const client = new Defender(credentials); - - const txRes = await client.relaySigner.sendTransaction({ - to: '0xC64f7ace6127bc7B0bAb23bD1871aC81e6AEC074', - speed: 'fast', - data: '0x62029d2a', - gasLimit: '80000', - ); - - console.log(txRes); - return txRes.hash; - } - ``` - The contract address is the target, which is `0xC64f7ace6127bc7B0bAb23bD1871aC81e6AEC074`, and data is `0x62029d2a`, the encoded version of the `addObject()` function of the contract. - -11. Click on **Save Action**. - -After saving, the Actions page should look like this: - -![Actions action card](/defender/tutorial-actions-action.png) - -Your action will now be running every hour! You can check the [Defender Logs](https://defender.openzeppelin.com/v2/#/logs) for more detailed information about the activity. - -## 2. Verify activity - -After the action has run for a while, you can verify that the transaction is being sent every hour. To do so, open the [Etherscan contract page](https://sepolia.etherscan.io/address/0xC64f7ace6127bc7B0bAb23bD1871aC81e6AEC074) and look for transactions from the configured Relayer. An alternative is to search your Relayer in Etherscan and look for the transactions sent to the contract. - -You will also receive alerts in case the action fails (for example, if the Relayer runs out of gas). They look like this: - -![Actions alert](/defender/tutorial-actions-alert.png) - -## Next steps - -Congratulations! You can modify the action to automate other contracts and build more complex transactions. In case you are interested in advanced use cases, we are working on actions-related guides. - - -Alongisde actions, we recommend using Access Control to manage a contract’s permissions through Defender. Learn how to use Access Control with its tutorial [here](/defender/tutorial/access-control). - - -## References - -* [Actions Documentation](/defender/module/actions) -* [More information on Action’s Javascript code](/defender/module/actions#defining-code) -* [BoxV2 Sepolia contract](https://sepolia.etherscan.io/address/0xC64f7ace6127bc7B0bAb23bD1871aC81e6AEC074) diff --git a/content/defender/tutorial/deploy.mdx b/content/defender/tutorial/deploy.mdx deleted file mode 100644 index 243ee1f0..00000000 --- a/content/defender/tutorial/deploy.mdx +++ /dev/null @@ -1,420 +0,0 @@ ---- -title: Securely deploy and upgrade a smart contract ---- - -Defender allows you to easily deploy and upgrade smart contracts across chains while maintaining the best security practices. This tutorial shows how to use a [Relayer](/defender/module/relayers) to deploy a contract called Box and upgrade it with the UUPS proxy pattern via a [Safe wallet](https://safe.global/) (multisig). - -## Pre-requisites - -* OpenZeppelin Defender account. -* [NodeJS and NPM](https://nodejs.org/en) -* Any IDE or text editor -* Web browser with Metamask (or any other compatible wallet), funded with Sepolia ETH. - -## 1. Configure - -### Safe wallet - -First, you need to create Safe wallet to manage the upgrade process. To do so, follow these steps: - -1. Open the [Safe app](https://app.safe.global/welcome) in a web browser and connect your wallet (make sure you are connected to the [Sepolia testnet](https://sepolia.etherscan.io/)). -2. Click on **Create new Account** and follow the steps. -3. Note the address of the Safe wallet you created, you will need it later. - - ![Deploy safe copy address](/defender/tutorial-deploy-safe.png) - -### Environment setup - -Now, you will create a Defender test environment with the Sepolia testnet, where you will deploy and upgrade the smart contracts. To do so, follow these steps: - -1. Open [Defender Deploy](https://defender.openzeppelin.com/v2/#/deploy). -2. Click on **Setup**. - - ![Deploy environments page](/defender/tutorial-deploy-environments.png) -3. Pick **Sepolia** from the dropdown. - - ![Deploy networks wizard](/defender/tutorial-deploy-step1-wizard.png) -4. Select the approval process associated with your funded relayer that will execute the deployments for the test environment. In case you don’t already have an approval process, Defender will allow you to create one within the wizard flow. Relayers automate the payment of gas fees and take care of private key secure storage, transaction signing, nonce management, gas pricing estimation, and resubmissions. However, you may also choose to deploy using an EOA ("Externally Owned Account") or Safe wallet. - - - Read more about relayers and how to manage them [here](/defender/module/relayers). - - -+ -image::tutorial-deploy-step2-wizard.png[Deploy block deploy wizard] - -1. Click on the Approval Process field to expand the dropdown and click on **Create an Approval Process**. Enter "Safe Wallet Approval Process" as the name and expand the contract field to click on **Add contract**. Enter "Safe Wallet" as the name, paste the address of your Safe wallet you copied before and click on **Create**. Select "Safe Wallet" in the contract dropdown and click on **Continue**. - -+ -image::tutorial-deploy-step3-wizard.png[Deploy block upgrade wizard] - -1. Defender will generate an API Key and Secret for this environment, so copy and store them safely. Click on **Let’s Deploy** to visit the environment page. - -+ -image::tutorial-deploy-step4-wizard.png[Deploy block end wizard] - - -You configured the test environment to learn without the risk of losing actual funds. The steps are the same to set up a production environment. - - -Defender supports both Hardhat and Foundry integrations. Pick the one that suits your project! - -### Foundry setup - -First, make sure you have [Foundry](https://book.getfoundry.sh/getting-started/installation) installed. Follow these steps to create a new directory and project: - -1. Run the this command in your terminal: - - ``` - forge init deploy-tutorial && cd deploy-tutorial && forge install foundry-rs/forge-std && forge install OpenZeppelin/openzeppelin-foundry-upgrades && forge install OpenZeppelin/openzeppelin-contracts-upgradeable - ``` -2. Now, configure the `foundry.toml` file to enable ffi, ast, build info and storage layout: - - ```json - [profile.default] - ffi = true - ast = true - build_info = true - extra_output = ["storageLayout"] - ``` -3. Create a new file called `.env` in the project root directory and add the following content with the keys you received after creating the Defender environment: - - ```json - DEFENDER_KEY = "<>" - DEFENDER_SECRET = "<>" - ``` - -### Hardhat setup - -First, make sure you have [Hardhat](https://hardhat.org/hardhat-runner/docs/getting-started#installation) installed with ethers v6. Follow these steps to create a new directory and project: - -1. Run the this command in your terminal: - - ``` - mkdir deploy-tutorial && cd deploy-tutorial && npx hardhat init - ``` -2. Hardhat will ask some questions to setup the configuration, so answer the following: -+ - * What do you want to do: Create a **Typescript** project - * Hardhat project root: _Leave it as it is_ - * Do you want to use .gitignore: Yes - * Do you want to install this sample project’s dependencies with npm: Yes -3. Hardhat will now install the tooling libraries, and create the project files for you. Afterwards, install the OpenZeppelin packages with the following command: - - ``` - npm i @openzeppelin/hardhat-upgrades @openzeppelin/contracts-upgradeable dotenv --save-dev - ``` - -+ -Once everything has been installed, your initial directory structure should look something like this: - -+ -image::tutorial-deploy-directory.png[Deploy directory structure,185,300] - -1. You now need to edit your Hardhat configuration to add the Defender keys and Sepolia network. Open the `hardhat.config.ts` file, and replace its content with the following code: - - ```jsx - import HardhatUserConfig from "hardhat/config"; - import "@nomicfoundation/hardhat-toolbox"; - import "@openzeppelin/hardhat-upgrades"; - - require("dotenv").config(); - - const config: HardhatUserConfig = - solidity: "0.8.20", - defender: { - apiKey: process.env.DEFENDER_KEY as string, - apiSecret: process.env.DEFENDER_SECRET as string, - , - networks: - sepolia: { - url: "https://ethereum-sepolia.publicnode.com", - chainId: 11155111 - , - }, - }; - - export default config; - ``` -2. Create a new file called `.env` in the project root directory and add the following content with the keys you received after creating the Defender environment: - - ```json - DEFENDER_KEY = "<>" - DEFENDER_SECRET = "<>" - ``` - -## 2. Deploy - -1. Create a new file called `Box.sol` inside the `contracts` or `src` directory and add the following code: - - ```jsx - // SPDX-License-Identifier: Unlicense - pragma solidity ^0.8.20; - - import Initializable from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; - import UUPSUpgradeable from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; - import OwnableUpgradeable from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - - /// @title Box - /// @notice A box with objects inside. - contract Box is Initializable, UUPSUpgradeable, OwnableUpgradeable - /*////////////////////////////////////////////////////////////// - VARIABLES - //////////////////////////////////////////////////////////////*/ - - /// @notice Number of objects inside the box. - uint256 public numberOfObjects; - - /*////////////////////////////////////////////////////////////// - FUNCTIONS - //////////////////////////////////////////////////////////////*/ - - /// @notice No constructor in upgradable contracts, so initialized with this function. - function initialize(uint256 objects, address multisig) public initializer { - __UUPSUpgradeable_init(); - __Ownable_init(multisig); - - numberOfObjects = objects; - - - /// @notice Remove an object from the box. - function removeObject() external - require(numberOfObjects > 1, "Nothing inside"); - numberOfObjects -= 1; - - - /// @dev Upgrades the implementation of the proxy to new address. - function _authorizeUpgrade(address) internal override onlyOwner {} - } - ``` - - This is a contract that replicates a box, with three functions: - - * `initialize()`: Initializes the upgradeable proxy with its initial implementation and sets the multisig as the owner. - * `removeObject()`: Decreases the number of objects in the box by removing one. - * `_authorizeUpgrade()`: Points the proxy to a new implementation address. - -### Foundry - -1. Create a file named `Deploy.s.sol` inside the `script` directory. This script will deploy the upgradeable Box contract through Defender with an initial amount of 5 objects inside and the owner as the multisig address configured in the environment setup. The `initializer` option is used to call the `initialize()` function after the contract is deployed. Copy and paste the code below into `Deploy.s.sol`: - - ```jsx - // SPDX-License-Identifier: Unlicense - pragma solidity ^0.8.20; - - import Script from "forge-std/Script.sol"; - import console from "forge-std/console.sol"; - - import Defender, ApprovalProcessResponse from "openzeppelin-foundry-upgrades/Defender.sol"; - import Upgrades, Options from "openzeppelin-foundry-upgrades/Upgrades.sol"; - - import Box from "src/Box.sol"; - - contract DefenderScript is Script - function setUp() public { - - function run() public - ApprovalProcessResponse memory upgradeApprovalProcess = Defender.getUpgradeApprovalProcess(); - - if (upgradeApprovalProcess.via == address(0)) { - revert( - string.concat( - "Upgrade approval process with id ", - upgradeApprovalProcess.approvalProcessId, - " has no assigned address" - ) - ); - - - Options memory opts; - opts.defender.useDefenderDeploy = true; - - address proxy = - Upgrades.deployUUPSProxy("Box.sol", abi.encodeCall(Box.initialize, (5, upgradeApprovalProcess.via)), opts); - - console.log("Deployed proxy to address", proxy); - } - } - ``` -2. Deploy by running the following command which executes your deployment script: - - ``` - forge script script/Deploy.s.sol --force --rpc-url https://ethereum-sepolia.publicnode.com - ``` - -### Hardhat - -1. Open the file `deploy.ts` inside the `scripts` directory. This script will deploy the upgradeable Box contract through Defender with an initial amount of 5 objects inside and the owner as the multisig address configured in the environment setup. The `initializer` option is used to call the `initialize()` function after the contract is deployed. Copy and paste the code below into `deploy.ts`: - - ```jsx - import ethers, defender from "hardhat"; - - async function main() - const Box = await ethers.getContractFactory("Box"); - - const upgradeApprovalProcess = await defender.getUpgradeApprovalProcess(); - - if (upgradeApprovalProcess.address === undefined) { - throw new Error(`Upgrade approval process with id ${upgradeApprovalProcess.approvalProcessId has no assigned address`); - } - - const deployment = await defender.deployProxy(Box, [5, upgradeApprovalProcess.address], initializer: "initialize" ); - - await deployment.waitForDeployment(); - - console.log(`Contract deployed to $await deployment.getAddress()`); - } - - // 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; - ); - ``` - - - You should use `deployProxy()`, `deployBeacon()` and `deployImplementation()` for upgradeable contracts, and `deployContract()` for non-upgradeable contracts. To forcefully use `deployContract()`, set the `unsafeAllowDeployContract` option to `true`. More information [here](https://github.com/OpenZeppelin/openzeppelin-upgrades/blob/master/docs/modules/ROOT/pages/defender-deploy). - -2. Deploy your box by running the following command which executes your deployment script: - - ``` - npx hardhat run --network sepolia scripts/deploy.ts - ``` - -Success! Your contracts should have been deployed in the Sepolia testnet. Navigate to Deploy in Defender and check that the proxy and implementation have been deployed inside the test environment. All Box transactions should be sent to the proxy address as it will store the state and point to the given implementation. Copy the address of the proxy to upgrade it next. - -![Deployed contract](/defender/tutorial-deploy-contract.png) - -### Caveats - -By default, Defender utilizes the `CREATE` opcode to deploy contracts. This method creates a new contract instance and assigns it a unique address. This address is determined by the transaction’s nonce and sender’s address. - -Defender also offers an advanced deployment option using the `CREATE2` opcode. When a deployment request includes a `salt`, Defender switches to using the `CREATE2` opcode. This opcode allows you to deploy contracts to a deterministic address based on a combination of the sender’s `address`, `salt`, and contract `bytecode`. - - -While `CREATE2` offers deterministic contract addresses, it alters `msg.sender` behavior. In `CREATE2` deployments, `msg.sender` in the constructor or initialization code refers to the factory address, not the deploying address as in standard `CREATE` deployments. This distinction can impact contract logic, so careful testing and consideration are advised when opting for `CREATE2` - - -## 3. Upgrade - -Upgrading a smart contract allows changing its logic while maintaining the same address and storage. - -1. Create a file called `BoxV2.sol` inside the `contracts` or `src` directory and add the following code: - - ```jsx - // SPDX-License-Identifier: Unlicense - pragma solidity ^0.8.20; - - import Box from "./Box.sol"; - - /// @title BoxV2 - /// @notice An improved box with objects inside. - /// @custom:oz-upgrades-from Box - contract BoxV2 is Box - /*////////////////////////////////////////////////////////////// - FUNCTIONS - //////////////////////////////////////////////////////////////*/ - - /// @notice Add an object to the box. - function addObject() external { - numberOfObjects += 1; - - - /// @notice Returns the box version. - function boxVersion() external pure returns (uint256) - return 2; - - } - ``` - - This is a contract adds two new functions to your box: - - * `addObject()`: Increases the number of objects in the box by adding one. - * `boxVersion()`: Returns the version of the box implementation. - -### Foundry - -1. Create a file called `Upgrade.s.sol` inside the `script` directory and paste the following code. Make sure to replace the `` with the address of the proxy you copied before. - - ```jsx - // SPDX-License-Identifier: Unlicense - pragma solidity ^0.8.20; - - import Script from "forge-std/Script.sol"; - import console from "forge-std/console.sol"; - - import ProposeUpgradeResponse, Defender, Options from "openzeppelin-foundry-upgrades/Defender.sol"; - - contract DefenderScript is Script - function setUp() public { - - function run() public - Options memory opts; - ProposeUpgradeResponse memory response = Defender.proposeUpgrade( - , - "BoxV2.sol", - opts - ); - console.log("Proposal id", response.proposalId); - console.log("Url", response.url); - - } - ``` -2. Create the upgrade proposal using the upgrade script with the the following command: - - ``` - forge script script/Upgrade.s.sol --force --rpc-url https://ethereum-sepolia.publicnode.com - ``` - -### Hardhat - -1. Create a file called `upgrade.ts` inside the `scripts` directory and paste the following code. Make sure to replace the `` with the address of the proxy you copied before. - - ```jsx - import ethers, defender from "hardhat"; - - async function main() - const BoxV2 = await ethers.getContractFactory("BoxV2"); - - const proposal = await defender.proposeUpgradeWithApproval('', BoxV2); - - console.log(`Upgrade proposed with URL: ${proposal.url`); - } - - // 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; - ); - ``` -2. Create the upgrade proposal using the upgrade script with the the following command: - - ``` - npx hardhat run --network sepolia scripts/upgrade.ts - ``` - -### Approve - -1. Navigate to the [Defender test environment](https://defender.openzeppelin.com/v2/#/deploy/environment/test) and click on the upgrade proposal, which expands a modal on the right side of the screen. -2. Click on **View Transaction Proposal** and click on **Approve and Execute** on the top right corner of the page. Sign and execute the transaction with your wallet that you used to create the Safe Wallet. - -Your box should now be upgraded to the new version! The upgrade proposal in your test environment page shold now be marked as **Executed**. - -![Uprade proposal executed](/defender/tutorial-deploy-executed-upgrade.png) - -## Next steps - -Congratulations! You can now deploy and upgrade other contracts using the same environment. In case you are interested in advanced use cases, we are working on deploy-related guides. - - -After deploying a contract, we recommended using Defender to monitor its state and transactions. Learn how to use Monitor [here](/defender/tutorial/monitor). - - -## References - -* [Deploy Documentation](/defender/module/deploy) -* [Foundry Upgrades Package](https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades) -* [Hardhat Upgrades Package](https://www.npmjs.com/package/@openzeppelin/hardhat-upgrades) -* [Upgrades Core Package](https://www.npmjs.com/package/@openzeppelin/upgrades-core) diff --git a/content/defender/tutorial/monitor.mdx b/content/defender/tutorial/monitor.mdx deleted file mode 100644 index 01ad4fed..00000000 --- a/content/defender/tutorial/monitor.mdx +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: Monitor a smart contract for on-chain activity ---- - -Defender allows you to monitor smart contract transactions and events across chains. This tutorial shows how to build a customized Monitor template and use it in a real-world context to monitor a [Uniswap V2](https://uniswap.org/) pool. - -## Pre-requisites - -* OpenZeppelin Defender account. - - -Learn to deploy contracts to monitor using Defender [here](/defender/tutorial/deploy)! - - -## 1. Configure the monitor - -You will monitor the `0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc` contract in the Ethereum mainnet, which is the [Uniswap V2 USDC-ETH pool](https://etherscan.io/address/0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc). This contract has constant activity, making it a good candidate to see how quick monitors are. To configure a monitor, follow these steps: - -1. Open [Defender Monitor](https://defender.openzeppelin.com/v2/#/monitor) in a web browser. -2. Click on **Create Monitor**. - - ![Monitor landing page](/defender/tutorial-monitor-landing.png) -3. Name this monitor as `Uniswap V2: USDC-ETH Monitor`. -4. Select the `Financial` risk category. -5. Click the **Contracts** field and select to add a new address. -6. Fill the form with the following parameters and select it as contract to monitor: - -+ -* Name: `Uniswap V2: USDC-ETH Pool` -* Network: `Mainnet` -* Address: `0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc` - -1. Select `1 confirmation block`. Defender will automatically pick up the ABI, so we can select the transaction filters next. - -+ -image::tutorial-monitor-first.png[Monitor added contract] - -1. Add the `status == "success"` parameter to **Transaction Properties** to filter by transaction-level data and confirm transactions are successfully confirmed and not reverted. - -+ -image::tutorial-monitor-transaction-filters.png[Monitor transaction filters] - -1. Select the `Swap` event from the dropdown menu. This event is emitted every time a swap is made in the pool. - -+ -image::tutorial-monitor-event-filter.png[Monitor event filter] - -1. Skip function-level filters as you are already tracking all `Swap` events emitted from the contract. -2. Select a notification channel of your choice (such as email). -3. Click on **Save Monitor**. - -+ -image::tutorial-monitor-alerts.png[Monitor alerts] - -Your monitor is now running! - -![Monitor card](/defender/tutorial-monitor-card.png) - -## 2. Receive alerts - -Alerts will start rolling in as long as the monitor is active. Your notifications should look like this if you selected email as the notification channel: - -![Monitor Telegram alert](/defender/tutorial-monitor-receive.png) - -You can pause or delete monitors on the [Defender Monitor](https://defender.openzeppelin.com/v2/#/monitor) page. This one will trigger frequently so you will likely want to pause it using the toggle on the right after you receive a couple of alerts. You can also save a monitor as a template by clicking on the dotted icon of its card and `Save as Template`. - -![Monitor save template](/defender/tutorial-monitor-save-template.png) - -## Next steps - -Congratulations! You can modify the monitor to filter for specific `Swap` data or target another pool. In case you are interested in advanced use cases, we are working on monitor-related guides. - - -After setting up a monitor, we recommend creating Actions on Defender. Learn how to use Actions with its tutorial [here](/defender/tutorial/actions). - - -## References - -* [Actions Documentation](/defender/module/actions) -* [Manage Notificacion Channels Documentation](/defender/settings#notifications) -* [Uniswap V2 USDC-ETH Pool](https://etherscan.io/address/0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc) diff --git a/content/defender/tutorial/relayer.mdx b/content/defender/tutorial/relayer.mdx deleted file mode 100644 index 96f161bf..00000000 --- a/content/defender/tutorial/relayer.mdx +++ /dev/null @@ -1,153 +0,0 @@ ---- -title: Using Relayer for Sending Transactions ---- - -In this tutorial, we will explore how to use the [Relayers](/defender/module/relayers) to send transactions. We will cover: - -* Checking relayer information. -* Sending a transaction. -* Checking the relayer status. - -By the end of this tutorial, you will have a basic understanding of how to use the Relayer to interact with smart contracts. - -## Pre-requisites - -* OpenZeppelin Defender account. -* [NodeJS and NPM](https://nodejs.org/en) -* [Typescript for Node js](https://www.npmjs.com/package/ts-node) -* Any IDE or text editor - -## 1. Set Up Relayer - -Let’s start by creating a Relayer: - -* Open [Defender Operate & Automate](https://defender.openzeppelin.com/#/relayers) in a web browser. - - ![Manage Relayer](/defender/tutorial-relayer-step1.png) -* Click on **Create Relayer** with the name ETH Sepolia Relayer and Sepolia network. - - ![Create Relayer](/defender/tutorial-relayer-step2.png) -* Fund it with some Sepolia ETH. This relayer will send and pay for the automated transactions. -* To create an API key for a Relayer, click on the Relayer and then on the **More** button to expand the dropdown and select **Create API Key** - - ![Create Relayer API](/defender/tutorial-relayer-step3.png) -* Now you can set API key expiration in minutes, hours or days. - - ![Save Relayer API](/defender/tutorial-relayer-step3-1.png) -* Once the API Key is created, make sure to write down the secret key. The API secret is only visible once during the creation — if you don’t write it down, it’s lost forever. - - ![Save Relayer API](/defender/tutorial-relayer-step4.png) - -## 2. Check Relayer Information - -* Let’s start by checking the information of our relayer. -* Add Relayer in `.env` File -* Edit `.env` file in your project root directory and add your Relayer API Key and Secret: - - ```jsx - RELAYER_API_KEY=your_api_key - RELAYER_SECRET_KEY=your_api_secret - ``` -* Create a file named `storeObject.ts` in the project. -* Now let’s add the following code: - - ```jsx - const Defender = require('@openzeppelin/defender-sdk'); - - const dotenv = require('dotenv'); - - dotenv.config(); - - async function main() - - const client = new Defender({ - - relayerApiKey: process.env.RELAYER_API_KEY, - relayerApiSecret: process.env.RELAYER_SECRET_KEY, - ); - - const info = await client.relaySigner.getRelayer(); - console.log('Relayer Info:', JSON.stringify(info, null, 2)); - - } - - main().catch((error) => - console.error(error); - process.exitCode = 1; - ); - - ``` -* Execute the script to check the relayer information: - - ```jsx - ts-node storeObject.ts - ``` - - Alternatively, if you want to use Node directly: -```jsx -node storeObject.js -``` - -## 3. Send Transaction - -Next, we will send a transaction using the relayer. - -* Let’s edit the same file and add the following code: - - ```jsx - const tx = await client.relaySigner.sendTransaction( - to: '0x1B9ec5Cc45977927fe6707f2A02F51e1415f2052', - speed: 'fast', - data: '0x6057361d000000000000000000000000000000000000000000000000000000000000000a', - gasLimit: '80000', - ); - console.log('Transaction sent! Hash:', tx.hash); - ``` - -Here we are using the Sepolia [Box contract](https://sepolia.etherscan.io/address/0x1B9ec5Cc45977927fe6707f2A02F51e1415f2052) as the target, which is: -```jsx -0x1B9ec5Cc45977927fe6707f2A02F51e1415f2052 -``` - -and data is the encoded version of the store() function with ‘10’ as input parameter. -```jsx -0x6057361d000000000000000000000000000000000000000000000000000000000000000a -``` - -* Execute the script to send a transaction: - - ```jsx - ts-node storeObject.ts - ``` - - Alternatively, if you want to use Node directly: -```jsx -node storeObject.js -``` - -## 4. Check Transaction Status - -Finally, let’s check the status of our transaction status. - -* Edit the file again and add the following code: - - ```jsx - const txUpdate = await client.relaySigner.getTransaction(tx.transactionId); - console.log('Tx Status', JSON.stringify(txUpdate, null, 2)); - ``` -* Execute the script to check the relayer status: - - ```jsx - ts-node storeObject.ts - ``` - - Alternatively, if you want to use Node directly: -```jsx -node storeObject.js -``` - -## 5. Next Steps -Congratulations! You have successfully used the Relayer to check information, send transactions, and verify the transaction status. By following this tutorial, you have gained a fundamental understanding of how to interact with smart contracts using the Relayer. - -* For more information on using Relayer, refer to the [Relayers](/defender/module/relayers) documentation. -* Explore the [Actions](/defender/tutorial/actions) to automate your smart contract operational tasks with easy integration with the rest of Defender. diff --git a/content/defender/tutorial/workflows.mdx b/content/defender/tutorial/workflows.mdx deleted file mode 100644 index 06256081..00000000 --- a/content/defender/tutorial/workflows.mdx +++ /dev/null @@ -1,115 +0,0 @@ ---- -title: Create an Action Workflow to decrease the number of objects in a Box contract ---- - -Defender allows you to target and activate on-chain activity using Action Workflow quickly. This tutorial shows how to create a workflow that monitors the number of objects in a Box contract and executes an action when an object is added to it. - -## Pre-requisites - -* OpenZeppelin Defender account. - -## 1. Action setup - -In this tutorial, you will monitor [this](https://sepolia.etherscan.io/address/0xC64f7ace6127bc7B0bAb23bD1871aC81e6AEC074) contract in Sepolia, which stores a number of objects while allowing anyone to add or remove objects using the `addObject()` and `removeObject()` functions respectively. For every object added, your workflow will execute an action that removes an object and decreases the total by one. To set up the action, follow these steps: - -1. Open [Defender Relayers](https://defender.openzeppelin.com/v2/#/relayers/new) in a web browser. -2. Fill the form with the following parameters and click on **Create**: - - * **Name**: `Relayer Sepolia` - * **Network**: `Sepolia` -3. Transfer some Sepolia ETH to the relayer address created in the previous step. -4. Navigate to [Defender Address Book](https://defender.openzeppelin.com/v2/#/address-book/new) to import the `BoxV2` contract. -5. Fill the form with the following parameters and click on **Create**: - - * **Name**: `BoxV2` - * **Network**: `Sepolia` - * **Address**: `0xC64f7ace6127bc7B0bAb23bD1871aC81e6AEC074` -6. Navigate to [Defender Workflows Transaction Template creation page](https://defender.openzeppelin.com/v2/#/actions/workflows/transaction-template/new?). -7. Fill the ***General Information*** section with the following parameters: - - * **Name**: `Remove object` - * **Contract**: `BoxV2` -8. Select the `removeObject` function from the dropdown menu in the ***Function*** section. -9. Expand the dropdown on the ***Approval Process*** section and click on `Create Approval Process`. -10. Fill the form with the following parameters and click on **Save Changes**: - - * **Name**: `BoxV2 IR Sender` - * **Relayer**: `Relayer Sepolia` (created in the first step) -11. Select `BoxV2 IR Sender` as the approval process and click on `Save Transaction Template` - -+ -image::tutorial-workflow-first-action.png[Workflow page with Transaction Template] - -## 2. Workflow setup - -With the action configured, you now need to create the workflow. To do so, follow these steps: - -1. Open the [Defender Workflows creation page](https://defender.openzeppelin.com/v2/#/actions/workflows/new). -2. Rename the workflow `Remove from BoxV2 if Object is Added`. -3. Drag the `Remove object` action to the first row. -4. Click on **Save**. - -+ -image::tutorial-workflow-scenario.png[BoxV2 workflow] - -## 3. Monitor setup - -After creating the workflow, you need to configure a monitor that keeps track of the number of objects in the BoxV2 contract to trigger the workflow. To do so, follow these steps: - -1. Open the [Defender Monitor creation page](https://defender.openzeppelin.com/v2/#/monitor/new/custom). -2. Fill the ***General Information*** section with the following parameters: - - * **Name**: `BoxV2 Objects Monitor` - * **Risk Category**: `Suspicious Activity` - * **Contract**: `BoxV2` - * **Confirmation Blocks**: `Confirmed (1 blocks)` - -+ -image::tutorial-ir-first-monitor.png[Workflow Monitor General Information] - -1. In the ***Transaction Filters*** section, add `status == "success"` for the `Transaction properties` field. -2. In the ***Function*** section, select `addObject()` -3. Within the ***Alerts*** section, select the `Remove from BoxV2 if Object is Added` workflow for the `Execute a Workflow` option. - -+ -image::tutorial-ir-monitor.png[Workflow BoxV2 Objects monitor] - -1. Click on **Save Monitor**, which will start running. - -## 4. Seeing it in action - -While the monitor runs, it will detect any transaction that matches the `addObject()` function to trigger the workflow. To manually execute such a transaction, follow these steps: - -1. Open the [Defender Transaction Proposal creation page](https://defender.openzeppelin.com/v2/#/transaction-proposals/new?). -2. Fill the form with the following parameters: - - * **Name**: `BoxV2 Add Object Trigger` - * **Contract**: `BoxV2` - * **Function**: `addObject` - * **Approval Process**: `BoxV2 IR Sender` -3. Click on **Submit Transaction Proposal**. - -+ -image::tutorial-ir-proposal-action.png[Transaction Proposal Trigger] - -1. Click on the transaction proposal to open its page. -2. Click on the top-right button **Approve and Execute** to execute the transaction, which will trigger the workflow through the monitor. -3. Wait for the transaction to be executed and open the [Defender Workflows page](https://defender.openzeppelin.com/v2/#/actions/workflows). - -+ -image::tutorial-workflow-active-scenario.png[Active Workflow] - -1. Click on **View Active Run** and check the details of your workflow response. -2. After the run is executed successfully, you can verify the response by checking the activity of the contract on [Etherscan](https://sepolia.etherscan.io/address/0xC64f7ace6127bc7B0bAb23bD1871aC81e6AEC074). It should look like this: - -+ -image::tutorial-ir-etherscan.png[Workflow Etherscan Response] - -## Next steps - -Congratulations! You now have a complete workflow that will be running and checking every confirmed block. Workflows can be expanded with parallel actions for more technical combinations. In case you are interested in advanced use cases, we are working on Workflow-related guides. - -## References - -* [Workflow Documentation](/defender/module/actions#workflows) -* [BoxV2](https://sepolia.etherscan.io/address/0xC64f7ace6127bc7B0bAb23bD1871aC81e6AEC074) diff --git a/content/defender/wizard-plugin.mdx b/content/defender/wizard-plugin.mdx deleted file mode 100644 index 477f59bf..00000000 --- a/content/defender/wizard-plugin.mdx +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: Contracts Wizard Deploy Plugin ---- - -When configuring contracts from [Contracts Wizard](https://wizard.openzeppelin.com/), you can directly deploy the configured Smart Contract using your Defender account. - -## Usage - -### API Key generation -In your Defender dashboard, go to **Settings -> API Keys** and click **Create API Key**, you only need _Manage Deployments_ permission. - - -We also recommend to set an expiration for the API Key, considering that is going to be used from an external site. - - -![Defender Remix Plugin Api Key](/defender/remix-plugin-api-key.png) - -### Deployment from Contracts Wizard - -Go to [Contracts Wizard](https://wizard.openzeppelin.com/) site, and after editing your contract, click on "Deploy with Defender". - -![Defender Wizard Plugin Getting Started](/defender/wizard-plugin-start.png) - -#### Configure -Set your **API Key** and **API Secret** and press "Authenticate". You should see a message below the button indicating that the credentials are valid. - -![Defender Wizard Plugin Configure](/defender/wizard-plugin-configure.png) -![Defender Wizard Plugin API keys](/defender/wizard-plugin-configure-2.png) - -#### Network -Select any of the supported networks. This also includes private and forked networks configured in your tenant. - -![Defender Wizard Plugin Network](/defender/wizard-plugin-network-2.png) - -#### Approval Process -Here you have 3 options: - -* Select an existing approval process from your **Deployment Environment** configured for the selected network. - - -If you have an existing deployment environment in the selected network, this is the only option allowed. - - -* If the **Deployment Envoronment** does not exist for the selected network, then you can create a new one. - - -If the Approval Process to be created is a Relayer, the API Key must include _Manage Relayers_ permission. - - -* Additionally, you can use the **injected provider** from Remix (a browser wallet) to deploy the contract, this will create a Defender **Deployment Environment** under the hood after deploying the contract. - -![Defender Wizard Plugin Approval Process](/defender/wizard-plugin-approval-process.png) - -#### Deploy -In this step, you should see the constructor inputs of your configured contract (if any), and the option to create a deterministic deployment. - - -This step is reactive, if you modify the contract you will see the new constructor arguments updated right after. - - - -Upgradable contracts are not yet fully supported. This action will only deploy the implementation contract without initializing. For safe upgrades, we strongly recommend usign [Upgrades Package](https://github.com/OpenZeppelin/openzeppelin-upgrades). - - -![Defender Wizard Plugin Deploy](/defender/wizard-plugin-deploy.png) - -#### Deterministic Deployments - -Defender Deploy supports a `salt` value to create deployments to deterministic addresses using `CREATE2`. Click on `Deterministic` checkbox and set the salt field to any arbitrary value. - - -If the approval process selected is a Multisig, the `salt` is required as Defender only support deterministic deployments when using Multisigs. - - -![Defender Wizard Plugin Deterministic Deployments](/defender/wizard-plugin-deterministic.png) - -#### Further Steps - -Once the contract deployment is submitted to Defender, in some cases you may need to complete the deployment from Defender Dashboard. You will see message indicating that the contract was submitted and a button that redirects to your Deployment in Defender. - -![Defender Wizard Plugin Further Steps](/defender/wizard-deploy-further-steps.png) - -## Feedback - -The Defender Deploy Plugin is open source, for feedback related to the plugin, please submit an issue in the [Github Repository](https://github.com/OpenZeppelin/defender-deploy-plugin) or send an email to `defender-support@openzeppelin.com`. diff --git a/content/tron-contracts/governance.mdx b/content/tron-contracts/governance.mdx index ef6461a8..8ac9507c 100644 --- a/content/tron-contracts/governance.mdx +++ b/content/tron-contracts/governance.mdx @@ -44,7 +44,7 @@ When using a timelock with your Governor contract, you can use either OpenZeppel As of this writing, TRON is not among [Tally's supported networks](https://docs.tally.xyz/set-up-and-technical-documentation/deploying-daos/smart-contract-compatibility/network-support). The compatibility described below is about the Governor contract's *interface*, the shape Tally expects a Governor to have, not a claim that you can point a live Tally dashboard at a TRON deployment today. -For all of these options, the Governor will be compatible with Tally: users will be able to create proposals, see voting periods and delays following ITRC6372, visualize voting power and advocates, navigate proposals, and cast votes. For proposal creation in particular, projects can also use [Defender Transaction Proposals](https://docs.openzeppelin.com/defender/module/actions#transaction-proposals-reference) as an alternative interface. +For all of these options, the Governor will be compatible with Tally: users will be able to create proposals, see voting periods and delays following ITRC6372, visualize voting power and advocates, navigate proposals, and cast votes. In the rest of this guide, we will focus on a fresh deploy of the vanilla OpenZeppelin Governor features without concern for compatibility with GovernorAlpha or Bravo. @@ -255,7 +255,7 @@ A proposal is a sequence of actions that the Governor contract will perform if i Let's say we want to create a proposal to give a team a grant, in the form of TRC-20 tokens from the governance treasury. This proposal will consist of a single action where the target is the TRC-20 token, calldata is the encoded function call `transfer(, )`, and with 0 TRX attached. -Generally a proposal will be created with the help of an interface such as Tally or [Defender Proposals](https://docs.openzeppelin.com/defender/module/actions#transaction-proposals-reference). Here we will show how to create the proposal using Ethers.js. +Generally a proposal will be created with the help of an interface such as Tally. Here we will show how to create the proposal using Ethers.js. First we get all the parameters necessary for the proposal action. diff --git a/content/upgrades-plugins/api-hardhat-upgrades.mdx b/content/upgrades-plugins/api-hardhat-upgrades.mdx index 97185c26..906beb14 100644 --- a/content/upgrades-plugins/api-hardhat-upgrades.mdx +++ b/content/upgrades-plugins/api-hardhat-upgrades.mdx @@ -24,14 +24,11 @@ In Hardhat 3, all of the functions below are accessed via an `upgradesApi` objec ```typescript import hre from 'hardhat'; -import { upgrades, defender } from '@openzeppelin/hardhat-upgrades'; +import { upgrades } from '@openzeppelin/hardhat-upgrades'; const connection = await hre.network.create(); const { ethers } = connection; const upgradesApi = await upgrades(hre, connection); - -// For Defender-specific functions: -const defenderApi = await defender(hre, connection); ``` @@ -45,12 +42,12 @@ const connection = await hre.network.create(); const upgradesApi = await upgrades(hre, connection); ``` -Contracts are referenced by name and returned as viem contract instances. OpenZeppelin Defender (`defender.*`) is available only with ethers. Transactions are signed by the connection's first wallet client by default; pass a specific one with the `client` option. +Contracts are referenced by name and returned as viem contract instances. Transactions are signed by the connection's first wallet client by default; pass a specific one with the `client` option. -`upgradesApi` exposes every top-level function documented below (e.g. `upgradesApi.deployProxy(...)`). With ethers, `defenderApi` exposes the same functions plus the `defender.*` functions (e.g. `defenderApi.deployContract(...)`, `defenderApi.proposeUpgradeWithApproval(...)`). The `admin`, `erc1967`, and `beacon` namespaces are accessed as `upgradesApi.admin.*`, `upgradesApi.erc1967.*`, and `upgradesApi.beacon.*`. +`upgradesApi` exposes every top-level function documented below (e.g. `upgradesApi.deployProxy(...)`). The `admin`, `erc1967`, and `beacon` namespaces are accessed as `upgradesApi.admin.*`, `upgradesApi.erc1967.*`, and `upgradesApi.beacon.*`. ## Common Options @@ -80,20 +77,15 @@ The following options are common to some functions. * `timeout`: (`number`) Timeout in milliseconds to wait for the transaction confirmation when deploying an implementation contract. Defaults to `60000`. Use `0` to wait indefinitely. * `pollingInterval`: (`number`) Polling interval in milliseconds between checks for the transaction confirmation when deploying an implementation contract. Defaults to `5000`. * `redeployImplementation`: (`"always" | "never" | "onchange"`) Determines whether the implementation contract will be redeployed. Defaults to `"onchange"`. - * If set to `"always"`, the implementation contract is always redeployed even if it was previously deployed with the same bytecode. This can be used with the `salt` option when deploying a proxy through OpenZeppelin Defender to ensure that the implementation contract is deployed with the same salt as the proxy. + * If set to `"always"`, the implementation contract is always redeployed even if it was previously deployed with the same bytecode. * If set to `"never"`, the implementation contract is never redeployed. If the implementation contract was not previously deployed or is not found in the network file, an error will be thrown. * If set to `"onchange"`, the implementation contract is redeployed only if the bytecode has changed from previous deployments. -* `txOverrides`: (`ethers.Overrides`) An ethers.js [Overrides](https://docs.ethers.org/v6/api/contract/#Overrides) object to override transaction parameters, such as `gasLimit` and `gasPrice`. Applies to all transactions sent by a function with this option, even if the function sends multiple transactions. For OpenZeppelin Defender deployments, only the `gasLimit`, `gasPrice`, `maxFeePerGas`, and `maxPriorityFeePerGas` parameters are supported. This option applies to the default ethers-based API. +* `txOverrides`: (`ethers.Overrides`) An ethers.js [Overrides](https://docs.ethers.org/v6/api/contract/#Overrides) object to override transaction parameters, such as `gasLimit` and `gasPrice`. Applies to all transactions sent by a function with this option, even if the function sends multiple transactions. This option applies to the default ethers-based API. * If you are using viem, `txOverrides` does not apply. Instead, pass the transaction parameters `gas`, `gasPrice`, `maxFeePerGas`, `maxPriorityFeePerGas`, and `value` directly as options, and use the `client` option to select the wallet/public client. * `client`: (`KeyedClient`) viem-based API only. The viem public and/or wallet clients to use, following `@nomicfoundation/hardhat-viem` conventions. `KeyedClient` is an object `{ public?: PublicClient; wallet?: WalletClient }` (with at least one of the two provided). The **wallet client** is the viem counterpart of the ethers signer: it selects the account that signs the plugin's transactions, and must be an account managed by the network connection. Defaults to the first wallet client from `connection.viem.getWalletClients()`. The `admin.*` functions instead take a wallet client as a positional argument, not via this option. -* `useDefenderDeploy`: (`boolean`) Deploy contracts using OpenZeppelin Defender instead of ethers.js. See [Using with OpenZeppelin Defender](/upgrades-plugins/defender-deploy). -* `verifySourceCode`: (`boolean`) When using OpenZeppelin Defender deployments, whether to verify source code on block explorers. Defaults to `true`. -* `relayerId`: (`string`) When using OpenZeppelin Defender deployments, the ID of the relayer to use for the deployment. Defaults to the relayer configured for your deployment environment on Defender. -* `salt`: (`string`) When using OpenZeppelin Defender deployments, if this is not set, deployments will be performed using the CREATE opcode. If this is set, deployments will be performed using the CREATE2 opcode with the provided salt. Note that deployments using a Safe are done using CREATE2 and require a salt. ***Warning:*** CREATE2 affects `msg.sender` behavior. See [Caveats](/defender/tutorial/deploy#caveats) for more information. -* `metadata`: (` commitHash?: string; tag?: string; [k: string]: any; `) When using OpenZeppelin Defender deployments, you can use this to identify, tag, or classify deployments. See [Metadata](/defender/module/deploy#metadata). * `proxyFactory`: (`ethers.ContractFactory`) Customizes the ethers contract factory to use for deploying the proxy, allowing a custom proxy contract to be deployed. See [factories.ts](https://github.com/OpenZeppelin/openzeppelin-upgrades/blob/master/packages/plugin-hardhat/src/utils/factories.ts) for the default contract factory for each kind of proxy. * **Since:** `@openzeppelin/hardhat-upgrades@3.7.0` -* `deployFunction`: (`(hre, opts, factory, ...args) => Promise`) Customizes the function used to deploy the proxy. Can be used along with the `proxyFactory` option to override constructor parameters for custom proxy deployments. See [deploy.ts](https://github.com/OpenZeppelin/openzeppelin-upgrades/blob/master/packages/plugin-hardhat/src/utils/deploy.ts) for the default deploy function. +* `deployFunction`: (`(hre, opts, factory, ...args) => Promise`) Customizes the function used to deploy the proxy. Can be used along with the `proxyFactory` option to override constructor parameters for custom proxy deployments. See [deploy.ts](https://github.com/OpenZeppelin/openzeppelin-upgrades/blob/master/packages/plugin-hardhat/src/utils/deploy.ts) for the default deploy function. `EthersOrDefenderDeployment` is the return type exported by `@openzeppelin/hardhat-upgrades`, kept under its upstream name. * **Since:** `@openzeppelin/hardhat-upgrades@3.7.0` Note that the options `unsafeAllow` can also be specified in a more granular way directly in the source code if using Solidity >=0.8.2. See [How can I disable some of the checks?](/upgrades-plugins/faq#how-can-i-disable-some-of-the-checks) @@ -124,7 +116,6 @@ async function deployProxy( redeployImplementation?: 'always' | 'never' | 'onchange', txOverrides?: ethers.Overrides, kind?: 'uups' | 'transparent', - useDefenderDeploy?: boolean, proxyFactory?: ethers.ContractFactory, deployFunction?: () => Promise, }, @@ -367,7 +358,6 @@ async function deployBeaconProxy( opts?: { initializer?: string | false, txOverrides?: ethers.Overrides, - useDefenderDeploy?: boolean, proxyFactory?: ethers.ContractFactory, deployFunction?: () => Promise, }, @@ -526,7 +516,6 @@ async function deployImplementation( txOverrides?: ethers.Overrides, getTxResponse?: boolean, kind?: 'uups' | 'transparent' | 'beacon', - useDefenderDeploy?: boolean, }, ): Promise ``` @@ -708,7 +697,6 @@ async function prepareUpgrade( txOverrides?: ethers.Overrides, getTxResponse?: boolean, kind?: 'uups' | 'transparent' | 'beacon', - useDefenderDeploy?: boolean, }, ): Promise ``` @@ -751,131 +739,6 @@ Validates and deploys a new implementation contract, and returns its address. If * the new implementation contract address (or, with the ethers-based API, an ethers transaction response when `getTxResponse` is set). -## defender.deployContract - - -The `defender.*` functions are available only with the ethers-based API (accessed via `defender(hre, connection)`); they are not part of the viem-based API. - - -```ts -async function deployContract( - Contract: ethers.ContractFactory, - args: unknown[] = [], - opts?: { - unsafeAllowDeployContract?: boolean, - pollingInterval?: number, - }, -): Promise -``` - -Deploys a non-upgradeable contract using OpenZeppelin Defender, and returns a contract instance. Throws an error if the contract looks like an implementation contract. - - -Do not use this function to deploy implementations of upgradeable contracts, because upgrade safety validations are not performed with this function. For implementation contracts, use [deployImplementation](#deployimplementation) instead. - - -**Parameters:** - -* `Contract` - an ethers contract factory to use as the contract to deploy. -* `opts` - an object with options: - * `unsafeAllowDeployContract`: if set to `true`, allows the contract to be deployed even if it looks like an implementation contract. Defaults to `false`. - * `pollingInterval`: polling interval in milliseconds between checks for the transaction confirmation when calling `.waitForDeployment()` on the resulting contract instance. Defaults to `5000`. - -**Returns:** - -* the contract instance. - -**Since:** - -* `@openzeppelin/hardhat-upgrades@2.2.0` - -## defender.getDeployApprovalProcess - -```ts -async function getDeployApprovalProcess( -): Promise< - approvalProcessId: string, - address?: string, - viaType?: 'EOA' | 'Contract' | 'Multisig' | 'Safe' | 'Gnosis Multisig' | 'Relayer' | 'Unknown' | 'Timelock Controller' | 'ERC20' | 'Governor' | 'Fireblocks', - > -``` - -Gets the default deploy approval process configured for your deployment environment on OpenZeppelin Defender. - -**Returns:** - -* an object with the default deploy approval process ID and the associated address, such as a Relayer, EOA, or multisig wallet address. - -**Since:** - -* `@openzeppelin/hardhat-upgrades@2.5.0` - -## defender.getUpgradeApprovalProcess - -```ts -async function getUpgradeApprovalProcess( -): Promise< - approvalProcessId: string, - address?: string, - viaType?: 'EOA' | 'Contract' | 'Multisig' | 'Safe' | 'Gnosis Multisig' | 'Relayer' | 'Unknown' | 'Timelock Controller' | 'ERC20' | 'Governor' | 'Fireblocks', - > -``` - -Gets the default upgrade approval process configured for your deployment environment on OpenZeppelin Defender. For example, this is useful for determining the default multisig wallet that you can use in your scripts to assign as the owner of your proxy. - -**Returns:** - -* an object with the default upgrade approval process ID and the associated address, such as a multisig or governor contract address. - -**Since:** - -* `@openzeppelin/hardhat-upgrades@2.5.0` - -## defender.proposeUpgradeWithApproval - -```ts -async function proposeUpgradeWithApproval( - proxyAddress: string, - ImplFactory: ContractFactory, - opts?: { - unsafeAllow?: ValidationError[], - unsafeAllowRenames?: boolean, - unsafeSkipStorageCheck?: boolean, - constructorArgs?: unknown[], - timeout?: number, - pollingInterval?: number, - redeployImplementation?: 'always' | 'never' | 'onchange', - kind?: 'uups' | 'transparent' | 'beacon', - useDefenderDeploy?: boolean, - approvalProcessId?: string, - }, -): Promise< - proposalId: string, - url: string, - txResponse?: ethers.providers.TransactionResponse, - > -``` - -Proposes an upgrade using an upgrade approval process on OpenZeppelin Defender. - -Similar to `prepareUpgrade`. This method validates and deploys the new implementation contract, but also proposes an upgrade using an upgrade approval process on OpenZeppelin Defender. Supported for UUPS or Transparent proxies. Not currently supported for beacon proxies or beacons. For beacons, use `prepareUpgrade` along with a transaction proposal on Defender to upgrade the beacon to the deployed implementation. - -**Parameters:** - -* `proxyAddress` - the proxy address. -* `ImplFactory` - the new implementation contract. -* `opts` - an object with options: - * `approvalProcessId`: The ID of the upgrade approval process. Defaults to the upgrade approval process configured for your deployment environment on Defender. - * additional options as described in [Common Options](#common-options). - -**Returns:** - -* an object with the Defender proposal ID, the URL of the proposal in Safe App if applicable, and the ethers transaction response corresponding to the deployment of the new implementation contract. Note that if the new implementation contract was originally imported as a result of `forceImport`, the ethers transaction response will be undefined. - -**Since:** - -* `@openzeppelin/hardhat-upgrades@2.2.0` - ## admin.changeProxyAdmin diff --git a/content/upgrades-plugins/defender-deploy.mdx b/content/upgrades-plugins/defender-deploy.mdx deleted file mode 100644 index e051d2f1..00000000 --- a/content/upgrades-plugins/defender-deploy.mdx +++ /dev/null @@ -1,111 +0,0 @@ ---- -title: OpenZeppelin Defender with Hardhat ---- - - -This page describes usage with Hardhat 2. If you are on Hardhat 3, apply the patterns from [Using with Hardhat](/upgrades-plugins/hardhat-upgrades) (ESM, `defineConfig`, and the `defender(hre, connection)` factory) to the examples below. - - -The Hardhat Upgrades package can use [OpenZeppelin Defender](/defender) for deployments instead of ethers.js, which allows for features such as gas pricing estimation, resubmissions, and automated bytecode and source code verification. - -## Configuration - -Create a deployment environment on OpenZeppelin Defender and provide the Team API Key and secret in your `hardhat.config.js` or `hardhat.config.ts` file under `defender`: - -```js -module.exports = - defender: { - apiKey: process.env.API_KEY, - apiSecret: process.env.API_SECRET, - -} -``` - - -The API key for the above must at least have the capability to Manage Deployments (optionally Manage Relayers is needed to create an approval process with a Relayer). You can configure your API keys at https://defender.openzeppelin.com/#/settings/api-keys. - - -## Network Selection - -The network that is used with OpenZeppelin Defender is determined by the network that Hardhat is connected to. -If you want to ensure that a specific network is used with Defender, set the `network` field in the `defender` section of your `hardhat.config.js` or `hardhat.config.ts` file: -```js -module.exports = - defender: { - apiKey: process.env.API_KEY, - apiSecret: process.env.API_SECRET, - network: "my-mainnet-fork", - -} -``` -If set, this must be the name of a public, private or forked network in Defender. If Hardhat is connected to a different network while this is set, the deployment will not occur and will throw an error instead. - - -This is required if you have multiple forked networks in Defender with the same chainId, in which case the one with name matching the `network` field will be used. - - -## Usage - -When using the [Hardhat Upgrades API functions](/upgrades-plugins/api-hardhat-upgrades), enable OpenZeppelin Defender deployments using any of the ways below. - - -Only functions that have the `useDefenderDeploy` option in their API reference support deployments through OpenZeppelin Defender. If you enable the following but use functions that do not support `useDefenderDeploy`, the first way below will cause those functions to deploy using ethers.js, whereas the second and third ways will cause those functions to give an error. - - -* Recommended: In `hardhat.config.js` or `hardhat.config.ts`, set `useDefenderDeploy: true` under `defender`. For example: - -```js -module.exports = - defender: { - apiKey: process.env.API_KEY, - apiSecret: process.env.API_SECRET, - useDefenderDeploy: true, - -} -``` - -```js -// scripts/create-box.js -const ethers, upgrades = require("hardhat"); - -async function main() - const Box = await ethers.getContractFactory("Box"); - const box = await upgrades.deployProxy(Box, [42]); - await box.waitForDeployment(); - console.log("Box deployed to:", await box.getAddress()); - - -main(); -``` - -* Use the `defender` module instead of `upgrades` from the Hardhat Runtime Environment. Use this if you want to make sure Defender is used and want to see an error if the function does not support Defender. For example: - -```js -// scripts/create-box.js -const ethers, defender = require("hardhat"); - -async function main() - const Box = await ethers.getContractFactory("Box"); - const box = await defender.deployProxy(Box, [42]); - await box.waitForDeployment(); - console.log("Box deployed to:", await box.getAddress()); - - -main(); -``` - -* Use the `useDefenderDeploy` common option. Setting this option overrides the above for specific functions. For example: - -```js -// scripts/create-box.js -const ethers, upgrades = require("hardhat"); - -async function main() - const Box = await ethers.getContractFactory("Box"); - const box = await upgrades.deployProxy(Box, [42], { useDefenderDeploy: true ); - await box.waitForDeployment(); - console.log("Box deployed to:", await box.getAddress()); -} - -main(); -``` diff --git a/content/upgrades-plugins/foundry-defender.mdx b/content/upgrades-plugins/foundry-defender.mdx deleted file mode 100644 index 2cde3ce3..00000000 --- a/content/upgrades-plugins/foundry-defender.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: foundry-defender ---- - diff --git a/content/upgrades-plugins/foundry/api/Defender.mdx b/content/upgrades-plugins/foundry/api/Defender.mdx deleted file mode 100644 index 8834f3b1..00000000 --- a/content/upgrades-plugins/foundry/api/Defender.mdx +++ /dev/null @@ -1,232 +0,0 @@ ---- -title: "Defender" -description: "Smart contract Defender utilities and implementations" ---- - - - -
- -## `Defender` - - - - - -
- -```solidity -import { Defender } from "openzeppelin-foundry-upgrades/Defender.sol"; -``` - -Library for interacting with OpenZeppelin Defender from Forge scripts or tests. - -
-

Functions

-
-- [deployContract(contractName)](#Defender-deployContract-string-) -- [deployContract(contractName, defenderOpts)](#Defender-deployContract-string-struct-DefenderOptions-) -- [deployContract(contractName, constructorData)](#Defender-deployContract-string-bytes-) -- [deployContract(contractName, constructorData, defenderOpts)](#Defender-deployContract-string-bytes-struct-DefenderOptions-) -- [proposeUpgrade(proxyAddress, newImplementationContractName, opts)](#Defender-proposeUpgrade-address-string-struct-Options-) -- [getDeployApprovalProcess()](#Defender-getDeployApprovalProcess--) -- [getUpgradeApprovalProcess()](#Defender-getUpgradeApprovalProcess--) -
-
- - - -
-
-

deployContract(string contractName) → address

-
-

internal

-# -
-
-
- -Deploys a contract to the current network using OpenZeppelin Defender. - - -Do not use this function directly if you are deploying an upgradeable contract. This function does not validate whether the contract is upgrade safe. - - -NOTE: If using an EOA or Safe to deploy, go to [Defender deploy](https://defender.openzeppelin.com/v2/#/deploy) to submit the pending deployment while the script is running. -The script waits for the deployment to complete before it continues. - -
-
- - - -
-
-

deployContract(string contractName, struct DefenderOptions defenderOpts) → address

-
-

internal

-# -
-
-
- -Deploys a contract to the current network using OpenZeppelin Defender. - - -Do not use this function directly if you are deploying an upgradeable contract. This function does not validate whether the contract is upgrade safe. - - -NOTE: If using an EOA or Safe to deploy, go to [Defender deploy](https://defender.openzeppelin.com/v2/#/deploy) to submit the pending deployment while the script is running. -The script waits for the deployment to complete before it continues. - -
-
- - - -
-
-

deployContract(string contractName, bytes constructorData) → address

-
-

internal

-# -
-
-
- -Deploys a contract with constructor arguments to the current network using OpenZeppelin Defender. - - -Do not use this function directly if you are deploying an upgradeable contract. This function does not validate whether the contract is upgrade safe. - - -NOTE: If using an EOA or Safe to deploy, go to [Defender deploy](https://defender.openzeppelin.com/v2/#/deploy) to submit the pending deployment while the script is running. -The script waits for the deployment to complete before it continues. - -
-
- - - -
-
-

deployContract(string contractName, bytes constructorData, struct DefenderOptions defenderOpts) → address

-
-

internal

-# -
-
-
- -Deploys a contract with constructor arguments to the current network using OpenZeppelin Defender. - - -Do not use this function directly if you are deploying an upgradeable contract. This function does not validate whether the contract is upgrade safe. - - -NOTE: If using an EOA or Safe to deploy, go to [Defender deploy](https://defender.openzeppelin.com/v2/#/deploy) to submit the pending deployment while the script is running. -The script waits for the deployment to complete before it continues. - -
-
- - - -
-
-

proposeUpgrade(address proxyAddress, string newImplementationContractName, struct Options opts) → struct ProposeUpgradeResponse

-
-

internal

-# -
-
-
- -Proposes an upgrade to an upgradeable proxy using OpenZeppelin Defender. - -This function validates a new implementation contract in comparison with a reference contract, deploys the new implementation contract using Defender, -and proposes an upgrade to the new implementation contract using an upgrade approval process on Defender. - -Supported for UUPS or Transparent proxies. Not currently supported for beacon proxies or beacons. -For beacons, use `Upgrades.prepareUpgrade` along with a transaction proposal on Defender to upgrade the beacon to the deployed implementation. - -Requires that either the `referenceContract` option is set, or the contract has a `@custom:oz-upgrades-from ` annotation. - - -Ensure that the reference contract is the same as the current implementation contract that the proxy is pointing to. -This function does not validate that the reference contract is the current implementation. - - -NOTE: If using an EOA or Safe to deploy, go to [Defender deploy](https://defender.openzeppelin.com/v2/#/deploy) to submit the pending deployment of the new implementation contract while the script is running. -The script waits for the deployment to complete before it continues. - -
-
- - - -
-
-

getDeployApprovalProcess() → struct ApprovalProcessResponse

-
-

internal

-# -
-
-
- -Gets the default deploy approval process configured for your deployment environment on OpenZeppelin Defender. - -
-
- - - -
-
-

getUpgradeApprovalProcess() → struct ApprovalProcessResponse

-
-

internal

-# -
-
-
- -Gets the default upgrade approval process configured for your deployment environment on OpenZeppelin Defender. -For example, this is useful for determining the default multisig wallet that you can use in your scripts to assign as the owner of your proxy. - -
-
- - - -
- -## `ProposeUpgradeResponse` - - - - - -
- -```solidity -import { ProposeUpgradeResponse } from "openzeppelin-foundry-upgrades/Defender.sol"; -``` - - - -
- -## `ApprovalProcessResponse` - - - - - -
- -```solidity -import { ApprovalProcessResponse } from "openzeppelin-foundry-upgrades/Defender.sol"; -``` - diff --git a/content/upgrades-plugins/foundry/api/LegacyUpgrades.mdx b/content/upgrades-plugins/foundry/api/LegacyUpgrades.mdx index 9898d154..6f3f8e78 100644 --- a/content/upgrades-plugins/foundry/api/LegacyUpgrades.mdx +++ b/content/upgrades-plugins/foundry/api/LegacyUpgrades.mdx @@ -320,8 +320,6 @@ Library for managing upgradeable contracts from Forge tests, without validations Can be used with `forge coverage`. Requires implementation contracts to be instantiated first. Does not require `--ffi` and does not require a clean compilation before each run. -Not supported for OpenZeppelin Defender deployments. - Not recommended for use in Forge scripts. `UnsafeUpgrades` does not validate whether your contracts are upgrade safe or whether new implementations are compatible with previous ones. diff --git a/content/upgrades-plugins/foundry/api/Options.mdx b/content/upgrades-plugins/foundry/api/Options.mdx index 0d2716fb..07bad745 100644 --- a/content/upgrades-plugins/foundry/api/Options.mdx +++ b/content/upgrades-plugins/foundry/api/Options.mdx @@ -19,22 +19,6 @@ description: "Smart contract Options utilities and implementations" import { Options } from "openzeppelin-foundry-upgrades/Options.sol"; ``` - - -
- -## `DefenderOptions` - - - - - -
- -```solidity -import { DefenderOptions } from "openzeppelin-foundry-upgrades/Options.sol"; -``` -
diff --git a/content/upgrades-plugins/foundry/api/Upgrades.mdx b/content/upgrades-plugins/foundry/api/Upgrades.mdx index d9e0c3e4..c4487577 100644 --- a/content/upgrades-plugins/foundry/api/Upgrades.mdx +++ b/content/upgrades-plugins/foundry/api/Upgrades.mdx @@ -499,8 +499,6 @@ Library for deploying and managing upgradeable contracts from Forge tests, witho Can be used with `forge coverage`. Requires implementation contracts to be instantiated first. Does not require `--ffi` and does not require a clean compilation before each run. -Not supported for OpenZeppelin Defender deployments. - Not recommended for use in Forge scripts. `UnsafeUpgrades` does not validate whether your contracts are upgrade safe or whether new implementations are compatible with previous ones. diff --git a/content/upgrades-plugins/foundry/api/index.mdx b/content/upgrades-plugins/foundry/api/index.mdx index d36a7617..4ca7bc71 100644 --- a/content/upgrades-plugins/foundry/api/index.mdx +++ b/content/upgrades-plugins/foundry/api/index.mdx @@ -44,8 +44,5 @@ Library for deploying and managing upgradeable contracts from Forge scripts or t ### [LegacyUpgrades](/upgrades-plugins/foundry/api/LegacyUpgrades) Library for managing upgradeable contracts from Forge scripts or tests. Only for upgrading existing deployments using OpenZeppelin Contracts v4. -### [Defender](/upgrades-plugins/foundry/api/Defender) -Library for interacting with OpenZeppelin Defender from Forge scripts or tests. - ### [Options](/upgrades-plugins/foundry/api/Options) Configuration options and structs used throughout the Upgrades libraries. diff --git a/content/upgrades-plugins/foundry/foundry-defender.mdx b/content/upgrades-plugins/foundry/foundry-defender.mdx deleted file mode 100644 index 5a23eca5..00000000 --- a/content/upgrades-plugins/foundry/foundry-defender.mdx +++ /dev/null @@ -1,180 +0,0 @@ ---- -title: OpenZeppelin Defender with Foundry ---- - -OpenZeppelin Foundry Upgrades can be used for performing deployments through [OpenZeppelin Defender](/defender), which allows for features such as gas pricing estimation, resubmissions, and automated bytecode and source code verification. - - -Defender deployments are ***always*** broadcast to a live network, regardless of whether you are using the `broadcast` cheatcode. -The recommended pattern is to separate Defender scripts from scripts that rely on network forking and simulations, to avoid mixing simulation and live network data. - - -## Installation - -See [Using with Foundry - Installation](/upgrades-plugins/foundry/foundry-upgrades#installation). - -## Prerequisites -1. Install [Node.js](https://nodejs.org/). -2. Configure your `foundry.toml` to enable ffi, ast, build info and storage layout: - -```toml -[profile.default] -ffi = true -ast = true -build_info = true -extra_output = ["storageLayout"] -``` - - -Metadata must also be included in the compiler output, which it is by default. - - -1. Set the following environment variables in your `.env` file at your project root, using your Team API key and secret from OpenZeppelin Defender: - -``` -DEFENDER_KEY= -DEFENDER_SECRET= -``` - - -The API key for the above must at least have the capability to Manage Deployments (optionally Manage Relayers is needed to create an approval process with a Relayer). You can configure your API keys at https://defender.openzeppelin.com/#/settings/api-keys. - - -## Network Selection - -The network that is used with OpenZeppelin Defender is determined by the network that Foundry is connected to. -If you want to ensure that a specific network is used with Defender, set the `DEFENDER_NETWORK` environment variable in your `.env` file, for example: - -``` -DEFENDER_NETWORK=my-mainnet-fork -``` -If set, this must be the name of a public, private or forked network in Defender. If Foundry is connected to a different network while this is set, the deployment will not occur and will throw an error instead. - - -This is required if you have multiple forked networks in Defender with the same chainId, in which case the one with name matching the `DEFENDER_NETWORK` environment variable will be used. - - -## Usage - -### Upgradeable Contracts - -If you are deploying upgradeable contracts, use the `Upgrades` library as described in [Using with Foundry - Installation](/upgrades-plugins/foundry/foundry-upgrades#installation) but set the option `defender.useDefenderDeploy = true` when calling functions to cause all deployments to occur through OpenZeppelin Defender. - -***Example 1 - Deploying a proxy***: -To deploy a UUPS proxy, create a script called `Defender.s.sol` like the following: -```solidity -pragma solidity ^0.8.20; - -import {Script} from "forge-std/Script.sol"; -import {console} from "forge-std/console.sol"; - -import {Defender, ApprovalProcessResponse} from "openzeppelin-foundry-upgrades/Defender.sol"; -import {Upgrades, Options} from "openzeppelin-foundry-upgrades/Upgrades.sol"; - -import {MyContract} from "../src/MyContract.sol"; - -contract DefenderScript is Script { - function setUp() public {} - - function run() public { - ApprovalProcessResponse memory upgradeApprovalProcess = Defender.getUpgradeApprovalProcess(); - - if (upgradeApprovalProcess.via == address(0)) { - revert(string.concat("Upgrade approval process with id ", upgradeApprovalProcess.approvalProcessId, " has no assigned address")); - } - - Options memory opts; - opts.defender.useDefenderDeploy = true; - - address proxy = Upgrades.deployUUPSProxy( - "MyContract.sol", - abi.encodeCall(MyContract.initialize, ("Hello World", upgradeApprovalProcess.via)), - opts - ); - - console.log("Deployed proxy to address", proxy); - } -} -``` - -Then run the following command: -```console -forge script --force --rpc-url -``` - -The above example assumes the implementation contract takes an initial owner address as an argument for its `initialize` function. The script retrieves the address associated with the upgrade approval process configured in Defender (such as a multisig address), and uses that address as the initial owner so that it can have upgrade rights for the proxy. - -This example calls the `Upgrades.deployUUPSProxy` function with the `defender.useDefenderDeploy` option to deploy both the implementation contract and a UUPS proxy to the connected network using Defender. The function waits for the deployments to complete, which may take a few minutes per contract, then returns with the deployed proxy address. While the function is waiting, you can monitor your deployment status in OpenZeppelin Defender’s [Deploy module](https://defender.openzeppelin.com/v2/#/deploy). - - -If using an EOA or Safe to deploy, you must submit the pending deployments in Defender while the script is running. The script waits for each deployment to complete before it continues. - - -***Example 2 - Proposing an upgrade to a proxy***: -To propose an upgrade through Defender, create a script like the following: -```solidity -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import {Script} from "forge-std/Script.sol"; -import {console} from "forge-std/console.sol"; - -import {MyContractV2} from "../src/MyContractV2.sol"; - -import {ProposeUpgradeResponse, Defender, Options} from "openzeppelin-foundry-upgrades/Defender.sol"; - -contract DefenderScript is Script { - function setUp() public {} - - function run() public { - Options memory opts; - ProposeUpgradeResponse memory response = Defender.proposeUpgrade( - , - "MyContractV2.sol", - opts - ); - console.log("Proposal id", response.proposalId); - console.log("Url", response.url); - } -} -``` - -Then run the script as in Example 1, and go the resulting URL to review and approve the upgrade proposal. - -### Non-Upgradeable Contracts - -If you are deploying non-upgradeable contracts, import the `Defender` library from `Defender.sol` and use its functions to deploy contracts through OpenZeppelin Defender. - -***Example:*** - -To deploy a non-upgradeable contract, create a script called `Defender.s.sol` like the following: -```solidity -pragma solidity ^0.8.20; - -import {Script} from "forge-std/Script.sol"; -import {console} from "forge-std/console.sol"; - -import {MyContract} from "../src/MyContract.sol"; - -import {Defender} from "openzeppelin-foundry-upgrades/Defender.sol"; - -contract DefenderScript is Script { - function setUp() public {} - - function run() public { - address deployed = Defender.deployContract("MyContract.sol", abi.encode("arguments for the constructor")); - console.log("Deployed contract to address", deployed); - } -} -``` - -Then run the following command: -```console -forge script --force --rpc-url -``` - -The above example calls the `Defender.deployContract` function to deploy the specified contract to the connected network using Defender. The function waits for the deployment to complete, which may take a few minutes, then returns with the deployed contract address. While the function is waiting, you can monitor your deployment status in OpenZeppelin Defender’s [Deploy module](https://defender.openzeppelin.com/v2/#/deploy). - - -If using an EOA or Safe to deploy, you must submit the pending deployment in Defender while the script is running. The script waits for the deployment to complete before it continues. - diff --git a/content/upgrades-plugins/foundry/foundry-upgrades.mdx b/content/upgrades-plugins/foundry/foundry-upgrades.mdx index ef0d683d..f0dd1ffa 100644 --- a/content/upgrades-plugins/foundry/foundry-upgrades.mdx +++ b/content/upgrades-plugins/foundry/foundry-upgrades.mdx @@ -133,12 +133,12 @@ In a Foundry project, you can set this in your project's `.env` file. ## Usage -Depending on which major version of OpenZeppelin Contracts you are using, and whether you want to run upgrade safety validations and/or use OpenZeppelin Defender, use the table below to determine which library to import: +Depending on which major version of OpenZeppelin Contracts you are using, and whether you want to run upgrade safety validations, use the table below to determine which library to import: | | OpenZeppelin Contracts v5 | OpenZeppelin Contracts v4 | | --- | --- | --- | -| **Runs validations, supports Defender** | `import {Upgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol";` | `import {Upgrades} from "openzeppelin-foundry-upgrades/LegacyUpgrades.sol";` | -| **No validations, does not support Defender** | `import {UnsafeUpgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol";` | `import {UnsafeUpgrades} from "openzeppelin-foundry-upgrades/LegacyUpgrades.sol";` | +| **Runs validations** | `import {Upgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol";` | `import {Upgrades} from "openzeppelin-foundry-upgrades/LegacyUpgrades.sol";` | +| **No validations** | `import {UnsafeUpgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol";` | `import {UnsafeUpgrades} from "openzeppelin-foundry-upgrades/LegacyUpgrades.sol";` | Import one of the above libraries in your Foundry scripts or tests, for example: ```solidity @@ -266,10 +266,6 @@ Include the `--sender
` flag for the `forge script` command when perfor Include the `--verify` flag for the `forge script` command if you want to verify source code such as on Etherscan. This will verify your implementation contracts along with any proxy contracts as part of the deployment. -## Usage with Defender - -If you are using OpenZeppelin Defender, see [OpenZeppelin Defender with Foundry](/upgrades-plugins/foundry/foundry-defender) for how to use it for deployments. - ## API See [Foundry Upgrades API](/upgrades-plugins/foundry/api) for the full API documentation. diff --git a/content/upgrades-plugins/hardhat-2/api-hardhat-upgrades.mdx b/content/upgrades-plugins/hardhat-2/api-hardhat-upgrades.mdx index 0cd53fcf..2bb655b7 100644 --- a/content/upgrades-plugins/hardhat-2/api-hardhat-upgrades.mdx +++ b/content/upgrades-plugins/hardhat-2/api-hardhat-upgrades.mdx @@ -36,18 +36,13 @@ The following options are common to some functions. * `timeout`: (`number`) Timeout in milliseconds to wait for the transaction confirmation when deploying an implementation contract. Defaults to `60000`. Use `0` to wait indefinitely. * `pollingInterval`: (`number`) Polling interval in milliseconds between checks for the transaction confirmation when deploying an implementation contract. Defaults to `5000`. * `redeployImplementation`: (`"always" | "never" | "onchange"`) Determines whether the implementation contract will be redeployed. Defaults to `"onchange"`. - * If set to `"always"`, the implementation contract is always redeployed even if it was previously deployed with the same bytecode. This can be used with the `salt` option when deploying a proxy through OpenZeppelin Defender to ensure that the implementation contract is deployed with the same salt as the proxy. + * If set to `"always"`, the implementation contract is always redeployed even if it was previously deployed with the same bytecode. * If set to `"never"`, the implementation contract is never redeployed. If the implementation contract was not previously deployed or is not found in the network file, an error will be thrown. * If set to `"onchange"`, the implementation contract is redeployed only if the bytecode has changed from previous deployments. -* `txOverrides`: (`ethers.Overrides`) An ethers.js [Overrides](https://docs.ethers.org/v6/api/contract/#Overrides) object to override transaction parameters, such as `gasLimit` and `gasPrice`. Applies to all transactions sent by a function with this option, even if the function sends multiple transactions. For OpenZeppelin Defender deployments, only the `gasLimit`, `gasPrice`, `maxFeePerGas`, and `maxPriorityFeePerGas` parameters are supported. -* `useDefenderDeploy`: (`boolean`) Deploy contracts using OpenZeppelin Defender instead of ethers.js. See [Using with OpenZeppelin Defender](/upgrades-plugins/defender-deploy). -* `verifySourceCode`: (`boolean`) When using OpenZeppelin Defender deployments, whether to verify source code on block explorers. Defaults to `true`. -* `relayerId`: (`string`) When using OpenZeppelin Defender deployments, the ID of the relayer to use for the deployment. Defaults to the relayer configured for your deployment environment on Defender. -* `salt`: (`string`) When using OpenZeppelin Defender deployments, if this is not set, deployments will be performed using the CREATE opcode. If this is set, deployments will be performed using the CREATE2 opcode with the provided salt. Note that deployments using a Safe are done using CREATE2 and require a salt. ***Warning:*** CREATE2 affects `msg.sender` behavior. See [Caveats](/defender/tutorial/deploy#caveats) for more information. -* `metadata`: (` commitHash?: string; tag?: string; [k: string]: any; `) When using OpenZeppelin Defender deployments, you can use this to identify, tag, or classify deployments. See [Metadata](/defender/module/deploy#metadata). +* `txOverrides`: (`ethers.Overrides`) An ethers.js [Overrides](https://docs.ethers.org/v6/api/contract/#Overrides) object to override transaction parameters, such as `gasLimit` and `gasPrice`. Applies to all transactions sent by a function with this option, even if the function sends multiple transactions. * `proxyFactory`: (`ethers.ContractFactory`) Customizes the ethers contract factory to use for deploying the proxy, allowing a custom proxy contract to be deployed. See [factories.ts](https://github.com/OpenZeppelin/openzeppelin-upgrades/blob/master/packages/plugin-hardhat/src/utils/factories.ts) for the default contract factory for each kind of proxy. * **Since:** `@openzeppelin/hardhat-upgrades@3.7.0` -* `deployFunction`: (`(hre, opts, factory, ...args) => Promise`) Customizes the function used to deploy the proxy. Can be used along with the `proxyFactory` option to override constructor parameters for custom proxy deployments. See [deploy.ts](https://github.com/OpenZeppelin/openzeppelin-upgrades/blob/master/packages/plugin-hardhat/src/utils/deploy.ts) for the default deploy function. +* `deployFunction`: (`(hre, opts, factory, ...args) => Promise`) Customizes the function used to deploy the proxy. Can be used along with the `proxyFactory` option to override constructor parameters for custom proxy deployments. See [deploy.ts](https://github.com/OpenZeppelin/openzeppelin-upgrades/blob/master/packages/plugin-hardhat/src/utils/deploy.ts) for the default deploy function. `EthersOrDefenderDeployment` is the return type exported by `@openzeppelin/hardhat-upgrades`, kept under its upstream name. * **Since:** `@openzeppelin/hardhat-upgrades@3.7.0` Note that the options `unsafeAllow` can also be specified in a more granular way directly in the source code if using Solidity >=0.8.2. See [How can I disable some of the checks?](/upgrades-plugins/faq#how-can-i-disable-some-of-the-checks) @@ -75,7 +70,6 @@ async function deployProxy( redeployImplementation?: 'always' | 'never' | 'onchange', txOverrides?: ethers.Overrides, kind?: 'uups' | 'transparent', - useDefenderDeploy?: boolean, proxyFactory?: ethers.ContractFactory, deployFunction?: () => Promise, , @@ -212,7 +206,6 @@ async function deployBeaconProxy( opts?: initializer?: string | false, txOverrides?: ethers.Overrides, - useDefenderDeploy?: boolean, proxyFactory?: ethers.ContractFactory, deployFunction?: () => Promise, , @@ -311,7 +304,6 @@ async function deployImplementation( txOverrides?: ethers.Overrides, getTxResponse?: boolean, kind?: 'uups' | 'transparent' | 'beacon', - useDefenderDeploy?: boolean, , ): Promise ``` @@ -397,7 +389,6 @@ async function prepareUpgrade( txOverrides?: ethers.Overrides, getTxResponse?: boolean, kind?: 'uups' | 'transparent' | 'beacon', - useDefenderDeploy?: boolean, , ): Promise ``` @@ -416,127 +407,6 @@ Validates and deploys a new implementation contract, and returns its address. If * the address or an ethers transaction response corresponding to the deployment of the new implementation contract. -## defender.deployContract - -```ts -async function deployContract( - Contract: ethers.ContractFactory, - args: unknown[] = [], - opts?: - unsafeAllowDeployContract?: boolean, - pollingInterval?: number, - , -): Promise -``` - -Deploys a non-upgradeable contract using OpenZeppelin Defender, and returns a contract instance. Throws an error if the contract looks like an implementation contract. - - -Do not use this function to deploy implementations of upgradeable contracts, because upgrade safety validations are not performed with this function. For implementation contracts, use [deployImplementation](#deployimplementation) instead. - - -**Parameters:** - -* `Contract` - an ethers contract factory to use as the contract to deploy. -* `opts` - an object with options: - * `unsafeAllowDeployContract`: if set to `true`, allows the contract to be deployed even if it looks like an implementation contract. Defaults to `false`. - * `pollingInterval`: polling interval in milliseconds between checks for the transaction confirmation when calling `.waitForDeployment()` on the resulting contract instance. Defaults to `5000`. - -**Returns:** - -* the contract instance. - -**Since:** - -* `@openzeppelin/hardhat-upgrades@2.2.0` - -## defender.getDeployApprovalProcess - -```ts -async function getDeployApprovalProcess( -): Promise< - approvalProcessId: string, - address?: string, - viaType?: 'EOA' | 'Contract' | 'Multisig' | 'Safe' | 'Gnosis Multisig' | 'Relayer' | 'Unknown' | 'Timelock Controller' | 'ERC20' | 'Governor' | 'Fireblocks', - > -``` - -Gets the default deploy approval process configured for your deployment environment on OpenZeppelin Defender. - -**Returns:** - -* an object with the default deploy approval process ID and the associated address, such as a Relayer, EOA, or multisig wallet address. - -**Since:** - -* `@openzeppelin/hardhat-upgrades@2.5.0` - -## defender.getUpgradeApprovalProcess - -```ts -async function getUpgradeApprovalProcess( -): Promise< - approvalProcessId: string, - address?: string, - viaType?: 'EOA' | 'Contract' | 'Multisig' | 'Safe' | 'Gnosis Multisig' | 'Relayer' | 'Unknown' | 'Timelock Controller' | 'ERC20' | 'Governor' | 'Fireblocks', - > -``` - -Gets the default upgrade approval process configured for your deployment environment on OpenZeppelin Defender. For example, this is useful for determining the default multisig wallet that you can use in your scripts to assign as the owner of your proxy. - -**Returns:** - -* an object with the default upgrade approval process ID and the associated address, such as a multisig or governor contract address. - -**Since:** - -* `@openzeppelin/hardhat-upgrades@2.5.0` - -## defender.proposeUpgradeWithApproval - -```ts -async function proposeUpgradeWithApproval( - proxyAddress: string, - ImplFactory: ContractFactory, - opts?: - unsafeAllow?: ValidationError[], - unsafeAllowRenames?: boolean, - unsafeSkipStorageCheck?: boolean, - constructorArgs?: unknown[], - timeout?: number, - pollingInterval?: number, - redeployImplementation?: 'always' | 'never' | 'onchange', - kind?: 'uups' | 'transparent' | 'beacon', - useDefenderDeploy?: boolean, - approvalProcessId?: string, - , -): Promise< - proposalId: string, - url: string, - txResponse?: ethers.providers.TransactionResponse, - > -``` - -Proposes an upgrade using an upgrade approval process on OpenZeppelin Defender. - -Similar to `prepareUpgrade`. This method validates and deploys the new implementation contract, but also proposes an upgrade using an upgrade approval process on OpenZeppelin Defender. Supported for UUPS or Transparent proxies. Not currently supported for beacon proxies or beacons. For beacons, use `prepareUpgrade` along with a transaction proposal on Defender to upgrade the beacon to the deployed implementation. - -**Parameters:** - -* `proxyAddress` - the proxy address. -* `ImplFactory` - the new implementation contract. -* `opts` - an object with options: - * `approvalProcessId`: The ID of the upgrade approval process. Defaults to the upgrade approval process configured for your deployment environment on Defender. - * additional options as described in [Common Options](#common-options). - -**Returns:** - -* an object with the Defender proposal ID, the URL of the proposal in Safe App if applicable, and the ethers transaction response corresponding to the deployment of the new implementation contract. Note that if the new implementation contract was originally imported as a result of `forceImport`, the ethers transaction response will be undefined. - -**Since:** - -* `@openzeppelin/hardhat-upgrades@2.2.0` - ## admin.changeProxyAdmin ```ts diff --git a/content/upgrades-plugins/hardhat-2/hardhat-upgrades.mdx b/content/upgrades-plugins/hardhat-2/hardhat-upgrades.mdx index a8c4cd3e..8c420d05 100644 --- a/content/upgrades-plugins/hardhat-2/hardhat-upgrades.mdx +++ b/content/upgrades-plugins/hardhat-2/hardhat-upgrades.mdx @@ -152,10 +152,6 @@ describe("Box", function() }); ``` -## Usage with Defender - -If you are using OpenZeppelin Defender, see [OpenZeppelin Defender with Hardhat](/upgrades-plugins/defender-deploy) for how to use it for deployments. - ## API See [Hardhat Upgrades API](/upgrades-plugins/api-hardhat-upgrades) for the full API documentation. diff --git a/content/upgrades-plugins/hardhat-upgrades.mdx b/content/upgrades-plugins/hardhat-upgrades.mdx index d6a63175..461363ec 100644 --- a/content/upgrades-plugins/hardhat-upgrades.mdx +++ b/content/upgrades-plugins/hardhat-upgrades.mdx @@ -570,10 +570,6 @@ $ npx hardhat compile --force $ npx hardhat test solidity ``` -## Usage with Defender - -If you are using OpenZeppelin Defender, see [OpenZeppelin Defender with Hardhat](/upgrades-plugins/defender-deploy) for how to use it for deployments. - ## API See [Hardhat Upgrades API](/upgrades-plugins/api-hardhat-upgrades) for the full API documentation. diff --git a/content/upgrades-plugins/index.mdx b/content/upgrades-plugins/index.mdx index ce05b334..427f783b 100644 --- a/content/upgrades-plugins/index.mdx +++ b/content/upgrades-plugins/index.mdx @@ -57,4 +57,4 @@ Do not reuse an already deployed `ProxyAdmin`. Before `@openzeppelin/contracts` UUPS and beacon proxies do not use admin addresses. UUPS proxies rely on an [`_authorizeUpgrade`](/contracts/5.x/api/proxy#UUPSUpgradeable-_authorizeUpgrade-address-) function to be overridden to include access restriction to the upgrade mechanism, whereas beacon proxies are upgradable only by the owner of their corresponding beacon. -Once you have transferred the rights to upgrade a proxy or beacon to another address, you can still use your local setup to validate and deploy the implementation contract. The plugins include a `prepareUpgrade` function that will validate that the new implementation is upgrade-safe and compatible with the previous one, and deploy it using your local Ethereum account. You can then execute the upgrade itself from the admin or owner address. You can also use the `defender.proposeUpgrade` or `defender.proposeUpgradeWithApproval` functions to automatically set up the upgrade in [OpenZeppelin Defender](/defender). +Once you have transferred the rights to upgrade a proxy or beacon to another address, you can still use your local setup to validate and deploy the implementation contract. The plugins include a `prepareUpgrade` function that will validate that the new implementation is upgrade-safe and compatible with the previous one, and deploy it using your local Ethereum account. You can then execute the upgrade itself from the admin or owner address. diff --git a/content/upgrades-plugins/migrate-from-hardhat-2.mdx b/content/upgrades-plugins/migrate-from-hardhat-2.mdx index 72d30251..b24f336a 100644 --- a/content/upgrades-plugins/migrate-from-hardhat-2.mdx +++ b/content/upgrades-plugins/migrate-from-hardhat-2.mdx @@ -73,10 +73,10 @@ import '@openzeppelin/hardhat-upgrades'; **After:** ```typescript -import { upgrades, defender } from '@openzeppelin/hardhat-upgrades'; +import { upgrades } from '@openzeppelin/hardhat-upgrades'; ``` -All functions are now exported by the API. Import `upgrades` for standard functions, or `defender` for Defender-specific functions. +All functions are now exported by the API. ### Update Usage @@ -94,7 +94,7 @@ await upgradesApi.deployProxy(MyContract, []); **Important:** -- Both `upgrades` and `defender` receive `hre` and `connection` as parameters: `upgrades(hre, connection)` or `defender(hre, connection)` +- `upgrades` receives `hre` and `connection` as parameters: `upgrades(hre, connection)` - Share the connection across multiple operations; do not create a new one each time (or use `hre.network.getOrCreate()`, which reuses a connection per network) - In tests, create the connection once in a `before` block or use top-level await (ESM) @@ -181,12 +181,11 @@ describe('MyContract', () => { **After (Hardhat 3) - with ESM top-level await:** ```typescript import hre from 'hardhat'; -import { upgrades, defender } from '@openzeppelin/hardhat-upgrades'; +import { upgrades } from '@openzeppelin/hardhat-upgrades'; const connection = await hre.network.create(); const { ethers } = connection; const upgradesApi = await upgrades(hre, connection); -const defenderApi = await defender(hre, connection); describe('MyContract', () => { it('should deploy', async () => { @@ -196,7 +195,7 @@ describe('MyContract', () => { }); ``` -Note: Both `upgrades` and `defender` receive `hre` and `connection` as parameters. +Note: `upgrades` receives `hre` and `connection` as parameters. Hardhat 3 also supports tests written in Solidity. See [Solidity tests](/upgrades-plugins/hardhat-upgrades#solidity-tests) for setup with `@openzeppelin/foundry-upgrades`. @@ -217,9 +216,8 @@ Note that you do not need to include constructor arguments when verifying if you - Install the peer dependencies for the API you use: `@nomicfoundation/hardhat-ethers` and `ethers` for the ethers-based API, or `@nomicfoundation/hardhat-viem` and `viem` if you are using viem - Add `hardhatUpgrades` to `plugins` in `hardhat.config.ts` - If using `verify`, add `hardhatVerify` to `plugins`, install `@nomicfoundation/hardhat-verify`, and configure Hardhat's `verify.etherscan.apiKey` setting -- Replace `import '@openzeppelin/hardhat-upgrades'` → `import { upgrades, defender } from '@openzeppelin/hardhat-upgrades'` in scripts/tests +- Replace `import '@openzeppelin/hardhat-upgrades'` → `import { upgrades } from '@openzeppelin/hardhat-upgrades'` in scripts/tests - Add `const connection = await hre.network.create();` (share connection across operations, don't create new ones) - Replace `hre.ethers` → `ethers` from connection (`const { ethers } = connection`) - Replace `hre.upgrades.method()` → call methods from `const upgradesApi = await upgrades(hre, connection)` -- Replace `hre.defender.method()` → call methods from `const defenderApi = await defender(hre, connection)` - Update all scripts, tasks, and tests diff --git a/netlify.toml b/netlify.toml index 8bcda62b..451e4f8e 100644 --- a/netlify.toml +++ b/netlify.toml @@ -312,6 +312,36 @@ from = "/sdk/*" to = "/" status = 301 +[[redirects]] +from = "/defender/*" +to = "/" +status = 301 + +[[redirects]] +from = "/upgrades-plugins/defender-deploy" +to = "/" +status = 301 + +[[redirects]] +from = "/upgrades-plugins/foundry-defender" +to = "/" +status = 301 + +[[redirects]] +from = "/upgrades-plugins/foundry/foundry-defender" +to = "/" +status = 301 + +[[redirects]] +from = "/upgrades-plugins/foundry/api/Defender" +to = "/" +status = 301 + +[[redirects]] +from = "/upgrades-plugins/foundry/api/defender" +to = "/" +status = 301 + [[redirects]] from = "/openzeppelin/*" to = "/:splat" diff --git a/public/defender/access-control-contract.png b/public/defender/access-control-contract.png deleted file mode 100644 index b3a53318..00000000 Binary files a/public/defender/access-control-contract.png and /dev/null differ diff --git a/public/defender/access-control.png b/public/defender/access-control.png deleted file mode 100644 index efc28fd5..00000000 Binary files a/public/defender/access-control.png and /dev/null differ diff --git a/public/defender/action-migration-2.0.png b/public/defender/action-migration-2.0.png deleted file mode 100644 index 62d30f1a..00000000 Binary files a/public/defender/action-migration-2.0.png and /dev/null differ diff --git a/public/defender/actions-autotask-faq.png b/public/defender/actions-autotask-faq.png deleted file mode 100644 index b9be9a92..00000000 Binary files a/public/defender/actions-autotask-faq.png and /dev/null differ diff --git a/public/defender/actions-parallel-workflow.png b/public/defender/actions-parallel-workflow.png deleted file mode 100644 index e5e4d2af..00000000 Binary files a/public/defender/actions-parallel-workflow.png and /dev/null differ diff --git a/public/defender/actions-start-workflow.png b/public/defender/actions-start-workflow.png deleted file mode 100644 index b9e0bf67..00000000 Binary files a/public/defender/actions-start-workflow.png and /dev/null differ diff --git a/public/defender/actions-workflow.png b/public/defender/actions-workflow.png deleted file mode 100644 index d8b81161..00000000 Binary files a/public/defender/actions-workflow.png and /dev/null differ diff --git a/public/defender/actions.webm b/public/defender/actions.webm deleted file mode 100644 index 59b2de78..00000000 Binary files a/public/defender/actions.webm and /dev/null differ diff --git a/public/defender/address-book-faq.png b/public/defender/address-book-faq.png deleted file mode 100644 index b045cc56..00000000 Binary files a/public/defender/address-book-faq.png and /dev/null differ diff --git a/public/defender/address-book-migration-1.0.png b/public/defender/address-book-migration-1.0.png deleted file mode 100644 index 09bf8823..00000000 Binary files a/public/defender/address-book-migration-1.0.png and /dev/null differ diff --git a/public/defender/address-book-migration-2.0.png b/public/defender/address-book-migration-2.0.png deleted file mode 100644 index bd4be94f..00000000 Binary files a/public/defender/address-book-migration-2.0.png and /dev/null differ diff --git a/public/defender/address-book.webm b/public/defender/address-book.webm deleted file mode 100644 index 115452db..00000000 Binary files a/public/defender/address-book.webm and /dev/null differ diff --git a/public/defender/api-key-expiration-config.png b/public/defender/api-key-expiration-config.png deleted file mode 100644 index ee39ff39..00000000 Binary files a/public/defender/api-key-expiration-config.png and /dev/null differ diff --git a/public/defender/audit-filter.png b/public/defender/audit-filter.png deleted file mode 100644 index 54e3115a..00000000 Binary files a/public/defender/audit-filter.png and /dev/null differ diff --git a/public/defender/audit-new-issue.png b/public/defender/audit-new-issue.png deleted file mode 100644 index fbf752c5..00000000 Binary files a/public/defender/audit-new-issue.png and /dev/null differ diff --git a/public/defender/audit-reply-issue.png b/public/defender/audit-reply-issue.png deleted file mode 100644 index 43529c3c..00000000 Binary files a/public/defender/audit-reply-issue.png and /dev/null differ diff --git a/public/defender/audit-side.png b/public/defender/audit-side.png deleted file mode 100644 index 13be5875..00000000 Binary files a/public/defender/audit-side.png and /dev/null differ diff --git a/public/defender/audit-status.png b/public/defender/audit-status.png deleted file mode 100644 index 5b5de4d5..00000000 Binary files a/public/defender/audit-status.png and /dev/null differ diff --git a/public/defender/audit-trail.png b/public/defender/audit-trail.png deleted file mode 100644 index 5520302a..00000000 Binary files a/public/defender/audit-trail.png and /dev/null differ diff --git a/public/defender/auto-action-general-info.png b/public/defender/auto-action-general-info.png deleted file mode 100644 index ae7c5070..00000000 Binary files a/public/defender/auto-action-general-info.png and /dev/null differ diff --git a/public/defender/autotasks-migration-1.0.png b/public/defender/autotasks-migration-1.0.png deleted file mode 100644 index af56afa2..00000000 Binary files a/public/defender/autotasks-migration-1.0.png and /dev/null differ diff --git a/public/defender/code-assets.png b/public/defender/code-assets.png deleted file mode 100644 index 8ff115eb..00000000 Binary files a/public/defender/code-assets.png and /dev/null differ diff --git a/public/defender/code-report-summary.png b/public/defender/code-report-summary.png deleted file mode 100644 index a9c42ab8..00000000 Binary files a/public/defender/code-report-summary.png and /dev/null differ diff --git a/public/defender/code-settings-advanced.png b/public/defender/code-settings-advanced.png deleted file mode 100644 index 67494491..00000000 Binary files a/public/defender/code-settings-advanced.png and /dev/null differ diff --git a/public/defender/code-settings-repositories.png b/public/defender/code-settings-repositories.png deleted file mode 100644 index e4a46f8e..00000000 Binary files a/public/defender/code-settings-repositories.png and /dev/null differ diff --git a/public/defender/contract-inspector-detailed-report.png b/public/defender/contract-inspector-detailed-report.png deleted file mode 100644 index 992db43d..00000000 Binary files a/public/defender/contract-inspector-detailed-report.png and /dev/null differ diff --git a/public/defender/dependency-checker-detailed-report.png b/public/defender/dependency-checker-detailed-report.png deleted file mode 100644 index 0142e16f..00000000 Binary files a/public/defender/dependency-checker-detailed-report.png and /dev/null differ diff --git a/public/defender/deploy-metadata-1.0.png b/public/defender/deploy-metadata-1.0.png deleted file mode 100644 index 73bfe7f4..00000000 Binary files a/public/defender/deploy-metadata-1.0.png and /dev/null differ diff --git a/public/defender/feedback-button.png b/public/defender/feedback-button.png deleted file mode 100644 index 339b2fe1..00000000 Binary files a/public/defender/feedback-button.png and /dev/null differ diff --git a/public/defender/feedback-form.png b/public/defender/feedback-form.png deleted file mode 100644 index de9358e4..00000000 Binary files a/public/defender/feedback-form.png and /dev/null differ diff --git a/public/defender/guide-configure-private-network.png b/public/defender/guide-configure-private-network.png deleted file mode 100644 index 5cfa3e02..00000000 Binary files a/public/defender/guide-configure-private-network.png and /dev/null differ diff --git a/public/defender/guide-edit-private-network.png b/public/defender/guide-edit-private-network.png deleted file mode 100644 index 32b17957..00000000 Binary files a/public/defender/guide-edit-private-network.png and /dev/null differ diff --git a/public/defender/guide-factory-action-run-history.png b/public/defender/guide-factory-action-run-history.png deleted file mode 100644 index a5f2b870..00000000 Binary files a/public/defender/guide-factory-action-run-history.png and /dev/null differ diff --git a/public/defender/guide-factory-api.png b/public/defender/guide-factory-api.png deleted file mode 100644 index daf9ca32..00000000 Binary files a/public/defender/guide-factory-api.png and /dev/null differ diff --git a/public/defender/guide-factory-create-action.png b/public/defender/guide-factory-create-action.png deleted file mode 100644 index d46b5270..00000000 Binary files a/public/defender/guide-factory-create-action.png and /dev/null differ diff --git a/public/defender/guide-factory-create-clone.png b/public/defender/guide-factory-create-clone.png deleted file mode 100644 index ea5d3aa2..00000000 Binary files a/public/defender/guide-factory-create-clone.png and /dev/null differ diff --git a/public/defender/guide-factory-monitor-alerts.png b/public/defender/guide-factory-monitor-alerts.png deleted file mode 100644 index 32a40968..00000000 Binary files a/public/defender/guide-factory-monitor-alerts.png and /dev/null differ diff --git a/public/defender/guide-factory-monitor-clones.png b/public/defender/guide-factory-monitor-clones.png deleted file mode 100644 index 80d3040b..00000000 Binary files a/public/defender/guide-factory-monitor-clones.png and /dev/null differ diff --git a/public/defender/guide-factory-monitor-events.png b/public/defender/guide-factory-monitor-events.png deleted file mode 100644 index df18aba7..00000000 Binary files a/public/defender/guide-factory-monitor-events.png and /dev/null differ diff --git a/public/defender/guide-factory-monitor-general-information.png b/public/defender/guide-factory-monitor-general-information.png deleted file mode 100644 index 108cb6a4..00000000 Binary files a/public/defender/guide-factory-monitor-general-information.png and /dev/null differ diff --git a/public/defender/guide-factory-secrets.png b/public/defender/guide-factory-secrets.png deleted file mode 100644 index eb298af1..00000000 Binary files a/public/defender/guide-factory-secrets.png and /dev/null differ diff --git a/public/defender/guide-fireblock-paste-api-key.png b/public/defender/guide-fireblock-paste-api-key.png deleted file mode 100644 index 3f86465c..00000000 Binary files a/public/defender/guide-fireblock-paste-api-key.png and /dev/null differ diff --git a/public/defender/guide-fireblocks-add-user.png b/public/defender/guide-fireblocks-add-user.png deleted file mode 100644 index 3900b833..00000000 Binary files a/public/defender/guide-fireblocks-add-user.png and /dev/null differ diff --git a/public/defender/guide-fireblocks-api-key.png b/public/defender/guide-fireblocks-api-key.png deleted file mode 100644 index 02ba22af..00000000 Binary files a/public/defender/guide-fireblocks-api-key.png and /dev/null differ diff --git a/public/defender/guide-fireblocks-approval-process-automatic.png b/public/defender/guide-fireblocks-approval-process-automatic.png deleted file mode 100644 index 29507dc8..00000000 Binary files a/public/defender/guide-fireblocks-approval-process-automatic.png and /dev/null differ diff --git a/public/defender/guide-fireblocks-approval-process-manual.png b/public/defender/guide-fireblocks-approval-process-manual.png deleted file mode 100644 index 5148c602..00000000 Binary files a/public/defender/guide-fireblocks-approval-process-manual.png and /dev/null differ diff --git a/public/defender/guide-fireblocks-asset-wallet-address.png b/public/defender/guide-fireblocks-asset-wallet-address.png deleted file mode 100644 index 33a3b6f2..00000000 Binary files a/public/defender/guide-fireblocks-asset-wallet-address.png and /dev/null differ diff --git a/public/defender/guide-fireblocks-csr-modal.png b/public/defender/guide-fireblocks-csr-modal.png deleted file mode 100644 index afc85eef..00000000 Binary files a/public/defender/guide-fireblocks-csr-modal.png and /dev/null differ diff --git a/public/defender/guide-fireblocks-edit-api-key.png b/public/defender/guide-fireblocks-edit-api-key.png deleted file mode 100644 index 43c15f54..00000000 Binary files a/public/defender/guide-fireblocks-edit-api-key.png and /dev/null differ diff --git a/public/defender/guide-fireblocks-integration-tab.png b/public/defender/guide-fireblocks-integration-tab.png deleted file mode 100644 index a593a6d5..00000000 Binary files a/public/defender/guide-fireblocks-integration-tab.png and /dev/null differ diff --git a/public/defender/guide-fireblocks-vault-id.png b/public/defender/guide-fireblocks-vault-id.png deleted file mode 100644 index 73de939a..00000000 Binary files a/public/defender/guide-fireblocks-vault-id.png and /dev/null differ diff --git a/public/defender/guide-forta-diagram.png b/public/defender/guide-forta-diagram.png deleted file mode 100644 index 6d342c5f..00000000 Binary files a/public/defender/guide-forta-diagram.png and /dev/null differ diff --git a/public/defender/guide-fund-private-network-relayer.png b/public/defender/guide-fund-private-network-relayer.png deleted file mode 100644 index 5f8cf711..00000000 Binary files a/public/defender/guide-fund-private-network-relayer.png and /dev/null differ diff --git a/public/defender/guide-meta-tx-copy-webhook.png b/public/defender/guide-meta-tx-copy-webhook.png deleted file mode 100644 index 0ab30776..00000000 Binary files a/public/defender/guide-meta-tx-copy-webhook.png and /dev/null differ diff --git a/public/defender/guide-profile-disable-system-notifications.png b/public/defender/guide-profile-disable-system-notifications.png deleted file mode 100644 index cc76af3d..00000000 Binary files a/public/defender/guide-profile-disable-system-notifications.png and /dev/null differ diff --git a/public/defender/guide-subgraph-private-network.png b/public/defender/guide-subgraph-private-network.png deleted file mode 100644 index a22b0a37..00000000 Binary files a/public/defender/guide-subgraph-private-network.png and /dev/null differ diff --git a/public/defender/guide-tenderly-private-network.png b/public/defender/guide-tenderly-private-network.png deleted file mode 100644 index 0a347cf8..00000000 Binary files a/public/defender/guide-tenderly-private-network.png and /dev/null differ diff --git a/public/defender/guide-timelock-proposer.png b/public/defender/guide-timelock-proposer.png deleted file mode 100644 index 4025337a..00000000 Binary files a/public/defender/guide-timelock-proposer.png and /dev/null differ diff --git a/public/defender/guide-timelock-role-receiver.png b/public/defender/guide-timelock-role-receiver.png deleted file mode 100644 index ff24b503..00000000 Binary files a/public/defender/guide-timelock-role-receiver.png and /dev/null differ diff --git a/public/defender/guide-timelock-role-remover.png b/public/defender/guide-timelock-role-remover.png deleted file mode 100644 index c10197af..00000000 Binary files a/public/defender/guide-timelock-role-remover.png and /dev/null differ diff --git a/public/defender/guide-timelock-role-revoked.png b/public/defender/guide-timelock-role-revoked.png deleted file mode 100644 index d1b218a2..00000000 Binary files a/public/defender/guide-timelock-role-revoked.png and /dev/null differ diff --git a/public/defender/guide-timelock-roles-add-contract.png b/public/defender/guide-timelock-roles-add-contract.png deleted file mode 100644 index 4cd28dc0..00000000 Binary files a/public/defender/guide-timelock-roles-add-contract.png and /dev/null differ diff --git a/public/defender/guide-timelock-roles-general-information.png b/public/defender/guide-timelock-roles-general-information.png deleted file mode 100644 index b0357c7d..00000000 Binary files a/public/defender/guide-timelock-roles-general-information.png and /dev/null differ diff --git a/public/defender/guide-timelock-roles-grant.png b/public/defender/guide-timelock-roles-grant.png deleted file mode 100644 index 7e449d9c..00000000 Binary files a/public/defender/guide-timelock-roles-grant.png and /dev/null differ diff --git a/public/defender/guide-timelock-roles-granted.png b/public/defender/guide-timelock-roles-granted.png deleted file mode 100644 index 6a64d4d5..00000000 Binary files a/public/defender/guide-timelock-roles-granted.png and /dev/null differ diff --git a/public/defender/guide-timelock-roles-schedule.png b/public/defender/guide-timelock-roles-schedule.png deleted file mode 100644 index dd23714b..00000000 Binary files a/public/defender/guide-timelock-roles-schedule.png and /dev/null differ diff --git a/public/defender/guide-timelock-roles.png b/public/defender/guide-timelock-roles.png deleted file mode 100644 index 97502501..00000000 Binary files a/public/defender/guide-timelock-roles.png and /dev/null differ diff --git a/public/defender/guide-usage-notifications-all.png b/public/defender/guide-usage-notifications-all.png deleted file mode 100644 index c53506ce..00000000 Binary files a/public/defender/guide-usage-notifications-all.png and /dev/null differ diff --git a/public/defender/guide-usage-notifications-create.png b/public/defender/guide-usage-notifications-create.png deleted file mode 100644 index 7406b447..00000000 Binary files a/public/defender/guide-usage-notifications-create.png and /dev/null differ diff --git a/public/defender/guide-usage-notifications-edit-menu.png b/public/defender/guide-usage-notifications-edit-menu.png deleted file mode 100644 index a61715e6..00000000 Binary files a/public/defender/guide-usage-notifications-edit-menu.png and /dev/null differ diff --git a/public/defender/guide-usage-notifications-system-unmetered.png b/public/defender/guide-usage-notifications-system-unmetered.png deleted file mode 100644 index 11f2d7fc..00000000 Binary files a/public/defender/guide-usage-notifications-system-unmetered.png and /dev/null differ diff --git a/public/defender/guide-usage-notifications-system.png b/public/defender/guide-usage-notifications-system.png deleted file mode 100644 index 3847240b..00000000 Binary files a/public/defender/guide-usage-notifications-system.png and /dev/null differ diff --git a/public/defender/logs-detailed.png b/public/defender/logs-detailed.png deleted file mode 100644 index c3a53eb0..00000000 Binary files a/public/defender/logs-detailed.png and /dev/null differ diff --git a/public/defender/logs-migration-1.0.png b/public/defender/logs-migration-1.0.png deleted file mode 100644 index 68068a85..00000000 Binary files a/public/defender/logs-migration-1.0.png and /dev/null differ diff --git a/public/defender/logs-migration-2.0.png b/public/defender/logs-migration-2.0.png deleted file mode 100644 index 1f70f794..00000000 Binary files a/public/defender/logs-migration-2.0.png and /dev/null differ diff --git a/public/defender/logs.png b/public/defender/logs.png deleted file mode 100644 index ea8052cf..00000000 Binary files a/public/defender/logs.png and /dev/null differ diff --git a/public/defender/manage-address-book.png b/public/defender/manage-address-book.png deleted file mode 100644 index 4ac56432..00000000 Binary files a/public/defender/manage-address-book.png and /dev/null differ diff --git a/public/defender/manage-advanced-export-serverless.png b/public/defender/manage-advanced-export-serverless.png deleted file mode 100644 index 1267d230..00000000 Binary files a/public/defender/manage-advanced-export-serverless.png and /dev/null differ diff --git a/public/defender/manage-api-key-v2.png b/public/defender/manage-api-key-v2.png deleted file mode 100644 index b5260a8c..00000000 Binary files a/public/defender/manage-api-key-v2.png and /dev/null differ diff --git a/public/defender/manage-api-key.png b/public/defender/manage-api-key.png deleted file mode 100644 index ea4494ff..00000000 Binary files a/public/defender/manage-api-key.png and /dev/null differ diff --git a/public/defender/manage-approvals.png b/public/defender/manage-approvals.png deleted file mode 100644 index 0b13000c..00000000 Binary files a/public/defender/manage-approvals.png and /dev/null differ diff --git a/public/defender/manage-forked-networks-create.png b/public/defender/manage-forked-networks-create.png deleted file mode 100644 index b847425a..00000000 Binary files a/public/defender/manage-forked-networks-create.png and /dev/null differ diff --git a/public/defender/manage-forked-networks-selection.png b/public/defender/manage-forked-networks-selection.png deleted file mode 100644 index 144526aa..00000000 Binary files a/public/defender/manage-forked-networks-selection.png and /dev/null differ diff --git a/public/defender/manage-new-api-key-v2.png b/public/defender/manage-new-api-key-v2.png deleted file mode 100644 index be26bd93..00000000 Binary files a/public/defender/manage-new-api-key-v2.png and /dev/null differ diff --git a/public/defender/manage-new-api-key.png b/public/defender/manage-new-api-key.png deleted file mode 100644 index 77a1f3b3..00000000 Binary files a/public/defender/manage-new-api-key.png and /dev/null differ diff --git a/public/defender/manage-notify-channels.png b/public/defender/manage-notify-channels.png deleted file mode 100644 index b27929f0..00000000 Binary files a/public/defender/manage-notify-channels.png and /dev/null differ diff --git a/public/defender/manage-notify-datadog.png b/public/defender/manage-notify-datadog.png deleted file mode 100644 index 910c04f5..00000000 Binary files a/public/defender/manage-notify-datadog.png and /dev/null differ diff --git a/public/defender/manage-notify-discord.png b/public/defender/manage-notify-discord.png deleted file mode 100644 index 8908a3d4..00000000 Binary files a/public/defender/manage-notify-discord.png and /dev/null differ diff --git a/public/defender/manage-notify-telegram.png b/public/defender/manage-notify-telegram.png deleted file mode 100644 index 5312bcf4..00000000 Binary files a/public/defender/manage-notify-telegram.png and /dev/null differ diff --git a/public/defender/manage-notify-webhook.png b/public/defender/manage-notify-webhook.png deleted file mode 100644 index 00c37c44..00000000 Binary files a/public/defender/manage-notify-webhook.png and /dev/null differ diff --git a/public/defender/manage-private-networks-create.png b/public/defender/manage-private-networks-create.png deleted file mode 100644 index 09cec0bf..00000000 Binary files a/public/defender/manage-private-networks-create.png and /dev/null differ diff --git a/public/defender/manage-private-networks-selection.png b/public/defender/manage-private-networks-selection.png deleted file mode 100644 index dc5e16e9..00000000 Binary files a/public/defender/manage-private-networks-selection.png and /dev/null differ diff --git a/public/defender/manage-relayer-api-key.png b/public/defender/manage-relayer-api-key.png deleted file mode 100644 index 0745d3a8..00000000 Binary files a/public/defender/manage-relayer-api-key.png and /dev/null differ diff --git a/public/defender/manage-relayer-policies.png b/public/defender/manage-relayer-policies.png deleted file mode 100644 index 81dec267..00000000 Binary files a/public/defender/manage-relayer-policies.png and /dev/null differ diff --git a/public/defender/manage-relayers-create-api-key.png b/public/defender/manage-relayers-create-api-key.png deleted file mode 100644 index 42079dda..00000000 Binary files a/public/defender/manage-relayers-create-api-key.png and /dev/null differ diff --git a/public/defender/manage-relayers-detail.png b/public/defender/manage-relayers-detail.png deleted file mode 100644 index 6a7fd6ff..00000000 Binary files a/public/defender/manage-relayers-detail.png and /dev/null differ diff --git a/public/defender/manage-relayers.png b/public/defender/manage-relayers.png deleted file mode 100644 index a0b0f16c..00000000 Binary files a/public/defender/manage-relayers.png and /dev/null differ diff --git a/public/defender/manage-role-create.png b/public/defender/manage-role-create.png deleted file mode 100644 index 738c667b..00000000 Binary files a/public/defender/manage-role-create.png and /dev/null differ diff --git a/public/defender/manage-secrets.png b/public/defender/manage-secrets.png deleted file mode 100644 index b1224c7e..00000000 Binary files a/public/defender/manage-secrets.png and /dev/null differ diff --git a/public/defender/manage-team-invite.png b/public/defender/manage-team-invite.png deleted file mode 100644 index 2429b8d4..00000000 Binary files a/public/defender/manage-team-invite.png and /dev/null differ diff --git a/public/defender/monitor-alert-v2.png b/public/defender/monitor-alert-v2.png deleted file mode 100644 index 5c18f3d9..00000000 Binary files a/public/defender/monitor-alert-v2.png and /dev/null differ diff --git a/public/defender/monitor-alert.png b/public/defender/monitor-alert.png deleted file mode 100644 index 105bb495..00000000 Binary files a/public/defender/monitor-alert.png and /dev/null differ diff --git a/public/defender/monitor-migration-2.0.png b/public/defender/monitor-migration-2.0.png deleted file mode 100644 index d0542aa3..00000000 Binary files a/public/defender/monitor-migration-2.0.png and /dev/null differ diff --git a/public/defender/monitor-migration-button.png b/public/defender/monitor-migration-button.png deleted file mode 100644 index d627fd70..00000000 Binary files a/public/defender/monitor-migration-button.png and /dev/null differ diff --git a/public/defender/monitor-migration-information.png b/public/defender/monitor-migration-information.png deleted file mode 100644 index 764f4ebd..00000000 Binary files a/public/defender/monitor-migration-information.png and /dev/null differ diff --git a/public/defender/monitor-settings.png b/public/defender/monitor-settings.png deleted file mode 100644 index 7b3087cc..00000000 Binary files a/public/defender/monitor-settings.png and /dev/null differ diff --git a/public/defender/monitor-templates.png b/public/defender/monitor-templates.png deleted file mode 100644 index 880c8a22..00000000 Binary files a/public/defender/monitor-templates.png and /dev/null differ diff --git a/public/defender/monitor.webm b/public/defender/monitor.webm deleted file mode 100644 index 5af09550..00000000 Binary files a/public/defender/monitor.webm and /dev/null differ diff --git a/public/defender/monitors-sentinels-faq.png b/public/defender/monitors-sentinels-faq.png deleted file mode 100644 index f56eadf4..00000000 Binary files a/public/defender/monitors-sentinels-faq.png and /dev/null differ diff --git a/public/defender/notification-channel-setup-1.0.png b/public/defender/notification-channel-setup-1.0.png deleted file mode 100644 index 5c4fc769..00000000 Binary files a/public/defender/notification-channel-setup-1.0.png and /dev/null differ diff --git a/public/defender/notification-channel-setup-2.0.png b/public/defender/notification-channel-setup-2.0.png deleted file mode 100644 index 737e61ef..00000000 Binary files a/public/defender/notification-channel-setup-2.0.png and /dev/null differ diff --git a/public/defender/proposal-migration-1.0.png b/public/defender/proposal-migration-1.0.png deleted file mode 100644 index 56641a84..00000000 Binary files a/public/defender/proposal-migration-1.0.png and /dev/null differ diff --git a/public/defender/proposal-migration-2.0.png b/public/defender/proposal-migration-2.0.png deleted file mode 100644 index 48d9dd6f..00000000 Binary files a/public/defender/proposal-migration-2.0.png and /dev/null differ diff --git a/public/defender/proposal.webm b/public/defender/proposal.webm deleted file mode 100644 index aaf5461c..00000000 Binary files a/public/defender/proposal.webm and /dev/null differ diff --git a/public/defender/relayer-mempool-visibility-check.png b/public/defender/relayer-mempool-visibility-check.png deleted file mode 100644 index 118c6f5e..00000000 Binary files a/public/defender/relayer-mempool-visibility-check.png and /dev/null differ diff --git a/public/defender/relayer-migration-button.png b/public/defender/relayer-migration-button.png deleted file mode 100644 index 14181659..00000000 Binary files a/public/defender/relayer-migration-button.png and /dev/null differ diff --git a/public/defender/relayer-withdraw-screen.png b/public/defender/relayer-withdraw-screen.png deleted file mode 100644 index 62a74a2b..00000000 Binary files a/public/defender/relayer-withdraw-screen.png and /dev/null differ diff --git a/public/defender/relayer-withdraw.png b/public/defender/relayer-withdraw.png deleted file mode 100644 index de2d203e..00000000 Binary files a/public/defender/relayer-withdraw.png and /dev/null differ diff --git a/public/defender/relayers-faq.png b/public/defender/relayers-faq.png deleted file mode 100644 index 3ce0a62a..00000000 Binary files a/public/defender/relayers-faq.png and /dev/null differ diff --git a/public/defender/relayers-migration-1.0.png b/public/defender/relayers-migration-1.0.png deleted file mode 100644 index 43fa267e..00000000 Binary files a/public/defender/relayers-migration-1.0.png and /dev/null differ diff --git a/public/defender/relayers-migration-2.0.png b/public/defender/relayers-migration-2.0.png deleted file mode 100644 index 7f5119be..00000000 Binary files a/public/defender/relayers-migration-2.0.png and /dev/null differ diff --git a/public/defender/relayers.webm b/public/defender/relayers.webm deleted file mode 100644 index 529a9e15..00000000 Binary files a/public/defender/relayers.webm and /dev/null differ diff --git a/public/defender/remix-plugin-api-key.png b/public/defender/remix-plugin-api-key.png deleted file mode 100644 index 76ab8a8a..00000000 Binary files a/public/defender/remix-plugin-api-key.png and /dev/null differ diff --git a/public/defender/remix-plugin-approval-process.png b/public/defender/remix-plugin-approval-process.png deleted file mode 100644 index 290fa5f3..00000000 Binary files a/public/defender/remix-plugin-approval-process.png and /dev/null differ diff --git a/public/defender/remix-plugin-deploy-completed.png b/public/defender/remix-plugin-deploy-completed.png deleted file mode 100644 index 6eff5246..00000000 Binary files a/public/defender/remix-plugin-deploy-completed.png and /dev/null differ diff --git a/public/defender/remix-plugin-deploy-deterministic.png b/public/defender/remix-plugin-deploy-deterministic.png deleted file mode 100644 index 22409470..00000000 Binary files a/public/defender/remix-plugin-deploy-deterministic.png and /dev/null differ diff --git a/public/defender/remix-plugin-deploy.png b/public/defender/remix-plugin-deploy.png deleted file mode 100644 index 244af1dc..00000000 Binary files a/public/defender/remix-plugin-deploy.png and /dev/null differ diff --git a/public/defender/remix-plugin-install.png b/public/defender/remix-plugin-install.png deleted file mode 100644 index 09b832f3..00000000 Binary files a/public/defender/remix-plugin-install.png and /dev/null differ diff --git a/public/defender/remix-plugin-network.png b/public/defender/remix-plugin-network.png deleted file mode 100644 index c259712f..00000000 Binary files a/public/defender/remix-plugin-network.png and /dev/null differ diff --git a/public/defender/remix-plugin-setup.png b/public/defender/remix-plugin-setup.png deleted file mode 100644 index 684457ac..00000000 Binary files a/public/defender/remix-plugin-setup.png and /dev/null differ diff --git a/public/defender/safe-migration-1.0.png b/public/defender/safe-migration-1.0.png deleted file mode 100644 index b9ebb409..00000000 Binary files a/public/defender/safe-migration-1.0.png and /dev/null differ diff --git a/public/defender/secrets-migration-1.0.png b/public/defender/secrets-migration-1.0.png deleted file mode 100644 index 5565677a..00000000 Binary files a/public/defender/secrets-migration-1.0.png and /dev/null differ diff --git a/public/defender/secrets-migration-2.0.png b/public/defender/secrets-migration-2.0.png deleted file mode 100644 index e1c0c8db..00000000 Binary files a/public/defender/secrets-migration-2.0.png and /dev/null differ diff --git a/public/defender/sentinel-migration-1.0.png b/public/defender/sentinel-migration-1.0.png deleted file mode 100644 index e54581de..00000000 Binary files a/public/defender/sentinel-migration-1.0.png and /dev/null differ diff --git a/public/defender/switch-back-faq.png b/public/defender/switch-back-faq.png deleted file mode 100644 index fcedf4cf..00000000 Binary files a/public/defender/switch-back-faq.png and /dev/null differ diff --git a/public/defender/tenant-migration-1.0.png b/public/defender/tenant-migration-1.0.png deleted file mode 100644 index 62d86ccb..00000000 Binary files a/public/defender/tenant-migration-1.0.png and /dev/null differ diff --git a/public/defender/tenant-migration-2.0.png b/public/defender/tenant-migration-2.0.png deleted file mode 100644 index b76c5800..00000000 Binary files a/public/defender/tenant-migration-2.0.png and /dev/null differ diff --git a/public/defender/timelock-migration-1.0.png b/public/defender/timelock-migration-1.0.png deleted file mode 100644 index 484bfe30..00000000 Binary files a/public/defender/timelock-migration-1.0.png and /dev/null differ diff --git a/public/defender/transaction-proposals-faq.png b/public/defender/transaction-proposals-faq.png deleted file mode 100644 index 234363d9..00000000 Binary files a/public/defender/transaction-proposals-faq.png and /dev/null differ diff --git a/public/defender/tutorial-access-control-add.gif b/public/defender/tutorial-access-control-add.gif deleted file mode 100644 index 002020b7..00000000 Binary files a/public/defender/tutorial-access-control-add.gif and /dev/null differ diff --git a/public/defender/tutorial-access-control-copy-address.png b/public/defender/tutorial-access-control-copy-address.png deleted file mode 100644 index 6382d6a8..00000000 Binary files a/public/defender/tutorial-access-control-copy-address.png and /dev/null differ diff --git a/public/defender/tutorial-access-control-factory.png b/public/defender/tutorial-access-control-factory.png deleted file mode 100644 index 98f7f5ed..00000000 Binary files a/public/defender/tutorial-access-control-factory.png and /dev/null differ diff --git a/public/defender/tutorial-access-control-page.gif b/public/defender/tutorial-access-control-page.gif deleted file mode 100644 index ee62c005..00000000 Binary files a/public/defender/tutorial-access-control-page.gif and /dev/null differ diff --git a/public/defender/tutorial-access-control-submit-proposal.gif b/public/defender/tutorial-access-control-submit-proposal.gif deleted file mode 100644 index 352e5b3d..00000000 Binary files a/public/defender/tutorial-access-control-submit-proposal.gif and /dev/null differ diff --git a/public/defender/tutorial-access-control-submit-tx.gif b/public/defender/tutorial-access-control-submit-tx.gif deleted file mode 100644 index 3577a2ad..00000000 Binary files a/public/defender/tutorial-access-control-submit-tx.gif and /dev/null differ diff --git a/public/defender/tutorial-access-control-tx-general.png b/public/defender/tutorial-access-control-tx-general.png deleted file mode 100644 index 40c9c04f..00000000 Binary files a/public/defender/tutorial-access-control-tx-general.png and /dev/null differ diff --git a/public/defender/tutorial-actions-action.png b/public/defender/tutorial-actions-action.png deleted file mode 100644 index 0427fde7..00000000 Binary files a/public/defender/tutorial-actions-action.png and /dev/null differ diff --git a/public/defender/tutorial-actions-alert.png b/public/defender/tutorial-actions-alert.png deleted file mode 100644 index de55d4d2..00000000 Binary files a/public/defender/tutorial-actions-alert.png and /dev/null differ diff --git a/public/defender/tutorial-deploy-block-explorer.png b/public/defender/tutorial-deploy-block-explorer.png deleted file mode 100644 index 29041be4..00000000 Binary files a/public/defender/tutorial-deploy-block-explorer.png and /dev/null differ diff --git a/public/defender/tutorial-deploy-contract.png b/public/defender/tutorial-deploy-contract.png deleted file mode 100644 index 2b9c99a3..00000000 Binary files a/public/defender/tutorial-deploy-contract.png and /dev/null differ diff --git a/public/defender/tutorial-deploy-copy-relayer.png b/public/defender/tutorial-deploy-copy-relayer.png deleted file mode 100644 index e47b88e0..00000000 Binary files a/public/defender/tutorial-deploy-copy-relayer.png and /dev/null differ diff --git a/public/defender/tutorial-deploy-directory.png b/public/defender/tutorial-deploy-directory.png deleted file mode 100644 index 9033fa6d..00000000 Binary files a/public/defender/tutorial-deploy-directory.png and /dev/null differ diff --git a/public/defender/tutorial-deploy-end-wizard.png b/public/defender/tutorial-deploy-end-wizard.png deleted file mode 100644 index b9d818fa..00000000 Binary files a/public/defender/tutorial-deploy-end-wizard.png and /dev/null differ diff --git a/public/defender/tutorial-deploy-environments.png b/public/defender/tutorial-deploy-environments.png deleted file mode 100644 index 5bce0b38..00000000 Binary files a/public/defender/tutorial-deploy-environments.png and /dev/null differ diff --git a/public/defender/tutorial-deploy-executed-upgrade.png b/public/defender/tutorial-deploy-executed-upgrade.png deleted file mode 100644 index 19434017..00000000 Binary files a/public/defender/tutorial-deploy-executed-upgrade.png and /dev/null differ diff --git a/public/defender/tutorial-deploy-networks.png b/public/defender/tutorial-deploy-networks.png deleted file mode 100644 index 68fde15f..00000000 Binary files a/public/defender/tutorial-deploy-networks.png and /dev/null differ diff --git a/public/defender/tutorial-deploy-relayer-wizard.png b/public/defender/tutorial-deploy-relayer-wizard.png deleted file mode 100644 index f41db288..00000000 Binary files a/public/defender/tutorial-deploy-relayer-wizard.png and /dev/null differ diff --git a/public/defender/tutorial-deploy-safe.png b/public/defender/tutorial-deploy-safe.png deleted file mode 100644 index d1f99bb7..00000000 Binary files a/public/defender/tutorial-deploy-safe.png and /dev/null differ diff --git a/public/defender/tutorial-deploy-step1-wizard.png b/public/defender/tutorial-deploy-step1-wizard.png deleted file mode 100644 index 0354542f..00000000 Binary files a/public/defender/tutorial-deploy-step1-wizard.png and /dev/null differ diff --git a/public/defender/tutorial-deploy-step2-wizard.png b/public/defender/tutorial-deploy-step2-wizard.png deleted file mode 100644 index cbaf0200..00000000 Binary files a/public/defender/tutorial-deploy-step2-wizard.png and /dev/null differ diff --git a/public/defender/tutorial-deploy-step3-wizard.png b/public/defender/tutorial-deploy-step3-wizard.png deleted file mode 100644 index 266717e1..00000000 Binary files a/public/defender/tutorial-deploy-step3-wizard.png and /dev/null differ diff --git a/public/defender/tutorial-deploy-step4-wizard.png b/public/defender/tutorial-deploy-step4-wizard.png deleted file mode 100644 index e9499152..00000000 Binary files a/public/defender/tutorial-deploy-step4-wizard.png and /dev/null differ diff --git a/public/defender/tutorial-deploy-upgrade-wizard.png b/public/defender/tutorial-deploy-upgrade-wizard.png deleted file mode 100644 index a316dcf1..00000000 Binary files a/public/defender/tutorial-deploy-upgrade-wizard.png and /dev/null differ diff --git a/public/defender/tutorial-forked-network-phalcon-create.png b/public/defender/tutorial-forked-network-phalcon-create.png deleted file mode 100644 index f0a52763..00000000 Binary files a/public/defender/tutorial-forked-network-phalcon-create.png and /dev/null differ diff --git a/public/defender/tutorial-forked-networks-create.png b/public/defender/tutorial-forked-networks-create.png deleted file mode 100644 index c97a9709..00000000 Binary files a/public/defender/tutorial-forked-networks-create.png and /dev/null differ diff --git a/public/defender/tutorial-forked-networks-deploy-intro.png b/public/defender/tutorial-forked-networks-deploy-intro.png deleted file mode 100644 index 3578ddd0..00000000 Binary files a/public/defender/tutorial-forked-networks-deploy-intro.png and /dev/null differ diff --git a/public/defender/tutorial-forked-networks-deploy-wizard-step1.png b/public/defender/tutorial-forked-networks-deploy-wizard-step1.png deleted file mode 100644 index c881416e..00000000 Binary files a/public/defender/tutorial-forked-networks-deploy-wizard-step1.png and /dev/null differ diff --git a/public/defender/tutorial-forked-networks-deploy-wizard-step2.png b/public/defender/tutorial-forked-networks-deploy-wizard-step2.png deleted file mode 100644 index 2424d935..00000000 Binary files a/public/defender/tutorial-forked-networks-deploy-wizard-step2.png and /dev/null differ diff --git a/public/defender/tutorial-forked-networks-deploy-wizard-step3.png b/public/defender/tutorial-forked-networks-deploy-wizard-step3.png deleted file mode 100644 index 3d4a5363..00000000 Binary files a/public/defender/tutorial-forked-networks-deploy-wizard-step3.png and /dev/null differ diff --git a/public/defender/tutorial-forked-networks-intro.png b/public/defender/tutorial-forked-networks-intro.png deleted file mode 100644 index f3696547..00000000 Binary files a/public/defender/tutorial-forked-networks-intro.png and /dev/null differ diff --git a/public/defender/tutorial-forked-networks-phalcon-dashboard.png b/public/defender/tutorial-forked-networks-phalcon-dashboard.png deleted file mode 100644 index df86c821..00000000 Binary files a/public/defender/tutorial-forked-networks-phalcon-dashboard.png and /dev/null differ diff --git a/public/defender/tutorial-ir-etherscan.png b/public/defender/tutorial-ir-etherscan.png deleted file mode 100644 index df4c7b21..00000000 Binary files a/public/defender/tutorial-ir-etherscan.png and /dev/null differ diff --git a/public/defender/tutorial-ir-first-monitor.png b/public/defender/tutorial-ir-first-monitor.png deleted file mode 100644 index bd24b479..00000000 Binary files a/public/defender/tutorial-ir-first-monitor.png and /dev/null differ diff --git a/public/defender/tutorial-ir-monitor.png b/public/defender/tutorial-ir-monitor.png deleted file mode 100644 index b633ffee..00000000 Binary files a/public/defender/tutorial-ir-monitor.png and /dev/null differ diff --git a/public/defender/tutorial-ir-proposal-action.png b/public/defender/tutorial-ir-proposal-action.png deleted file mode 100644 index da17d06d..00000000 Binary files a/public/defender/tutorial-ir-proposal-action.png and /dev/null differ diff --git a/public/defender/tutorial-monitor-alerts.png b/public/defender/tutorial-monitor-alerts.png deleted file mode 100644 index 22a40134..00000000 Binary files a/public/defender/tutorial-monitor-alerts.png and /dev/null differ diff --git a/public/defender/tutorial-monitor-card.png b/public/defender/tutorial-monitor-card.png deleted file mode 100644 index 0ce119aa..00000000 Binary files a/public/defender/tutorial-monitor-card.png and /dev/null differ diff --git a/public/defender/tutorial-monitor-event-filter.png b/public/defender/tutorial-monitor-event-filter.png deleted file mode 100644 index a1c77ffc..00000000 Binary files a/public/defender/tutorial-monitor-event-filter.png and /dev/null differ diff --git a/public/defender/tutorial-monitor-first.png b/public/defender/tutorial-monitor-first.png deleted file mode 100644 index fddae806..00000000 Binary files a/public/defender/tutorial-monitor-first.png and /dev/null differ diff --git a/public/defender/tutorial-monitor-landing.png b/public/defender/tutorial-monitor-landing.png deleted file mode 100644 index 8ed5609b..00000000 Binary files a/public/defender/tutorial-monitor-landing.png and /dev/null differ diff --git a/public/defender/tutorial-monitor-receive.png b/public/defender/tutorial-monitor-receive.png deleted file mode 100644 index 0edda75c..00000000 Binary files a/public/defender/tutorial-monitor-receive.png and /dev/null differ diff --git a/public/defender/tutorial-monitor-save-template.png b/public/defender/tutorial-monitor-save-template.png deleted file mode 100644 index db1b333a..00000000 Binary files a/public/defender/tutorial-monitor-save-template.png and /dev/null differ diff --git a/public/defender/tutorial-monitor-transaction-filters.png b/public/defender/tutorial-monitor-transaction-filters.png deleted file mode 100644 index e206a97a..00000000 Binary files a/public/defender/tutorial-monitor-transaction-filters.png and /dev/null differ diff --git a/public/defender/tutorial-relayer-step1.png b/public/defender/tutorial-relayer-step1.png deleted file mode 100644 index 4ab83a28..00000000 Binary files a/public/defender/tutorial-relayer-step1.png and /dev/null differ diff --git a/public/defender/tutorial-relayer-step2.png b/public/defender/tutorial-relayer-step2.png deleted file mode 100644 index 79d90791..00000000 Binary files a/public/defender/tutorial-relayer-step2.png and /dev/null differ diff --git a/public/defender/tutorial-relayer-step3-1.png b/public/defender/tutorial-relayer-step3-1.png deleted file mode 100644 index 25dc2484..00000000 Binary files a/public/defender/tutorial-relayer-step3-1.png and /dev/null differ diff --git a/public/defender/tutorial-relayer-step3.png b/public/defender/tutorial-relayer-step3.png deleted file mode 100644 index 6f40138f..00000000 Binary files a/public/defender/tutorial-relayer-step3.png and /dev/null differ diff --git a/public/defender/tutorial-relayer-step4.png b/public/defender/tutorial-relayer-step4.png deleted file mode 100644 index 6a2bfce4..00000000 Binary files a/public/defender/tutorial-relayer-step4.png and /dev/null differ diff --git a/public/defender/tutorial-workflow-active-scenario.png b/public/defender/tutorial-workflow-active-scenario.png deleted file mode 100644 index 6a7c99d6..00000000 Binary files a/public/defender/tutorial-workflow-active-scenario.png and /dev/null differ diff --git a/public/defender/tutorial-workflow-first-action.png b/public/defender/tutorial-workflow-first-action.png deleted file mode 100644 index a0a3e152..00000000 Binary files a/public/defender/tutorial-workflow-first-action.png and /dev/null differ diff --git a/public/defender/tutorial-workflow-scenario.png b/public/defender/tutorial-workflow-scenario.png deleted file mode 100644 index 482334c3..00000000 Binary files a/public/defender/tutorial-workflow-scenario.png and /dev/null differ diff --git a/public/defender/withdraw.png b/public/defender/withdraw.png deleted file mode 100644 index b3c2c7f6..00000000 Binary files a/public/defender/withdraw.png and /dev/null differ diff --git a/public/defender/wizard-deploy-further-steps.png b/public/defender/wizard-deploy-further-steps.png deleted file mode 100644 index 297c2d66..00000000 Binary files a/public/defender/wizard-deploy-further-steps.png and /dev/null differ diff --git a/public/defender/wizard-plugin-approval-process.png b/public/defender/wizard-plugin-approval-process.png deleted file mode 100644 index 1088bb20..00000000 Binary files a/public/defender/wizard-plugin-approval-process.png and /dev/null differ diff --git a/public/defender/wizard-plugin-configure-2.png b/public/defender/wizard-plugin-configure-2.png deleted file mode 100644 index cda0b276..00000000 Binary files a/public/defender/wizard-plugin-configure-2.png and /dev/null differ diff --git a/public/defender/wizard-plugin-configure.png b/public/defender/wizard-plugin-configure.png deleted file mode 100644 index 93af80dd..00000000 Binary files a/public/defender/wizard-plugin-configure.png and /dev/null differ diff --git a/public/defender/wizard-plugin-deploy.png b/public/defender/wizard-plugin-deploy.png deleted file mode 100644 index 229c5153..00000000 Binary files a/public/defender/wizard-plugin-deploy.png and /dev/null differ diff --git a/public/defender/wizard-plugin-deterministic.png b/public/defender/wizard-plugin-deterministic.png deleted file mode 100644 index 00bf3388..00000000 Binary files a/public/defender/wizard-plugin-deterministic.png and /dev/null differ diff --git a/public/defender/wizard-plugin-network-2.png b/public/defender/wizard-plugin-network-2.png deleted file mode 100644 index 6882cb49..00000000 Binary files a/public/defender/wizard-plugin-network-2.png and /dev/null differ diff --git a/public/defender/wizard-plugin-start.png b/public/defender/wizard-plugin-start.png deleted file mode 100644 index 0a14a2ed..00000000 Binary files a/public/defender/wizard-plugin-start.png and /dev/null differ diff --git a/public/llms.txt b/public/llms.txt index 8842dd6a..59ab2d1f 100644 --- a/public/llms.txt +++ b/public/llms.txt @@ -1,6 +1,6 @@ # OpenZeppelin Docs -> Security-first libraries, tools, and infrastructure for building on Ethereum and other blockchains. Covers smart contract libraries for Solidity, Cairo, Stylus, Sui, Midnight, Stellar, Zama FHEVM, and Polkadot; operational tools (Defender, Monitor, Relayer, UI Builder); and the Upgrades Plugins and Contract Wizard. +> Security-first libraries, tools, and infrastructure for building on Ethereum and other blockchains. Covers smart contract libraries for Solidity, Cairo, Stylus, Sui, Midnight, Stellar, Zama FHEVM, and Polkadot; operational tools (Monitor, Relayer, UI Builder); and the Upgrades Plugins and Contract Wizard. Each ecosystem section lists the smart-contract libraries and language-specific guides for that chain. Cross-ecosystem developer libraries and tools are grouped at the end to avoid duplication. Unversioned URLs (for example `/contracts/`) redirect to the latest supported version. @@ -128,7 +128,6 @@ Each ecosystem section lists the smart-contract libraries and language-specific - [Upgrades Plugins — Foundry Upgrades API — Overview](https://docs.openzeppelin.com/upgrades-plugins/foundry/api) - [Upgrades Plugins — Foundry Upgrades API — Upgrades](https://docs.openzeppelin.com/upgrades-plugins/foundry/api/Upgrades): Smart contract Upgrades utilities and implementations - [Upgrades Plugins — Foundry Upgrades API — LegacyUpgrades](https://docs.openzeppelin.com/upgrades-plugins/foundry/api/LegacyUpgrades): Smart contract LegacyUpgrades utilities and implementations -- [Upgrades Plugins — Foundry Upgrades API — Defender](https://docs.openzeppelin.com/upgrades-plugins/foundry/api/Defender): Smart contract Defender utilities and implementations - [Upgrades Plugins — Foundry Upgrades API — Options](https://docs.openzeppelin.com/upgrades-plugins/foundry/api/Options): Smart contract Options utilities and implementations - [Upgrades Plugins — Upgrades Core & CLI](https://docs.openzeppelin.com/upgrades-plugins/api-core) @@ -633,39 +632,4 @@ Each ecosystem section lists the smart-contract libraries and language-specific - [UI Builder — Building Adapters](https://docs.openzeppelin.com/ui-builder/building-adapters) - [UI Builder — Changelog](https://docs.openzeppelin.com/ui-builder/changelog) - [Role Manager](https://docs.openzeppelin.com/role-manager) -- [Defender — Overview](https://docs.openzeppelin.com/defender) -- [Defender — Modules — Code Inspector](https://docs.openzeppelin.com/defender/module/code) -- [Defender — Modules — Audit](https://docs.openzeppelin.com/defender/module/audit) -- [Defender — Modules — Deploy](https://docs.openzeppelin.com/defender/module/deploy) -- [Defender — Modules — Relayers](https://docs.openzeppelin.com/defender/module/relayers) -- [Defender — Modules — Monitor](https://docs.openzeppelin.com/defender/module/monitor) -- [Defender — Modules — Actions](https://docs.openzeppelin.com/defender/module/actions) -- [Defender — Modules — Transaction Proposals](https://docs.openzeppelin.com/defender/module/transaction-proposals) -- [Defender — Modules — Address Book](https://docs.openzeppelin.com/defender/module/address-book) -- [Defender — Modules — Access Control](https://docs.openzeppelin.com/defender/module/access-control) -- [Defender — Settings — Overview](https://docs.openzeppelin.com/defender/settings) -- [Defender — Settings — Logs](https://docs.openzeppelin.com/defender/logs) -- [Defender — Settings — Notifications](https://docs.openzeppelin.com/defender/settings/notifications) -- [Defender — Tutorials — Deploy](https://docs.openzeppelin.com/defender/tutorial/deploy) -- [Defender — Tutorials — Relayer](https://docs.openzeppelin.com/defender/tutorial/relayer) -- [Defender — Tutorials — Monitor](https://docs.openzeppelin.com/defender/tutorial/monitor) -- [Defender — Tutorials — Actions](https://docs.openzeppelin.com/defender/tutorial/actions) -- [Defender — Tutorials — Access Control](https://docs.openzeppelin.com/defender/tutorial/access-control) -- [Defender — Tutorials — Workflows](https://docs.openzeppelin.com/defender/tutorial/workflows) -- [Defender — Guides — Deploy a smart contract on a forked network](https://docs.openzeppelin.com/defender/guide/forked-network) -- [Defender — Guides — Adding a complete private network](https://docs.openzeppelin.com/defender/guide/private-network) -- [Defender — Guides — Relaying gasless meta-transactions](https://docs.openzeppelin.com/defender/guide/meta-tx) -- [Defender — Guides — Automatic monitoring for factory clones](https://docs.openzeppelin.com/defender/guide/factory-monitor) -- [Defender — Guides — Managing roles of a TimelockController](https://docs.openzeppelin.com/defender/guide/timelock-roles) -- [Defender — Guides — Managing usage notifications](https://docs.openzeppelin.com/defender/guide/usage-notification) -- [Defender — Guides — Setup Fireblocks integrations within Defender](https://docs.openzeppelin.com/defender/guide/fireblock-defender-integration) -- [Defender — Guides — Upgrading actions dependencies](https://docs.openzeppelin.com/defender/guide/upgrade-actions-dependencies) -- [Defender — Defender as Code](https://docs.openzeppelin.com/defender/dac) -- [Defender — Remix Plugin](https://docs.openzeppelin.com/defender/remix-plugin) -- [Defender — Contracts Wizard Plugin](https://docs.openzeppelin.com/defender/wizard-plugin) -- [Defender — SDK and API](https://docs.openzeppelin.com/defender/sdk) -- [Defender — Migration to Open Source](https://docs.openzeppelin.com/defender/migration) -- [Defender — Integrations](https://docs.openzeppelin.com/defender/integrations) -- [Defender — FAQ](https://docs.openzeppelin.com/defender/faq) -- [Defender — Changelog](https://docs.openzeppelin.com/defender/changelog) - [RWA Wizard](https://docs.openzeppelin.com/rwa-wizard): A tool for building real-world asset token projects diff --git a/scripts/convert-adoc.js b/scripts/convert-adoc.js index 140c0ef2..246135e1 100755 --- a/scripts/convert-adoc.js +++ b/scripts/convert-adoc.js @@ -130,7 +130,6 @@ async function convertAdocFiles(directory, apiRoute = "contracts/5.x/api") { "community-contracts": "/community-contracts", "confidential-contracts": "/confidential-contracts", "upgrades-plugins": "/upgrades-plugins", - defender: "/defender", learn: "/contracts/5.x/learn", }; mdContent = mdContent.replace( diff --git a/scripts/generate-llms-txt.ts b/scripts/generate-llms-txt.ts index 1cef3bad..63755037 100644 --- a/scripts/generate-llms-txt.ts +++ b/scripts/generate-llms-txt.ts @@ -36,7 +36,7 @@ const TREES: NavigationTree[] = [ const INTRO = `# OpenZeppelin Docs -> Security-first libraries, tools, and infrastructure for building on Ethereum and other blockchains. Covers smart contract libraries for Solidity, Cairo, Stylus, Sui, Midnight, Stellar, Zama FHEVM, and Polkadot; operational tools (Defender, Monitor, Relayer, UI Builder); and the Upgrades Plugins and Contract Wizard. +> Security-first libraries, tools, and infrastructure for building on Ethereum and other blockchains. Covers smart contract libraries for Solidity, Cairo, Stylus, Sui, Midnight, Stellar, Zama FHEVM, and Polkadot; operational tools (Monitor, Relayer, UI Builder); and the Upgrades Plugins and Contract Wizard. Each ecosystem section lists the smart-contract libraries and language-specific guides for that chain. Cross-ecosystem developer libraries and tools are grouped at the end to avoid duplication. Unversioned URLs (for example \`/contracts/\`) redirect to the latest supported version. `; diff --git a/src/app/page.tsx b/src/app/page.tsx index 80c14022..54fcd40b 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -30,7 +30,6 @@ import { UniswapIcon, ZamaIcon, } from "@/components/icons"; -import { DefenderIcon } from "@/components/icons/defender-icon"; import { latestStable as monitorLatestStable } from "../../content/monitor/latest-versions"; import { latestStable as relayerLatestStable } from "../../content/relayer/latest-versions"; import { baseOptions } from "./layout.config"; @@ -171,13 +170,6 @@ export default function HomePage() { title="UI Builder" description="Spin up user interfaces for any deployed contract. Select the function, auto-generate a React UI with wallet-connect and multi-network support, and export a complete app." /> - - } - title="Defender" - description="Code, audit, deploy, monitor, and operate blockchain applications with OpenZeppelin's legacy developer security platform (maintenance mode)." - />
diff --git a/src/components/icons/defender-icon.tsx b/src/components/icons/defender-icon.tsx deleted file mode 100644 index 9aaee1b0..00000000 --- a/src/components/icons/defender-icon.tsx +++ /dev/null @@ -1,20 +0,0 @@ -export function DefenderIcon({ className }: { className: string }) { - return ( - - Defender Icon - - - - - - - - ); -} diff --git a/src/components/layout/docs-layout-client.tsx b/src/components/layout/docs-layout-client.tsx index cb72358f..a4721ce1 100644 --- a/src/components/layout/docs-layout-client.tsx +++ b/src/components/layout/docs-layout-client.tsx @@ -104,7 +104,6 @@ export function DocsLayoutClient({ children }: DocsLayoutClientProps) { "/monitor", "/ui-builder", "/upgrades", - "/defender", ]); if ( !isSharedPath || diff --git a/src/hooks/use-navigation-tree.ts b/src/hooks/use-navigation-tree.ts index 73b57c61..f1de9ffc 100644 --- a/src/hooks/use-navigation-tree.ts +++ b/src/hooks/use-navigation-tree.ts @@ -53,8 +53,7 @@ export function useNavigationTree() { pathname.startsWith("/community-contracts") || pathname.startsWith("/upgrades-plugins") || pathname.startsWith("/wizard") || - pathname.startsWith("/upgrades") || - pathname.startsWith("/defender") + pathname.startsWith("/upgrades") ) { sessionStorage.setItem("lastEcosystem", "ethereum"); } else { diff --git a/src/navigation/ethereum-evm.json b/src/navigation/ethereum-evm.json index 6e547822..7b774700 100644 --- a/src/navigation/ethereum-evm.json +++ b/src/navigation/ethereum-evm.json @@ -739,11 +739,6 @@ "name": "LegacyUpgrades", "url": "/upgrades-plugins/foundry/api/LegacyUpgrades" }, - { - "type": "page", - "name": "Defender", - "url": "/upgrades-plugins/foundry/api/Defender" - }, { "type": "page", "name": "Options", @@ -1342,210 +1337,5 @@ "type": "page", "name": "Role Manager", "url": "/role-manager" - }, - { - "type": "folder", - "name": "Defender", - "children": [ - { - "type": "page", - "name": "Overview", - "url": "/defender" - }, - { - "type": "folder", - "name": "Modules", - "children": [ - { - "type": "page", - "name": "Code Inspector", - "url": "/defender/module/code" - }, - { - "type": "page", - "name": "Audit", - "url": "/defender/module/audit" - }, - { - "type": "page", - "name": "Deploy", - "url": "/defender/module/deploy" - }, - { - "type": "page", - "name": "Relayers", - "url": "/defender/module/relayers" - }, - { - "type": "page", - "name": "Monitor", - "url": "/defender/module/monitor" - }, - { - "type": "page", - "name": "Actions", - "url": "/defender/module/actions" - }, - { - "type": "page", - "name": "Transaction Proposals", - "url": "/defender/module/transaction-proposals" - }, - { - "type": "page", - "name": "Address Book", - "url": "/defender/module/address-book" - }, - { - "type": "page", - "name": "Access Control", - "url": "/defender/module/access-control" - } - ] - }, - { - "type": "folder", - "name": "Settings", - "index": { - "type": "page", - "name": "Overview", - "url": "/defender/settings" - }, - "children": [ - { - "type": "page", - "name": "Logs", - "url": "/defender/logs" - }, - { - "type": "page", - "name": "Notifications", - "url": "/defender/settings/notifications" - } - ] - }, - { - "type": "folder", - "name": "Tutorials", - "children": [ - { - "type": "page", - "name": "Deploy", - "url": "/defender/tutorial/deploy" - }, - { - "type": "page", - "name": "Relayer", - "url": "/defender/tutorial/relayer" - }, - { - "type": "page", - "name": "Monitor", - "url": "/defender/tutorial/monitor" - }, - { - "type": "page", - "name": "Actions", - "url": "/defender/tutorial/actions" - }, - { - "type": "page", - "name": "Access Control", - "url": "/defender/tutorial/access-control" - }, - { - "type": "page", - "name": "Workflows", - "url": "/defender/tutorial/workflows" - } - ] - }, - { - "type": "folder", - "name": "Guides", - "children": [ - { - "type": "page", - "name": "Deploy a smart contract on a forked network", - "url": "/defender/guide/forked-network" - }, - { - "type": "page", - "name": "Adding a complete private network", - "url": "/defender/guide/private-network" - }, - { - "type": "page", - "name": "Relaying gasless meta-transactions", - "url": "/defender/guide/meta-tx" - }, - { - "type": "page", - "name": "Automatic monitoring for factory clones", - "url": "/defender/guide/factory-monitor" - }, - { - "type": "page", - "name": "Managing roles of a TimelockController", - "url": "/defender/guide/timelock-roles" - }, - { - "type": "page", - "name": "Managing usage notifications", - "url": "/defender/guide/usage-notification" - }, - { - "type": "page", - "name": "Setup Fireblocks integrations within Defender", - "url": "/defender/guide/fireblock-defender-integration" - }, - { - "type": "page", - "name": "Upgrading actions dependencies", - "url": "/defender/guide/upgrade-actions-dependencies" - } - ] - }, - { - "type": "page", - "name": "Defender as Code", - "url": "/defender/dac" - }, - { - "type": "page", - "name": "Remix Plugin", - "url": "/defender/remix-plugin" - }, - { - "type": "page", - "name": "Contracts Wizard Plugin", - "url": "/defender/wizard-plugin" - }, - { - "type": "page", - "name": "SDK and API", - "url": "/defender/sdk" - }, - { - "type": "page", - "name": "Migration to Open Source", - "url": "/defender/migration" - }, - { - "type": "page", - "name": "Integrations", - "url": "/defender/integrations" - }, - { - "type": "page", - "name": "FAQ", - "url": "/defender/faq" - }, - { - "type": "page", - "name": "Changelog", - "url": "/defender/changelog" - } - ] } ]