From e9cc7280c7288c7542dc0d58620d14f82284063f Mon Sep 17 00:00:00 2001 From: "Odysseas.eth" Date: Wed, 1 Jun 2022 18:21:46 -0700 Subject: [PATCH 1/7] migrate learn to docs repo --- .github/CODEOWNERS | 1 - .gitignore | 29 +- .nvmrc | 1 - LICENSE | 13 + README.md | 32 +- babel.config.js | 3 + docs/.vitepress/config.js | 94 - docs/.vitepress/theme/custom.css | 8 - docs/.vitepress/theme/index.js | 4 - docs/agents/overview.md | 0 docs/agents/processor.md | 0 docs/agents/relayer.md | 0 docs/agents/updater.md | 0 docs/agents/watcher.md | 0 docs/brand-kit.md | 19 - docs/bridge/domains-testnet.md | 35 - docs/bridge/domains.md | 119 - docs/bridge/etherscan-native.md | 8 - docs/bridge/etherscan.md | 8 - docs/bridge/faq.md | 128 - docs/bridge/index.md | 16 - docs/bridge/nomad-gui.md | 122 - docs/bridge/resources.md | 8 - docs/build/agents.md | 0 docs/build/checklist.md | 0 docs/build/invariants.md | 0 docs/build/overview.md | 0 docs/build/sdk.md | 0 docs/build/smart-contracts.md | 0 docs/dev/agents/agent-development.md | 83 - docs/dev/agents/agent-operations.md | 339 - docs/dev/agents/debug-agents.md | 96 - docs/dev/agents/index.md | 11 - docs/dev/agents/the-keymaster.md | 105 - docs/dev/architecture.md | 90 - docs/dev/dev-contract-deployment.md | 94 - docs/dev/domain-ids.md | 19 - docs/dev/governance.md | 175 - docs/dev/index.md | 18 - docs/dev/prod-contract-deployment.md | 8 - docs/dev/sdk.md | 25 - docs/dev/token-bridge.md | 156 - docs/dev/topology.md | 46 - docs/dev/upgrade-setup.md | 40 - docs/dev/xapps.md | 112 - docs/docs.mdx | 13 + docs/governance-bridge/overview.md | 0 docs/index.md | 215 - docs/overview/nomad-vs-the-world.md | 0 docs/overview/what-is-nomad.md | 0 docs/overview/why-nomad.md | 0 docs/partners/nomad-appendix.md | 52 - docs/partners/nomad-bridging-to-evmos.md | 122 - docs/partners/nomad-bridging-to-milkomeda.md | 122 - docs/partners/nomad-building-xapps.md | 59 - docs/partners/nomad-integrating-bridge.md | 100 - docs/partners/nomad-overview.md | 95 - docs/protocol/agents.md | 0 docs/protocol/governance.md | 0 docs/protocol/messaging.md | 0 docs/protocol/overview.md | 0 docs/protocol/security.md | 0 docs/public/Logo-Black.png | Bin 23691 -> 0 bytes docs/public/Logo-Black.svg | 7 - docs/public/Logo-White.png | Bin 21940 -> 0 bytes docs/public/Logo-White.svg | 7 - docs/public/Nomad-Architecture.png | Bin 792611 -> 0 bytes docs/public/Upgrade-Setup-1.png | Bin 230423 -> 0 bytes docs/public/Upgrade-Setup-2.png | Bin 302298 -> 0 bytes docs/public/brand-kit.css | 27 - docs/public/download.svg | 4 - docs/public/favicon.png | Bin 434 -> 0 bytes docs/public/governance-diagram.png | Bin 132649 -> 0 bytes docs/public/multi-provider/.nojekyll | 1 - .../multi-provider/assets/highlight.css | 85 - docs/public/multi-provider/assets/icons.css | 1043 -- docs/public/multi-provider/assets/icons.png | Bin 9615 -> 0 bytes .../public/multi-provider/assets/icons@2x.png | Bin 28144 -> 0 bytes docs/public/multi-provider/assets/main.js | 52 - docs/public/multi-provider/assets/search.js | 1 - docs/public/multi-provider/assets/style.css | 1413 --- docs/public/multi-provider/assets/widgets.png | Bin 480 -> 0 bytes .../multi-provider/assets/widgets@2x.png | Bin 855 -> 0 bytes .../multi-provider/classes/Contracts.html | 5 - .../multi-provider/classes/MultiProvider.html | 132 - docs/public/multi-provider/index.html | 22 - .../multi-provider/interfaces/Domain.html | 5 - .../multi-provider/interfaces/Pagination.html | 3 - docs/public/multi-provider/modules.html | 1 - docs/public/multi-provider/modules/utils.html | 53 - docs/public/nomad-brand-assets.zip | Bin 44002 -> 0 bytes .../ethereum-to-evmos/change-dest-1.png | Bin 58442 -> 0 bytes .../ethereum-to-evmos/change-dest-2.png | Bin 58972 -> 0 bytes .../ethereum-to-evmos/check-connext.png | Bin 77519 -> 0 bytes .../ethereum-to-evmos/complete-transfer.png | Bin 54438 -> 0 bytes .../ethereum-to-evmos/connect-metamask.png | Bin 112610 -> 0 bytes .../ethereum-to-evmos/connext-claim.png | Bin 42628 -> 0 bytes .../ethereum-to-evmos/expand-status.png | Bin 38063 -> 0 bytes .../ethereum-to-evmos/input-data.png | Bin 83488 -> 0 bytes .../ethereum-to-evmos/review.png | Bin 76121 -> 0 bytes .../ethereum-to-evmos/search-transfer.png | Bin 18881 -> 0 bytes .../ethereum-to-evmos/select-networks.png | Bin 52229 -> 0 bytes .../ethereum-to-evmos/select-token.png | Bin 52792 -> 0 bytes .../ethereum-to-evmos/sending.png | Bin 132735 -> 0 bytes .../ethereum-to-evmos/transfer-complete.png | Bin 58771 -> 0 bytes .../ethereum-to-evmos/transfer-pending.png | Bin 63243 -> 0 bytes .../ethereum-to-milkomeda/change-dest-1.png | Bin 58442 -> 0 bytes .../ethereum-to-milkomeda/change-dest-2.png | Bin 58972 -> 0 bytes .../ethereum-to-milkomeda/check-connext.png | Bin 78028 -> 0 bytes .../complete-transfer.png | Bin 54697 -> 0 bytes .../connect-metamask.png | Bin 112610 -> 0 bytes .../ethereum-to-milkomeda/connext-claim.png | Bin 44755 -> 0 bytes .../ethereum-to-milkomeda/expand-status.png | Bin 38063 -> 0 bytes .../ethereum-to-milkomeda/input-data.png | Bin 84033 -> 0 bytes .../ethereum-to-milkomeda/review.png | Bin 76646 -> 0 bytes .../ethereum-to-milkomeda/search-transfer.png | Bin 18881 -> 0 bytes .../ethereum-to-milkomeda/select-networks.png | Bin 98401 -> 0 bytes .../ethereum-to-milkomeda/select-token.png | Bin 52792 -> 0 bytes .../ethereum-to-milkomeda/sending.png | Bin 132735 -> 0 bytes .../transfer-complete.png | Bin 59121 -> 0 bytes .../transfer-pending.png | Bin 63601 -> 0 bytes .../overview/connext-architecture.png | Bin 27320 -> 0 bytes .../overview/connext-highlevel-flow.png | Bin 39692 -> 0 bytes docs/public/sdk-bridge/.nojekyll | 1 - docs/public/sdk-bridge/assets/highlight.css | 36 - docs/public/sdk-bridge/assets/icons.css | 1043 -- docs/public/sdk-bridge/assets/icons.png | Bin 9615 -> 0 bytes docs/public/sdk-bridge/assets/icons@2x.png | Bin 28144 -> 0 bytes docs/public/sdk-bridge/assets/main.js | 52 - docs/public/sdk-bridge/assets/search.js | 1 - docs/public/sdk-bridge/assets/style.css | 1413 --- docs/public/sdk-bridge/assets/widgets.png | Bin 480 -> 0 bytes docs/public/sdk-bridge/assets/widgets@2x.png | Bin 855 -> 0 bytes .../sdk-bridge/classes/BridgeContext.html | 236 - .../sdk-bridge/classes/BridgeContracts.html | 1 - .../sdk-bridge/classes/BridgeMessage.html | 180 - .../sdk-bridge/classes/TransferMessage.html | 189 - docs/public/sdk-bridge/index.html | 15 - .../interfaces/TokenIdentifier.html | 1 - docs/public/sdk-bridge/modules.html | 1 - .../sdk-bridge/modules/bridgeEvents.html | 1 - docs/public/sdk-govern/.nojekyll | 1 - docs/public/sdk-govern/assets/highlight.css | 36 - docs/public/sdk-govern/assets/icons.css | 1043 -- docs/public/sdk-govern/assets/icons.png | Bin 9615 -> 0 bytes docs/public/sdk-govern/assets/icons@2x.png | Bin 28144 -> 0 bytes docs/public/sdk-govern/assets/main.js | 52 - docs/public/sdk-govern/assets/search.js | 1 - docs/public/sdk-govern/assets/style.css | 1413 --- docs/public/sdk-govern/assets/widgets.png | Bin 480 -> 0 bytes docs/public/sdk-govern/assets/widgets@2x.png | Bin 855 -> 0 bytes docs/public/sdk-govern/classes/CallBatch.html | 1 - docs/public/sdk-govern/index.html | 15 - docs/public/sdk-govern/interfaces/Call.html | 1 - .../interfaces/CallBatchContents.html | 1 - .../sdk-govern/interfaces/RemoteContents.html | 1 - docs/public/sdk-govern/modules.html | 1 - docs/public/sdk/.nojekyll | 1 - docs/public/sdk/assets/highlight.css | 36 - docs/public/sdk/assets/icons.css | 1043 -- docs/public/sdk/assets/icons.png | Bin 9615 -> 0 bytes docs/public/sdk/assets/icons@2x.png | Bin 28144 -> 0 bytes docs/public/sdk/assets/main.js | 52 - docs/public/sdk/assets/search.js | 1 - docs/public/sdk/assets/style.css | 1413 --- docs/public/sdk/assets/widgets.png | Bin 480 -> 0 bytes docs/public/sdk/assets/widgets@2x.png | Bin 855 -> 0 bytes docs/public/sdk/classes/Annotated.html | 1 - docs/public/sdk/classes/CoreContracts.html | 1 - docs/public/sdk/classes/FailedHomeError.html | 6 - docs/public/sdk/classes/NomadContext.html | 153 - docs/public/sdk/classes/NomadMessage.html | 109 - docs/public/sdk/enums/MessageStatus.html | 1 - .../sdk/enums/ReplicaMessageStatus.html | 1 - docs/public/sdk/index.html | 14 - docs/public/sdk/interfaces/TSContract.html | 1 - docs/public/sdk/modules.html | 3 - .../tutorials/bridge-gui/change-dest-1.png | Bin 58442 -> 0 bytes .../tutorials/bridge-gui/change-dest-2.png | Bin 58972 -> 0 bytes .../tutorials/bridge-gui/check-connext.png | Bin 77796 -> 0 bytes .../bridge-gui/complete-transfer.png | Bin 54621 -> 0 bytes .../tutorials/bridge-gui/connect-metamask.png | Bin 112610 -> 0 bytes .../tutorials/bridge-gui/connext-claim.png | Bin 43829 -> 0 bytes .../tutorials/bridge-gui/expand-status.png | Bin 38063 -> 0 bytes .../tutorials/bridge-gui/input-data.png | Bin 83695 -> 0 bytes docs/public/tutorials/bridge-gui/review.png | Bin 76407 -> 0 bytes .../tutorials/bridge-gui/search-transfer.png | Bin 18881 -> 0 bytes .../tutorials/bridge-gui/select-networks.png | Bin 98489 -> 0 bytes .../tutorials/bridge-gui/select-token.png | Bin 52792 -> 0 bytes docs/public/tutorials/bridge-gui/sending.png | Bin 132735 -> 0 bytes .../bridge-gui/transfer-complete.png | Bin 59028 -> 0 bytes .../tutorials/bridge-gui/transfer-pending.png | Bin 63507 -> 0 bytes .../tutorials/debug-agents/agents-no-zoom.png | Bin 214450 -> 0 bytes .../debug-agents/agents-regression-zoom.png | Bin 185432 -> 0 bytes .../debug-agents/agents-timestamp-paste.png | Bin 825399 -> 0 bytes .../debug-agents/bridge-health-overview.png | Bin 1075655 -> 0 bytes .../enter-agent-pod-and-timestamp.png | Bin 186319 -> 0 bytes .../debug-agents/find-bridge-health.png | Bin 155536 -> 0 bytes .../debug-agents/find-dashboards.png | Bin 1527034 -> 0 bytes .../tutorials/debug-agents/find-explore.png | Bin 1545404 -> 0 bytes .../debug-agents/identify-regression.png | Bin 247778 -> 0 bytes .../tutorials/debug-agents/log-errors.png | Bin 687374 -> 0 bytes .../debug-agents/zoom-in-regression.png | Bin 613445 -> 0 bytes .../governance-signer/approve-on-device.png | Bin 887316 -> 0 bytes .../governance-signer/approve-on-metamask.png | Bin 103892 -> 0 bytes .../governance-signer/confirm-address.png | Bin 93171 -> 0 bytes .../governance-signer/connect-to-metamask.png | Bin 180845 -> 0 bytes .../governance-signer/select-wallet.png | Bin 218448 -> 0 bytes .../governance-signer/sign-message.png | Bin 97411 -> 0 bytes .../governance-signer/signature-success.png | Bin 101465 -> 0 bytes docs/reference/contracts-bridge.md | 0 docs/reference/contracts-core.md | 1 + docs/resources/audits.md | 0 docs/resources/deployed-contracts.md | 0 docs/resources/faq.md | 0 docs/token-bridge/nomad-connext.md | 0 docs/token-bridge/overview.md | 0 docs/tutorials/governance-onboarding.md | 123 - docusaurus.config.js | 150 + guides/develop/how-to-build-simple-xapp.mdx | 14 + netlify.toml | 3 + package-lock.json | 875 -- package.json | 61 +- sidebars.js | 176 + tailwind.config.js | 157 + yarn.lock | 10263 ++++++++++++++++ 226 files changed, 10883 insertions(+), 15216 deletions(-) delete mode 100644 .github/CODEOWNERS delete mode 100644 .nvmrc create mode 100644 LICENSE create mode 100644 babel.config.js delete mode 100644 docs/.vitepress/config.js delete mode 100644 docs/.vitepress/theme/custom.css delete mode 100644 docs/.vitepress/theme/index.js create mode 100644 docs/agents/overview.md create mode 100644 docs/agents/processor.md create mode 100644 docs/agents/relayer.md create mode 100644 docs/agents/updater.md create mode 100644 docs/agents/watcher.md delete mode 100644 docs/brand-kit.md delete mode 100644 docs/bridge/domains-testnet.md delete mode 100644 docs/bridge/domains.md delete mode 100644 docs/bridge/etherscan-native.md delete mode 100644 docs/bridge/etherscan.md delete mode 100644 docs/bridge/faq.md delete mode 100644 docs/bridge/index.md delete mode 100644 docs/bridge/nomad-gui.md delete mode 100644 docs/bridge/resources.md create mode 100644 docs/build/agents.md create mode 100644 docs/build/checklist.md create mode 100644 docs/build/invariants.md create mode 100644 docs/build/overview.md create mode 100644 docs/build/sdk.md create mode 100644 docs/build/smart-contracts.md delete mode 100644 docs/dev/agents/agent-development.md delete mode 100644 docs/dev/agents/agent-operations.md delete mode 100644 docs/dev/agents/debug-agents.md delete mode 100644 docs/dev/agents/index.md delete mode 100644 docs/dev/agents/the-keymaster.md delete mode 100644 docs/dev/architecture.md delete mode 100644 docs/dev/dev-contract-deployment.md delete mode 100644 docs/dev/domain-ids.md delete mode 100644 docs/dev/governance.md delete mode 100644 docs/dev/index.md delete mode 100644 docs/dev/prod-contract-deployment.md delete mode 100644 docs/dev/sdk.md delete mode 100644 docs/dev/token-bridge.md delete mode 100644 docs/dev/topology.md delete mode 100644 docs/dev/upgrade-setup.md delete mode 100644 docs/dev/xapps.md create mode 100644 docs/docs.mdx create mode 100644 docs/governance-bridge/overview.md delete mode 100644 docs/index.md create mode 100644 docs/overview/nomad-vs-the-world.md create mode 100644 docs/overview/what-is-nomad.md create mode 100644 docs/overview/why-nomad.md delete mode 100644 docs/partners/nomad-appendix.md delete mode 100644 docs/partners/nomad-bridging-to-evmos.md delete mode 100644 docs/partners/nomad-bridging-to-milkomeda.md delete mode 100644 docs/partners/nomad-building-xapps.md delete mode 100644 docs/partners/nomad-integrating-bridge.md delete mode 100644 docs/partners/nomad-overview.md create mode 100644 docs/protocol/agents.md create mode 100644 docs/protocol/governance.md create mode 100644 docs/protocol/messaging.md create mode 100644 docs/protocol/overview.md create mode 100644 docs/protocol/security.md delete mode 100644 docs/public/Logo-Black.png delete mode 100644 docs/public/Logo-Black.svg delete mode 100644 docs/public/Logo-White.png delete mode 100644 docs/public/Logo-White.svg delete mode 100644 docs/public/Nomad-Architecture.png delete mode 100644 docs/public/Upgrade-Setup-1.png delete mode 100644 docs/public/Upgrade-Setup-2.png delete mode 100644 docs/public/brand-kit.css delete mode 100644 docs/public/download.svg delete mode 100644 docs/public/favicon.png delete mode 100644 docs/public/governance-diagram.png delete mode 100644 docs/public/multi-provider/.nojekyll delete mode 100644 docs/public/multi-provider/assets/highlight.css delete mode 100644 docs/public/multi-provider/assets/icons.css delete mode 100644 docs/public/multi-provider/assets/icons.png delete mode 100644 docs/public/multi-provider/assets/icons@2x.png delete mode 100644 docs/public/multi-provider/assets/main.js delete mode 100644 docs/public/multi-provider/assets/search.js delete mode 100644 docs/public/multi-provider/assets/style.css delete mode 100644 docs/public/multi-provider/assets/widgets.png delete mode 100644 docs/public/multi-provider/assets/widgets@2x.png delete mode 100644 docs/public/multi-provider/classes/Contracts.html delete mode 100644 docs/public/multi-provider/classes/MultiProvider.html delete mode 100644 docs/public/multi-provider/index.html delete mode 100644 docs/public/multi-provider/interfaces/Domain.html delete mode 100644 docs/public/multi-provider/interfaces/Pagination.html delete mode 100644 docs/public/multi-provider/modules.html delete mode 100644 docs/public/multi-provider/modules/utils.html delete mode 100644 docs/public/nomad-brand-assets.zip delete mode 100644 docs/public/partner-assets/ethereum-to-evmos/change-dest-1.png delete mode 100644 docs/public/partner-assets/ethereum-to-evmos/change-dest-2.png delete mode 100644 docs/public/partner-assets/ethereum-to-evmos/check-connext.png delete mode 100644 docs/public/partner-assets/ethereum-to-evmos/complete-transfer.png delete mode 100644 docs/public/partner-assets/ethereum-to-evmos/connect-metamask.png delete mode 100644 docs/public/partner-assets/ethereum-to-evmos/connext-claim.png delete mode 100644 docs/public/partner-assets/ethereum-to-evmos/expand-status.png delete mode 100644 docs/public/partner-assets/ethereum-to-evmos/input-data.png delete mode 100644 docs/public/partner-assets/ethereum-to-evmos/review.png delete mode 100644 docs/public/partner-assets/ethereum-to-evmos/search-transfer.png delete mode 100644 docs/public/partner-assets/ethereum-to-evmos/select-networks.png delete mode 100644 docs/public/partner-assets/ethereum-to-evmos/select-token.png delete mode 100644 docs/public/partner-assets/ethereum-to-evmos/sending.png delete mode 100644 docs/public/partner-assets/ethereum-to-evmos/transfer-complete.png delete mode 100644 docs/public/partner-assets/ethereum-to-evmos/transfer-pending.png delete mode 100644 docs/public/partner-assets/ethereum-to-milkomeda/change-dest-1.png delete mode 100644 docs/public/partner-assets/ethereum-to-milkomeda/change-dest-2.png delete mode 100644 docs/public/partner-assets/ethereum-to-milkomeda/check-connext.png delete mode 100644 docs/public/partner-assets/ethereum-to-milkomeda/complete-transfer.png delete mode 100644 docs/public/partner-assets/ethereum-to-milkomeda/connect-metamask.png delete mode 100644 docs/public/partner-assets/ethereum-to-milkomeda/connext-claim.png delete mode 100644 docs/public/partner-assets/ethereum-to-milkomeda/expand-status.png delete mode 100644 docs/public/partner-assets/ethereum-to-milkomeda/input-data.png delete mode 100644 docs/public/partner-assets/ethereum-to-milkomeda/review.png delete mode 100644 docs/public/partner-assets/ethereum-to-milkomeda/search-transfer.png delete mode 100644 docs/public/partner-assets/ethereum-to-milkomeda/select-networks.png delete mode 100644 docs/public/partner-assets/ethereum-to-milkomeda/select-token.png delete mode 100644 docs/public/partner-assets/ethereum-to-milkomeda/sending.png delete mode 100644 docs/public/partner-assets/ethereum-to-milkomeda/transfer-complete.png delete mode 100644 docs/public/partner-assets/ethereum-to-milkomeda/transfer-pending.png delete mode 100644 docs/public/partner-assets/overview/connext-architecture.png delete mode 100644 docs/public/partner-assets/overview/connext-highlevel-flow.png delete mode 100644 docs/public/sdk-bridge/.nojekyll delete mode 100644 docs/public/sdk-bridge/assets/highlight.css delete mode 100644 docs/public/sdk-bridge/assets/icons.css delete mode 100644 docs/public/sdk-bridge/assets/icons.png delete mode 100644 docs/public/sdk-bridge/assets/icons@2x.png delete mode 100644 docs/public/sdk-bridge/assets/main.js delete mode 100644 docs/public/sdk-bridge/assets/search.js delete mode 100644 docs/public/sdk-bridge/assets/style.css delete mode 100644 docs/public/sdk-bridge/assets/widgets.png delete mode 100644 docs/public/sdk-bridge/assets/widgets@2x.png delete mode 100644 docs/public/sdk-bridge/classes/BridgeContext.html delete mode 100644 docs/public/sdk-bridge/classes/BridgeContracts.html delete mode 100644 docs/public/sdk-bridge/classes/BridgeMessage.html delete mode 100644 docs/public/sdk-bridge/classes/TransferMessage.html delete mode 100644 docs/public/sdk-bridge/index.html delete mode 100644 docs/public/sdk-bridge/interfaces/TokenIdentifier.html delete mode 100644 docs/public/sdk-bridge/modules.html delete mode 100644 docs/public/sdk-bridge/modules/bridgeEvents.html delete mode 100644 docs/public/sdk-govern/.nojekyll delete mode 100644 docs/public/sdk-govern/assets/highlight.css delete mode 100644 docs/public/sdk-govern/assets/icons.css delete mode 100644 docs/public/sdk-govern/assets/icons.png delete mode 100644 docs/public/sdk-govern/assets/icons@2x.png delete mode 100644 docs/public/sdk-govern/assets/main.js delete mode 100644 docs/public/sdk-govern/assets/search.js delete mode 100644 docs/public/sdk-govern/assets/style.css delete mode 100644 docs/public/sdk-govern/assets/widgets.png delete mode 100644 docs/public/sdk-govern/assets/widgets@2x.png delete mode 100644 docs/public/sdk-govern/classes/CallBatch.html delete mode 100644 docs/public/sdk-govern/index.html delete mode 100644 docs/public/sdk-govern/interfaces/Call.html delete mode 100644 docs/public/sdk-govern/interfaces/CallBatchContents.html delete mode 100644 docs/public/sdk-govern/interfaces/RemoteContents.html delete mode 100644 docs/public/sdk-govern/modules.html delete mode 100644 docs/public/sdk/.nojekyll delete mode 100644 docs/public/sdk/assets/highlight.css delete mode 100644 docs/public/sdk/assets/icons.css delete mode 100644 docs/public/sdk/assets/icons.png delete mode 100644 docs/public/sdk/assets/icons@2x.png delete mode 100644 docs/public/sdk/assets/main.js delete mode 100644 docs/public/sdk/assets/search.js delete mode 100644 docs/public/sdk/assets/style.css delete mode 100644 docs/public/sdk/assets/widgets.png delete mode 100644 docs/public/sdk/assets/widgets@2x.png delete mode 100644 docs/public/sdk/classes/Annotated.html delete mode 100644 docs/public/sdk/classes/CoreContracts.html delete mode 100644 docs/public/sdk/classes/FailedHomeError.html delete mode 100644 docs/public/sdk/classes/NomadContext.html delete mode 100644 docs/public/sdk/classes/NomadMessage.html delete mode 100644 docs/public/sdk/enums/MessageStatus.html delete mode 100644 docs/public/sdk/enums/ReplicaMessageStatus.html delete mode 100644 docs/public/sdk/index.html delete mode 100644 docs/public/sdk/interfaces/TSContract.html delete mode 100644 docs/public/sdk/modules.html delete mode 100644 docs/public/tutorials/bridge-gui/change-dest-1.png delete mode 100644 docs/public/tutorials/bridge-gui/change-dest-2.png delete mode 100644 docs/public/tutorials/bridge-gui/check-connext.png delete mode 100644 docs/public/tutorials/bridge-gui/complete-transfer.png delete mode 100644 docs/public/tutorials/bridge-gui/connect-metamask.png delete mode 100644 docs/public/tutorials/bridge-gui/connext-claim.png delete mode 100644 docs/public/tutorials/bridge-gui/expand-status.png delete mode 100644 docs/public/tutorials/bridge-gui/input-data.png delete mode 100644 docs/public/tutorials/bridge-gui/review.png delete mode 100644 docs/public/tutorials/bridge-gui/search-transfer.png delete mode 100644 docs/public/tutorials/bridge-gui/select-networks.png delete mode 100644 docs/public/tutorials/bridge-gui/select-token.png delete mode 100644 docs/public/tutorials/bridge-gui/sending.png delete mode 100644 docs/public/tutorials/bridge-gui/transfer-complete.png delete mode 100644 docs/public/tutorials/bridge-gui/transfer-pending.png delete mode 100644 docs/public/tutorials/debug-agents/agents-no-zoom.png delete mode 100644 docs/public/tutorials/debug-agents/agents-regression-zoom.png delete mode 100644 docs/public/tutorials/debug-agents/agents-timestamp-paste.png delete mode 100644 docs/public/tutorials/debug-agents/bridge-health-overview.png delete mode 100644 docs/public/tutorials/debug-agents/enter-agent-pod-and-timestamp.png delete mode 100644 docs/public/tutorials/debug-agents/find-bridge-health.png delete mode 100644 docs/public/tutorials/debug-agents/find-dashboards.png delete mode 100644 docs/public/tutorials/debug-agents/find-explore.png delete mode 100644 docs/public/tutorials/debug-agents/identify-regression.png delete mode 100644 docs/public/tutorials/debug-agents/log-errors.png delete mode 100644 docs/public/tutorials/debug-agents/zoom-in-regression.png delete mode 100644 docs/public/tutorials/governance-signer/approve-on-device.png delete mode 100644 docs/public/tutorials/governance-signer/approve-on-metamask.png delete mode 100644 docs/public/tutorials/governance-signer/confirm-address.png delete mode 100644 docs/public/tutorials/governance-signer/connect-to-metamask.png delete mode 100644 docs/public/tutorials/governance-signer/select-wallet.png delete mode 100644 docs/public/tutorials/governance-signer/sign-message.png delete mode 100644 docs/public/tutorials/governance-signer/signature-success.png create mode 100644 docs/reference/contracts-bridge.md create mode 100644 docs/reference/contracts-core.md create mode 100644 docs/resources/audits.md create mode 100644 docs/resources/deployed-contracts.md create mode 100644 docs/resources/faq.md create mode 100644 docs/token-bridge/nomad-connext.md create mode 100644 docs/token-bridge/overview.md delete mode 100644 docs/tutorials/governance-onboarding.md create mode 100644 docusaurus.config.js create mode 100644 guides/develop/how-to-build-simple-xapp.mdx create mode 100644 netlify.toml delete mode 100644 package-lock.json create mode 100644 sidebars.js create mode 100644 tailwind.config.js create mode 100644 yarn.lock diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index ac00976..0000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1 +0,0 @@ -* @prestwich @ltchang2019 @erinhales @yourbuddyconner @kekonen @anna-carroll @imti @pranaymohan @barbaraliau \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3d6a3b1..942ad41 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,26 @@ -node_modules -docs/.vitepress/dist -.DS_STORE \ No newline at end of file +# Dependencies +node_modules/ + +# Production +/build + +# Generated files +.docusaurus/ +.cache-loader + +# Misc +.DS_Store +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Local Netlify folder +.netlify +.vscode/settings.json +/.idea/ diff --git a/.nvmrc b/.nvmrc deleted file mode 100644 index f0b10f1..0000000 --- a/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v16.13.1 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..38e5be8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Copyright 2022 Illusory Systems Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/README.md b/README.md index ddcf93d..8a37d63 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,21 @@ -# Documentation Site +# Nomad Docs -## Install -```sh -npm install -``` +## Development -## Build +- You will need `docusaurus` and `node 16` to develop and test locally the documentation website +- [Install Docusaurus](https://docusaurus.io/docs/installation) +- `git clone` the repository locally +- Run `yarn` or `npm install` from inside the repository to install all dependencies +- `yarn start`: Will start a local dev server that will automatically reload with every change to the source code +- Please use named or forked branches. All changes should be PRed to `dev` and if everything works as expected, only then `dev` should be merged into `main` -```sh -npm run docs:build -``` +## Deployment -## Serve Dev Environment +- The docs are automatically deployed from the github repo via Netlify + - `main` is deployed to `docs.nomad.xyz` + - `dev` is deployed to `dev.docs.nomad.xyz` -```sh -npm run docs:dev -``` +## License -## Serve Prod Environment - -```sh -npm run docs:serve -``` +Apache License 2.0 diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..03afab4 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: [require.resolve('@docusaurus/core/lib/babel/preset')], +}; \ No newline at end of file diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.js deleted file mode 100644 index 79cdc26..0000000 --- a/docs/.vitepress/config.js +++ /dev/null @@ -1,94 +0,0 @@ -module.exports = { - lang: "en-US", - title: "Nomad", - description: "Documentation", - - head: [["link", { rel: "icon", href: `/favicon.png` }]], - - themeConfig: { - // repo: 'https://github.com/nomad-xyz/nomad-monorepo', - docsDir: "docs", - - nav: [ - { text: "Home", link: "/", activeMatch: "^/$|^/home/" }, - { text: "Bridge", link: "/bridge/index.html", activeMatch: "^/bridge" }, - { - text: "Developer Resources", - link: "/dev/index.html", - activeMatch: "^/dev/", - }, - ], - - sidebar: { - "/home/": getHomeSidebar(), - "/bridge/": getBridgeSidebar(), - "/dev": getIntegrationsSidebar(), - "/": getHomeSidebar(), - }, - }, -}; - -function getHomeSidebar() { - return [ - { text: "What is Nomad?", link: "/" }, - { text: "Brand Kit", link: "/brand-kit.html" }, - ]; -} - -function getBridgeSidebar() { - return [ - { text: "Getting Started", link: "/bridge/index.html" }, - { - text: "Resources", - children: [ - { text: "Deployed Domains and Addresses", link: "/bridge/domains.html" }, - ], - }, - { text: "FAQs", link: "/bridge/faq.html" }, - { - text: "Ways to Bridge Using Nomad", - children: [ - { text: "Nomad GUI", link: "/bridge/nomad-gui.html" }, - { - text: "Send Native Tokens Using Etherscan", - link: "/bridge/etherscan-native.html", - }, - { - text: "Send ERC-20 Tokens Using Etherscan", - link: "/bridge/etherscan.html", - }, - ], - }, - ]; -} - -function getIntegrationsSidebar() { - return [ - { - text: "Developer Resources", - children: [ - { text: "Nomad Domain IDs", link: "/dev/domain-ids.html" }, - { text: "SDK Documentation", link: "/dev/sdk.html" }, - { text: "Writing a xApp", link: "/dev/xapps.html" }, - ], - }, - { - text: "Technical Docs", - children: [ - { text: "Nomad Architecture", link: "/dev/architecture.html" }, - { text: "Token Bridge xApp", link: "/dev/token-bridge.html" }, - { text: "Governance", link: "/dev/governance.html" }, - { text: "Upgrade Setup", link: "/dev/upgrade-setup.html" }, - { - text: "Deploy Contracts to Dev", - link: "/dev/dev-contract-deployment.html", - }, - { - text: "Deploy Contracts to Prod", - link: "/dev/prod-contract-deployment.html", - }, - { text: "Off-Chain Agents", link: "/dev/agents/" }, - ], - }, - ]; -} diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css deleted file mode 100644 index b64dddc..0000000 --- a/docs/.vitepress/theme/custom.css +++ /dev/null @@ -1,8 +0,0 @@ -:root { - --c-brand: #4b7bec; - --c-brand-light: #5b8bfc; -} - -.container { - max-width: 60rem !important; -} \ No newline at end of file diff --git a/docs/.vitepress/theme/index.js b/docs/.vitepress/theme/index.js deleted file mode 100644 index 42fe9a9..0000000 --- a/docs/.vitepress/theme/index.js +++ /dev/null @@ -1,4 +0,0 @@ -import DefaultTheme from 'vitepress/theme' -import './custom.css' - -export default DefaultTheme diff --git a/docs/agents/overview.md b/docs/agents/overview.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/agents/processor.md b/docs/agents/processor.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/agents/relayer.md b/docs/agents/relayer.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/agents/updater.md b/docs/agents/updater.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/agents/watcher.md b/docs/agents/watcher.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/brand-kit.md b/docs/brand-kit.md deleted file mode 100644 index f3c3064..0000000 --- a/docs/brand-kit.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: Nomad Brand Kit -lang: en-US ---- - -# Brand kit - - - My HTML Document - - - - - - -

