From 829a7fec0dc7032f8affcad82d85becad627e1ec Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Wed, 10 Jul 2024 11:32:11 -0500 Subject: [PATCH 1/8] separate implementation and management sections --- contracts/src/Teleporter/upgrades/README.md | 69 ++++++++++++++++----- 1 file changed, 54 insertions(+), 15 deletions(-) diff --git a/contracts/src/Teleporter/upgrades/README.md b/contracts/src/Teleporter/upgrades/README.md index f98728567..49a910024 100644 --- a/contracts/src/Teleporter/upgrades/README.md +++ b/contracts/src/Teleporter/upgrades/README.md @@ -27,7 +27,7 @@ In the `TeleporterRegistry` contract, the `latestVersion` state variable returns - Version zero is an invalid version, and is used to indicate that a `TeleporterMessenger` contract has not been registered yet. - Once a version number is registered in the registry, it cannot be changed, but a previous registered protocol address can be added to the registry with a new version. This is especially important in the case of a rollback to a previous Teleporter version, in which case the previous Teleporter contract address would need to be registered with a new version to the registry. -## Integrating `TeleporterRegistry` with `TeleporterUpgradeable` +## Integrating `TeleporterUpgradeable` into a dApp
Upgrade UML diagram @@ -76,17 +76,7 @@ contract ExampleApp is } ``` -### TeleporterUpgradeable utility - -#### Initialization - -The `TeleporterUpgradeable` contract constructor saves the Teleporter registry in a state variable used by the inheriting contract, and initializes a `minTeleporterVersion` to the highest `TeleporterMessenger` version registered in `TeleporterRegistry`. `minTeleporterVersion` is used to allow dApp's to specify the Teleporter versions allowed to interact with it. - -#### Updating `minTeleporterVersion` - -The `TeleporterUpgradeable.updateMinTeleporterVersion` function updates the `minTeleporterVersion` used to check which Teleporter versions can deliver messages to the dApp, and emits the `MinTeleporterVersionUpdated` event. The `updateMinTeleporterVersion` function should **ONLY** be called by the dApp when it completes delivery of messages from the old Teleporter contract, and now wants to update the `minTeleporterVersion` to only allow the new Teleporter version. By default, `updateMinTeleporterVersion` can only be called with a version greater than the current `minTeleporterVersion` and less than `latestVersion` in the Teleporter registry. So once this function is called, the dApp will no longer be able to receive messages from the old Teleporter contract version, unless the old version's Teleporter address was registered in the registry again with a new version. - -#### Checking Teleporter upgrade access +### Checking Teleporter upgrade access To prevent anyone from calling the dApp's `updateMinTeleporterVersion`, which would disallow messages from old Teleporter versions from being received, this function should be safeguarded with access controls. All contracts deriving from `TeleporterUpgradeable` will need to implement `TeleporterUpgradeable._checkTeleporterUpgradeAccess`. For example, [TeleporterOwnerUpgrade](./TeleporterOwnerUpgradeable.sol) is an abstract contract that inherits `TeleporterUpgradeable`, and implements `_checkTeleporterUpgradeAccess` to check whether the caller is the owner. @@ -107,7 +97,7 @@ Another example would be a dApp that has different roles and priveleges. `_check } ``` -#### Sending with specific Teleporter version +### Sending with specific Teleporter version For sending messages with the Teleporter registry, dapps should use `TeleporterUpgradeable._getTeleporterMessenger`. This function by default extends `TeleporterRegistry.getLatestTeleporter`, using the latest version, and adds an extra check on whether the latest Teleporter address is paused. If the dApp wants to send a message through a specific Teleporter version, it can override `_getTeleporterMessenger()` to use the specific Teleporter version with `TeleporterRegistry.getTeleporterFromVersion`. @@ -137,18 +127,67 @@ Using specific version: ITeleporterMessenger teleporterMessenger = _getTeleporterMessenger(); ``` -#### Receiving from specific Teleporter versions +### Receiving from specific Teleporter versions `TeleporterUpgradeable` also provides an initial implementation of [ITeleporterReceiver.receiveTeleporterMessage](../ITeleporterReceiver.sol) that ensures `_msgSender` is a `TeleporterMessenger` contract with a version greater than or equal to `minTeleporterVersion`. This supports the case where a dApp wants to upgrade to a new version of the `TeleporterMessenger` contract, but still wants to be able to receive messages from the old Teleporter contract.The dApp can override `_receiveTeleporterMessage` to implement its own logic for receiving messages from Teleporter contracts. -#### Pausing Teleporter version interactions +## Managing a TeleporterUpgradeable contract + +### Managing the Minimum Teleporter version + +The `TeleporterUpgradeable` contract constructor saves the Teleporter registry in a state variable used by the inheriting contract, and initializes a `minTeleporterVersion` to the highest `TeleporterMessenger` version registered in `TeleporterRegistry`. `minTeleporterVersion` is used to allow dApp's to specify the Teleporter versions allowed to interact with it. + +#### Updating `minTeleporterVersion` + +The `TeleporterUpgradeable.updateMinTeleporterVersion` function updates the `minTeleporterVersion` used to check which Teleporter versions can deliver messages to the dApp, and emits the `MinTeleporterVersionUpdated` event. The `updateMinTeleporterVersion` function should **ONLY** be called by the dApp when it completes delivery of messages from the old Teleporter contract, and now wants to update the `minTeleporterVersion` to only allow the new Teleporter version. By default, `updateMinTeleporterVersion` can only be called with a version greater than the current `minTeleporterVersion` and less than `latestVersion` in the Teleporter registry. So once this function is called, the dApp will no longer be able to receive messages from the old Teleporter contract version, unless the old version's Teleporter address was registered in the registry again with a new version. + +> Example: Update the minimum Teleporter version to 2 +>``` +>cast send "updateMinTeleporterVersion(uint256)" 2 +>``` + +### Pausing Teleporter version interactions Dapps that inherit from `TeleporterUpgradeable` can pause Teleporter interactions by calling `TeleporterUpgradeable.pauseTeleporterAddress`. This function prevents the contract from interacting with the paused Teleporter address when sending or receiving Teleporter messages. `pauseTeleporterAddress` can only be called by addresses with the dApp's upgrade access, checked through `TeleporterUpgradeable._checkTeleporterUpgradeAccess`. +The Teleporter address corresponding to a Teleporter version can be fetched from the registry with `TeleporterRegistry.getAddressFromVersion` + +> Example: Pause Teleporter version 3 +>``` +>versionThreeAddress=$(cast call "getAddressFromVersion(uint256)(address)" 3) +>cast send "pauseTeleporterAddress(address)" $versionThreeAddress +>``` + +#### Pause all Teleporter interaction + +To pause all Teleporter interaction, `TeleporterUpgradeable.pauseTeleporterAddress` must be called for every Teleporter version from the `minTeleporterVersion` to the latest Teleporter version registered in `TeleporterRegistry`. The latest Teleporter version can be obtained by inspecting the public variable `TeleporterRegistry.latestVersion`. The `minTeleporterVersion` can be obtained by calling `TeleporterUpgradeable.getMinTeleporterVersion`. + +> Example: Pause all registered Teleporter versions +>``` +># Fetch the minimum Teleporter version +>minVersion=$(cast call "getMinTeleporterVersion()(uint256)") +> +># Fetch the latest registered version +>latestVersion=$(cast call "latestVersion()(uint256)") +> +># Pause all registered versions +>for ((version=minVersion; version<=latestVersion; version++)) +>do +> versionAddress=$(cast call "getAddressFromVersion(uint256)(address)" $version) +> cast send "pauseTeleporterAddress(address)" $versionAddress +>done +> + #### Unpausing Teleporter version interactions As with pausing, dapps can unpause Teleporter interactions by calling `TeleporterUpgradeable.unpauseTeleporterAddress`. This unpause function allows receiving Teleporter message from the unpaused Teleporter address, and also enables the sending of messages through the unpaused Teleporter address in `_getTeleporterMessenger()`. Unpausing is also only allowed by addresses with the dApp's upgrade access. Note that receiving Teleporter messages is still governed by the `minTeleporterVersion` check, so even if a Teleporter address is unpaused, the dApp will not receive messages from the unpaused Teleporter address if the Teleporter version is less than `minTeleporterVersion`. + +> Example: Unpause Teleporter version 3 +>``` +>versionThreeAddress=$(cast call "getAddressFromVersion(uint256)(address)" 3) +>cast send "unpauseTeleporterAddress(address)" $versionThreeAddress +>``` From 342c52ad5b5ed180253b8fc76afcdfa84714b654 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Wed, 10 Jul 2024 11:38:18 -0500 Subject: [PATCH 2/8] consistent use of dApp --- contracts/src/Teleporter/upgrades/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/src/Teleporter/upgrades/README.md b/contracts/src/Teleporter/upgrades/README.md index 49a910024..ff320999c 100644 --- a/contracts/src/Teleporter/upgrades/README.md +++ b/contracts/src/Teleporter/upgrades/README.md @@ -131,11 +131,11 @@ Using specific version: `TeleporterUpgradeable` also provides an initial implementation of [ITeleporterReceiver.receiveTeleporterMessage](../ITeleporterReceiver.sol) that ensures `_msgSender` is a `TeleporterMessenger` contract with a version greater than or equal to `minTeleporterVersion`. This supports the case where a dApp wants to upgrade to a new version of the `TeleporterMessenger` contract, but still wants to be able to receive messages from the old Teleporter contract.The dApp can override `_receiveTeleporterMessage` to implement its own logic for receiving messages from Teleporter contracts. -## Managing a TeleporterUpgradeable contract +## Managing a TeleporterUpgradeable dApp ### Managing the Minimum Teleporter version -The `TeleporterUpgradeable` contract constructor saves the Teleporter registry in a state variable used by the inheriting contract, and initializes a `minTeleporterVersion` to the highest `TeleporterMessenger` version registered in `TeleporterRegistry`. `minTeleporterVersion` is used to allow dApp's to specify the Teleporter versions allowed to interact with it. +The `TeleporterUpgradeable` contract constructor saves the Teleporter registry in a state variable used by the inheriting dApp contract, and initializes a `minTeleporterVersion` to the highest `TeleporterMessenger` version registered in `TeleporterRegistry`. `minTeleporterVersion` is used to allow dApp's to specify the Teleporter versions allowed to interact with it. #### Updating `minTeleporterVersion` @@ -148,7 +148,7 @@ The `TeleporterUpgradeable.updateMinTeleporterVersion` function updates the `min ### Pausing Teleporter version interactions -Dapps that inherit from `TeleporterUpgradeable` can pause Teleporter interactions by calling `TeleporterUpgradeable.pauseTeleporterAddress`. This function prevents the contract from interacting with the paused Teleporter address when sending or receiving Teleporter messages. +Dapps that inherit from `TeleporterUpgradeable` can pause Teleporter interactions by calling `TeleporterUpgradeable.pauseTeleporterAddress`. This function prevents the dApp contract from interacting with the paused Teleporter address when sending or receiving Teleporter messages. `pauseTeleporterAddress` can only be called by addresses with the dApp's upgrade access, checked through `TeleporterUpgradeable._checkTeleporterUpgradeAccess`. From 6d78d161cabdf5ceca439c7b975626aa247a2a11 Mon Sep 17 00:00:00 2001 From: cam-schultz <78878559+cam-schultz@users.noreply.github.com> Date: Wed, 10 Jul 2024 13:14:58 -0500 Subject: [PATCH 3/8] Update contracts/src/Teleporter/upgrades/README.md Co-authored-by: bernard-avalabs <53795885+bernard-avalabs@users.noreply.github.com> Signed-off-by: cam-schultz <78878559+cam-schultz@users.noreply.github.com> --- contracts/src/Teleporter/upgrades/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/src/Teleporter/upgrades/README.md b/contracts/src/Teleporter/upgrades/README.md index ff320999c..7cfbceb54 100644 --- a/contracts/src/Teleporter/upgrades/README.md +++ b/contracts/src/Teleporter/upgrades/README.md @@ -160,7 +160,7 @@ The Teleporter address corresponding to a Teleporter version can be fetched from >cast send "pauseTeleporterAddress(address)" $versionThreeAddress >``` -#### Pause all Teleporter interaction +#### Pause all Teleporter interactions To pause all Teleporter interaction, `TeleporterUpgradeable.pauseTeleporterAddress` must be called for every Teleporter version from the `minTeleporterVersion` to the latest Teleporter version registered in `TeleporterRegistry`. The latest Teleporter version can be obtained by inspecting the public variable `TeleporterRegistry.latestVersion`. The `minTeleporterVersion` can be obtained by calling `TeleporterUpgradeable.getMinTeleporterVersion`. From f940ce90ebfa0548016534138b209de046de583d Mon Sep 17 00:00:00 2001 From: cam-schultz <78878559+cam-schultz@users.noreply.github.com> Date: Wed, 10 Jul 2024 13:15:04 -0500 Subject: [PATCH 4/8] Update contracts/src/Teleporter/upgrades/README.md Co-authored-by: bernard-avalabs <53795885+bernard-avalabs@users.noreply.github.com> Signed-off-by: cam-schultz <78878559+cam-schultz@users.noreply.github.com> --- contracts/src/Teleporter/upgrades/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/src/Teleporter/upgrades/README.md b/contracts/src/Teleporter/upgrades/README.md index 7cfbceb54..0d2d8988d 100644 --- a/contracts/src/Teleporter/upgrades/README.md +++ b/contracts/src/Teleporter/upgrades/README.md @@ -162,7 +162,7 @@ The Teleporter address corresponding to a Teleporter version can be fetched from #### Pause all Teleporter interactions -To pause all Teleporter interaction, `TeleporterUpgradeable.pauseTeleporterAddress` must be called for every Teleporter version from the `minTeleporterVersion` to the latest Teleporter version registered in `TeleporterRegistry`. The latest Teleporter version can be obtained by inspecting the public variable `TeleporterRegistry.latestVersion`. The `minTeleporterVersion` can be obtained by calling `TeleporterUpgradeable.getMinTeleporterVersion`. +To pause all Teleporter interactions, `TeleporterUpgradeable.pauseTeleporterAddress` must be called for every Teleporter version from the `minTeleporterVersion` to the latest Teleporter version registered in `TeleporterRegistry`. The latest Teleporter version can be obtained by inspecting the public variable `TeleporterRegistry.latestVersion`. The `minTeleporterVersion` can be obtained by calling `TeleporterUpgradeable.getMinTeleporterVersion`. > Example: Pause all registered Teleporter versions >``` From 9cfbfffc9a4964226c1cf829d58c0934869b37c6 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Wed, 10 Jul 2024 13:28:40 -0500 Subject: [PATCH 5/8] contract management summary --- contracts/src/Teleporter/upgrades/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contracts/src/Teleporter/upgrades/README.md b/contracts/src/Teleporter/upgrades/README.md index 0d2d8988d..e7a4742ac 100644 --- a/contracts/src/Teleporter/upgrades/README.md +++ b/contracts/src/Teleporter/upgrades/README.md @@ -133,6 +133,8 @@ Using specific version: ## Managing a TeleporterUpgradeable dApp +dApps that implement `TeleporterUpgradeable` automatically use the latest Teleporter version registered with the `TeleporterRegistry`. Interaction with underlying `TeleporterMessenger` versions can be managed by setting the minimum Teleporter version, and pausing and unpausing specific versions. + ### Managing the Minimum Teleporter version The `TeleporterUpgradeable` contract constructor saves the Teleporter registry in a state variable used by the inheriting dApp contract, and initializes a `minTeleporterVersion` to the highest `TeleporterMessenger` version registered in `TeleporterRegistry`. `minTeleporterVersion` is used to allow dApp's to specify the Teleporter versions allowed to interact with it. From 9e13adcb3708884cf60e4f3ee01efa76ef4021cf Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Fri, 12 Jul 2024 11:07:05 -0500 Subject: [PATCH 6/8] pr feedback --- contracts/src/Teleporter/upgrades/README.md | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/contracts/src/Teleporter/upgrades/README.md b/contracts/src/Teleporter/upgrades/README.md index e7a4742ac..2e689de1d 100644 --- a/contracts/src/Teleporter/upgrades/README.md +++ b/contracts/src/Teleporter/upgrades/README.md @@ -135,6 +135,8 @@ Using specific version: dApps that implement `TeleporterUpgradeable` automatically use the latest Teleporter version registered with the `TeleporterRegistry`. Interaction with underlying `TeleporterMessenger` versions can be managed by setting the minimum Teleporter version, and pausing and unpausing specific versions. +The following sections include example `cast send` commands for issuing transactions that call contract functions. See the [Foundry Book](https://book.getfoundry.sh/reference/cast/cast-send) for details on how to issue transactions using common wallet options. + ### Managing the Minimum Teleporter version The `TeleporterUpgradeable` contract constructor saves the Teleporter registry in a state variable used by the inheriting dApp contract, and initializes a `minTeleporterVersion` to the highest `TeleporterMessenger` version registered in `TeleporterRegistry`. `minTeleporterVersion` is used to allow dApp's to specify the Teleporter versions allowed to interact with it. @@ -150,9 +152,9 @@ The `TeleporterUpgradeable.updateMinTeleporterVersion` function updates the `min ### Pausing Teleporter version interactions -Dapps that inherit from `TeleporterUpgradeable` can pause Teleporter interactions by calling `TeleporterUpgradeable.pauseTeleporterAddress`. This function prevents the dApp contract from interacting with the paused Teleporter address when sending or receiving Teleporter messages. +dApps that inherit from `TeleporterUpgradeable` can pause Teleporter interactions by calling `TeleporterUpgradeable.pauseTeleporterAddress`. This function prevents the dApp contract from interacting with the paused Teleporter address when sending or receiving Teleporter messages. -`pauseTeleporterAddress` can only be called by addresses with the dApp's upgrade access, checked through `TeleporterUpgradeable._checkTeleporterUpgradeAccess`. +`pauseTeleporterAddress` can only be called by addresses with the dApps upgrade access, checked through `TeleporterUpgradeable._checkTeleporterUpgradeAccess`. The Teleporter address corresponding to a Teleporter version can be fetched from the registry with `TeleporterRegistry.getAddressFromVersion` @@ -164,7 +166,7 @@ The Teleporter address corresponding to a Teleporter version can be fetched from #### Pause all Teleporter interactions -To pause all Teleporter interactions, `TeleporterUpgradeable.pauseTeleporterAddress` must be called for every Teleporter version from the `minTeleporterVersion` to the latest Teleporter version registered in `TeleporterRegistry`. The latest Teleporter version can be obtained by inspecting the public variable `TeleporterRegistry.latestVersion`. The `minTeleporterVersion` can be obtained by calling `TeleporterUpgradeable.getMinTeleporterVersion`. +To pause all Teleporter interactions, `TeleporterUpgradeable.pauseTeleporterAddress` must be called for every Teleporter version from the `minTeleporterVersion` to the latest Teleporter version registered in `TeleporterRegistry`. Note that there may be gaps in Teleporter versions registered with `TeleporterRegistry`, but they will always be in increasing order. The latest Teleporter version can be obtained by inspecting the public variable `TeleporterRegistry.latestVersion`. The `minTeleporterVersion` can be obtained by calling `TeleporterUpgradeable.getMinTeleporterVersion`. > Example: Pause all registered Teleporter versions >``` @@ -177,10 +179,18 @@ To pause all Teleporter interactions, `TeleporterUpgradeable.pauseTeleporterAddr ># Pause all registered versions >for ((version=minVersion; version<=latestVersion; version++)) >do +> # Fetch the version address if it's registered > versionAddress=$(cast call "getAddressFromVersion(uint256)(address)" $version) -> cast send "pauseTeleporterAddress(address)" $versionAddress ->done > +> if [ $? -eq 0 ]; then +> # If cast call is successful, proceed to cast send +> cast send "pauseTeleporterAddress(address)" $versionAddress +> else +> # If cast call fails, print an error message and skip to the next iteration +> echo "Version $version not registered. Skipping." +> fi +>done +>``` #### Unpausing Teleporter version interactions From 492db9e9c9e0ec705525ab5f13694ee9a06930f4 Mon Sep 17 00:00:00 2001 From: cam-schultz <78878559+cam-schultz@users.noreply.github.com> Date: Fri, 12 Jul 2024 11:07:24 -0500 Subject: [PATCH 7/8] Update contracts/src/Teleporter/upgrades/README.md Co-authored-by: Michael Kaplan <55204436+michaelkaplan13@users.noreply.github.com> Signed-off-by: cam-schultz <78878559+cam-schultz@users.noreply.github.com> --- contracts/src/Teleporter/upgrades/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/src/Teleporter/upgrades/README.md b/contracts/src/Teleporter/upgrades/README.md index 2e689de1d..827fd53f5 100644 --- a/contracts/src/Teleporter/upgrades/README.md +++ b/contracts/src/Teleporter/upgrades/README.md @@ -143,7 +143,7 @@ The `TeleporterUpgradeable` contract constructor saves the Teleporter registry i #### Updating `minTeleporterVersion` -The `TeleporterUpgradeable.updateMinTeleporterVersion` function updates the `minTeleporterVersion` used to check which Teleporter versions can deliver messages to the dApp, and emits the `MinTeleporterVersionUpdated` event. The `updateMinTeleporterVersion` function should **ONLY** be called by the dApp when it completes delivery of messages from the old Teleporter contract, and now wants to update the `minTeleporterVersion` to only allow the new Teleporter version. By default, `updateMinTeleporterVersion` can only be called with a version greater than the current `minTeleporterVersion` and less than `latestVersion` in the Teleporter registry. So once this function is called, the dApp will no longer be able to receive messages from the old Teleporter contract version, unless the old version's Teleporter address was registered in the registry again with a new version. +The `TeleporterUpgradeable.updateMinTeleporterVersion` function updates the `minTeleporterVersion` used to check which Teleporter versions can be used for sending and receiving messages. **Once the `minTeleporterVersion` is increased, any undelivered messages sent by other chains using older versions of Teleporter will never be able to be received**. The `updateMinTeleporterVersion` function can only be called with a version greater than the current `minTeleporterVersion` and less than `latestVersion` in the Teleporter registry. > Example: Update the minimum Teleporter version to 2 >``` From 9d36ddd359902d0ac2018f58e33c7c48b7a3a36e Mon Sep 17 00:00:00 2001 From: cam-schultz <78878559+cam-schultz@users.noreply.github.com> Date: Fri, 12 Jul 2024 13:55:10 -0500 Subject: [PATCH 8/8] Update contracts/src/Teleporter/upgrades/README.md Co-authored-by: Michael Kaplan <55204436+michaelkaplan13@users.noreply.github.com> Signed-off-by: cam-schultz <78878559+cam-schultz@users.noreply.github.com> --- contracts/src/Teleporter/upgrades/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/src/Teleporter/upgrades/README.md b/contracts/src/Teleporter/upgrades/README.md index 827fd53f5..c8811e20b 100644 --- a/contracts/src/Teleporter/upgrades/README.md +++ b/contracts/src/Teleporter/upgrades/README.md @@ -27,7 +27,7 @@ In the `TeleporterRegistry` contract, the `latestVersion` state variable returns - Version zero is an invalid version, and is used to indicate that a `TeleporterMessenger` contract has not been registered yet. - Once a version number is registered in the registry, it cannot be changed, but a previous registered protocol address can be added to the registry with a new version. This is especially important in the case of a rollback to a previous Teleporter version, in which case the previous Teleporter contract address would need to be registered with a new version to the registry. -## Integrating `TeleporterUpgradeable` into a dApp +## Integrating `TeleporterUpgradeable` into a dApp
Upgrade UML diagram