Download

- -
- diff --git a/docs/bridge/domains-testnet.md b/docs/bridge/domains-testnet.md deleted file mode 100644 index 764acda..0000000 --- a/docs/bridge/domains-testnet.md +++ /dev/null @@ -1,35 +0,0 @@ -# Deployed ERC-20 Tokens (Production) - -## Rinkeby - -**Domain ID:** `2000` - -| Name | Symbol | Decimals | Address | -| ------------ | ------ | -------- | ------------------------------------------ | -| Wrapped GLMR | WGLMR | `18` | 0xba8d75BAcCC4d5c4bD814FDe69267213052EA663 | - -
- -## Moonbeam - -**Domain ID:** `1650811245` - -| Name | Symbol | Decimals | Address | -| -------------- | ------ | -------- | ------------------------------------------ | -| Wrapped Ether | WETH | `18` | 0x30D2a9F5FDf90ACe8c17952cbb4eE48a55D916A7 | -| Wrapped BTC | WBTC | `8` | 0x1DC78Acda13a8BC4408B207c9E48CDBc096D95e0 | -| Dai Stablecoin | DAI | `18` | 0xc234A67a4F840E61adE794be47de455361b52413 | -| USD Coin | USDC | `6` | 0x8f552a71EFE5eeFc207Bf75485b356A0b3f01eC9 | -| Tether USD | USDT | `6` | 0x8e70cD5B4Ff3f62659049e74b6649c6603A0E594 | - -## Milkomeda C1 - -**Domain ID:** `25393` - -| Name | Symbol | Decimals | Address | -| -------------- | ------ | -------- | ------------------------------------------ | -| Wrapped Ether | WETH | `18` | 0x5950F9B6EF36f3127Ea66799e64D0ea1f5fdb9D1 | -| Wrapped BTC | WBTC | `8` | 0x48AEB7584BA26D3791f06fBA360dB435B3d7A174 | -| Dai Stablecoin | DAI | `18` | 0x41eAFC40CD5Cb904157A10158F73fF2824dC1339 | -| USD Coin | USDC | `6` | 0x5a955FDdF055F2dE3281d99718f5f1531744B102 | -| Tether USD | USDT | `6` | 0xab58DA63DFDd6B97EAaB3C94165Ef6f43d951fb2 | diff --git a/docs/bridge/domains.md b/docs/bridge/domains.md deleted file mode 100644 index 7659949..0000000 --- a/docs/bridge/domains.md +++ /dev/null @@ -1,119 +0,0 @@ -# Nomad - Deployed Domains - -## Production (Mainnet) - -### Ethereum - -**Domain ID:** `6648936` - -| Name | Symbol | Decimals | Address | Origin | -| ------------ | ------ | -------- | ------------------------------------------ | -------- | -| Wrapped GLMR | WGLMR | `18` | 0xba8d75BAcCC4d5c4bD814FDe69267213052EA663 | Moonbeam | - -### Moonbeam - -**Domain ID:** `1650811245` - -| Name | Symbol | Decimals | Address | Origin | -| -------------- | ------ | -------- | ------------------------------------------ | -------- | -| Wrapped Ether | WETH | `18` | 0x30D2a9F5FDf90ACe8c17952cbb4eE48a55D916A7 | Ethereum | -| Wrapped BTC | WBTC | `8` | 0x1DC78Acda13a8BC4408B207c9E48CDBc096D95e0 | Ethereum | -| Dai Stablecoin | DAI | `18` | 0xc234A67a4F840E61adE794be47de455361b52413 | Ethereum | -| USD Coin | USDC | `6` | 0x8f552a71EFE5eeFc207Bf75485b356A0b3f01eC9 | Ethereum | -| Tether USD | USDT | `6` | 0x8e70cD5B4Ff3f62659049e74b6649c6603A0E594 | Ethereum | -| CQT | CQT | `18` | 0x5130ca61bf02618548dfc3fdef50b50b36b11f2b | Ethereum | -| FRAX | FRAX | `18` | 0x8d6e233106733c7cc1ba962f8de9e4dcd3b0308e | Ethereum | -| FXS | FXS | `18` | 0x21a8daca6a56434bdb6f39e7616c0f9891829aec | Ethereum | - -### Milkomeda C1 - -**Domain ID:** `25393` - -| Name | Symbol | Decimals | Address | Origin | -| -------------- | ------ | -------- | ------------------------------------------ | -------- | -| Wrapped Ether | WETH | `18` | 0x5950F9B6EF36f3127Ea66799e64D0ea1f5fdb9D1 | Ethereum | -| Wrapped BTC | WBTC | `8` | 0x48AEB7584BA26D3791f06fBA360dB435B3d7A174 | Ethereum | -| Dai Stablecoin | DAI | `18` | 0x41eAFC40CD5Cb904157A10158F73fF2824dC1339 | Ethereum | -| USD Coin | USDC | `6` | 0x5a955FDdF055F2dE3281d99718f5f1531744B102 | Ethereum | -| Tether USD | USDT | `6` | 0xab58DA63DFDd6B97EAaB3C94165Ef6f43d951fb2 | Ethereum | -| FRAX | FRAX | `18` | 0x362233f1ef554ca08555ca191b4887c2c3132834 | Ethereum | -| FXS | FXS | `18` | 0xe5e25df85f6a17fc5681dee7b6b080933476630d | Ethereum | -| Wrapped STR | WSTR | `18` | 0x0c2d8604c89d126133bed39967e69272960bc430 | Ethereum | - -### Evmos - -**Domain ID:** `1702260083` - -**wEVMOS9 Contract Address**: [`0xD4949664cD82660AaE99bEdc034a0deA8A0bd517`](https://evm.evmos.org/address/0xD4949664cD82660AaE99bEdc034a0deA8A0bd517) - -| Name | Symbol | Decimals | Address | Origin | -| -------------- | ------ | -------- | ------------------------------------------ | -------- | -| Wrapped Ether | WETH | `18` | 0x5842C5532b61aCF3227679a8b1BD0242a41752f2 | Ethereum | -| Wrapped BTC | WBTC | `8` | 0xF80699Dc594e00aE7bA200c7533a07C1604A106D | Ethereum | -| Dai Stablecoin | DAI | `18` | 0x63743ACF2c7cfee65A5E356A4C4A005b586fC7AA | Ethereum | -| USD Coin | USDC | `6` | 0x51e44FfaD5C2B122C8b635671FCC8139dc636E82 | Ethereum | -| Tether USD | USDT | `6` | 0x7FF4a56B32ee13D7D4D405887E0eA37d61Ed919e | Ethereum | -| FRAX | FRAX | `18` | 0x28eC4B29657959F4A5052B41079fe32919Ec3Bd3 | Ethereum | -| FXS | FXS | `18` | 0xd0ec216A38F199B0229AE668a96c3Cd9F9f118A6 | Ethereum | - -
- -## Development (Testnet) - -### Rinkeby (Testnet) - -**Domain ID:** `2000` - -| Name | Symbol | Decimals | Address | Origin Domain | -| ------------- | ------ | -------- | ------------------------------------------ | ------------- | -| Wrapped Ether | WETH | `18` | 0xf1A137F67aa6aE2FEba192de252f7D4FC244766A | 3000 | -| Test Token | TEST | `18` | 0xf4CF3FcC8dC7E5171Bb08bef75EDe3fEf00F46E6 | 3000 | -| USD Coin | USDC | `6` | 0x238Afa01c004CD2a82908D3B80CF421040601244 | 3000 | -| Wrapped wADA | WWADA | `18` | 0xeBe76a234bC185606601C807352876Ae757b54D5 | 8000 | -| Wrapped MOVR | WMOVR | `18` | 0x6FAe8aee3A8681B604837a72b203A72C93987562 | 5000 | -| Wrapped wADA | WWADA | `18` | 0xc7D9c115e40Bd0a362270A9240975C0009E97c31 | 8000 | -| Random ERC20 | rERC20 | `18` | 0x2D997F0917Ce644B6d31303300913E17178F3F3F | 3000 | -| Wrapped ADA | WADA | `18` | 0xA9aE90E9D541F726ae8Fb39C5172F2c9D09E2E54 | 8000 | -| Wrapped Ether | WETH | `18` | 0x12a89f0Cdf44082aEEF0194924A5280Cc178073A | 9000 | - -
- -### Kovan (Testnet) - -**Domain ID:** `3000` - -| Name | Symbol | Decimals | Address | Origin Domain | -| ------------- | ------ | -------- | ------------------------------------------ | ------------- | -| Wrapped Ether | WETH | `18` | 0x6A8a5FB1bd977849b4fEcFb1e104ABfeB23b440b | 2000 | -| USD Coin | USDC | `6` | 0x10e8BD2aEa9d43439aC072bF4C68Fb41fa6eB73A | 2000 | - -
- -### Moonbase Alpha (Testnet) - -**Domain ID:** `5000` - -| Name | Symbol | Decimals | Address | Origin Domain | -| ------------- | ------ | -------- | ------------------------------------------ | ------------- | -| Wrapped Ether | WETH | `18` | 0x6A8a5FB1bd977849b4fEcFb1e104ABfeB23b440b | 2000 | -| USD Coin | USDC | `6` | 0x10e8BD2aEa9d43439aC072bF4C68Fb41fa6eB73A | 2000 | - -
- -### Milkomeda C1 (Testnet) - -**Domain ID:** `8000` - -| Name | Symbol | Decimals | Address | Origin Domain | -| ------------- | ------ | -------- | ------------------------------------------ | ------------- | -| Wrapped Ether | WETH | `18` | 0x6A8a5FB1bd977849b4fEcFb1e104ABfeB23b440b | 2000 | -| USD Coin | USDC | `6` | 0x10e8BD2aEa9d43439aC072bF4C68Fb41fa6eB73A | 2000 | - -
- -### Evmos (Testnet) - -**Domain ID:** `9000` - -| Name | Symbol | Decimals | Address | Origin Domain | -| ---- | ------ | -------- | ------- | ------------- | diff --git a/docs/bridge/etherscan-native.md b/docs/bridge/etherscan-native.md deleted file mode 100644 index eaf3d56..0000000 --- a/docs/bridge/etherscan-native.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Bridge Using Etherscan -lang: en-US ---- - -# Bridge Native Assets with Etherscan - -Coming soon! \ No newline at end of file diff --git a/docs/bridge/etherscan.md b/docs/bridge/etherscan.md deleted file mode 100644 index 6d978dc..0000000 --- a/docs/bridge/etherscan.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Bridge ERC-20s Using Etherscan -lang: en-US ---- - -# Bridge Tokens with Etherscan - -Coming soon! \ No newline at end of file diff --git a/docs/bridge/faq.md b/docs/bridge/faq.md deleted file mode 100644 index e8aacf4..0000000 --- a/docs/bridge/faq.md +++ /dev/null @@ -1,128 +0,0 @@ ---- -title: FAQs -lang: en-US ---- - -# FAQs - -## Nomad Bridge Features - -### What assets are available to bridge? (updated 01/13/2022) - -The Nomad app at https://app.nomad.xyz supports the following assets. For a complete list of tokens and their addresses see the [Deployed Tokens List](./domains.md). - -* WETH -* ETH -* USDT -* USDC -* DAI -* GLMR -* WGLMR -* WBTC -* FRAX -* FXS - -We are actively adding more assets. If you would like an asset listed, make your voice heard in the Nomad [Discord](https://discord.gg/RurtmJApqm)!! - -### Do you have `` feature? - -We deployed on Jan 11, 2022 🚀 and are adding new features and making updates on a daily basis. Some things we have in the works: - -* Transaction History View -* WalletConnect Support -* Better error messages -* UI improvements - -## Bridging 101 - -### I bridged over my assets with `someOtherBridgeNotNomad`, why can’t I see them? - -Each bridge deploys their own token contracts, so assets bridged using one Bridge A are not compatible with assets bridged using Bridge B, even though they started out with the same original asset. - -If you want to bridge over with Nomad but you've already used another bridge, you'll need to bridge _back_ to the origin chain, and then bridge again with Nomad. This will get you back on track. - -### How long does it take to bridge? - -Bridging using Nomad usually takes around 35 mins, but can be up to +60 mins depending on on- and off- chain activity (see our [docs on the Nomad architecture](../index.md) for more information). - -However, we've partnered with Connext to give users an option to have a faster cross-chain experience! For a small fee, you can use Connext to enable faster transfers--around 7-15 mins! - -### It's been longer than the estimated time--where are my tokens? - -Ocassionally there are times where it takes longer to process a transaction. This could be due to on-chain activity, or a delay in agent processing. - -This could also be due to missing a step in the process, such as when sending assets back to Ethereum. You'll need to manually process the transaction. See [this answer](#why-is-gas-estimate-so-high-to-get-my-funds-on-ethereum). - -### Do I get WETH or ETH? - -You can bridge over WETH or ETH from Ethereum, but you will always receive WETH on the destination. If you bridge over ETH, the contract will automatically call a helper function to wrap your ETH for you. - -If you use Connext to bridge your WETH back to Ethereum, you will receive ETH automatically through the Connext process. - -If you use Nomad to bridge your WETH back to Ethereum, you will receive WETH and will need to unwrap it manually if you want ETH again. - -### Do you have a development/testnet site? - -Yes! It is available at [development.app.nomad.xyz](https://development.app.nomad.xyz) - -## Connext + Nomad ----- -### What is your relationship with Connext? - -Nomad and Connext are complementary pieces that work together to provide a better cross-chain experience for users. Connext is an interoperability protocol that allows users to swap/transact over liquidity that already exists on the chain. Nomad is at its core protocol for passing generalized data between arbitrary chains, and the Nomad Bridge is an application built to pass specific kinds of messages that allow you to bridge tokens. - -Connext routers set up cross-chain liquidity pools for Nomad assets. For a small fee, these liquidity pools allow users to make faster swaps, since the assets have already been bridged over. - -### I bridged using Connext, where are my tokens? - -When you bridge with Connext, you'll need to manually claim your tokens after the transaction has processed. You can claim your transaction using the [Nomad bridge](https://app.nomad.xyz), or you can also use the Connext UI at `https://connextscan.io/tx/` - -## Bridging to Ethereum ------- - -### I'm trying to bridge my assets back to Ethereum and it's taking a long time. - -When you bridge back to Ethereum, you'll need to process the transaction manually to disperse your funds at the end. You can do this by going to: -`https://app.nomad.xyz/tx/nomad//` - -### Why is gas estimate so high to get my funds on Ethereum? - -You need to submit a higher buffer for gas because the function that needs to be called to disperse funds, `proveAndProcess`, is permissionless. If there was no gas buffer, anyone could cancel your transaction by processing it with too-low gas. So the protocol specifies a gas buffer in order to submit the transaction, but in this case, the majority of the gas is not actually used. - -**In actuality, only about 1/5 of the estimated gas is used.** - -Here are a few transactions you can look at to see what the actual cost of the transaction was: -* [Transaction 1](https://etherscan.io/tx/0x60e20861d22a6931d9731e0c00dcd6984857140c86cf83f94be888e7af5bab91) -* [Transaction 2](https://etherscan.io/tx/0x73bae115015885371b295daad8225493571b6963f550cd1d7b009c00921b9b91) - -You can also look through the [contract](https://etherscan.io/address/0x049b51e531fd8f90da6d92ea83dc4125002f20ef) for the transactions that called the `Prove And Process` method for further verification. - -## General - -### What is Nomad's security model? How does it compare to other well-known models, such as header verification? - -Every cross-chain message passing system is going to have tradeoffs, and we've carefully considered how security is affected with design choices. Nomad adopts an optimistic mechanism inspired by optimistic roll-ups like Optimism and Arbitrum, which is a different approach than block header verification. You can read a little bit more about the benefits and tradeoffs of this kind of architecture in our [docs](https://docs.nomad.xyz/#benefits-and-trade-offs-of-the-nomad-architecture). - -### Wen token? - -Nomad does not have a token at this time. If you hear any references to a Nomad token, they are definitely scams. - -### What is madWETH? - -These are the same assets! Often times applications will prefix assets depending on the bridge that was used. Nomad assets are listed with either no prefix (WETH), or the mad- prefix (madWETH). We prefer to use no prefix or the mad- prefix and will kindly ask applications to change this for us, but sometimes there may be a delay in this change. - -### Why does my recently-bridged token have a funny name like `0006648936.eb48`? - -In order to avoid sending redundant data like the token name and symbol with every message, the first time a bridged ERC-20 Token representation is deployed, metadata is pulled from the originating chain after initial deployment. This involves a round-trip between the replica and originating chain wherein data about name/symbol/decimals is synced. - -This is expected behavior, and the explorer will update after a day or two. - -### Why is the ERC-20 token placeholder name like that? - -`0006648936.eb48` is the Nomad domain ID for Ethereum and the last 4 letters of the token address on Ethereum - -`6648936 == 0x657468` -- the utf8 encoding of 'eth' - -USDC's address is `0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48` - -Note the `eb48` at the end. diff --git a/docs/bridge/index.md b/docs/bridge/index.md deleted file mode 100644 index 0f76821..0000000 --- a/docs/bridge/index.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Bridging with Nomad -lang: en-US ---- - -# Bridging with Nomad - -* [Nomad Bridge](../index.md) - * Nomad Web UIs - * [Nomad GUI](./nomad-gui.md) - * [Testnet GUI](https://development.app.nomad.xyz) - * Manually Using Etherscan - * [Bridge Native Tokens via Etherscan](./etherscan-native.md) - * [Bridge ERC-20 Tokens via Etherscan](./etherscan.md) - -

Nomad is a novel new cross-chain protocol. Please only bridge funds to the extent that you feel comfortable deploying on chain.

diff --git a/docs/bridge/nomad-gui.md b/docs/bridge/nomad-gui.md deleted file mode 100644 index bf5c3c4..0000000 --- a/docs/bridge/nomad-gui.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Nomad Bridge GUI -lang: en-US ---- - -# Nomad Bridge GUI - -## Nomad vs Connext, which should I use? - -There are two options available to send funds through the GUI, Nomad and Connext. These are two distinct protocols that are complimentary to one another. We have partnered with Connext to provide an optimal experience for users! - -Nomad is a secure gas efficient cross-chain protocol that allows users to bridge funds between networks. This takes, on average, 35-60 minutes. There are no fees associated with Nomad, just pay gas! Connext provides liquidity pools for Nomad assets, meaning users can receive funds on the destination chain much faster (less than 10 minutes) for an additional fee. Nomad is advised for large transfers. - -Connext is not available for every asset and may not be available for larger sums. We recommend using Nomad if you intend to send large transfers. - -## Bridging Through Nomad - -Bridging assets across chains using Nomad should be intuitive and easy with the Nomad GUI. In this tutorial, we will walk through the steps required to bridge your assets. - -Please find our production bridge GUI at [app.nomad.xyz](https://app.nomad.xyz/). - -If you would like to test our bridge using testnet funds before using real funds, please visit our development GUI at [development.app.nomad.xyz](https://development.app.nomad.xyz/). - -
- -Connect to Metamask: - -![Connect to Metamask](../public/tutorials/bridge-gui/connect-metamask.png) - -
- -Select origin and destination networks: - -![Select Origin and Destination Networks](../public/tutorials/bridge-gui/select-networks.png) - -
- -(Optional) Change Destination address. This is set as your wallet address by default. Click "edit". A modal will pop up, click "change" inside the input. Then copy your address, click to paste, and save. -::: warning CAUTION -Sending assets to an address you do not control can result in a permanent loss of funds! -::: - -![Change Destination](../public/tutorials/bridge-gui/change-dest-1.png) -![Paste Destination](../public/tutorials/bridge-gui/change-dest-2.png) - -
- -Select the asset you want to send using the asset dropdown menu and the amount you want to send using the input prompt: - -![Select an Asset and Amount](../public/tutorials/bridge-gui/select-token.png) - -
- -Click `Next`: - -![Select an Asset and Amount](../public/tutorials/bridge-gui/input-data.png) - -
- -Review your transaction details and associated fees. Check if Connext liquidity is available for your transfer for a faster bridging experience! If proceeding with Connext, continue reading [here](#fast-transfers-with-connext). - -![Approve Bridge Transaction](../public/tutorials/bridge-gui/review.png) - -
- -Click `Bridge Tokens` and approve the transaction in Metamask: - -![Approve Bridge Transaction](../public/tutorials/bridge-gui/sending.png) - -
- -After approving the transaction, you will be taken to the transaction details page. Here, you will see the estimated time remaining for your transfer to complete. Please save your transaction hash for convenience. If you lose it, you can visit your wallet address on the block explorer of the origin network and find the transaction again. - -::: info -You must return to the Transaction Page after bridging has concluded to pay for gas and complete your transfer. Nomad may cover the processing and gas fees for some chains. -::: - -![See Transaction Details](../public/tutorials/bridge-gui/transfer-pending.png) - -
- -You can expand the time estimate tab to track your transaction status by clicking the down arrow in the blue box: - -![See Expanded Transaction Details](../public/tutorials/bridge-gui/expand-status.png) - -
- -(Optional) If you navigated away from the GUI at any point and want to find your transfer's progress page again, visit [https://app.nomad.xyz/tx](https://app.nomad.xyz/tx) and enter the origin network and your transfer's transaction hash. - -![Search Tx](../public/tutorials/bridge-gui/search-transfer.png) - -
- -Once your transfer has completed, you should see the below display and your funds will be in the account of your destination address. If your transfer is taking longer than expected, please reach out to us on [Discord](https://discord.gg/RurtmJApqm) in the #support channel: - -![Finished](../public/tutorials/bridge-gui/transfer-complete.png) - -
- -## Completing a Transfer (Ethereum Destination Only) - -If you are sending to Ethereum, there is one additional processing step due to the high cost of processing transactions on Ethereum. You will see the following display and should click "Complete Transfer" and complete the Metamask transaction. After this, your funds should be at your destination on Ethereum! - -![Self Process](../public/tutorials/bridge-gui/complete-transfer.png) - -
- -## Fast Transfers with Connext - -Fill out data for your transfer and click "Next." Select "Connext." If there is liquidity available for your transfer, it will calculate associated fees for your transaction. Note that Connext collects gas fees in the asset that is being sent. - -If there is not liquidity available, you can continue by using Nomad. - -![Self Process](../public/tutorials/bridge-gui/check-connext.png) - -Click `Send` and approve the transaction in Metamask! - -In a few minutes, you will see your transfer appear in a table below. Click "Claim" to submit a transaction to receive your funds on the destination chain. - -Click "View" to go to your transaction in the ConnextScan block explorer. Or you can visit `https://connextscan.io/tx/`. - -![Claim Connext funds](../public/tutorials/bridge-gui/connext-claim.png) diff --git a/docs/bridge/resources.md b/docs/bridge/resources.md deleted file mode 100644 index 1182622..0000000 --- a/docs/bridge/resources.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: FAQs -lang: en-US ---- - -# Resources - -- [Deployed Tokens List](domains.md) diff --git a/docs/build/agents.md b/docs/build/agents.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/build/checklist.md b/docs/build/checklist.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/build/invariants.md b/docs/build/invariants.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/build/overview.md b/docs/build/overview.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/build/sdk.md b/docs/build/sdk.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/build/smart-contracts.md b/docs/build/smart-contracts.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/dev/agents/agent-development.md b/docs/dev/agents/agent-development.md deleted file mode 100644 index b15342e..0000000 --- a/docs/dev/agents/agent-development.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -title: Agent Development -lang: en-US ---- - -# Developing the Agents - -## Configuration - -Agents read settings from the config files and/or env. - -Config files are loaded from `rust/config/default` unless specified otherwise. Currently deployment config directories are labeled by the timestamp at which they were deployed - -Configuration key/value pairs are loaded in the following order, with later sources taking precedence: - -1. The config file specified by the `RUN_ENV` and `BASE_CONFIG` env vars. `$RUN_ENV/$BASE_CONFIG` -2. The config file specified by the `RUN_ENV` env var and the agent's name. `$RUN_ENV/{agent}-partial.json`. - E.g. `$RUN_ENV/updater-partial.json` -3. Configuration env vars with the prefix `OPT_BASE` intended to be shared by multiple agents in the same environment - E.g. `export OPT_BASE_REPLICAS_KOVAN_DOMAIN=3000` -4. Configuration env vars with the prefix `OPT_{agent name}` intended to be used by a specific agent. - E.g. `export OPT_KATHY_CHAT_TYPE="static message"` - -## Building an Agent for Development - -For contributing to the Rust codebase, it is advantageous and preferable to build agents using your host dev environment. As mentioned in the previous section, configuration precedence is your friend here. You can specify the base config json to use, and then override variables via the environment. - -Below is a sample env file with appropriate variables to run an agent instance against the development environment. - -Note: You will need to fetch dev keys (or generate your own via a contract deployment) for this to work properly. - -``` -RUN_ENV=1625169020727 -OPT_BASE_TRACING_LEVEL=info - -OPT_UPDATER_UPDATER_KEY= - -OPT_UPDATER_DB=updaterdb -OPT_RELAYER_DB=relayerdb -OPT_KATHY_DB=kathydb - -OPT_KATHY_SIGNERS_ALFAJORES_KEY= -OPT_UPDATER_SIGNERS_ALFAJORES_KEY= -OPT_RELAYER_SIGNERS_ALFAJORES_KEY= -OPT_PROCESSOR_SIGNERS_ALFAJORES_KEY= - -OPT_KATHY_SIGNERS_KOVAN_KEY= -OPT_UPDATER_SIGNERS_KOVAN_KEY= -OPT_RELAYER_SIGNERS_KOVAN_KEY= -OPT_PROCESSOR_SIGNERS_KOVAN_KEY= -``` - -Lets walk through the variables here: - -`RUN_ENV` - Specifies the config folder to load configuration from, defaults to `default`. -`OPT_BASE_TRACING_LEVEL` - Specifies the log level the agents should boot up with. -`OPT_UPDATER_UPDATER_KEY` - The Updater attestation key. - - - -For a full list of potentially useful common environment variables, check out the Agent Helm Chart's [ConfigMap](https://github.com/nomad-xyz/nomad-monorepo/blob/main/rust/helm/nomad-agent/templates/configmap.yaml#L8-L34) - -Agents also have role-specific environment variables in their StatefulSet definitions: -- [Updater](https://github.com/nomad-xyz/nomad-monorepo/blob/main/rust/helm/nomad-agent/templates/updater-statefulset.yaml#L54-L89) -- [Relayer](https://github.com/nomad-xyz/nomad-monorepo/blob/main/rust/helm/nomad-agent/templates/relayer-statefulset.yaml#L54-L74) -- [Processor](https://github.com/nomad-xyz/nomad-monorepo/blob/main/rust/helm/nomad-agent/templates/processor-statefulset.yaml#L54-L74) -- [Kathy](https://github.com/nomad-xyz/nomad-monorepo/blob/main/rust/helm/nomad-agent/templates/kathy-statefulset.yaml#L54-L74) - -To run an agent, you can use the following command: -`BASE_CONFIG=kovan_config.json env $(cat ../tmp.env | xargs) cargo run --bin ` - -This will build the codebase and run the specified `` binary using the provided environment variables. - -## Production Builds - -It is important when making changes to the Rust codebase, to ensure the Docker build used in production environments still works. You can check this automatically in CI as it is built on every PR ([see docker workflow here](https://github.com/nomad-xyz/nomad-monorepo/blob/main/.github/workflows/docker.yml)), however you can check it much faster usually by attempting to build it locally. - -You can build the docker image by running the following script in the `rust` directory: - -`./build.sh latest` - -If that goes smoothly, you can rest assured it will most likely also work in CI. diff --git a/docs/dev/agents/agent-operations.md b/docs/dev/agents/agent-operations.md deleted file mode 100644 index a68b135..0000000 --- a/docs/dev/agents/agent-operations.md +++ /dev/null @@ -1,339 +0,0 @@ ---- -title: Agent Operations -lang: en-US ---- - -# Agent Operations - -## Deployment Environments - -There will exist several logical deployments of Nomad to enable us to test new code/logic before releasing it to Mainnet. Each environment encompasses the various Home/Replica contracts deployed to many blockchains, as well as the agent deployments and their associated account secrets. - -The environments have various purposes and can be described as follows: - -### Development - -Purpose: Allows us to test changes to contracts and agents. *Bugs should be found here.* - -- Deployed against testnets -- Agent Accounts: HexKeys stored in a secret manager for ease of rotation/access -- Agent Infrastructure: Nomad core team will operate agent infrastructure for this. -- Node Infrastructure: Forno/Infura -- Agent Deployments: Automatic, continuous deployment -- Contract Deployments: Automatic, with human intervention required for updating the **upgradeBeacon**. - -**Current Dev Contract Deployment:** - -[development](https://github.com/nomad-xyz/nomad-monorepo/rust/config/development/) - -### Staging - -Purpose: Allows us to test the full-stack integration, specifically surrounding the KMS access control and federated secret management. *Issues with process should be found here.* - -- Deployed against testnets, mirrors Mainnet deployment. -- Agent Accounts: KMS-provisioned keys -- Agent Infrastructure: Agent operations will be decentralized -- Node Infrastructure: Node infrastructure will be decentralized -- Agent Deployments: Determined by whoever is running the agents -- Contract Deployments: Automatic, with human intervention required for updating the **upgradeBeacon**. - -**Current Staging Contract Deployment:** - -[staging](https://github.com/nomad-xyz/nomad-monorepo/rust/config/staging/) - -### Production - -Purpose: Where the magic happens, **things should not break here.** - -- Deployed against Mainnets -- Agent Accounts: KMS-provisioned keys -- Agent Infrastructure: Agent operations will be decentralized -- Node Infrastructure: Node infrastructure will be decentralized -- Agent Deployments: Determined by whoever is running the agents -- Contract Deployments: ***Manual*** - Existing tooling can be used, but deploys will be gated and require approval as contract deployments are expensive on Mainnet. - -**Current Production Contract Deployment:** - -[mainnet](https://github.com/nomad-xyz/nomad-monorepo/rust/config/mainnet/) - -## Key Material - -Keys for Staging and Production environments will be stored in AWS KMS, which is a highly flexible solution in terms of granting access. It guarantees nobody will ever have access to the key material itself, while still allowing granular permissions over access to remote signing. - -At the outset, the Nomad team will have full control over agent keys, and any contracted party will simply be granted access through existing IAM tooling/roles. - -### Provision KMS Keys - -There exists a script in the monorepo [(`rust/provision_kms_keys.py`)](https://github.com/nomad-xyz/nomad-monorepo/blob/main/rust/provision_kms_keys.py) that facilitates KMS key provisioning for agent roles. - -The script will produce a single set of keys per "environment." Where an __environment__ is a logical set of smart contract deployments, as documented [here](#deployment-environments). By default there are two environments configured, `staging` and `production`. - -#### Keys Explained - -**Transaction Signers** - -One signer key should be provisioned for each agent per-network. These keys are used to sign transactions on the respective networks Nomad is deployed to. - -**Attestation Signers** - -One additional key is provisioned for both the Watcher and Updater Agents. The Updater uses its key to sign updates to its assigned Home contract, while the Watcher uses its key to sign fraud proofs when it observes the Updater commiting fraud. - -Note: Attestation signer addresses are used as input to the contract deployment process. They can be configured in the `nomad-deploy` package [like so](https://github.com/nomad-xyz/nomad-monorepo/blob/main/typescript/nomad-deploy/config/testnets/kovan.ts#L28-L30). - -You may configure the script to generate arbitrary signer keys on a per-environment basis. -```python -# Agent Keys -agent_keys = { - "staging": [ - "watcher-signer", - "watcher-attestation", - "updater-signer", - "updater-attestation", - "processor-signer", - "relayer-signer", - "kathy-signer" - ], - "production": [ - "watcher-signer", - "watcher-attestation", - "updater-signer", - "updater-attestation", - "processor-signer", - "relayer-signer", - ] -} -``` - -Additionally, the supported networks for each environment are configured below. -```python -networks = { - "production": [ - "ethereum", - "moonbeam", - "evmos" - ], - "staging": [ - "moonbasealpha", - "kovan" - ] -} -``` - - -#### Run the Key Provisioning Script - -```bash -AWS_ACCESS_KEY_ID=accesskey AWS_SECRET_ACCESS_KEY=secretkey python3 provision_kms_keys.py -``` - -If the required keys are not present, the script will generate them. If they keys _are_ present, their information will be fetched and displayed non-destructively. - -Upon successful operation, the script will output a table of the required keys, their ARNs, ETH addresses (for funding the accounts), and their regions. - -#### Provision IAM Policies and Users - -This is an opinionated setup that works for most general agent operations use-cases. The same permissions boundaries can be achieved through different means, like using only [Key Policies](https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html) - -Background Reading/Documentation: - -- [KMS Policy Conditions](https://docs.aws.amazon.com/kms/latest/developerguide/policy-conditions.htm) -- [KMS Policy Examples](https://docs.aws.amazon.com/kms/latest/developerguide/customer-managed-policies.html) -- [CMK Alias Authorization](https://docs.aws.amazon.com/kms/latest/developerguide/alias-authorization.html) - -The following sequence describes how to set up IAM policies staging and production deployments. - -- Create two users - - nomad-signer-staging - - nomad-signer-production - - kms-admin - - Save IAM credential CSV -- Create staging signer policies - - staging-processor-signer - - staging-relayer-signer - - staging-updater-signer - - staging-watcher-signer - - With the following policy, modified appropriately: - - ```json - { - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "NomadStagingPolicy", - "Effect": "Allow", - "Action": [ - "kms:GetPublicKey", - "kms:Sign" - ], - "Resource": "arn:aws:kms:*:11111111111:key/*", - "Condition": { - "ForAnyValue:StringLike": { - "kms:ResourceAliases": "alias/staging-processor*" - } - } - } - ] - } - ``` - - - production-processor-signer - - production-relayer-signer - - production-updater-signer - - production-watcher-signer - - With the following policy, modified appropriately: - - ```json - { - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "NomadProductionPolicy", - "Effect": "Allow", - "Action": [ - "kms:GetPublicKey", - "kms:Sign" - ], - "Resource": "arn:aws:kms:*:11111111111:key/*", - "Condition": { - "ForAnyValue:StringLike": { - "kms:ResourceAliases": "alias/production-processor*" - } - } - } - ] - } - ``` - -- Create kms-admin policy - - ```json - { - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "KMSAdminPolicy", - "Effect": "Allow", - "Action": [ - "kms:DescribeCustomKeyStores", - "kms:ListKeys", - "kms:DeleteCustomKeyStore", - "kms:GenerateRandom", - "kms:UpdateCustomKeyStore", - "kms:ListAliases", - "kms:DisconnectCustomKeyStore", - "kms:CreateKey", - "kms:ConnectCustomKeyStore", - "kms:CreateCustomKeyStore" - ], - "Resource": "*" - }, - { - "Sid": "VisualEditor1", - "Effect": "Allow", - "Action": "kms:*", - "Resource": [ - "arn:aws:kms:*:756467427867:alias/*", - "arn:aws:kms:*:756467427867:key/*" - ] - } - ] - } - ``` - - - Create IAM groups - - staging-signer - - production-signer - - kms-admin - - Add previously created users to the corresponding groups - - nomad-signer-staging -> staging-signer - - nomad-signer-production -> production-signer - - kms-admin -> kms-admin - -## Funding Addresses - -Each agent should be configured with a unique wallet to be used to signing transactions and paying gas. In order to automate the process of monitoring and topping up agent wallets, the Nomad core team built a CLI tool called [The Keymaster](the-keymaster.md). - -The Keymaster, upon configuration, enables the manual one-off topping up of agent wallets on an arbitrary number of netorks. Additionally, it is capable of running this functionality as a service, topping up accounts on an interval and exposing prometheus metrics about the addresses it is monitoring for use in dashboards. - -## Self-Service Proofs in S3 - -In order to facilitate users processing their own proofs in the GUI, agents (specifically the Processor), have the functionality to upload raw proofs to an AWS S3 bucket. In the default configuration, the bucket is publicly accessible and allows end-users to fetch them via the GUI and submit them in a transaction to the apropriate blockchain. - -### Pre-Requisites -- AWS Account -- Agent Infrastructure - -### Bucket Setup - -Setup is simple, create a bucket in your desired region via the AWS UI, ensuring to uncheck "Block Public Access" as the desired outcome is for the contents of this bucket to be publicly accessible on the internet. - -Use the following bucket policy to enable public access to `s3:getObject` in your newly created bucket: - -``` -{ - "Version": "2012-10-17", - "Id": "S3PublicRead", - "Statement": [ - { - "Sid": "IPAllow", - "Effect": "Allow", - "Principal": "*", - "Action": "s3:getObject", - "Resource": "arn:aws:s3:::/*" - } - ] -} -``` - -### AWS IAM Permissions - -NOTE: Currently, Agents only support a single AWS key for both KMS Signing and S3 Upload. This enforces a non-functional requirement that the S3 bucket proofs are uploaded to and the KMS keys used to sign transactions are in the same logical AWS account. - -Create an IAM policy that allows a user to write to the S3 bucket you created in the previous step: - -``` -{ - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "ListObjectsInBucket", - "Effect": "Allow", - "Action": [ - "s3:ListBucket" - ], - "Resource": [ - "arn:aws:s3:::" - ] - }, - { - "Sid": "AllObjectActions", - "Effect": "Allow", - "Action": "s3:*Object*", - "Resource": [ - "arn:aws:s3:::/*" - ] - } - ] -} -``` - -Attach this policy to an IAM user and provision/download AWS keys. - -### Configuring the Agent - -The Processor agent has special config for S3 proof indexing, located in the code [here](https://github.com/nomad-xyz/nomad-monorepo-archive/blob/main/rust/agents/processor/src/settings.rs#L9-L24). - -Buckets can be configured at agent runtime via the following environment variables: - -`OPT_PROCESSOR_S3_BUCKET` -> Name of the bucket. Ex. `nomadxyz-development-proofs` -`OPT_PROCESSOR_S3_REGION` -> AWS region the bucket lives in. Ex. `us-west-1` - -If you are using the helm chart, these values can be passed via [`values.yaml`](https://github.com/nomad-xyz/nomad-monorepo/blob/main/rust/helm/nomad-agent/values.yaml#L147-L149) like so: - -``` -processor: -... - s3Proofs: - bucket: nomadxyz-development-proofs - region: us-west-1 -``` \ No newline at end of file diff --git a/docs/dev/agents/debug-agents.md b/docs/dev/agents/debug-agents.md deleted file mode 100644 index b5d13c1..0000000 --- a/docs/dev/agents/debug-agents.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Debugging Agents using Grafana -lang: en-US ---- - -# Nomad Bridge GUI - -As much as we'd like agents to run smoothly 24/7 without a hitch, in practice, this doesn't always happen. As we deploy to new networks, bugs in both our code and those of our RPC providers will surface over time. This tutorial examines a hypothetical example regression and to how to use Grafana dashboards and logs to debug the issue. - -## Example Investigation - -At a high level, these are the steps to debugging a regression: - -1. Identify a regression and its time window. -2. Examine that time window in other dashboards for any immediate hints. -3. Query logs and reference the code to identify the root cause of the error or stall. - -
- -We will go through these steps in more detail below, starting with identifying a regression. - -The most important birds-eye-view dashboard for initially spotting a regression is the `Bridge Health `dashboard. This dashboard tracks the number of outstanding, unprocessed messages and the number of processed messages. If our agents are keeping up with processing messages, these lines should always follow each other and should never diverge. - -First navigate to the Bridge Health dashboard as shown below. On the main page, click on the `Search dashboards` tab on the far left. - -![Find Explore](../public/../../public/tutorials/debug-agents/find-dashboards.png) - -
- -Now find the Bridge Health dashboard among the listed dashboards. - -![Find Bridge Health](../public/../../public/tutorials/debug-agents/find-bridge-health.png) - -
- -Now that we have the `Bridge Health` dashboard in front of us, we spot a regression. In the highlighted region, we see that while the number of unprocessed messages continued increasing, the number of processed messages did not, meaning that there was a some kind of stall. This is almost always what regressions look like. - -![Regression Found](../public/../../public/tutorials/debug-agents/identify-regression.png) - -
- -Highlight the regression to zoom in. We can already see a plethora of errors emitted during the stall in the error graph below the regression. More importantly, by highlighting the regression, we have identified the start and end timestamps for which the regression occurred (see top right corner). - -![Regression Zoom](../public/../../public/tutorials/debug-agents/zoom-in-regression.png) - -
- -Now that we know the general timestamp of the regression, we know where to look in other dashboards and in logs. Lets take a look at the `Agents` dashboard to see if we can find anything. This dashboard shows several agent-specific metrics and the activity rates of each agent. Navigate back to the Grafana home page and find the `Agents` dashboard in the same way we found the `Bridge Health` dashboard. - -
- -Once you have navigated to the `Agents` dashboard, copy-paste the regression timestamps into the timestamp window in the top right. This will narrow our examination window. - -![Agents Timestamp Paste](../public/../../public/tutorials/debug-agents/agents-timestamp-paste.png) - -
- -Once we've narrowed our time window, let's look at the processor `next_message_nonce` metric. This metric tracks what message a given processor is currently on for each channel. The `next_message_nonce` should be moving up and to the right if all is healthy. In the highlighted region, however, it looks it looks like the Moonbase processor metric stopped being reported. - -![Zoom Agent Regression](../public/../../public/tutorials/debug-agents/agents-no-zoom.png) - -
- -Lets zoom in even more to see the discontinued reporting. - -![Zoom Agent Regression](../public/../../public/tutorials/debug-agents/agents-regression-zoom.png) - -
- -Now that we have a better idea of what our issue might be, let's check if our hypothesis about crash looping is correct using Grafana logs. Navigate back to the Grafana home page and find the `Explore` tab on the far left. - -![Find Explore](../public/../../public/tutorials/debug-agents/find-explore.png) - -
- -You should see a prompt at the top where you can write log queries. To query Grafana logs, we write Loki queries. For more details on writing Loki queries to narrow down your searches, see this [cheat sheet](https://grafana.com/docs/loki/latest/logql/log_queries/). Here, we just want a simple query that shows all logs during the time window for the Moonbase processor (see query in prompt). - -![Write Query](../public/../../public/tutorials/debug-agents/enter-agent-pod-and-timestamp.png) - -
- -If we look at our query results, we can see, the Moonbase processor is indeed crash looping with some error about a local root mismatch. This is when we would go back to the codebase and piece together the root cause of the error. The same applies for stalls that are not emitting explicit errors. - -![Error Logs](../public/../../public/tutorials/debug-agents/log-errors.png) - -
- -While we are not going to actually debug this regression, you get the idea. To reiterate, the general steps are to: - -1. Identify a regression and its time window. -2. Examine that time window in other dashboards for any immediate hints. -3. Query logs and reference the code to identify the root cause of the error or stall. - -
- -In an ideal world, nobody has to go through these steps but errors and stalls are inevitable in the messy world of off-chain operations. With that said, happy debugging! diff --git a/docs/dev/agents/index.md b/docs/dev/agents/index.md deleted file mode 100644 index 748f718..0000000 --- a/docs/dev/agents/index.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Developer Resources -lang: en-US ---- - -# Agent Resources - -- [Agent Development](./agent-development.md) - How to Contribute to the Agent Codebase -- [Agent Operations](./agent-operations.md) - How to Run Agents in Production -- [Agent Debugging](./debug-agents.md) - Runbook for Debugging Agent Regressions -- [The Keymaster](./the-keymaster.md) - Tooling for Agent Wallets diff --git a/docs/dev/agents/the-keymaster.md b/docs/dev/agents/the-keymaster.md deleted file mode 100644 index bcd6241..0000000 --- a/docs/dev/agents/the-keymaster.md +++ /dev/null @@ -1,105 +0,0 @@ -# The Keymaster - -[_I am Vinz, Vinz Clortho, Keymaster of Gozer...Volguus Zildrohoar, Lord of the Seboullia. Are you the Gatekeeper?_](https://www.youtube.com/watch?v=xSp5QwKRwqM) - -![Keymaster from Ghostbusters](https://i.pinimg.com/originals/9d/5b/a0/9d5ba02875ce7921d092038d1543b1f4.jpg) - -## Summary - -The Keymaster is a tool that is used to manage funds for Nomad Agent Wallets. Due to the sheer number of networks Nomad supports, and the necessity for having a unique set of keys for each home, managing funds and ensuring agents can continue to function quickly becomes difficult as the network of Nomad channels grows. - -Example: - -For 4 homes (alfajores, kovan, rinkeby, rinkarby) with 5 addresses each (kathy, watcher, updater, processor, relayer), this means there will be 20 unique addresses and each address has to be funded on each network resulting in 20 \* 4 = 80 unique accounts across all networks which must be funded and topped up regularly. - -Generalized: num_homes^2 \* num_addresses - -The Keymaster stores metadata about addresses, sources of funds, network RPC endpoints, and more to facilitate solving this problem. - -## Using The Keymaster - -Note: Before you do _anything_, [call the Ghostbusters](https://www.youtube.com/watch?v=Fe93CLbHjxQ). - -The Keymaster is a simple Python-based CLI program, the entrypoint is `keymaster.py` - -Install the requirements via pip: - -`pip3 install -r requirements.txt` - -The Keymaster can be invoked via `python3` like so: - -``` -$ python3 keymaster.py --help -Usage: keymaster.py [OPTIONS] COMMAND [ARGS]... - -Options: - --debug / --no-debug - --config-path TEXT - --help Show this message and exit. - -Commands: - top-up -``` - -Subcommands can be invoked by passing them as arguments to the CLI: - -``` -$ python3 keymaster.py top-up --help -Usage: keymaster.py top-up [OPTIONS] - -Options: - --help Show this message and exit. -``` - -## Configuration File - -The Keymaster relies on a JSON configuration file, by default located at `./keymaster.json`. You can pass a new path to the file using the `--config-path` argument. - -An example can be found at `./keymaster-example.json` and its contents are repeated here for convenience: - -``` -{ - "networks": { - "alfajores": { - "endpoint": "https://alfajores-forno.celo-testnet.org", - "bank": { - "signer": "", - "address": "
" - }, - "threshold": 500000000000000000 - }, - "kovan": { - "endpoint": "", - "bank": { - "signer": "", - "address": "
" - }, - "threshold": 500000000000000000 - } - }, - "homes": { - "alfajores": { - "replicas": ["kovan"], - "addresses": { - "kathy": "
", - "watcher": "
", - "updater": "
", - "relayer": "
", - "processor": "
" - } - }, - "kovan": { - "replicas": ["alfajores"], - "addresses": { - "kathy": "
", - "watcher": "
", - "updater": "
", - "relayer": "
", - "processor": "
" - } - } - } -} -``` - -In the `top-up` command, The Keymaster will load the contents of this file and use it to dynamically query the configured accounts and determine if they need to be topped up. \ No newline at end of file diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md deleted file mode 100644 index 4b3a59f..0000000 --- a/docs/dev/architecture.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: Architecture -lang: en-US ---- - -# Nomad Architecture - -## Components - -![Nomad Architecture Diagram](/Nomad-Architecture.png) - -Nomad has several logical components: - -- Home - The on-chain contract responsible for producing the message tree -- Replica - The on-chain contract responsible for replicating the message root on some other chain -- Updater - The off-chain participant responsible for submitting updates to the home chain -- Watcher - The off-chain participant responsible for observing a replica, and submitting fraud proofs to the home chain -- Relayer - The off-chain participant responsible for submitting updates to a replica -- Processor - The off-chain participant responsible for causing messages to be processed - -### On-chain (Contracts) - -#### Home - -The home contract is responsible for managing production of the message tree and holding custody of the updater bond. It performs the following functions: - -1. Expose a "send message" API to other contracts on the home chain -2. Enforce the message format -3. Commit messages to the message tree -4. Maintain a queue of tree roots -5. Hold the updater bond -6. Slash on double-update proofs (not implemented) -7. Slash on improper update proofs (not implemented) -8. Future: manage updater rotation/bond -9. Future: recover from `FAILED` state - -#### Replica - -The replica contract is responsible for managing optimistic replication and dispatching messages to end recipients. It performs the following functions: - -1. Maintain a queue of pending updates -2. Finalize updates as their timeouts elapse -3. Accept double-update proofs -4. Validate message proofs -5. Enforce the message format -6. Dispatch messages to their destination -7. Expose a "disconnect" feature -8. Future: recover from `FAILED` state - -### Off-chain (Agents) - -#### Updater - -The updater is responsible for signing attestations of new roots. It is an off-chain actor that does the following: - -1. Observe the home chain contract -2. Sign attestations to new roots -3. Publish the signed attestation to the home chain -4. Future: manage Updater bond - -#### Watcher - -The watcher observes the Updater's interactions with the Home contract (by watching the Home contract) and reacts to malicious or faulty attestations. It also observes any number of replicas to ensure the Updater does not bypass the Home and go straight to a replica. It is an off-chain actor that does the following: - -1. Observe the home -2. Observe 1 or more replicas -3. Maintain a DB of seen updates -4. Submit double-update proofs -5. Submit invalid update proofs -6. If configured, issue an emergency halt transaction - -#### Relayer - -The relayer forwards updates from the home to one or more replicas. It is an off-chain actor that does the following: - -1. Observe the home -2. Observe 1 or more replicas -3. Polls home for new signed updates (since replica's current root) and submits them to replica -4. Polls replica for confirmable updates (that have passed their optimistic time window) and confirms if available (updating replica's current root) - -#### Processor - -The processor proves the validity of pending messages and sends them to end recipients. It is an off-chain actor that does the following: - -1. Observe the home -2. Generate and submit merkle proofs for pending (unproven) messages -3. Maintain local merkle tree with all leaves -4. Observe 1 or more replicas -5. Maintain list of messages corresponding to each leaf -6. Dispatch proven messages to end recipients diff --git a/docs/dev/dev-contract-deployment.md b/docs/dev/dev-contract-deployment.md deleted file mode 100644 index d69f9de..0000000 --- a/docs/dev/dev-contract-deployment.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: Dev Contract Deployment -lang: en-US ---- - -# Deploying Dev Setup - -This section goes through the steps of adding a new development network to `nomad-deploy` and deploying a new set of dev contracts. If you will not be adding a new network, please skip to [Deploying the Contracts to Dev](#deploying-the-contracts-to-dev). If you are looking to deploy a new network to the production setup, please refer to the separate page on deploying new contracts to production. - -## Add a New Network Config - -If you are looking to add a new network to your dev setup, you will need to create a new config file for that network in `typescript/nomad-deploy/config/testnets`. - -1. Copy the contents of one of the existing network's files into a new file titled `.ts`. -2. Rename the `process.env` variables (deployer key and RPC URL) such that they pull from the `.env` variables for your new network. -3. Set the `chainJson` fields appropriately. For dev, this usually just means updating the following fields: `name`, `domain`, `timelag`. -4. Set the `devConfig` and `stagingConfig` object fields appropriately. In practice, for dev, you leave `devConfig` the same and only update `stagingConfig.optimisticSeconds`. - -## Writing a New Deploy Script - -Now that you've added a new network config, you must write a new deploy script that includes your new network. - -1. Duplicate the contents of an existing folder in `typescript/nomad-deploy/scripts` (`core.ts` and `bridge.ts`) and put them in a new folder for your new deploy script. -2. In `core.ts` and `bridge.ts` adjust any import paths to pull in your new network config from `typescript/nomad-deploy/config/testnets`. -3. Add or remove any other existing networks in `core.ts` and `bridge.ts` and ensure that the `CoreDeploy` objects for the desired networks are used in the `deployTwoChains` or `deployNChains` calls at the bottom of the files. -4. Add new npm scripts to `typescript/nomad-deploy/package.json` that execute your new `core.ts` and `bridge.ts` files. The scripts will look like the following: - -``` -"scripts": { - ... - "deploy--core": npx ts-node scripts//core.ts, - "deploy--bridge": npx ts-node scripts//bridge.ts - ... -} -``` - -## Deploying the Contracts to Dev - -The following section walks through the steps for deploying a new set of contracts to dev. - -1. Clone the monorepo and take a look at [nomad-deploy](https://github.com/nomad-xyz/nomad-monorepo/tree/main/typescript/nomad-deploy). - -2. Populate `.env.example` with the required RPC endpoints and funded deployer keys -- place it at `typescript/nomad-deploy/.env`, [see the example](https://github.com/nomad-xyz/nomad-monorepo/blob/main/typescript/nomad-deploy/.env.example) - -3. Prepare Local Dependencies - -`nomad-deploy` is configured to use the local versions of the Nomad typechain interface and the Nomad SDK, as such the local Node modules must be initialized. - -``` -# Install dependencies for typechain -$ cd typescript/typechain -$ npm i - -... - -# Install dependencies for nomad-sdk -$ cd typescript/nomad-sdk -$ npm i -``` - -3. Install Dependencies - -``` -$ cd typescript/nomad-deploy -$ npm i -# Links local modules to nomad-deploy -$ npm run relink-all -``` - -4. Execute a Deploy Script - -Note: See below for more details about the available deployment scripts. - -``` -# Deploy core contracts first -$ npm run deploy--core - -# Then deploy bridge contracts -$ npm run deploy--bridge -``` - -5. Commit Outputted Configs - -If all goes according to plan, you will have a new folder at `rust/config/` containing JSON files that are used by the Off-Chain Agents. Please rename this folder appropriately (`development` if this will become the new dev setup). When committed to the monorepo, the config files are automatically bundled into the resultant Agent docker image in CI. - -Note: Deployment environments may be overridden by replacing the environment's config folder with the contents of your new timestamped configuration. - -## Updating Nomad SDK Dev Addresses - -If your newly deployed setup will become the new dev setup, you will need to adjust the hardcoded domains, indexing parameters, and addresses in the Nomad SDK. Go to `typescript/nomad-sdk/src/nomad/domains/dev.ts`. For each `NomadDomain` object: - -1. Update the indexing parameters (`blocks` and `from`) with the `chunk` and `from` fields from `rust/config/development/_config.json`. -2. Replace all addresses with those in the the newly outputted config file `rust/config/development/_contracts.json`. For the home and replica addresses, use the _proxy_ addresses. -3. If you deployed a new network that has not been seen before, add a new `NomadDomain` object and fill it with the correct fields. diff --git a/docs/dev/domain-ids.md b/docs/dev/domain-ids.md deleted file mode 100644 index 1f5a898..0000000 --- a/docs/dev/domain-ids.md +++ /dev/null @@ -1,19 +0,0 @@ -# Nomad Domain IDs - -## Mainnet - -| Chain | Domain | -| -------------- | ----------- | -| Ethereum (hub) | 6648936 | -| Moonbeam | 1650811245 | - -
- -## Testnet - -| Chain | Domain | -| ---------------- | ----------- | -| Rinkeby (hub) | 2000 | -| Kovan | 3000 | -| MoonbaseAlpha | 5000 | -| MilkomedaTestnet | 8000 | \ No newline at end of file diff --git a/docs/dev/governance.md b/docs/dev/governance.md deleted file mode 100644 index ccddfef..0000000 --- a/docs/dev/governance.md +++ /dev/null @@ -1,175 +0,0 @@ ---- -title: Governance -lang: en-US ---- - -# Cross-Chain Governance - -## Pre-Requisite Reading - -- [Nomad: Optimistic Interchain Communication](../index.md) - -## Summary - -### Purpose - -This document describes **a governable system for executing permissioned actions across chains**. - -We aim to clearly describe - -- **what** contracts comprise the system for calling permissioned functions across chains -- **which** functions will be delegated to this system at launch, and -- (directionally) **who** will have permission to call these functions at launch and in the future - -### Out of Scope - -This document does NOT describe a system for **how** governance actions will be proposed, voted on, and/or approved before being executed. - -It does not describe how contract upgrades will be written, reviewed, verified. - -### Overview - -We define a role, `governor`, with the power to perform permissioned actions across chains. In order to empower the `governor`, we deploy a cross-chain application comprised of a `GovernanceRouter` contract on each chain. - -Each `GovernanceRouter` can be delegated control over an arbitrary set of permissioned functions on its local chain. The only way to access the permissioned functionality is to call the function via the `GovernanceRouter` contract. - -Each `GovernanceRouter` is programmed to accept messages ***only*** from the `governor`, which is deployed on only one chain. The `governor` may call the contract locally (if it is deployed on the same chain), or it may send it messages remotely via Nomad. Because of its exclusive power over the `GovernanceRouter` contracts, the `governor` has exclusive rights to perform **all** of the permissioned roles that are delegated to the `GovernanceRouter` on each chain. - -The system receives orders from the `governor` and carries out their effects across chains; it is agnostic to how the `governor` chooses to operate. This maintains flexibility to design the governance proposal process in the future. - -At launch, the core functionality that will be delegated to the `GovernanceRouter` on each chain is the power to upgrade the implementation of the `Home` and `Replica` contracts. This way, the `governor` will have the power to conduct upgrades of the Nomad system on every chain. More details on the upgradability system can be found [here](./upgrade-setup.md). - -At launch, the `governor` will be a multisig of trusted team and community members. In the near future, the `governor` role will most likely be transferred to a more fully-featured set of contracts capable of accepting proposals, tallying votes, and executing successful proposals. - -## Message Flow Diagram - -![Cross-chain Governance Diagram](/governance-diagram.png) - -1. `governor` sends message to its local `GovernanceRouter` -2. `GovernanceRouter` dispatches the message... - 1. if the recipient is local, to the recipient directly (→ process finished) - 2. if the recipient is remote, via Nomad to the local Home contract (→ continue to 3) -3. Message is relayed from local `Home` to remote `Replica` via Nomad -4. `Replica` dispatches message to the remote `GovernanceRouter` -5. `GovernanceRouter` dispatched the message directly to the local recipient - -**Note on message recipient:** - -- the recipient may be a `Replica` or `Home` contract -- it may be an `UpgradeBeacon` that controls the implementation of `Replica` or `Home` -- it may be any other app - -For simplicity & clarity to show the message flow, this diagram represents the recipient as a generic "App" - -## Specification - -### Glossary of Terms - -- **xApp** - Cross-Chain Application -- **role** — - - an address stored in a smart contract's state that specifies an entity with special permissions on the contract - - permission to call certain functions is usually implemented using a function modifier that requires that the caller of the function is one of the roles with permission to call it; all contract calls sent from callers that do not have valid permission will revert - - *example*: `owner` is the **role** set on all [Ownable](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol) contracts upon deployment; the `owner` **role** has exclusive permission to call functions with the `onlyOwner` modifier -- **permissioned function** — - - any smart contract function that restricts callers of the function to a certain role or roles - - *example*: functions using the `onlyOwner` modifier on [Ownable](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol) contracts -- **permissioned call** — a call to a **permissioned function** -- **governor chain** — - - the chain on which the `governor` is deployed - - the chain whose `GovernanceRouter` is also the special `GovernorRouter` which can *send* messages; all `GovernanceRouters` on other chains can only *receive* governance messages - -### On-Chain Components - -#### **GovernanceRouter** - -- xApp designed to perform permissioned roles on core Nomad contracts on all chains -- State Variables -- **governor** state variable - - if the `governor` is local, `governor` will be set to the EVM address of the `governor` - - if the `governor` is remote, `governor` will be `address(0)` -- **governorDomain** state variable - - the Nomad domain of the **governor chain** - - stored as a state variable on all `GovernanceRouters`; should be the same on all `GovernanceRouters`; always non-zero - - if the `governor` is local, `governorDomain` is equal to the `originDomain` of the local `Home` contract - - if the `governor` is remote, `governorDomain` is equal to the `originDomain` of the remote `Home` contract - - equal to the `originDomain` of the local `Home` contract on the chain of the `GovernorRouter` - - used by all `GovernanceRouters` to determine whether an incoming Nomad message was sent from the `GovernorRouter` - - if the message is from the `GovernorRouter`, the `GovernanceRouter` will handle the incoming message - - if not, it will revert -- **routers** state variable - - a mapping of domain → address of the remote `GovernanceRouter` on every other chain -- **domains** state variable - - an array of all domains that are registered in `routers` - - used to loop through and message all other chains when taking governance actions - - there is the possibility that some domains in the array are null (if a chain has been de-registered) -- **GovernorRouter** - - the special `GovernanceRouter` that has *permission to send* governance messages to all other `GovernanceRouters` - - the `GovernanceRouter` on the **governor chain** - -#### **Governor** - -- via the `GovernanceRouter` system, it has the unique ability to call permissioned functions on **any contract** on **any chain** that transfers permission to the local `GovernanceRouter` -- the **role** with permission to send messages to the `GovernorRouter` - - the `GovernorRouter` has exclusive permission to send messages via Nomad to all other `GovernanceRouters` - - the `GovernanceRouters` can have arbitrary permissions delegated to them by any contract on their local chain - - therefore, the `governor` is the entity with the power to call any **permissioned function** delegated to any `GovernanceRouter` on any chain -- there is only one `governor` throughout the Nomad system; it can be deployed on any chain -- the `governor` role can always be transferred to another contract, on the same chain **or** a different remote chain -- stored as a state variable on `GovernanceRouters`; set to zero on all `GovernanceRouters` except on the **governor chain** -- **Any contract** on **any chain** that wishes for this governance system to have discretion to call a set of its functions can create a role & a function modifier giving exclusive permission to that role to call the function(s) (similar pattern to Ownable). The contract must then set the local `GovernanceRouter` to the permissioned role, which — by extension — gives the `governor` exclusive permission to call those functions (regardless of whether the `governor` is remote or local) - -### Failure States - -If there is fraud on the Nomad `Home` contract on the **governor chain**, this is currently a "catastrophic failure state" — no further governance actions can be rolled out to remote chains; we must create a plan to recover the system in this case. - ---- - -## Message Types - -### Executing (Arbitrary) Calls - -1. **for each chain**, the `governor` constructs the array of `(to, data)` calls to the permissioned functions on the contracts that will perform the upgrades on that chain -2. the `governor` sends a transaction to the `GovernanceRouter.callRemote` function on its local the , passing in the `domain` of the remote chain and the array of `(to, data)` calls of transactions to execute on that chain -3. the local `GovernanceRouter` constructs an Nomad-compatible message from the array of calls, addresses the message to the remote `GovernanceRouter`, and sends the message to the local `Home` contract -4. the message is relayed from the local `Home` to the remote `Replica` contract on the specified `domain` -5. the `Replica` dispatches the message to the specified recipient, which is the local `GovernanceRouter` -6. the `GovernanceRouter` parses the message to decode the array of `(to, data)` calls -7. the `GovernanceRouter` uses low-level call to execute each of the transactions in the array within the local chain - -### **Transferring Governor** - -#### **Possible State Transitions** - -1. called by the local owner to transfer ownership to another local owner (`domain` does not change, `owner` changes to a new `bytes32` address) -2. called by the local owner to transfer ownership to a remote owner (`domain` changes to the remote, `owner` changes from a non-zero `bytes32` to `bytes32(0)`) -3. called by a remote owner to transfer ownership to a local owner (`domain` changes to the local domain, `owner` changes from `bytes32(0)` to a non-zero `bytes32`) -4. called by a remote owner to transfer ownership to another remote owner (`domain` changes to the new remote owner, `owner` remains `bytes32(0)`) - -### Enrolling a Router - -- used when a new chain is added to Nomad after we've already set up the system and transferred governorship -- add a new domain → address mapping to the `routers` mapping on every other `GovernanceRouter` - ---- - -## Functionality at Launch - -### Permissioned Roles - -At launch, the `GovernanceRouter` system **will have the following permissions**: - -1. upgrade the implementation of `Home` (via `UpgradeBeacon` pattern) -2. upgrade the implementation of all `Replicas` (via 1-to-N `UpgradeBeacon` pattern) -3. upgrade the implementation of itself (via `UpgradeBeacon` pattern) - -The `GovernanceRouter` **will NOT have permission** to: - -- un-enroll a `Replica` from the `UsingNomad` contract, which will require a specialized role that can act quickly - -### Governor - -The flexibility of this system will support a move to progressive decentralization. - -Initially, the `governor` will most likely be a multisig controlled by trusted team and community members - -Later, the `governor` role will most likely be transferred to a decentralized governance contract \ No newline at end of file diff --git a/docs/dev/index.md b/docs/dev/index.md deleted file mode 100644 index 9cff2b6..0000000 --- a/docs/dev/index.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Developer Resources -lang: en-US ---- - -# Developer Resources for Nomad Integration - -- [Nomad](../index.md) -- [xApps](./xapps.md) -- [Token Bridge xApp](./token-bridge.md) -- [SDK](./sdk.md) -- [Agents](./agents/index.md) -- [Network Topology](./topology.md) - -# Code Examples - -- [Counter xApp](https://github.com/nomad-xyz/nomad-monorepo/tree/main/examples/counter-xapp) -- [Example UI](https://github.com/nomad-xyz/nomad-monorepo/tree/main/examples/example-ui) diff --git a/docs/dev/prod-contract-deployment.md b/docs/dev/prod-contract-deployment.md deleted file mode 100644 index c2236ef..0000000 --- a/docs/dev/prod-contract-deployment.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Production Contract Deployment -lang: en-US ---- - -# Incrementally Deploy New Network to Production Setup - -TODO diff --git a/docs/dev/sdk.md b/docs/dev/sdk.md deleted file mode 100644 index efe4476..0000000 --- a/docs/dev/sdk.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Nomad SDK -lang: en-US ---- - -# Nomad SDK - -### Core - - - npm package - - docs - -### Bridge - - - npm package - - docs - -### Governance - - - npm package - - docs - -### Multi Provider - - - npm package diff --git a/docs/dev/token-bridge.md b/docs/dev/token-bridge.md deleted file mode 100644 index 9717a1a..0000000 --- a/docs/dev/token-bridge.md +++ /dev/null @@ -1,156 +0,0 @@ ---- -title: Token Bridge xApp -lang: en-US ---- - -# Token Bridge xApp - -## Summary - -The Token Bridge xApp implements a bridge that is capable of sending tokens across blockchains. - -Features: - -- Ensures that circulating token supply remains constant across all chains. - -## Limitations - -The Token Bridge xApp only supports standard, non-rebasing ERC20-compliant tokens. - -## Protocol - -### Handling Messages - -- the BridgeRouter contract only accepts messages from other remote BridgeRouter contracts, which are registered by each BridgeRouter - - therefore, every message received follows the same "rules" that the local BridgeRouter expects - - for example, any tokens sent in a message are ensured to be valid, because the remote BridgeRouter sending the message should locally enforce that a user has custody before sending the message to the remote chain -- the messages from remote BridgeRouter contracts must be sent via Nomad, dispatched by a local Replica contract, which are registered with the UsingNomad contract - - thus, the BridgeRouter depends on the UsingNomad contract for a valid registry of local Replicas -- if another chain has sent a token that's "native" to this chain, we send that token from the Router contract's escrow to the recipient on this chain -- if we're receiving a token that's not "native" to this chain, - - we check whether a representation token contract has already been deployed by the Router contract on this chain; if not, we deploy that representation token contract and add its address to the token registry - - we mint representation tokens on this chain and send them to the recipient - -### Dispatching Messages - -- **TODO**: describe rules — person must approve token to Router on local chain (if it's a native token) proving they have ownership over that token and can send to the native chain -- sending tokens - - the user uses ERC-20 `approve` to grant allowance for the tokens being sent to the local BridgeRouter contract - - the user calls send on the local BridgeRouter to transfer the tokens to a remote -- if the token being sent is "native" to the BridgeRouter's chain, the BridgeRouter contract holds the token in escrow -- if the token being sent is not "native" to the chain, then the local token is a representation token contract deployed by the BridgeRouter in the first place; the BridgeRouter contract burns the tokens before sending them to another chain - -### Message Format - -- **TODO**: specify how messages are encoded for this application - -## Architecture - -**BridgeRouter ([code](https://github.com/nomad-xyz/nomad-monorepo/blob/main/solidity/nomad-xapps/contracts/bridge/BridgeRouter.sol))** - -- Receives incoming messages from local `Replica` contracts sending tokens from another chain -- Dispatches outgoing messages to local `Home` contract in order to send tokens to other chains -- Manages a registry of representation ERC-20 token contracts that it deploys on its local chain -- Maintains a registry of remote `BridgeRouter` contracts to - - authenticate that incoming messages come from a remote `BridgeRouter` contract - - properly address outgoing messages to remote `BridgeRouter` contracts - -**TokenRegistry ([code](https://github.com/nomad-xyz/nomad-monorepo/blob/main/solidity/nomad-xapps/contracts/bridge/TokenRegistry.sol))** - -- Responsible for deploying and keeping track of representation ERC-20 token contracts on this chain -- When a new token is transferred, deploys a new representation token contract on this chain, and stores a two-way mapping between the information of the original token contract & the address of the representation on this chain -- Inherited by the `BridgeRouter`, who uses this to make sure a representation of the token exists on this chain before minting/burning - -**BridgeMessage library ([code](https://github.com/nomad-xyz/nomad-monorepo/blob/main/solidity/nomad-xapps/contracts/bridge/BridgeMessage.sol))** - -- Library for handling all the nitty gritty of encoding / decoding messages in a standardized way so they can be sent via Nomad - -## Message Flow - -The logical steps and flow of information involved in sending tokens from one chain to another. - -- **Chain A** - - User wants to send their tokens to Chain B - - If it's a native token, the user must first `approve` tokens to the local `BridgeRouter-A` - - User calls `send` on the local `BridgeRouter-A` - - If it's a native token, tokens are pulled from the User's wallet to `BridgeRouter-A` and held in escrow - - If it's a non-native token, tokens are burned from User's wallet by `BridgeRouter-A` - - _Note:_ `BridgeRouter-A` can burn non-native tokens because the representative contract for the token on its non-native chain was originally deployed by `BridgeRouter-A` when it received a message sending the token from another chain. The router has administrative rights on representations - - `BridgeRouter-A` constructs a message to `BridgeRouter-B` - - `BridgeRouter-A` keeps a mapping of `BridgeRouter` contracts on other chains so it knows where to send the message on Chain B - - `BridgeRouter-A` calls `enqueue` on `Home-A` contract to send the message to Chain B -- **Off-Chain** - - Standard Nomad behavior. Updater → Relayer → Processor - - Relayers see message on `Home-A` - - Relayers pass message to `Replica-A` on Chain B -- **Chain B** - - After waiting for the acceptance timeout, `Replica-A` processes the message and dispatches it to `BridgeRouter-B` - - `BridgeRouter-B` keeps a mapping `Replica` contracts that it trusts on the local chain. It uses this to authenticate that the incoming message came from chain A - - `BridgeRouter-B` keeps a mapping of `BridgeRouter` contracts on other chains, so it can authenticate that this message came from `BridgeRouter-A` - - `BridgeRouter-B` looks for the corresponding ERC-20 token contract in its registry, and deploys a new representative one if it doesn't already exist - - `BridgeRouter-B` sends the token to the recipient - - If it's a native token, `BridgeRouter-B` sends the tokens from the pool it's holding in escrow - - If it's a non-native token, `BridgeRouter-B` mints the token to the recipient ( - - _Note:_ `BridgeRouter-B` can mint non-native tokens because the representative contract for the token on its non-native chain is deployed by `BridgeRouter-B` when it received a message sending the token from another chain. The router has administrative rights on representations. - -## Tracing a Message - -Nomad is currently still under active development. Because Nomad batches messages and sends only tree roots, there is no way to track individual messages on-chain once a message is passed to the Home contract. A agent-querying tool could be built to query off-chain agents for individual transactions, but such a tool does not currently exist. - -What this means for the token bridge is that there is going to be a state of unknown during the time of send and receipt. You can think of this as snail mail without any tracking but with delivery confirmation. The only things that can be confirmed on-chain are: - -1. A transaction was sent on chain A to the BridgeRouter contract -2. The recipient addressed received a token mint on chain B - -### Pseudo-tracking - -1. Start by locating the `bridgeRouter` contract you are looking for, addresses in the config dir: - -- [Dev Contracts](https://github.com/nomad-xyz/nomad-monorepo/tree/main/rust/config/development) -- [Staging Contracts](https://github.com/nomad-xyz/nomad-monorepo/tree/main/rust/config/staging) -- [Prod Contracts](https://github.com/nomad-xyz/nomad-monorepo/tree/main/rust/config/mainnet) - -2. Verify that a transaction was sent to the BridgeRouter contract on the Home chain - - - _Wait time_: dependent on block confirmation times for each chain - -3. Verify a transaction was sent on the Home contract - - - _Wait time_: dependent on block confirmation for each chain, but should be shortly after transaction is sent to BridgeRouter contract - - There is not a way to query for a particular transactions at this time. Cross-check timestamps with BridgeRouter transaction. - -4. After acceptance period, verify a transaction was sent on the destination Replica - - - _Wait time_: acceptance period. Currently 30 minutes - - Cross-check timestamps - -5. Verify a transaction was sent on the destination BridgeRouter - - - _Wait time_: acceptance period + block confirmation time - -6. Verify that the recipient address received a token mint - 1. _Wait time_: block confirmation time for chain A + acceptance period + block confirmation time for chain B - -## The Token Registry - -The Token Bridge xApp relies on a [`TokenRegistry`](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-bridge/contracts/TokenRegistry.sol) smart contract. This contract handles mapping canonical Nomad token identifiers to their local representation (or native local deployment) and vice versa. - -For most tokens there is a 1:1 relationship between the canonical identifier and the local version. Regrettably, tokens are not always that simple. The token registry allows us to support more complex use cases by adjusting the relationship between identifiers and local tokens. - -### Custom Tokens - -To support teams desiring specific token functionality, the registry supports enrolling "custom" tokens. Governance may instruct the token registry to change the official local representation of a token to a new address. Any ERC20-compliant contract that allows the Bridge Router to mint & burn tokens may be enrolled as a custom token. - -When a custom token is enrolled, that token no longer has a 1:1 correspondence between local representation and canonical identifier. Instead, there are >1 local representations. Incoming transfers mint the **latest** representation (the most recently enrolled custom token), while outgoing transfer may burn **any** previous representation. This ensures that users' tokens are never invalidated, but new users get the best version. - -For convenience, we also expose a `migrate` function that allows users to immediately exchange any previous representation for the **latest** representation. This allows a user to upgrade outdated representations and receive the latest without dispatching a cross-chain message. - -### Dust - -We provide the users with `dust` in order to facilitate their onboarding to the chain (all chains apart from Ethereum). - -We provide no guarantees to the end users that they will necessarily receive gas from the Dust feature. We provide it in **good faith** that it won't be abused and will be used by users who need it. - -Dust is donated by people who are incentivized for users to have gas after they bridge. Large $$$ values of dust should not be donated at any given time and we are actively talking with teams to avoid doing so. - -It is hoped that the gas is used for genuine users, but not a concern if the gas is used improperly, as it should be of negligible importance to the donor. diff --git a/docs/dev/topology.md b/docs/dev/topology.md deleted file mode 100644 index 9b68f96..0000000 --- a/docs/dev/topology.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Nomad Network Topology -lang: en-US ---- - -Nomad provides cheap cross-chain communication channels, which are (documented -[here](./architecture.md)). From there we have to decide which -chains are worth connecting. The map of connections between chains is called -the network topology. - -## Nomad's Topology - -Generally, Nomad follows a **Hub and Spoke** network topology. That is to say, -one chain (Ethereum) is the logical hub of the Nomad network. We guarantee that -all other chains have active channels to Ethereum. While connections between -spokes may exist, we don't guarantee that they do. - -Hub and Spoke topology has a number of advantages: - -1. It guarantees a route from point A to point B exists. -1. It makes finding that route very simple. -1. It guarantees that the route is at most 2 hops. -1. It allows applications to assume direct communication with their own hub. -1. It minimizes the number of channels we must deploy and maintain -1. It allows us to directly connect spokes _if there is a compelling reason to - do so_ - -### Other Options - -IBC follows a **Mesh** topology, which does not guarantee that any specific -cross-chain channel exists. Instead, users must observe the available channels -and chart a route that hops across some number of channels to get to their -destination. - -Some networks may follow a **Total Graph** topology, which guarantees that all -chains are connected to all other chains. This results in a very large number -of channels, but cuts out all route finding. - -## For Developers - -xApp developers may make the following assumptions: - -- That a Nomad channel to Ethereum exists on any chain in the Nomad network. -- That a xApp contract deployed on Ethereum can communicate directly with xApp - contracts on any chain in the Nomad network. -- That this will remain true as new chains are added to the Nomad network. diff --git a/docs/dev/upgrade-setup.md b/docs/dev/upgrade-setup.md deleted file mode 100644 index 3a9e4a7..0000000 --- a/docs/dev/upgrade-setup.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: Upgrade Setup -lang: en-US ---- - -# Upgrade Setup - -We will use the `UpgradeBeacon` pattern to implement three upgradable contract types: `Home`, `Replica`, and `GovernanceRouter`. - -Each upgradable contract will have: - -- **Proxy** - - the permanent address of the contract that external entities interact with - - holds the storage of the contract - - uses the logic specified by `Implementation` - - uses `delegatecall` to forward contract calls from `Proxy` → `UpgradeBeacon` → `Implementation` -- **UpgradeBeacon** - - stores the (mutable) address of the `Implementation` - - forwards `delegatecalls` to the `Implementation` - - accepts new `Implementation` addresses from its `Controller` (thereby performing upgrades for all `Proxies`) -- **Implementation** - - specifies the logic of the contract - - code is the same as a normal, non-upgradable contract implementation (though it should use upgrade-safe storage) - -Each of the three `UpgradeBeacon` contracts will share a the same `Controller` — the contract with the power to perform upgrades. - -The **Controller** contract will have two roles: controller and saver. - -- `controller` - - is a transferrable role that should be performing upgrades in almost every case. - - will be set to the `GovernanceRouter Proxy`, so that the Governance xApp ultimately controls the upgrades of the entire system. Note that this creates a circular dependency which makes upgrades of the `GovernanceRouter Implementation` particularly sensitive. -- `saver` - - is a transferrable(?) role that is responsible for recovering the system in a catastrophic failure case. Actions performed by the `saver` will be subject to a timelock enforced by the Controller contract. - - will be set to a multisig contract where the signatories are a set of known / trusted community members. the signatories for the `saver` multisig be the same on every chain - -## Diagrams - -![Upgrade Setup Diagram 1](/Upgrade-Setup-1.png) - -![Upgrade Setup Diagram 2](/Upgrade-Setup-2.png) diff --git a/docs/dev/xapps.md b/docs/dev/xapps.md deleted file mode 100644 index f77a615..0000000 --- a/docs/dev/xapps.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: xApps -lang: en-US ---- - -# Developing Cross-Chain Applications - -::: info -A xApp (pronounced "zap") is a cross-chain application built on top of the [Nomad Protocol](../index.md). -::: - -## Summary - -Nomad sends messages from one chain to another in the form of raw bytes. A cross-chain application that wishes to _use_ Nomad will need to define the rules for sending and receiving messages for its use case. - -Each cross-chain application must implement its own messaging protocol. By convention, we call the contracts that implement this protocol the application's **Router contracts.** These Router contracts must: - -- **maintain a permissioned set** of the contract(s) on remote chains from which it will accept messages via Nomad — this could be a single owner of the application on one chain; it could be a registry of other applications implementing the same rules on various chains -- **maintain a permissioned registry of connections** via the `XappConnectionManager` contract (see "Connection Management"). -- **encode messages in a standardized format**, so they can be decoded by the Router contract on the destination chain -- **handle messages** from remote Router contracts -- **dispatch messages** to remote Router contracts - -By implementing these pieces of functionality within a Router contract and deploying it across multiple chains, we create a working cross-chain application using a common language and set of rules. Applications of this kind may use Nomad as the cross-chain courier for sending and receiving messages to each other. - -## Example Code - -This repository has several examples one can use to build understanding around Cross-Chain Applications. - -### xApp Template - -**Important!** The template supported Solidity version is **<0.8**! - -[This is a template](https://github.com/nomad-xyz/nomad-monorepo/tree/main/solidity/nomad-xapps/contracts/xapp-template) provided by the Nomad team that shows the high-level components of an xApp, ready for one to fill in their own application logic and utilize an Nomad channel for cross-chain communication. - -To implement a xApp, define the actions you would like to execute across chains. -For each type of action, - -- in the [xApp Router](https://github.com/nomad-xyz/nomad-monorepo/blob/main/solidity/nomad-xapps/contracts/xapp-template/RouterTemplate.sol) - - implement a function like doTypeA to initiate the action from one domain to another (add your own parameters and logic) - - implement a corresponding \_handle function to receive, parse, and execute this type of message on the remote domain - - add logic to the handle function to route incoming messages to the appropriate \_handle function -- in the [Message library](https://github.com/nomad-xyz/nomad-monorepo/blob/main/solidity/nomad-xapps/contracts/xapp-template/MessageTemplate.sol), - - implement functions to _format_ the message to send to the other chain (encodes all necessary information for the action) - - implement functions to _parse_ the message once it is received on the other chain (decode all necessary information for the action) - -### Connection Management - -The router implements the [`XappConnectionClient`](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-router/contracts/XAppConnectionClient.sol) abstract contract. This contract provides convenience functions for working with a [`XAppConnectionManager`](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/XAppConnectionManager.sol). - -The XCM is the primary permissioning point for channels. It provides functions by which - -- xApp administrators can enroll or unenroll `Replica` contracts for inbound messages -- xApp administrators can enroll or unenroll a `Home` contract for outbound messages -- xApp administrators can permission or de-permission watchers -- watchers can unenroll `Replica` contracts - -When deploying a xApp `Router`, the xApp administrators must select an existing XCM, or deploy their own. The address of the XCM must be passed to the router's initialization method. - -### Ping Pong xApp - -**Important!** The Ping Pong xApp is for reference only. Please do not deploy! - -[The PingPong xApp](https://github.com/nomad-xyz/nomad-monorepo/tree/main/solidity/nomad-xapps/contracts/ping-pong) is capable of initiating PingPong "matches" between two chains. A match consists of "volleys" sent back-and-forth between the two chains via Nomad. - -The first volley in a match is always a Ping volley. - -- When a Router receives a Ping volley, it returns a Pong. -- When a Router receives a Pong volley, it returns a Ping. - -The Routers keep track of the number of volleys in a given match, and emit events for each Sent and Received volley so that spectators can watch. - -### Token Bridge xApp - -See the full-length [Token Bridge Documentation](./token-bridge.md) for in-depth details on Token Bridge operation and construction. - -[Link to Contracts](https://github.com/nomad-xyz/nomad-monorepo/tree/main/solidity/nomad-xapps/contracts/bridge) - -### Cross-Chain Governance xApp - -See the full-length [Nomad Governance Documentation](./governance.md) for in-depth details on Governance xApp operation and construction. - -[Link to Contracts](https://github.com/nomad-xyz/nomad-monorepo/tree/main/solidity/nomad-core/contracts/governance) - -## Useful Links - -- [xApp Developers Workshop @ EthCC 2021 by Anna Carroll](https://www.youtube.com/watch?v=E_zhTRsxWtw) - -## Glossary of Terms - -- **Local vs Remote**: in the context of discussing a particular contract, it is deployed on a particular chain. Contracts and assets on that chain are "local." Contracts and assets on another chain are "remote" - - e.g. Uniswap is deployed on Ethereum. Ethereum is the local chain. Celo is a remote chain - - e.g. there is a token deployed on Celo. There is a local `Home` contract (on Celo), and a local `Replica` contract (on Celo) receiving messages from Ethereum. There is a remote `Home` (on Ethereum) sending messages. There is a remote `Replica` (on Ethereum) receiving messages from Celo. There is a remote `Router` (on Ethereum) communicating with the local `Router` on Celo. -- **"Locally originating" vs "Remotely Originating"**: in the context of a token or asset in a specific contract, these terms denote whether the original canonical contract is deployed on the local chain, or on a remote chain - - e.g. cUSD originates on Celo. in the context of the Celo blockchain, cUSD is "of local origin" or "locally originating"; in the context of the Ethereum blockchain, cUSD is "of remote origin" - - e.g. Ether and WETH originate on Ethereum. When used in a Celo contract, they are "remotely originating" or "of remote origin" - - e.g. a `Router` receives a Transfer message for a remotely-originating asset. It finds the local contract that represents that asset. When it receives a message for a locally originating asset, it knows that it can find the original asset contract locally -- **Router Contract**: a contract that implements a cross-chain application by specifying the: - - **message format** - the bytes-encoded format of messages for the application - - **registry of remote Router contracts** that implement the same application on remote chains - - **rules & behavior for handling messages** sent via Nomad by a registered Router contract on a remote chain - - **rules & behavior for dispatching messages** via Nomad to a registered Router contract on a remote chain -- **Message**: bytes transferred via Nomad that encode some application-specific instructions via a standardized set of rules -- **Instructions**: set of application-specific actions (e.g. "send 5 token X to 0x123...456 on chain Z" in the case of a Token Bridge); calls to functions on the Router contract -- **Handling Messages from Nomad Channels**: - - receive bytes-encoded message from Nomad (sent from a remote chain) - - enact or dispatch the instructions on the local chain - - local handler decodes the message into application-specific instructions -- **Dispatching Message to Nomad Channels**: - - receive instructions on the local chain (via local users and contracts calling functions on the contract) - - encode the instructions into bytes using standardized message format - - dispatch the bytes-encoded message to Nomad (to be sent to a remote chain) diff --git a/docs/docs.mdx b/docs/docs.mdx new file mode 100644 index 0000000..3a59616 --- /dev/null +++ b/docs/docs.mdx @@ -0,0 +1,13 @@ +--- +title: Nomad Docs +description: Use Nomad's documentation to dive into the cross-chain world of tomorrow +sidebar_label: 'Home' +custom_edit_url: https://github.com/nomad-xyz/learn/blob/master/docs/docs.mdx +id: docs +slug: / +--- + +_Welcome!_ You’ve arrived at Nomad's documentation. + +Nomad is a novel approach to blockchain interoperability that leverages an optimistic mechanism to increase the security of cross-chain communication. Using Nomad, developers can securely build cross-chain applications (or xApps) and bridge assets between chains. Nomad channels and the flagship xApp, the Nomad token bridge, are live on Ethereum and Moonbeam, with more chains coming soon. + diff --git a/docs/governance-bridge/overview.md b/docs/governance-bridge/overview.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index 0c6b3c8..0000000 --- a/docs/index.md +++ /dev/null @@ -1,215 +0,0 @@ ---- -title: What is the Nomad Protocol? -lang: en-US ---- - -# What is the Nomad Protocol? - -Nomad is a new design for radically cheaper cross-chain communication without header verification. We expect operating Nomad to cut 90% of gas costs compared to a traditional header relay. To accomplish this, we took inspiration from optimistic systems (a la Optimistic Roll-ups). Nomad features many of the features we prize in an optimistic mechanism, like public verification, low gas fees, broad participation, but has a slightly different security model. - -Nomad will form the base layer of a cross-chain communication network that provides fast, cheap communication for all smart contract chains and rollups. It relies only on widely-available cryptographic primitives (unlike header relays), has a latency of thirty minutes (rather than an ORU’s one week latency), and imposes only about 120,000 gas overhead on message senders. - -Nomad has been designed for ease of implementation in any blockchain that supports user-defined computations. We will provide initial Solidity implementations of the on-chain contracts, and Rust implementations of the off-chain system agents. - -Nomad is an implementation and extension of the [Optics protocol](https://github.com/celo-org/celo-monorepo) (OPTimistic Interchain Communication). - -## Building Intuition for Nomad - -Nomad works something like a notary service. - -nomad-notary - -The sending (or “home”) chain produces a series of documents ("messages") that needs notarization. A notary (called the “updater”) is contracted to sign it. The notary can produce a fraudulent copy, but they will be punished by having their bond and license publicly revoked. When this happens, everyone relying on the notary learns that the notary is malicious. All the notary's customers can immediately block the notary and prevent any malicious access to their accounts. - -## How does Nomad work? - -Nomad is patterned after optimistic systems. It sees an attestation of some data, and accepts it as valid after a timer elapses. While the timer is running, honest participants have a chance to respond to the attestation and/or submit fraud proofs. - -Unlike most optimistic systems, Nomad spans multiple chains. The sending chain is the source of truth, and contains the “Home” contract where messages are enqueued. Messages are committed to in a merkle tree (the “message tree”). The root of this tree is notarized by the updater and relayed to the receiving chain in an “update”. Updates are signed by the updater. They commit to the previous root and a new root. - -Any chain can maintain a “Replica” contract, which holds knowledge of the updater and the current root. Signed updates are held by the Replica, and accepted after a timeout. The Replica effectively replays a series of updates to reach the same root as the Home chain. Because the root commits to the message tree, once the root has been transmitted this way, the message can be proven and processed. - -This leaves open the possibility that the Updater signs a fraudulent update. Unlike an optimistic rollup, Nomad permits fraud. This is the single most important change to the security model. Importantly, fraud can always be proven to the Home contract on the sending chain. Because of this, the updater must submit a bonded stake on the sending chain. Fraud can always be proven on the sending chain, and the bond can be slashed as punishment. - -Unfortunately, certain types of fraud can't be objectively proven on the receiving chain; Replicas can't know which messages the home chain intended to send and therefore can't check message tree validity in all cases. However, if a message is falsified by an Updater and submitted to the Replica, that update is public. This means that any honest actor can prove this fraud on the original Home contract and cause slashing. There is no way to hide fraud. - -In addition, because the Replica waits to process messages, Nomad guarantees that honest dapps can always prevent processing of dishonest messages. Fraud is always public knowledge before the fraudulent message is processed. In this sense, Nomad (like atomic swaps and other locally verified systems) includes a requirement for honest users to stay online. We have built a robust system for delegating this responsibility. - -All off-chain observers can be immediately convinced of fraud (as they can check the home chain). This means that the validity of a message sent by Nomad is not 100% guaranteed. - -Instead, Nomad guarantees the following: - -- Fraud is costly -- All users can learn about fraud -- All users can block a fraudulent message before they are accepted - - In other words, rather than using a globally verifiable fraud-proof, Nomad relies on local verification by participants. This tradeoff allows Nomad to save 90% on gas fees compared to pessimistic relays, while still maintaining a high degree of security. - -## Nomad Architecture - -Nomad contains several on-chain and off-chain components. For convenience, we’ll be referring to the Home and Replica as contracts, when in fact they are several contracts working together. - -![Nomad Components](/Nomad-Architecture.png) - -## On-chain (Contracts) - -### Home - -The home contract is responsible for managing production of the message tree and holding custody of the updater bond. - -__It performs the following functions:__ - -- Expose a "send message" API to other contracts on the home chain -- Enforce the message format -- Commit messages to the message tree -- Maintain a queue of tree roots -- Slash the updater's bond - - Double-update proofs - - Improper update proofs - -### Replica - -The replica contract is responsible for managing optimistic replication and dispatching messages to end recipients. - -__It performs the following functions:__ - -- Maintain a queue of pending updates -- Finalize updates as their timeouts elapse -- Accept double-update proofs -- Validate message inclusion proofs -- Enforce the message format -- Dispatch messages to their destination - -## Off-chain (Agents) - -### Updater - -The updater is responsible for signing attestations of new roots. - -__It is an off-chain actor that does the following:__ - -- Observe the home chain contract -- Sign attestations to new roots -- Publish the signed attestation to the home chain - -### Watcher - -The watcher observes the Updater's interactions with the Home contract (by watching the Home contract) and reacts to malicious or faulty attestations. It also observes any number of replicas to ensure the Updater does not bypass the Home and go straight to a replica. - -__It is an off-chain actor that does the following:__ - -- Observe the home -- Observe 1 or more replicas -- Maintain a DB of seen updates -- Submit double-update proofs -- Submit invalid update proofs -- If configured, issue an emergency halt transaction - -### Relayer - -The relayer forwards updates from the home to one or more replicas. - -__It is an off-chain actor that does the following:__ - -- Observe the home -- Observe 1 or more replicas -- Polls home for new signed updates (since replica's current root) and submits them to replica -- Polls replica for confirmable updates (that have passed their optimistic time window) and confirms if available (updating replica's current root) - -### Processor - -The processor proves the validity of pending messages and sends them to end recipients. - -__It is an off-chain actor that does the following:__ - -- Observe the home -- Maintain local merkle tree with all leaves -- Observe 1 or more replicas -- Maintain list of messages corresponding to each leaf -- Generate and submit merkle proofs for pending (unproven) messages -- Dispatch proven messages to end recipients - -## How Nomad passes messages between chains - -Nomad creates an authenticated data structure on a home chain, and relays updates to that data structure on any number of replicas. As a result, the home chain and all replicas will agree on the state of the data structure. By embedding data ("messages") in this data structure we can propagate it between chains with a high degree of confidence. - -The home chain enforces rules on the creation of this data structure. In the current design, this data structure is a sparse merkle tree based on the design used in the eth2 deposit contract. This tree commits to the vector of all previous messages. The home chain enforces an addressing and message scheme for messages and calculates the tree root. This root will be propagated to the replicas. The home chain maintains a queue of roots (one for each message). - -The home chain elects an "updater" that must attest to the state of the message tree. The updater places a bond on the home chain and is required to periodically sign attestations (updates or U). Each attestation contains the root from the previous attestation (U_prev), and a new root (U_new). - -The home chain slashes when it sees two conflicting updates (U_i and U_i' where U_i_prev == U_i'_prev && U_i_new != U_i'_new) or a single update where U_new is not an element of the queue. The new root MUST be a member of the queue. E.g a list of updates U_1...U_i should follow the form [(A, B), (B, C), (C, D)...]. - -Semantically, updates represent a batch commitment to the messages between the two roots. Updates contain one or more messages that ought to be propagated to the replica chain. Updates may occur at any frequency, as often as once per message. Because updates are chain-independent, any home chain update may be presented to any replica, and any replica update may be presented to the home chain. In other words, data availability of signed updates is guaranteed by each chain. - -Before accepting an update, a replica places it into a queue of pending updates. Each update must wait for some time parameter before being accepted. While a replica can't know that an update is certainly valid, the waiting system guarantees that fraud is publicly visible on the home chain before being accepted by the replica. In other words, the security guarantee of the system is that all frauds may be published by any participant, all published frauds may be slashed, and all participants have a window to react to any fraud. Therefore updates that are not blacklisted by participants are sufficiently trustworthy for the replica to accept. - -## Nomad Channels for Cross-Chain Communication - -Nomad sends messages from one chain to another in the form of raw bytes. A cross-chain application that wishes to use Nomad will need to define the rules for sending and receiving messages for its use case. - -Each cross-chain application must implement its own messaging protocol. By convention, we call the contracts that implement this protocol the application's Router contracts. Their function is broadly similar to routers in local networks. They ensure that incoming and outgoing messages are in the protocol-defined format, and facilitate handling and dispatch. - -__These Router contracts must:__ - -- maintain a permissioned set of the contract(s) on remote chains from which it will accept messages via Nomad — this could be a single owner of the application on one chain; it could be a registry of other applications implementing the same rules on various chains -- encode messages in a standardized format, so they can be decoded by the Router contract on the destination chain -- handle messages from remote Router contracts -- dispatch messages to remote Router contracts - - By implementing these pieces of functionality within a Router contract and deploying it across multiple chains, we create a working cross-chain application using a common language and set of rules. Applications of this kind may use Nomad as the cross-chain courier for sending and receiving messages to each other. - -## Benefits and Trade-offs of the Nomad Architecture - -__Benefits__ | __Challenges__ --- | -- -Broadcast channel | 1-of-N fraud-proof trust model -Cheap | Liveness failure if updater goes down -One-solution fits all | Updater could voluntarily forfeit bond to try to pass forged messages -Simple |   - -The benefit of Nomad is that the broadcast channel allows for a single-producer, multi-consumer model. This ensures that 1 accumulator can communicate with any number of receiving chains. It’s also much cheaper than other options, allowing updates and proofs to cost <100k gas and be checked by only 1 signature. With Nomad, one-solution fits all meaning that constraints on receiving chains are minimal (1 hash function + 1 signature check). There is no implementation or security difference between Proof of Stake and Proof of Work chains. There is also many fewer LoC than a Relay, much lower design maintenance overhead, and much less expertise required to maintain and operate. - -We’ve been careful to address all concerns with the Nomad system and have designed solutions that allow for optimal speed, cost, and security of the network. For example, we rely on fraud publication rather than fraud proofs to improve the speed and cost of sending messages. In this security model, any potential fraud is disincentivized and costly, and all participants will always learn of any potential fraud with plenty of time to mitigate harm. - -## Governance - -Nomad will roll out its finalized governance process and signer composition in April 2022. - -### Governor - -[Etherscan](https://etherscan.io/address/0x93277b8f5939975b9e6694d5fd2837143afbf68a), [Gnosis Safe](https://gnosis-safe.io/app/eth:0x93277b8f5939975b9E6694d5Fd2837143afBf68A/settings/owners) - -**Policy:** 3 of 5 - of the five total signers, three signatures are required to execute a transaction - -**Signers:** -- [Layne Haber](https://twitter.com/LayneHaber): `0xC69b66cc2811B509829448FBFfb2553c4CBb627e` -- [Praneeth Srikanti](https://twitter.com/bees_neeth): `0x9bdD76b2a69Db43Fa695a10f5977b8FD891225f3` -- [Pranay Mohan](https://twitter.com/pranaymohan): `0xab0614cE8d53ea2c67B87f8ad4d8Fac7A4a516e5` -- [Anna Carroll](https://twitter.com/annascarroll): `0x25270d2e6980C5b343C4866Aea904a9A9bCA733F` -- [Katherine Wu](https://twitter.com/katherineykwu): `0x83865712c50f702fA4650C7fadEd90A54242046e` - ----- -### Ethereum Recovery Manager - -[Etherscan](https://etherscan.io/address/0xda2f881f7f4e9d2b9559f97c7670472a85c1986a), [Gnosis Safe](https://gnosis-safe.io/app/eth:0xda2f881f7f4e9d2b9559f97c7670472a85c1986a/settings/owners) - -**Policy:** 2 of 3 - of the three total signers, two signatures are required to execute a transaction - -**Signers:** -- [Eli Krenzke](https://twitter.com/eKRENZKE): `0x347Ae1a35BED71BB796A5279CD85FED964468aE9` -- [Barbara Liau](https://twitter.com/barbaraliau): `0xDE9cfb1216889Dee0cAB8afB04c63911427659E4` -- [Conner Swann](https://twitter.com/YourBuddyConner): `0xea24Ac04DEFb338CA8595C3750E20166F3b4998A` - ----- -### Moonbeam Recovery Manager - -[Moonscan](https://moonbeam.moonscan.io/address/0x2D23B3865D5B7CD88Ce9CE7514a13545672d9eF7), [Gnosis Safe](https://multisig.moonbeam.network/mbeam:0x2D23B3865D5B7CD88Ce9CE7514a13545672d9eF7/settings/owners) - -**Policy:** 3 of 5 - of the five total signers, three signatures are required to execute a transaction - -**Signers:** -- [Barbara Liau](https://twitter.com/barbaraliau): `0xDE9cfb1216889Dee0cAB8afB04c63911427659E4` -- [Conner Swann](https://twitter.com/YourBuddyConner): `0xea24Ac04DEFb338CA8595C3750E20166F3b4998A` -- [Alberto Viera](https://twitter.com/theAlbertoV19): `0x4E8ee1AEFEf37c431c6B68F1F5fE6e309ba44376` -- [Arthur Kaseman](https://www.purestake.com/about/): `0x9A23197B7d8bA57E8fe62c3047003C8854F688Cc` -- [Aaron Evans](https://www.linkedin.com/in/aaron-evans-a2366/): `0x3DfED02fEFDDA06A80E21f35097fb910a4a790ef` diff --git a/docs/overview/nomad-vs-the-world.md b/docs/overview/nomad-vs-the-world.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/overview/what-is-nomad.md b/docs/overview/what-is-nomad.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/overview/why-nomad.md b/docs/overview/why-nomad.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/partners/nomad-appendix.md b/docs/partners/nomad-appendix.md deleted file mode 100644 index 2d01940..0000000 --- a/docs/partners/nomad-appendix.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: Nomad - Appendix -lang: en-US ---- - -# Appendix - - - **Nomad**: A security-first cross-chain messaging protocol. Nomad is radically cheaper compared to a traditional header relay. Additionally, it is designed for high reusability, meaning it can be quickly deployed to any EVM chain without the need for any custom logic. - - - **Nomad Token Bridge**: A xApp (cross-chain application) that leverages the Nomad messaging channels to enable sending ERC-20 tokens between supported chains. - - - **Connext**: An interoperability protocol that allows users to swap/transact existing liquidity across chains. Connext is closely partnered with Nomad and is a complementary piece for a seamless end-user experience. Nomad includes a thirty minute dispute window as part of its security model. However, Connext routers are able to bridge funds in advance and pre-fill liquidity for a faster bridging experience. - - - **Message**: Bytes transferred via Nomad that encode some application-specific instructions via a standardized set of rules. - - - **Messaging Channel**: The infrustructure laid by the core Nomad protocol that allows for the passing of arbitrary bytes between chains. - - - **Origin vs Destination**: Most often refers to the direction of a message, where `origin` is the sending chain and `destination` is the receiving chain. - - - **Local vs Remote**: In the context of discussing a particular contract, it is deployed on a particular chain. Contracts and assets on that chain are `local`. Contracts and assets on another chain are `remote`. - - - **Native Assets**: Any asset that resides on it's original chain (e.g. `ETH`, `DAI` and `USDC` are native to the Ethereum chain) - - - **Representations**: When an asset is sent cross-chain, the Token Bridge mints a representation of that token on the destination chain. - - - **Core**: Reference to the core Nomad protocol, or the messaging channels implemented by the core protocol. - - - **xApps**: Pronounced `zap`. A cross-chain application that utilizes the infrastructure of the core Nomad protocol. xApps define the rules for encoding and decoding messages sent via Nomad. - - - **Routers**: A xApp contract that implements a cross-chain application by specifying the message format, as well as rules for dispatching and handling messages. - - - **Domain**: The Nomad-specific id associated with a chain. - - - **Home**: The on-chain contract that is responsible for managing production of the message tree and holding custody of the updater bond. - - - **Replica**: The on-chain contract that is responsible for managing optimistic replication and dispatching messages to end recipients. There is a Replica responsible for each remote chain. - - - **Updater**: The off-chain agent responsible for signing attestations of new roots. - - - **Watcher**: The off-chain agent responsible for reporting faulty attestations. Note that Nomad needs only *one* honest watcher to maintain security of the entire system, rather that relying on custodians or external validators. This allows Nomad to be decentralized and *highly* secure. - - - **Relayer**: The off-chain agent which forwards updates from the home to one or more replicas. - - - **Processor**: The off-chain agent which proves the validity of pending messages and sends them to end recipients. - - - **Governor**: A multi-sig with the power to perform permissioned actions across chains. [Learn more](../dev/governance.md) - - - **Dispute Window**: The time period during which fraud (if any) would be reported. Currently 30 minutes for each chain. - - - **Merkle (or Message) Tree**: A data structure that encodes data efficiently and securely. Used to verify message authenticity by the Home, Updater and Watcher. - - - **Processing or Claiming**: The final step of dispatching a message to the recipient. Processing gas fees are subsidized on most chains. However, when sending to Ethereum (due to the high gas fees), users are required to submit an additional transaction to process messages or token transfers. diff --git a/docs/partners/nomad-bridging-to-evmos.md b/docs/partners/nomad-bridging-to-evmos.md deleted file mode 100644 index 81fa213..0000000 --- a/docs/partners/nomad-bridging-to-evmos.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Nomad Bridge GUI -lang: en-US ---- - -# Nomad Bridge GUI - -## Nomad vs Connext, which should I use? - -There are two options available to send funds through the GUI, Nomad and Connext. These are two distinct protocols that are complimentary to one another. We have partnered with Connext to provide an optimal experience for users! - -Nomad is a secure gas efficient cross-chain protocol that allows users to bridge funds between networks. This takes, on average, 35-60 minutes. There are no fees associated with Nomad, just pay gas! Connext provides liquidity pools for Nomad assets, meaning users can receive funds on the destination chain much faster (less than 10 minutes) for an additional fee. Nomad is advised for large transfers. - -Connext is not available for every asset and may not be available for larger sums. We recommend using Nomad if you intend to send large transfers. - -## Bridging Through Nomad - -Bridging assets across chains using Nomad should be intuitive and easy with the Nomad GUI. In this tutorial, we will walk through the steps required to bridge your assets. - -Please find our production bridge GUI at [app.nomad.xyz](https://app.nomad.xyz/). - -If you would like to test our bridge using testnet funds before using real funds, please visit our development GUI at [development.app.nomad.xyz](https://development.app.nomad.xyz/). - -
- -Connect to Metamask: - -![Connect to Metamask](../public/partner-assets/ethereum-to-evmos/connect-metamask.png) - -
- -Select origin and destination networks: - -![Select Origin and Destination Networks](../public/partner-assets/ethereum-to-evmos/select-networks.png) - -
- -(Optional) Change Destination address. This is set as your wallet address by default. Click "edit". A modal will pop up, click "change" inside the input. Then copy your address, click to paste, and save. -::: warning CAUTION -Sending assets to an address you do not control can result in a permanent loss of funds! -::: - -![Change Destination](../public/partner-assets/ethereum-to-evmos/change-dest-1.png) -![Paste Destination](../public/partner-assets/ethereum-to-evmos/change-dest-2.png) - -
- -Select the asset you want to send using the asset dropdown menu and the amount you want to send using the input prompt: - -![Select an Asset and Amount](../public/partner-assets/ethereum-to-evmos/select-token.png) - -
- -Click `Next`: - -![Select an Asset and Amount](../public/partner-assets/ethereum-to-evmos/input-data.png) - -
- -Review your transaction details and associated fees. Check if Connext liquidity is available for your transfer for a faster bridging experience! If proceeding with Connext, continue reading [here](#fast-transfers-with-connext). - -![Approve Bridge Transaction](../public/partner-assets/ethereum-to-evmos/review.png) - -
- -Click `Bridge Tokens` and approve the transaction in Metamask: - -![Approve Bridge Transaction](../public/partner-assets/ethereum-to-evmos/sending.png) - -
- -After approving the transaction, you will be taken to the transaction details page. Here, you will see the estimated time remaining for your transfer to complete. Please save your transaction hash for convenience. If you lose it, you can visit your wallet address on the block explorer of the origin network and find the transaction again. - -::: info -You must return to the Transaction Page after bridging has concluded to pay for gas and complete your transfer. Nomad may cover the processing and gas fees for some chains. -::: - -![See Transaction Details](../public/partner-assets/ethereum-to-evmos/transfer-pending.png) - -
- -You can expand the time estimate tab to track your transaction status by clicking the down arrow in the blue box: - -![See Expanded Transaction Details](../public/partner-assets/ethereum-to-evmos/expand-status.png) - -
- -(Optional) If you navigated away from the GUI at any point and want to find your transfer's progress page again, visit [https://app.nomad.xyz/tx](https://app.nomad.xyz/tx) and enter the origin network and your transfer's transaction hash. - -![Search Tx](../public/partner-assets/ethereum-to-evmos/search-transfer.png) - -
- -Once your transfer has completed, you should see the below display and your funds will be in the account of your destination address. If your transfer is taking longer than expected, please reach out to us on [Discord](https://discord.gg/RurtmJApqm) in the #support channel: - -![Finished](../public/partner-assets/ethereum-to-evmos/transfer-complete.png) - -
- -## Completing a Transfer (Ethereum Destination Only) - -If you are sending to Ethereum, there is one additional processing step due to the high cost of processing transactions on Ethereum. You will see the following display and should click "Complete Transfer" and complete the Metamask transaction. After this, your funds should be at your destination on Ethereum! - -![Self Process](../public/partner-assets/ethereum-to-evmos/complete-transfer.png) - -
- -## Fast Transfers with Connext - -Fill out data for your transfer and click "Next." Select "Connext." If there is liquidity available for your transfer, it will calculate associated fees for your transaction. Note that Connext collects gas fees in the asset that is being sent. - -If there is not liquidity available, you can continue by using Nomad. - -![Self Process](../public/partner-assets/ethereum-to-evmos/check-connext.png) - -Click `Send` and approve the transaction in Metamask! - -In a few minutes, you will see your transfer appear in a table below. Click "Claim" to submit a transaction to receive your funds on the destination chain. - -Click "View" to go to your transaction in the ConnextScan block explorer. Or you can visit `https://connextscan.io/tx/`. - -![Claim Connext funds](../public/partner-assets/ethereum-to-evmos/connext-claim.png) diff --git a/docs/partners/nomad-bridging-to-milkomeda.md b/docs/partners/nomad-bridging-to-milkomeda.md deleted file mode 100644 index f6e0f17..0000000 --- a/docs/partners/nomad-bridging-to-milkomeda.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Nomad Bridge GUI -lang: en-US ---- - -# Nomad Bridge GUI - -## Nomad vs Connext, which should I use? - -There are two options available to send funds through the GUI, Nomad and Connext. These are two distinct protocols that are complimentary to one another. We have partnered with Connext to provide an optimal experience for users! - -Nomad is a secure gas efficient cross-chain protocol that allows users to bridge funds between networks. This takes, on average, 35-60 minutes. There are no fees associated with Nomad, just pay gas! Connext provides liquidity pools for Nomad assets, meaning users can receive funds on the destination chain much faster (less than 10 minutes) for an additional fee. Nomad is advised for large transfers. - -Connext is not available for every asset and may not be available for larger sums. We recommend using Nomad if you intend to send large transfers. - -## Bridging Through Nomad - -Bridging assets across chains using Nomad should be intuitive and easy with the Nomad GUI. In this tutorial, we will walk through the steps required to bridge your assets. - -Please find our production bridge GUI at [app.nomad.xyz](https://app.nomad.xyz/). - -If you would like to test our bridge using testnet funds before using real funds, please visit our development GUI at [development.app.nomad.xyz](https://development.app.nomad.xyz/). - -
- -Connect to Metamask: - -![Connect to Metamask](../public/partner-assets/ethereum-to-milkomeda/connect-metamask.png) - -
- -Select origin and destination networks: - -![Select Origin and Destination Networks](../public/partner-assets/ethereum-to-milkomeda/select-networks.png) - -
- -(Optional) Change Destination address. This is set as your wallet address by default. Click "edit". A modal will pop up, click "change" inside the input. Then copy your address, click to paste, and save. -::: warning CAUTION -Sending assets to an address you do not control can result in a permanent loss of funds! -::: - -![Change Destination](../public/partner-assets/ethereum-to-milkomeda/change-dest-1.png) -![Paste Destination](../public/partner-assets/ethereum-to-milkomeda/change-dest-2.png) - -
- -Select the asset you want to send using the asset dropdown menu and the amount you want to send using the input prompt: - -![Select an Asset and Amount](../public/partner-assets/ethereum-to-milkomeda/select-token.png) - -
- -Click `Next`: - -![Select an Asset and Amount](../public/partner-assets/ethereum-to-milkomeda/input-data.png) - -
- -Review your transaction details and associated fees. Check if Connext liquidity is available for your transfer for a faster bridging experience! If proceeding with Connext, continue reading [here](#fast-transfers-with-connext). - -![Approve Bridge Transaction](../public/partner-assets/ethereum-to-milkomeda/review.png) - -
- -Click `Bridge Tokens` and approve the transaction in Metamask: - -![Approve Bridge Transaction](../public/partner-assets/ethereum-to-milkomeda/sending.png) - -
- -After approving the transaction, you will be taken to the transaction details page. Here, you will see the estimated time remaining for your transfer to complete. Please save your transaction hash for convenience. If you lose it, you can visit your wallet address on the block explorer of the origin network and find the transaction again. - -::: info -You must return to the Transaction Page after bridging has concluded to pay for gas and complete your transfer. Nomad may cover the processing and gas fees for some chains. -::: - -![See Transaction Details](../public/partner-assets/ethereum-to-milkomeda/transfer-pending.png) - -
- -You can expand the time estimate tab to track your transaction status by clicking the down arrow in the blue box: - -![See Expanded Transaction Details](../public/partner-assets/ethereum-to-milkomeda/expand-status.png) - -
- -(Optional) If you navigated away from the GUI at any point and want to find your transfer's progress page again, visit [https://app.nomad.xyz/tx](https://app.nomad.xyz/tx) and enter the origin network and your transfer's transaction hash. - -![Search Tx](../public/partner-assets/ethereum-to-milkomeda/search-transfer.png) - -
- -Once your transfer has completed, you should see the below display and your funds will be in the account of your destination address. If your transfer is taking longer than expected, please reach out to us on [Discord](https://discord.gg/RurtmJApqm) in the #support channel: - -![Finished](../public/partner-assets/ethereum-to-milkomeda/transfer-complete.png) - -
- -## Completing a Transfer (Ethereum Destination Only) - -If you are sending to Ethereum, there is one additional processing step due to the high cost of processing transactions on Ethereum. You will see the following display and should click "Complete Transfer" and complete the Metamask transaction. After this, your funds should be at your destination on Ethereum! - -![Self Process](../public/partner-assets/ethereum-to-milkomeda/complete-transfer.png) - -
- -## Fast Transfers with Connext - -Fill out data for your transfer and click "Next." Select "Connext." If there is liquidity available for your transfer, it will calculate associated fees for your transaction. Note that Connext collects gas fees in the asset that is being sent. - -If there is not liquidity available, you can continue by using Nomad. - -![Self Process](../public/partner-assets/ethereum-to-milkomeda/check-connext.png) - -Click `Send` and approve the transaction in Metamask! - -In a few minutes, you will see your transfer appear in a table below. Click "Claim" to submit a transaction to receive your funds on the destination chain. - -Click "View" to go to your transaction in the ConnextScan block explorer. Or you can visit `https://connextscan.io/tx/`. - -![Claim Connext funds](../public/partner-assets/ethereum-to-milkomeda/connext-claim.png) diff --git a/docs/partners/nomad-building-xapps.md b/docs/partners/nomad-building-xapps.md deleted file mode 100644 index 62ccd03..0000000 --- a/docs/partners/nomad-building-xapps.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Building Cross-Chain Apps -lang: en-US ---- - -# Building Cross-Chain Apps (xApps) - -### What is a xApp? - -xApp (pronounced "zap") is short for cross-chain application. A xApp is an application that uses cross-chain messaging channels. - -Nomad makes it radically easier to use cross-chain messaging channels to communicate between chains in the form of raw bytes, which can be used to execute actions on-chain. xApp developers - -### What are some examples of a xApp? -- token bridge (most common example) -- on-chain treasury -- permissionless faucet - -### How do I build a xApp? - -To get started with building your own xApp, first you'll need to define the rules for sending and receiving messages for your xApps' use case. We call these rules the ***Router Contracts***. These Router contracts must: - -- ***maintain a permissioned set*** of the contract(s) on remote chains from which it will accept messages via Nomad — this could be a single owner of the application on one chain; it could be a registry of other applications implementing the same rules on various chains - -- ***encode messages in a standardized format***, so they can be decoded by the Router contract on the destination chain - -- ***handle messages*** from remote Router contracts - -- ***dispatch messages*** to remote Router contracts - -By implementing these pieces of functionality within a Router contract and deploying it across multiple chains, we create a working xApp using a common language and set of rules. - -## Example xApp Code - -[The examples repo](https://github.com/nomad-xyz/examples) has several code examples for sample xApps. - -### xApp Template - -Start building your own xApp today! We've got you started with this simple [template](https://github.com/nomad-xyz/examples/tree/main/packages/xapp-example/contracts/xapp-template) - -### Ping Pong xApp - -See how messages are passed back and forth between 2 chains in our [Ping Pong example](https://github.com/nomad-xyz/examples/tree/main/packages/xapp-example/contracts/ping-pong) - -### Token Bridge xApp - -The Token Bridge xApp is our first fully fledged application and is maintained by the Nomad core team. Users can bridge tokens between any networks currently supported by Nomad. - - - [Code](https://github.com/nomad-xyz/monorepo/tree/main/packages/contracts-bridge) - - [Bridge GUI](https://app.nomad.xyz/) - -### Cross-Chain Governance xApp - -Coming soon - -## Additional Resources - -- [How to Build xApps](https://www.youtube.com/watch?v=E_zhTRsxWtw) -- [Connext Network](https://docs.connext.network/) \ No newline at end of file diff --git a/docs/partners/nomad-integrating-bridge.md b/docs/partners/nomad-integrating-bridge.md deleted file mode 100644 index ecb0743..0000000 --- a/docs/partners/nomad-integrating-bridge.md +++ /dev/null @@ -1,100 +0,0 @@ ---- -title: Integrating with Nomad Bridge -lang: en-US ---- - -# Integrating with Nomad Bridge - -You: *“Ahhhhhhhh I’m Integratinggg!!”* - -There are several target audiences for this section: -- dApps deployed to a Nomad-supported Domain -- Wallets or DeFi portals looking to natively embed a bridge in the app -- Anyone who would like to write software that reacts to or ingests state from Nomad - -## The Nomad SDKs - -Nomad has a suite of SDKs that are used to interact with Nomad Protocol. The functionality of each package is split logically between the various components of Nomad: - -- `@nomad-xyz/configuration` - - Configuration data for all Nomad domains (includes network data, core contract addresses, bridge contract addresses, etc) - - [Link to NPM](https://www.npmjs.com/package/@nomad-xyz/configuration) -- `@nomad-xyz/multi-provider` - - A useful library for interacting with many blockchains at once via Ethers.js, underpins the entirety of the Nomad SDK stack. - - [Link to NPM](https://www.npmjs.com/package/@nomad-xyz/multi-provider) -- `@nomad-xyz/sdk` - - The Core SDK, encapsulating the core contracts and providing primitives which are used by higher layers - - [Link to NPM](https://www.npmjs.com/package/@nomad-xyz/sdk) - - [API Documentation](https://docs.nomad.xyz/sdk/) -- `@nomad-xyz/sdk-bridge` - - The Bridge SDK, encapsulating the bridge contracts, providing primitives and convenience methods for interacting with the Nomad Bridge xApp. - - [Link to NPM](https://www.npmjs.com/package/@nomad-xyz/sdk-bridge) - - [API Documentation](https://docs.nomad.xyz/sdk-bridge/) - -## Examples Repository - -Nomad has a wonderful [Examples Repo](https://github.com/nomad-xyz/examples) which you may use as a reference when planning your integration. - -If you're: -- Building a Bridge UI, check out the [Example UI](https://github.com/nomad-xyz/examples/tree/main/packages/sdk-bridge-integration) -- Interested in writing scripts that query or interact with Nomad, check out the [SDK Quickstart](https://github.com/nomad-xyz/examples/tree/main/packages/sdk-quickstart) - -## A note about Nomad Representation Tokens - -The Nomad bridge is a burn/lock/mint model. When a user bridges an asset *from* it's native chain, that amount is locked and the Nomad representation is minted by the bridge contracts. When bridging *back* to the native chain, the representation tokens are burned and the native token is unlocked. This lock/mint model is common among many bridges. However, as a result, this means that Nomad representations are differnt from other bridges' representations. - -Why? Think of this arcade scenario (where arcades are bridges, USD is the native token and arcade coins are representations on other chains). You pay money and receive coins that you can use to play games. These coins would not be accepted at another arcade (You didn't pay that arcade for your tokens!). Likewise, coins from other arcades would not be accepted here. At the end of the night, some coins will have been spent and other coins can be turned in for the equivalent amount in cash. - -See the [token list](../bridge/domains.md) for a complete documentation of all Nomad tokens on each chain. - -## Integrading the Nomad Bridge - -### Getting started - -```ts -import { BridgeContext } from '@nomad-xyz/configuration' -const nomad = new BridgeContext('production') -nomad.registerRpcProvider('ethereum', 'https://some-rpc-url') -nomad.registerRpcProvider('moonbeam', 'https://some-rpc-url') -nomad.registerSigner('ethereum', someSigner) -nomad.registerSigner('moonbeam', someSigner) -``` - -### Sending tokens using the sdk-bridge - -**`sendNative`**: -The Nomad bridge can only send ERC-20 tokens. This function is available for native assets, such as ETH, that need to be wrapped prior to bridging. -```ts -const transferMessage = await nomad.sendNative( - originDomain, // 'ethereum' or 6648936 - destDomain, // 'moonbeam' or 1650811245 - amnt: ethers.utils.parseUnits(amnt, 18), // amount as a big number, format by token decimals (ETH has 18) - destinationAddr, // user's address -) -``` - -**`send`**: -This function is for sending any ERC-20 token. Each token has a corresponding `tokenIdentifier` which includes the name or domain of it's native chain and its address on that native chain. -```ts -// USDC has 6 decimals. Format amount accordingly -const decimals = 6 -const amountBN = ethers.utils.parseUnits(amnt, 6) -// Token Identifier for USDC -const USDCTokenIdentifier = { - domain: 'ethereum', - id: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', -} -const transferMessage = await nomad.send( - originDomain, // 'ethereum' or 6648936 - destDomain, // 'moonbeam' or 1650811245 - USDCTokenIdentifier, - amnt, // amount as a big number, format by token decimals - destinationAddr, // user's address -) -``` - -### Useful Helper Functions - -**`resolveDomain`**: Takes a domain name *or* number and returns the domain number -**`resolveDomainName`**: Takes a domain name *or* number and returns the domain name -**`resolveRepresentation`**: Takes a domain and Token Identifier and returns the token representation on that chain. diff --git a/docs/partners/nomad-overview.md b/docs/partners/nomad-overview.md deleted file mode 100644 index 16fdf78..0000000 --- a/docs/partners/nomad-overview.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -title: Nomad Protocol - Overview -lang: en-US ---- - -# Nomad and Connext - An Overview - -Nomad and Connext are available on ``! - -- Bridge Today: [app.nomad.xyz](https://app.nomad.xyz) -- Read the Docs: [docs.nomad.xyz](https://docs.nomad.xyz) -- Join the Nomad Discord: [Become a MadLad](https://discord.gg/nomadxyz) -- Follow [Nomad](https://twitter.com/nomadxyz_) and [Connext](https://twitter.com/ConnextNetwork) on Twitter! - -## What is Nomad Protocol? - -Nomad is a new design for radically cheaper cross-chain communication without header verification, taking inspiration from optimistic systems (a la Optimistic Roll-ups). Nomad features many of the properties we prize in an optimistic mechanism, like public verification, low gas fees, broad participation, but has a slightly different security model. - -Nomad provides the base layer of a cross-chain communication network that provides fast, cheap communication for all smart contract chains and rollups. It relies only on widely-available cryptographic primitives (unlike header relays) and measures message latency in minutes (rather than an ORU’s one-week latency). - -## What is Connext? - -Connext, using the **N**oncustodial **X**domain **T**ransfer **P**rotocol or **NXTP**, is a lightweight protocol that enables cross-chain/rollup transactions that retain the security properties of the underlying execution environment. It facilitates cross-chain value transfers via a network of liquidity providers (called Routers) which allows for near-instant settlement of cross-chain token transfers, assuming an existing liquidity environment on the receiving blockchain. - -Connext does not rely on any external validator set in order to operate -- a trust model that is highly complimentary with that of Nomad. - - -## Nomad Architecture - -Nomad works something like a notary service. - -nomad-notary - -The sending (or “home”) chain produces a series of documents ("messages") that needs notarization. A notary (called the “updater”) is contracted to sign it. The notary can produce a fraudulent copy, but they will be punished by having their bond and license publicly revoked. When this happens, everyone relying on the notary learns that the notary is malicious. All the notary's customers can immediately block the notary and prevent any malicious access to their accounts. - -Nomad's Core system is split between on-chain and off-chain components. The protocol is implemented in Smart Contracts, with the bulk of the protocol interactions being automated by a series of off-chain "Agents". - -![Nomad Components](../public/Nomad-Architecture.png) - -For a detailed deep dive on the protocol, check out the complete [Nomad Documentation](https://docs.nomad.xyz/) - -## Connext Architecture - -### How it works - -This iteration of Connext's network utilizes NXTP, a lightweight protocol for generalized crosschain transfers. - -Nxtp is made up of a simple contract that uses a locking pattern to prepare and fulfill transactions, a network of offchain routers that participate in pricing auctions and pass calldata between chains, and a user-side sdk that finds routes and prompts onchain transactions. - -### Transaction Lifecycle - -![Connext High Level Flow](../public/partner-assets/overview/connext-highlevel-flow.png) - -Transactions go through three phases: - -1. **Route Auction**: User broadcasts to our network signalling their desired route. Routers respond with sealed bids containing commitments to fulfilling the transaction within a certain time and price range. -2. **Prepare**: Once the auction is completed, the transaction can be prepared. The user submits a transaction to TransactionManager contract on sender-side chain containing router's signed bid. This transaction locks up the users funds on the sending chiain. Upon detecting an event containing their signed bid from the chain, router submits the same transaction to TransactionManager on the receiver-side chain, and locks up a corresponding amount of liquidity. The amount locked on the receiving chain is sending amount - auction fee so the router is incentivized to complete the transaction. -3. **Fulfill**: Upon detecting the TransactionPrepared event on the receiver-side chain, the user signs a message and sends it to a relayer, who will earn a fee for submission. The relayer (which is typically another router) then submits the message to the TransactionManager to complete the user's transaction on receiver-side chain and claim the funds locked by the router. A relayer is used here to allow users to submit transactions with arbitrary calldata on the receiving chain without needing gas to do so. The router then submits the same signed message and completes transaction on sender-side, unlocking the original amount. - -If a transaction is not fulfilled within a fixed expiry, it reverts and can be reclaimed by the party that called prepare on each chain (initiator). - -Additionally, transactions can be cancelled unilaterally by the person owed funds on that chain (router for sending chain, user for receiving chain) prior to expiry. - -It is important to note that neither participant should require a store to complete these transactions. All information to `prepare`, `fulfill`, or `cancel` transactions should be retrievable through contract events. - -### Architecture - -![Connext Architecture](../public/partner-assets/overview/connext-architecture.png) - -The system contains the following pieces: - - - Contracts - hold funds for all network participants, and lock/unlock based on data submitted by users and routers - - Subgraph - enables scalable querying/responding by caching onchain data and events. - - TxService - resiliently attempts to send transactions to chain (with retries, etc.) - - Messaging - prepares, sends, and listens for message data over nats - - Router - listens for events from messaging service and subgraph, and then dispatches transactions to txService - - SDK - creates auctions, listens for events and creates transactions on the user side. - -## Nomad x Connext vs XYZ Bridge - -| Approach | Mechanism | Examples | Trust Minimized | Generalized | Cheap/Fast to Implement | -| ------------------- | ---------------------------------------------------- | ------------------------------------------------------ | --------------- | ----------- | ----------------------- | -| Natively Verified | Chain's own validator set verifies xchain data. | IBC, Near Rainbowbridge, BTC Relay, rollup entry/exit | ✅ | ✅ | ❌ | -| Externally Verified | 3rd party validator set verifies data across chains. | Thorchain, Anyswap, Synapse, Hyphen, many many others. | ❌ | ✅ | ✅ | -| Locally Verified | N-party system is reduced to 1:1 interaction | Connext, Hop, Nomad, simple atomic swaps. | ✅ | ❌ | ✅ | - -### The Nomad x Connext Approach to Bridging - -Nomad's core protocol facilitates generalized cross-chain message passing via an Optimistic Mechaism. While not 100% locally verified, it enables broad protocol participation via the inclusion of fraud proofs, enabling anyone with a computer to participate in securing the protocol. The main trade-off that results in the desirable trust model, also introduces a period of latency for each message. Many users will opt to leverage the highly secure Nomad Messaging channels, despite the increased latency! - -This is where the properties of Connext become highly desirable, as it provides comparatively quick settlement of cross-chain transfers without sacrificing on trust model, assuming there's enough liquidity to complete the transfer. - -## Try It For Yourself - -You can bridge today via the [Nomad Bridge App](https://app.nomad.xyz)! \ No newline at end of file diff --git a/docs/protocol/agents.md b/docs/protocol/agents.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/protocol/governance.md b/docs/protocol/governance.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/protocol/messaging.md b/docs/protocol/messaging.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/protocol/overview.md b/docs/protocol/overview.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/protocol/security.md b/docs/protocol/security.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/public/Logo-Black.png b/docs/public/Logo-Black.png deleted file mode 100644 index 76fb61899515c25262695deba26419194fbf0a89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23691 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 diff --git a/docs/public/Logo-Black.svg b/docs/public/Logo-Black.svg deleted file mode 100644 index e9e656d..0000000 --- a/docs/public/Logo-Black.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/docs/public/Logo-White.png b/docs/public/Logo-White.png deleted file mode 100644 index 0c9867e0901a8a05c773399ba28d18970fb1391b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21940 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 nXL}LYi@;t4_9F2ABQSH@n5tEJb - - - - - - diff --git a/docs/public/Nomad-Architecture.png b/docs/public/Nomad-Architecture.png deleted file mode 100644 index 5486999de25afe9a827b4f3f63158380ca0e76a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 792611 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�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