From 73d6fff6af9a687b5ca62f51cae5ef10498ffe2f Mon Sep 17 00:00:00 2001 From: sendra Date: Tue, 30 Jul 2024 10:36:56 +0200 Subject: [PATCH 1/3] add payload templates --- src/templates/BaseADIPayloadUpdate.sol | 15 ++ src/templates/BaseAdaptersUpdate.sol | 27 +++ src/templates/BaseCCCUpdate.sol | 48 ++++++ src/templates/BaseForwarderAdaptersUpdate.sol | 47 +++++ src/templates/BaseReceiverAdaptersUpdate.sol | 48 ++++++ src/templates/SimpleAddForwarderAdapter.sol | 48 ++++++ .../SimpleOneToManyAdapterUpdate.sol | 160 ++++++++++++++++++ src/templates/SimpleReceiverAdapterUpdate.sol | 86 ++++++++++ .../interfaces/IBaseAdaptersUpdate.sol | 13 ++ .../IBaseForwarderAdaptersUpdate.sol | 35 ++++ .../IBaseReceiverAdaptersUpdate.sol | 34 ++++ 11 files changed, 561 insertions(+) create mode 100644 src/templates/BaseADIPayloadUpdate.sol create mode 100644 src/templates/BaseAdaptersUpdate.sol create mode 100644 src/templates/BaseCCCUpdate.sol create mode 100644 src/templates/BaseForwarderAdaptersUpdate.sol create mode 100644 src/templates/BaseReceiverAdaptersUpdate.sol create mode 100644 src/templates/SimpleAddForwarderAdapter.sol create mode 100644 src/templates/SimpleOneToManyAdapterUpdate.sol create mode 100644 src/templates/SimpleReceiverAdapterUpdate.sol create mode 100644 src/templates/interfaces/IBaseAdaptersUpdate.sol create mode 100644 src/templates/interfaces/IBaseForwarderAdaptersUpdate.sol create mode 100644 src/templates/interfaces/IBaseReceiverAdaptersUpdate.sol diff --git a/src/templates/BaseADIPayloadUpdate.sol b/src/templates/BaseADIPayloadUpdate.sol new file mode 100644 index 0000000..7e57d8d --- /dev/null +++ b/src/templates/BaseADIPayloadUpdate.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +import {IProposalGenericExecutor} from 'aave-helpers/interfaces/IProposalGenericExecutor.sol'; + +abstract contract BaseADIPayloadUpdate is IProposalGenericExecutor { + address public immutable CROSS_CHAIN_CONTROLLER; + + /** + * @param crossChainController address of the CCC of the network where payload will be deployed + */ + constructor(address crossChainController) { + CROSS_CHAIN_CONTROLLER = crossChainController; + } +} diff --git a/src/templates/BaseAdaptersUpdate.sol b/src/templates/BaseAdaptersUpdate.sol new file mode 100644 index 0000000..a2fd0ff --- /dev/null +++ b/src/templates/BaseAdaptersUpdate.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import './BaseReceiverAdaptersUpdate.sol'; +import './BaseForwarderAdaptersUpdate.sol'; +import './BaseADIPayloadUpdate.sol'; + +/** + * @title Base payload aDI and bridge adapters update + * @author BGD Labs @bgdlabs + */ +abstract contract BaseAdaptersUpdate is + BaseReceiverAdaptersUpdate, + BaseForwarderAdaptersUpdate, + BaseADIPayloadUpdate +{ + /** + * @param crossChainController address of the CCC of the network where payload will be deployed + */ + constructor(address crossChainController) BaseADIPayloadUpdate(crossChainController) {} + + function execute() public virtual { + executeReceiversUpdate(CROSS_CHAIN_CONTROLLER); + + executeForwardersUpdate(CROSS_CHAIN_CONTROLLER); + } +} diff --git a/src/templates/BaseCCCUpdate.sol b/src/templates/BaseCCCUpdate.sol new file mode 100644 index 0000000..3529bc6 --- /dev/null +++ b/src/templates/BaseCCCUpdate.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; +import {TransparentProxyFactory} from 'solidity-utils/contracts/transparent-proxy/TransparentProxyFactory.sol'; +import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; +import './BaseADIPayloadUpdate.sol'; + +/** + * @param crossChainController address of the CCC of the network where payload will be deployed + * @param newCCCImpl address of the new ccc implementation + * @param proxyAdmin address of the proxy admin owner of ccc + */ +struct CCCUpdateArgs { + address crossChainController; + address crossChainControllerImpl; + address proxyAdmin; +} + +/** + * @title Base payload to update CCC + * @author BGD Labs @bgdlabs + */ +abstract contract BaseCCCUpdate is BaseADIPayloadUpdate { + address public immutable NEW_CCC_IMPL; + address public immutable PROXY_ADMIN; + + /* + * @param cccUpdateArgs arguments necessary to update ccc implementation + */ + constructor( + CCCUpdateArgs memory cccUpdateArgs + ) BaseADIPayloadUpdate(cccUpdateArgs.crossChainController) { + NEW_CCC_IMPL = cccUpdateArgs.crossChainControllerImpl; + PROXY_ADMIN = cccUpdateArgs.proxyAdmin; + } + + function getInitializeSignature() public virtual returns (bytes memory); + + /// @inheritdoc IProposalGenericExecutor + function execute() external virtual override { + ProxyAdmin(PROXY_ADMIN).upgradeAndCall( + TransparentUpgradeableProxy(payable(CROSS_CHAIN_CONTROLLER)), + NEW_CCC_IMPL, + getInitializeSignature() + ); + } +} diff --git a/src/templates/BaseForwarderAdaptersUpdate.sol b/src/templates/BaseForwarderAdaptersUpdate.sol new file mode 100644 index 0000000..a28b12d --- /dev/null +++ b/src/templates/BaseForwarderAdaptersUpdate.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IBaseForwarderAdaptersUpdate, ICrossChainForwarder} from './interfaces/IBaseForwarderAdaptersUpdate.sol'; + +/** + * @title Base forwarder payload. It has the methods to update the forwarder bridge adapters. + * @author BGD Labs @bgdlabs + */ +abstract contract BaseForwarderAdaptersUpdate is IBaseForwarderAdaptersUpdate { + /// @inheritdoc IBaseForwarderAdaptersUpdate + function getForwarderBridgeAdaptersToRemove() + public + view + virtual + returns (ICrossChainForwarder.BridgeAdapterToDisable[] memory) + { + return new ICrossChainForwarder.BridgeAdapterToDisable[](0); + } + + /// @inheritdoc IBaseForwarderAdaptersUpdate + function getForwarderBridgeAdaptersToEnable() + public + view + virtual + returns (ICrossChainForwarder.ForwarderBridgeAdapterConfigInput[] memory) + { + return new ICrossChainForwarder.ForwarderBridgeAdapterConfigInput[](0); + } + + /// @inheritdoc IBaseForwarderAdaptersUpdate + function executeForwardersUpdate(address crossChainController) public virtual { + // remove forwarding adapters + ICrossChainForwarder.BridgeAdapterToDisable[] + memory forwardersToRemove = getForwarderBridgeAdaptersToRemove(); + if (forwardersToRemove.length != 0) { + ICrossChainForwarder(crossChainController).disableBridgeAdapters(forwardersToRemove); + } + + // add forwarding adapters + ICrossChainForwarder.ForwarderBridgeAdapterConfigInput[] + memory forwardersToEnable = getForwarderBridgeAdaptersToEnable(); + if (forwardersToEnable.length != 0) { + ICrossChainForwarder(crossChainController).enableBridgeAdapters(forwardersToEnable); + } + } +} diff --git a/src/templates/BaseReceiverAdaptersUpdate.sol b/src/templates/BaseReceiverAdaptersUpdate.sol new file mode 100644 index 0000000..1b5ee26 --- /dev/null +++ b/src/templates/BaseReceiverAdaptersUpdate.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IBaseReceiverAdaptersUpdate, ICrossChainReceiver} from './interfaces/IBaseReceiverAdaptersUpdate.sol'; + +/** + * @title Base receiver payload. It has the methods to update the receiver bridge adapters. + * @author BGD Labs @bgdlabs + */ +abstract contract BaseReceiverAdaptersUpdate is IBaseReceiverAdaptersUpdate { + /// @inheritdoc IBaseReceiverAdaptersUpdate + function getReceiverBridgeAdaptersToRemove() + public + view + virtual + returns (ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[] memory) + { + // remove old Receiver bridge adapter + return new ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[](0); + } + + /// @inheritdoc IBaseReceiverAdaptersUpdate + function getReceiverBridgeAdaptersToAllow() + public + view + virtual + returns (ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[] memory) + { + return new ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[](0); + } + + /// @inheritdoc IBaseReceiverAdaptersUpdate + function executeReceiversUpdate(address crossChainController) public virtual { + // remove old Receiver bridge adapter + ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[] + memory receiversToRemove = getReceiverBridgeAdaptersToRemove(); + if (receiversToRemove.length != 0) { + ICrossChainReceiver(crossChainController).disallowReceiverBridgeAdapters(receiversToRemove); + } + + // add receiver adapters + ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[] + memory receiversToAllow = getReceiverBridgeAdaptersToAllow(); + if (receiversToAllow.length != 0) { + ICrossChainReceiver(crossChainController).allowReceiverBridgeAdapters(receiversToAllow); + } + } +} diff --git a/src/templates/SimpleAddForwarderAdapter.sol b/src/templates/SimpleAddForwarderAdapter.sol new file mode 100644 index 0000000..2e3cb5b --- /dev/null +++ b/src/templates/SimpleAddForwarderAdapter.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import './BaseAdaptersUpdate.sol'; + +struct AddForwarderAdapterArgs { + address crossChainController; + address currentChainBridgeAdapter; + address destinationChainBridgeAdapter; + uint256 destinationChainId; +} + +/** + * @title SimpleAddForwarderAdapter + * @author BGD Labs @bgdlabs + * @dev this payload should be used when adding a new bridging path to adi + */ +contract SimpleAddForwarderAdapter is BaseAdaptersUpdate { + address public immutable CURRENT_CHAIN_BRIDGE_ADAPTER; + address public immutable DESTINATION_CHAIN_BRIDGE_ADAPTER; + uint256 public immutable DESTINATION_CHAIN_ID; + + constructor( + AddForwarderAdapterArgs memory forwarderArgs + ) BaseAdaptersUpdate(forwarderArgs.crossChainController) { + CURRENT_CHAIN_BRIDGE_ADAPTER = forwarderArgs.currentChainBridgeAdapter; + DESTINATION_CHAIN_BRIDGE_ADAPTER = forwarderArgs.destinationChainBridgeAdapter; + DESTINATION_CHAIN_ID = forwarderArgs.destinationChainId; + } + + function getForwarderBridgeAdaptersToEnable() + public + view + override + returns (ICrossChainForwarder.ForwarderBridgeAdapterConfigInput[] memory) + { + ICrossChainForwarder.ForwarderBridgeAdapterConfigInput[] + memory newForwarders = new ICrossChainForwarder.ForwarderBridgeAdapterConfigInput[](1); + + newForwarders[0] = ICrossChainForwarder.ForwarderBridgeAdapterConfigInput({ + currentChainBridgeAdapter: CURRENT_CHAIN_BRIDGE_ADAPTER, + destinationBridgeAdapter: DESTINATION_CHAIN_BRIDGE_ADAPTER, + destinationChainId: DESTINATION_CHAIN_ID + }); + + return newForwarders; + } +} diff --git a/src/templates/SimpleOneToManyAdapterUpdate.sol b/src/templates/SimpleOneToManyAdapterUpdate.sol new file mode 100644 index 0000000..a76db72 --- /dev/null +++ b/src/templates/SimpleOneToManyAdapterUpdate.sol @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import './BaseAdaptersUpdate.sol'; + +/** + * @title Base payload aDI and bridge adapters update + * @author BGD Labs @bgdlabs + * @dev This payload should be used when wanting to substitute an adapter that receives and also forwards + */ +abstract contract SimpleOneToManyAdapterUpdate is BaseAdaptersUpdate { + struct ConstructorInput { + address ccc; + address adapterToRemove; + address newAdapter; + } + + struct DestinationAdaptersInput { + address adapter; + uint256 chainId; + } + + address public immutable ADAPTER_TO_REMOVE; + address public immutable NEW_ADAPTER; + + constructor(ConstructorInput memory constructorInput) BaseAdaptersUpdate(constructorInput.ccc) { + ADAPTER_TO_REMOVE = constructorInput.adapterToRemove; + NEW_ADAPTER = constructorInput.newAdapter; + } + + /** + * @notice method used to get the adapters for the destination chain ids + * @return array of adapter - destination chain pairs + */ + function getDestinationAdapters() + public + pure + virtual + returns (DestinationAdaptersInput[] memory) + { + return new DestinationAdaptersInput[](0); + } + + /** + * @notice method to get the chains that a new adapter will receive messages from + * @return an array of chain ids + */ + function getChainsToReceive() public pure virtual returns (uint256[] memory); + + /** + * @notice method to get a list of chain ids that the new adapter will use to send messages to + * @return an array of chain ids + */ + function getChainsToSend() public pure virtual returns (uint256[] memory) { + DestinationAdaptersInput[] memory destinationAdapters = getDestinationAdapters(); + uint256[] memory chainsToSend = new uint256[](destinationAdapters.length); + for (uint256 i = 0; i < destinationAdapters.length; i++) { + chainsToSend[i] = destinationAdapters[i].chainId; + } + return chainsToSend; + } + + /// @inheritdoc IBaseReceiverAdaptersUpdate + function getReceiverBridgeAdaptersToRemove() + public + view + virtual + override + returns (ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[] memory) + { + if (ADAPTER_TO_REMOVE != address(0)) { + // remove old Receiver bridge adapter + ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[] + memory bridgeAdaptersToRemove = new ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[]( + 1 + ); + + bridgeAdaptersToRemove[0] = ICrossChainReceiver.ReceiverBridgeAdapterConfigInput({ + bridgeAdapter: ADAPTER_TO_REMOVE, + chainIds: getChainsToReceive() + }); + + return bridgeAdaptersToRemove; + } else { + return new ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[](0); + } + } + + /// @inheritdoc IBaseForwarderAdaptersUpdate + function getForwarderBridgeAdaptersToRemove() + public + view + virtual + override + returns (ICrossChainForwarder.BridgeAdapterToDisable[] memory) + { + if (ADAPTER_TO_REMOVE != address(0)) { + ICrossChainForwarder.BridgeAdapterToDisable[] + memory forwarderAdaptersToRemove = new ICrossChainForwarder.BridgeAdapterToDisable[](1); + + forwarderAdaptersToRemove[0] = ICrossChainForwarder.BridgeAdapterToDisable({ + bridgeAdapter: ADAPTER_TO_REMOVE, + chainIds: getChainsToSend() + }); + + return forwarderAdaptersToRemove; + } else { + return new ICrossChainForwarder.BridgeAdapterToDisable[](0); + } + } + + /// @inheritdoc IBaseReceiverAdaptersUpdate + function getReceiverBridgeAdaptersToAllow() + public + view + virtual + override + returns (ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[] memory) + { + if (NEW_ADAPTER != address(0)) { + ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[] + memory bridgeAdapterConfig = new ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[](1); + + bridgeAdapterConfig[0] = ICrossChainReceiver.ReceiverBridgeAdapterConfigInput({ + bridgeAdapter: NEW_ADAPTER, + chainIds: getChainsToReceive() + }); + + return bridgeAdapterConfig; + } else { + return new ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[](0); + } + } + + /// @inheritdoc IBaseForwarderAdaptersUpdate + function getForwarderBridgeAdaptersToEnable() + public + view + virtual + override + returns (ICrossChainForwarder.ForwarderBridgeAdapterConfigInput[] memory) + { + DestinationAdaptersInput[] memory destinationAdapters = getDestinationAdapters(); + + ICrossChainForwarder.ForwarderBridgeAdapterConfigInput[] + memory bridgeAdaptersToEnable = new ICrossChainForwarder.ForwarderBridgeAdapterConfigInput[]( + destinationAdapters.length + ); + + for (uint256 i = 0; i < destinationAdapters.length; i++) { + bridgeAdaptersToEnable[i] = ICrossChainForwarder.ForwarderBridgeAdapterConfigInput({ + currentChainBridgeAdapter: NEW_ADAPTER, + destinationBridgeAdapter: destinationAdapters[i].adapter, + destinationChainId: destinationAdapters[i].chainId + }); + } + + return bridgeAdaptersToEnable; + } +} diff --git a/src/templates/SimpleReceiverAdapterUpdate.sol b/src/templates/SimpleReceiverAdapterUpdate.sol new file mode 100644 index 0000000..f876249 --- /dev/null +++ b/src/templates/SimpleReceiverAdapterUpdate.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import './BaseAdaptersUpdate.sol'; + +/** + * @title Base payload aDI and bridge adapters update + * @author BGD Labs @bgdlabs + * @dev This payload should be used when wanting to add or remove (or both) a receiver adapter. If one of the + addresses is left as 0, the addition or removal will not be done + */ +abstract contract SimpleReceiverAdapterUpdate is BaseAdaptersUpdate { + struct ConstructorInput { + address ccc; + address adapterToRemove; + address newAdapter; + } + + struct DestinationAdaptersInput { + address adapter; + uint256 chainId; + } + + address public immutable ADAPTER_TO_REMOVE; + address public immutable NEW_ADAPTER; + + constructor(ConstructorInput memory constructorInput) BaseAdaptersUpdate(constructorInput.ccc) { + ADAPTER_TO_REMOVE = constructorInput.adapterToRemove; + NEW_ADAPTER = constructorInput.newAdapter; + } + + /** + * @notice method to get the chains that a new adapter will receive messages from + * @return an array of chain ids + */ + function getChainsToReceive() public pure virtual returns (uint256[] memory); + + /// @inheritdoc IBaseReceiverAdaptersUpdate + function getReceiverBridgeAdaptersToRemove() + public + view + virtual + override + returns (ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[] memory) + { + if (ADAPTER_TO_REMOVE != address(0)) { + // remove old Receiver bridge adapter + ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[] + memory bridgeAdaptersToRemove = new ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[]( + 1 + ); + + bridgeAdaptersToRemove[0] = ICrossChainReceiver.ReceiverBridgeAdapterConfigInput({ + bridgeAdapter: ADAPTER_TO_REMOVE, + chainIds: getChainsToReceive() + }); + + return bridgeAdaptersToRemove; + } else { + return new ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[](0); + } + } + + /// @inheritdoc IBaseReceiverAdaptersUpdate + function getReceiverBridgeAdaptersToAllow() + public + view + virtual + override + returns (ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[] memory) + { + if (NEW_ADAPTER != address(0)) { + ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[] + memory bridgeAdapterConfig = new ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[](1); + + bridgeAdapterConfig[0] = ICrossChainReceiver.ReceiverBridgeAdapterConfigInput({ + bridgeAdapter: NEW_ADAPTER, + chainIds: getChainsToReceive() + }); + + return bridgeAdapterConfig; + } else { + return new ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[](0); + } + } +} diff --git a/src/templates/interfaces/IBaseAdaptersUpdate.sol b/src/templates/interfaces/IBaseAdaptersUpdate.sol new file mode 100644 index 0000000..1074ba2 --- /dev/null +++ b/src/templates/interfaces/IBaseAdaptersUpdate.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IBaseReceiverAdaptersUpdate} from './IBaseReceiverAdaptersUpdate.sol'; +import {IBaseForwarderAdaptersUpdate} from './IBaseForwarderAdaptersUpdate.sol'; + +/** + * @title Interface of the base payload aDI and bridge adapters update + * @author BGD Labs @bgdlabs + */ +interface IBaseAdaptersUpdate is IBaseReceiverAdaptersUpdate, IBaseForwarderAdaptersUpdate { + +} diff --git a/src/templates/interfaces/IBaseForwarderAdaptersUpdate.sol b/src/templates/interfaces/IBaseForwarderAdaptersUpdate.sol new file mode 100644 index 0000000..615a1b2 --- /dev/null +++ b/src/templates/interfaces/IBaseForwarderAdaptersUpdate.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ICrossChainForwarder} from 'aave-address-book/common/ICrossChainController.sol'; + +/** + * @title Interface for base forwarder payload. + * @author BGD Labs @bgdlabs + */ +interface IBaseForwarderAdaptersUpdate { + /** + * @notice method to get the forwarder adapters to remove + * @return object array with the adapter to remove and an array of chain ids to remove it from + */ + function getForwarderBridgeAdaptersToRemove() + external + view + returns (ICrossChainForwarder.BridgeAdapterToDisable[] memory); + + /** + * @notice method to get the forwarder adapters to enable + * @return object array with the current and destination pair of adapters to enable and the chainId + to communicate with + */ + function getForwarderBridgeAdaptersToEnable() + external + view + returns (ICrossChainForwarder.ForwarderBridgeAdapterConfigInput[] memory); + + /** + * @notice method to add and remove forwarder adapters + * @param crossChainController address of the CCC on the networks where the adapters are going to be updated + */ + function executeForwardersUpdate(address crossChainController) external; +} diff --git a/src/templates/interfaces/IBaseReceiverAdaptersUpdate.sol b/src/templates/interfaces/IBaseReceiverAdaptersUpdate.sol new file mode 100644 index 0000000..77cccb1 --- /dev/null +++ b/src/templates/interfaces/IBaseReceiverAdaptersUpdate.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ICrossChainReceiver} from 'aave-address-book/common/ICrossChainController.sol'; + +/** + * @title Interface of the base payload aDI and bridge adapters update + * @author BGD Labs @bgdlabs + */ +interface IBaseReceiverAdaptersUpdate { + /** + * @notice method to get the receiver adapters to remove + * @return object array with the adapter to remove and an array of chain ids to remove it from + */ + function getReceiverBridgeAdaptersToRemove() + external + view + returns (ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[] memory); + + /** + * @notice method to get the receiver adapters to allow + * @return object array with the adapter to allow and an array of chain ids to allow it to receive messages from + */ + function getReceiverBridgeAdaptersToAllow() + external + view + returns (ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[] memory); + + /** + * @notice method to add and remove receiver adapters + * @param crossChainController address of the CCC on the networks where the adapters are going to be updated + */ + function executeReceiversUpdate(address crossChainController) external; +} From 037952f51db14bf06df432ce555a68ad8274060e Mon Sep 17 00:00:00 2001 From: sendra Date: Tue, 30 Jul 2024 11:11:35 +0200 Subject: [PATCH 2/3] fix: updated paths to use local templates instead of helpers --- scripts/payloads/adapters/zksync/Base_Add_Zksync_Path.s.sol | 2 +- scripts/payloads/ccc/shuffle/Base_Deploy_Shuffle_Update.s.sol | 2 +- src/ccc_payloads/shuffle/ShuffleCCCUpdatePayload.sol | 2 +- tests/payloads/zksync/AddZkSyncPathTest.t.sol | 3 +-- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/scripts/payloads/adapters/zksync/Base_Add_Zksync_Path.s.sol b/scripts/payloads/adapters/zksync/Base_Add_Zksync_Path.s.sol index 045d80d..d48a2bb 100644 --- a/scripts/payloads/adapters/zksync/Base_Add_Zksync_Path.s.sol +++ b/scripts/payloads/adapters/zksync/Base_Add_Zksync_Path.s.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; import '../../../BaseDeployerScript.sol'; -import 'aave-helpers/adi/SimpleAddForwarderAdapter.sol'; +import '../../../../src/templates/SimpleAddForwarderAdapter.sol'; abstract contract Base_Deploy_Add_ZkSync_Path_Payload is BaseDeployerScript { function _getPayloadByteCode() internal virtual returns (bytes memory); diff --git a/scripts/payloads/ccc/shuffle/Base_Deploy_Shuffle_Update.s.sol b/scripts/payloads/ccc/shuffle/Base_Deploy_Shuffle_Update.s.sol index 11bfcb6..97486a7 100644 --- a/scripts/payloads/ccc/shuffle/Base_Deploy_Shuffle_Update.s.sol +++ b/scripts/payloads/ccc/shuffle/Base_Deploy_Shuffle_Update.s.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import '../../../BaseDeployerScript.sol'; import {CrossChainControllerUpgradeRev3} from 'adi/revisions/update_to_rev_3/CrossChainController.sol'; import {CrossChainControllerWithEmergencyModeUpgradeRev3} from 'adi/revisions/update_to_rev_3/CrossChainControllerWithEmergencyMode.sol'; -import {CCCUpdateArgs} from 'aave-helpers/adi/BaseCCCUpdate.sol'; +import {CCCUpdateArgs} from '../../../../src/templates/BaseCCCUpdate.sol'; // Library to get the code of ccc revision 3 (shuffle) library CCCUpdateDeploymentHelper { diff --git a/src/ccc_payloads/shuffle/ShuffleCCCUpdatePayload.sol b/src/ccc_payloads/shuffle/ShuffleCCCUpdatePayload.sol index 42f879e..57b9fb9 100644 --- a/src/ccc_payloads/shuffle/ShuffleCCCUpdatePayload.sol +++ b/src/ccc_payloads/shuffle/ShuffleCCCUpdatePayload.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import 'aave-helpers/adi/BaseCCCUpdate.sol'; +import '../../../src/templates/BaseCCCUpdate.sol'; import {IReinitialize} from 'adi/revisions/update_to_rev_3/IReinitialize.sol'; import {ICrossChainForwarder} from 'adi/interfaces/ICrossChainForwarder.sol'; import {ChainIds} from 'solidity-utils/contracts/utils/ChainHelpers.sol'; diff --git a/tests/payloads/zksync/AddZkSyncPathTest.t.sol b/tests/payloads/zksync/AddZkSyncPathTest.t.sol index f39473b..6a7e530 100644 --- a/tests/payloads/zksync/AddZkSyncPathTest.t.sol +++ b/tests/payloads/zksync/AddZkSyncPathTest.t.sol @@ -4,8 +4,7 @@ pragma solidity ^0.8.0; import 'forge-std/console.sol'; import {ADITestBase} from 'aave-helpers/adi/test/ADITestBase.sol'; import {Addresses, Ethereum as PayloadEthereumScript} from '../../../scripts/payloads/adapters/zksync/Network_Deployments.s.sol'; -import {AddForwarderAdapterArgs} from 'aave-helpers/adi/SimpleAddForwarderAdapter.sol'; -import 'aave-helpers/adi/SimpleAddForwarderAdapter.sol'; +import '../../../src/templates/SimpleAddForwarderAdapter.sol'; abstract contract BaseAddZkSyncPathPayloadTest is ADITestBase { address internal _payload; From 0362a18614325de76fa1ab4b9ae5c3172d382ec6 Mon Sep 17 00:00:00 2001 From: sendra Date: Tue, 30 Jul 2024 11:26:10 +0200 Subject: [PATCH 3/3] fix: add adi base test --- tests/adi/ADITestBase.sol | 678 ++++++++++++++++++ tests/ccc/shuffle/ShufflePayloadTests.t.sol | 2 +- tests/payloads/zksync/AddZkSyncPathTest.t.sol | 2 +- 3 files changed, 680 insertions(+), 2 deletions(-) create mode 100644 tests/adi/ADITestBase.sol diff --git a/tests/adi/ADITestBase.sol b/tests/adi/ADITestBase.sol new file mode 100644 index 0000000..3907ff4 --- /dev/null +++ b/tests/adi/ADITestBase.sol @@ -0,0 +1,678 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +import 'forge-std/StdJson.sol'; +import 'forge-std/Test.sol'; +import {IBaseAdaptersUpdate} from '../../src/templates/interfaces/IBaseAdaptersUpdate.sol'; +import {ChainHelpers, ChainIds} from 'solidity-utils/contracts/utils/ChainHelpers.sol'; +import {GovV3Helpers} from 'aave-helpers/GovV3Helpers.sol'; +import {ProxyHelpers} from 'aave-helpers/ProxyHelpers.sol'; + +import {ICrossChainReceiver, ICrossChainForwarder} from 'aave-address-book/common/ICrossChainController.sol'; +import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; +import {GovernanceV3Polygon} from 'aave-address-book/GovernanceV3Polygon.sol'; +import {GovernanceV3Avalanche} from 'aave-address-book/GovernanceV3Avalanche.sol'; +import {GovernanceV3Optimism} from 'aave-address-book/GovernanceV3Optimism.sol'; +import {GovernanceV3BNB} from 'aave-address-book/GovernanceV3BNB.sol'; +import {GovernanceV3Metis} from 'aave-address-book/GovernanceV3Metis.sol'; +import {GovernanceV3Base} from 'aave-address-book/GovernanceV3Base.sol'; +import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol'; +import {GovernanceV3Gnosis} from 'aave-address-book/GovernanceV3Gnosis.sol'; +import {GovernanceV3Scroll} from 'aave-address-book/GovernanceV3Scroll.sol'; +import {IBaseAdapter} from 'aave-address-book/common/IBaseAdapter.sol'; + +contract ADITestBase is Test { + using stdJson for string; + + struct ReceiverConfigByChain { + uint8 requiredConfirmations; + uint256 chainId; + uint256 validityTimestamp; + } + + struct ReceiverAdaptersByChain { + uint256 chainId; + address[] receiverAdapters; + } + + struct ForwarderAdaptersByChain { + uint256 chainId; + ICrossChainForwarder.ChainIdBridgeConfig[] forwarders; + } + + struct CCCConfig { + address crossChainControllerImpl; + ReceiverConfigByChain[] receiverConfigs; + ReceiverAdaptersByChain[] receiverAdaptersConfig; + ForwarderAdaptersByChain[] forwarderAdaptersConfig; + } + + struct ForwarderAdapters { + ICrossChainForwarder.ChainIdBridgeConfig[] adapters; + uint256 chainId; + } + + struct AdaptersByChain { + address[] adapters; + uint256 chainId; + } + + struct DestinationPayload { + uint256 chainId; + bytes payloadCode; + } + + struct SnapshotParams { + address crossChainController; + bool receiverConfigs; + bool receiverAdapterConfigs; + bool forwarderAdapterConfigs; + bool cccImplUpdate; + string reportName; + } + + function executePayload(Vm vm, address payload) internal { + GovV3Helpers.executePayload(vm, payload); + } + + /** + * @dev generates the diff between two reports + */ + function diffReports(string memory reportBefore, string memory reportAfter) internal { + string memory outPath = string( + abi.encodePacked('./diffs/', reportBefore, '_', reportAfter, '.md') + ); + string memory beforePath = string(abi.encodePacked('./reports/', reportBefore, '.json')); + string memory afterPath = string(abi.encodePacked('./reports/', reportAfter, '.json')); + + string[] memory inputs = new string[](7); + inputs[0] = 'npx'; + inputs[1] = '@bgd-labs/aave-cli@^0.16.2'; + inputs[2] = 'adi-diff-snapshots'; + inputs[3] = beforePath; + inputs[4] = afterPath; + inputs[5] = '-o'; + inputs[6] = outPath; + vm.ffi(inputs); + } + + function defaultTest( + string memory reportName, + address crossChainController, + address payload, + bool runE2E, + Vm vm + ) public returns (CCCConfig memory, CCCConfig memory) { + string memory beforeString = string(abi.encodePacked('adi_', reportName, '_before')); + CCCConfig memory configBefore = createConfigurationSnapshot(beforeString, crossChainController); + + uint256 snapshotId = vm.snapshot(); + + executePayload(vm, payload); + + string memory afterString = string(abi.encodePacked('adi_', reportName, '_after')); + CCCConfig memory configAfter = createConfigurationSnapshot(afterString, crossChainController); + + diffReports(beforeString, afterString); + + vm.revertTo(snapshotId); + if (runE2E) e2eTest(payload, crossChainController); + + return (configBefore, configAfter); + } + + function e2eTest(address payload, address crossChainController) public { + // test receivers + ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[] + memory receiversToAllow = IBaseAdaptersUpdate(payload).getReceiverBridgeAdaptersToAllow(); + if (receiversToAllow.length != 0) { + _testCorrectReceiverAdaptersConfiguration(payload, receiversToAllow, crossChainController); + _testCorrectTrustedRemotes(receiversToAllow); + } + ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[] + memory receiversToRemove = IBaseAdaptersUpdate(payload).getReceiverBridgeAdaptersToRemove(); + if (receiversToRemove.length != 0) { + _testOnlyRemovedSpecifiedReceiverAdapters(payload, receiversToRemove, crossChainController); + } + + // test forwarders + ICrossChainForwarder.ForwarderBridgeAdapterConfigInput[] + memory forwardersToEnable = IBaseAdaptersUpdate(payload).getForwarderBridgeAdaptersToEnable(); + if (forwardersToEnable.length != 0) { + _testCorrectForwarderAdaptersConfiguration(payload, crossChainController, forwardersToEnable); + _testDestinationAdapterIsRegistered(forwardersToEnable); + } + ICrossChainForwarder.BridgeAdapterToDisable[] memory forwardersToRemove = IBaseAdaptersUpdate( + payload + ).getForwarderBridgeAdaptersToRemove(); + if (forwardersToRemove.length != 0) { + _testOnlyRemovedSpecificForwarderAdapters(payload, crossChainController, forwardersToRemove); + } + } + + function getDestinationPayloadsByChain() + public + view + virtual + returns (DestinationPayload[] memory) + { + return new DestinationPayload[](0); + } + + function _testDestinationAdapterIsRegistered( + ICrossChainForwarder.ForwarderBridgeAdapterConfigInput[] memory forwardersToEnable + ) internal { + DestinationPayload[] memory destinationPayloads = getDestinationPayloadsByChain(); + bytes memory empty; + + for (uint256 i = 0; i < forwardersToEnable.length; i++) { + uint256 currentChainId = block.chainid; + // change fork to destination network + (uint256 previousFork, ) = ChainHelpers.selectChain( + vm, + forwardersToEnable[i].destinationChainId + ); + address destinationCCC = getCCCByChainId(block.chainid); + if (destinationPayloads.length > 0) { + for (uint256 j = 0; j < destinationPayloads.length; j++) { + if (destinationPayloads[j].chainId == forwardersToEnable[i].destinationChainId) { + if (keccak256(destinationPayloads[j].payloadCode) != keccak256(empty)) { + address destinationPayload = GovV3Helpers.deployDeterministic( + destinationPayloads[j].payloadCode + ); + + executePayload(vm, destinationPayload); + // check that adapter is registered + assertEq( + ICrossChainReceiver(destinationCCC).isReceiverBridgeAdapterAllowed( + forwardersToEnable[i].destinationBridgeAdapter, + currentChainId + ), + true + ); + break; + } + } + } + } else { + assertEq( + ICrossChainReceiver(destinationCCC).isReceiverBridgeAdapterAllowed( + forwardersToEnable[i].destinationBridgeAdapter, + currentChainId + ), + true + ); + } + vm.selectFork(previousFork); + } + } + + function _testOnlyRemovedSpecificForwarderAdapters( + address payload, + address crossChainController, + ICrossChainForwarder.BridgeAdapterToDisable[] memory adaptersToRemove + ) internal { + ForwarderAdapters[] + memory forwardersBridgeAdaptersByChainBefore = _getCurrentForwarderAdaptersByChain( + crossChainController, + block.chainid + ); + + executePayload(vm, payload); + + ForwarderAdapters[] + memory forwardersBridgeAdaptersByChainAfter = _getCurrentForwarderAdaptersByChain( + crossChainController, + block.chainid + ); + + for (uint256 l = 0; l < forwardersBridgeAdaptersByChainBefore.length; l++) { + for (uint256 j = 0; j < forwardersBridgeAdaptersByChainAfter.length; j++) { + if ( + forwardersBridgeAdaptersByChainBefore[l].chainId == + forwardersBridgeAdaptersByChainAfter[j].chainId + ) { + for (uint256 i = 0; i < forwardersBridgeAdaptersByChainBefore[l].adapters.length; i++) { + bool forwarderFound; + for (uint256 m = 0; m < forwardersBridgeAdaptersByChainAfter[j].adapters.length; m++) { + if ( + forwardersBridgeAdaptersByChainBefore[l].adapters[i].destinationBridgeAdapter == + forwardersBridgeAdaptersByChainAfter[j].adapters[m].destinationBridgeAdapter && + forwardersBridgeAdaptersByChainBefore[l].adapters[i].currentChainBridgeAdapter == + forwardersBridgeAdaptersByChainAfter[j].adapters[m].currentChainBridgeAdapter + ) { + forwarderFound = true; + break; + } + } + if (!forwarderFound) { + bool isAdapterToBeRemoved; + for (uint256 k = 0; k < adaptersToRemove.length; k++) { + if ( + forwardersBridgeAdaptersByChainBefore[l].adapters[i].currentChainBridgeAdapter == + adaptersToRemove[k].bridgeAdapter + ) { + for (uint256 n = 0; n < adaptersToRemove[k].chainIds.length; n++) { + if ( + forwardersBridgeAdaptersByChainBefore[l].chainId == + adaptersToRemove[k].chainIds[n] + ) { + isAdapterToBeRemoved = true; + break; + } + } + } + } + assertEq(isAdapterToBeRemoved, true); + } + } + } + } + } + } + + function _testCorrectForwarderAdaptersConfiguration( + address payload, + address crossChainController, + ICrossChainForwarder.ForwarderBridgeAdapterConfigInput[] memory forwardersToEnable + ) internal { + executePayload(vm, payload); + + for (uint256 i = 0; i < forwardersToEnable.length; i++) { + ICrossChainForwarder.ChainIdBridgeConfig[] + memory forwardersBridgeAdaptersByChain = ICrossChainForwarder(crossChainController) + .getForwarderBridgeAdaptersByChain(forwardersToEnable[i].destinationChainId); + bool newAdapterFound; + for (uint256 j = 0; j < forwardersBridgeAdaptersByChain.length; j++) { + if ( + forwardersBridgeAdaptersByChain[j].destinationBridgeAdapter == + forwardersToEnable[i].destinationBridgeAdapter && + forwardersBridgeAdaptersByChain[j].currentChainBridgeAdapter == + forwardersToEnable[i].currentChainBridgeAdapter + ) { + newAdapterFound = true; + break; + } + } + assertEq(newAdapterFound, true); + } + } + + function _testCorrectTrustedRemotes( + ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[] memory receiversToAllow + ) internal { + for (uint256 i = 0; i < receiversToAllow.length; i++) { + for (uint256 j = 0; j < receiversToAllow[i].chainIds.length; j++) { + address trustedRemote = IBaseAdapter(receiversToAllow[i].bridgeAdapter) + .getTrustedRemoteByChainId(receiversToAllow[i].chainIds[j]); + assertEq(trustedRemote, getCCCByChainId(receiversToAllow[i].chainIds[j])); + } + } + } + + function _testOnlyRemovedSpecifiedReceiverAdapters( + address payload, + ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[] memory adaptersToRemove, + address crossChainController + ) internal { + AdaptersByChain[] memory adaptersBefore = _getCurrentReceiverAdaptersByChain( + crossChainController + ); + + executePayload(vm, payload); + + for (uint256 i = 0; i < adaptersBefore.length; i++) { + for (uint256 j = 0; j < adaptersToRemove.length; j++) { + for (uint256 x = 0; x < adaptersToRemove[j].chainIds.length; x++) { + if (adaptersToRemove[j].chainIds[x] == adaptersBefore[i].chainId) { + for (uint256 k = 0; k < adaptersBefore[i].adapters.length; k++) { + if (adaptersBefore[i].adapters[k] == adaptersToRemove[j].bridgeAdapter) { + assertEq( + ICrossChainReceiver(crossChainController).isReceiverBridgeAdapterAllowed( + adaptersToRemove[j].bridgeAdapter, + adaptersBefore[i].chainId + ), + false + ); + } else { + assertEq( + ICrossChainReceiver(crossChainController).isReceiverBridgeAdapterAllowed( + adaptersBefore[i].adapters[k], + adaptersBefore[i].chainId + ), + true + ); + } + } + } + } + } + } + } + + function _testCorrectReceiverAdaptersConfiguration( + address payload, + ICrossChainReceiver.ReceiverBridgeAdapterConfigInput[] memory receiversToAllow, + address crossChainController + ) internal { + for (uint256 i = 0; i < receiversToAllow.length; i++) { + for (uint256 j = 0; j < receiversToAllow[i].chainIds.length; j++) { + assertEq( + ICrossChainReceiver(crossChainController).isReceiverBridgeAdapterAllowed( + receiversToAllow[i].bridgeAdapter, + receiversToAllow[i].chainIds[j] + ), + false + ); + } + } + + executePayload(vm, payload); + + for (uint256 i = 0; i < receiversToAllow.length; i++) { + for (uint256 j = 0; j < receiversToAllow[i].chainIds.length; j++) { + assertEq( + ICrossChainReceiver(crossChainController).isReceiverBridgeAdapterAllowed( + receiversToAllow[i].bridgeAdapter, + receiversToAllow[i].chainIds[j] + ), + true + ); + } + } + } + + /** + * @dev Generates a markdown compatible snapshot of the whole CrossChainController configuration into `/reports`. + * @param reportName filename suffix for the generated reports. + * @param crossChainController the ccc to be snapshot + * @return ReserveConfig[] list of configs + */ + function createConfigurationSnapshot( + string memory reportName, + address crossChainController + ) public returns (CCCConfig memory) { + return + createConfigurationSnapshot( + SnapshotParams({ + crossChainController: crossChainController, + receiverConfigs: true, + receiverAdapterConfigs: true, + forwarderAdapterConfigs: true, + cccImplUpdate: true, + reportName: reportName + }) + ); + } + + function createConfigurationSnapshot( + SnapshotParams memory snapshotParams + ) public returns (CCCConfig memory) { + string memory path = string(abi.encodePacked('./reports/', snapshotParams.reportName, '.json')); + // overwrite with empty json to later be extended + vm.writeFile( + path, + '{ "cccImplementation": {}, "receiverConfigsByChain": {}, "receiverAdaptersByChain": {}, "forwarderAdaptersByChain": {}}' + ); + vm.serializeUint('root', 'chainId', block.chainid); + CCCConfig memory config = _getCCCConfig(snapshotParams.crossChainController); + if (snapshotParams.receiverConfigs) _writeReceiverConfigs(path, config); + if (snapshotParams.receiverAdapterConfigs) _writeReceiverAdapters(path, config); + if (snapshotParams.forwarderAdapterConfigs) _writeForwarderAdapters(path, config); + if (snapshotParams.cccImplUpdate) _writeCCCImplUpdate(path, config); + + return config; + } + + function _writeCCCImplUpdate(string memory path, CCCConfig memory config) internal { + string memory output = vm.serializeAddress( + 'root', + 'crossChainControllerImpl', + config.crossChainControllerImpl + ); + vm.writeJson(output, path); + } + + function _writeForwarderAdapters(string memory path, CCCConfig memory config) internal { + // keys for json stringification + string memory forwarderAdaptersKey = 'forwarderAdapters'; + string memory content = '{}'; + vm.serializeJson(forwarderAdaptersKey, '{}'); + ForwarderAdaptersByChain[] memory forwarderConfig = config.forwarderAdaptersConfig; + + for (uint256 i = 0; i < forwarderConfig.length; i++) { + uint256 chainId = forwarderConfig[i].chainId; + string memory key = vm.toString(chainId); + vm.serializeJson(key, '{}'); + string memory object; + + ICrossChainForwarder.ChainIdBridgeConfig[] memory forwarders = forwarderConfig[i].forwarders; + for (uint256 j = 0; j < forwarders.length; j++) { + if (j == forwarders.length - 1) { + object = vm.serializeString( + key, + vm.toString(forwarders[j].currentChainBridgeAdapter), + vm.toString(forwarders[j].destinationBridgeAdapter) + ); + } else { + vm.serializeString( + key, + vm.toString(forwarders[j].currentChainBridgeAdapter), + vm.toString(forwarders[j].destinationBridgeAdapter) + ); + } + } + content = vm.serializeString(forwarderAdaptersKey, key, object); + } + string memory output = vm.serializeString('root', 'forwarderAdaptersByChain', content); + vm.writeJson(output, path); + } + + function _writeReceiverAdapters(string memory path, CCCConfig memory config) internal { + // keys for json stringification + string memory receiverAdaptersKey = 'receiverAdapters'; + string memory content = '{}'; + vm.serializeJson(receiverAdaptersKey, '{}'); + ReceiverAdaptersByChain[] memory receiverConfig = config.receiverAdaptersConfig; + + for (uint256 i = 0; i < receiverConfig.length; i++) { + uint256 chainId = receiverConfig[i].chainId; + string memory key = vm.toString(chainId); + vm.serializeJson(key, '{}'); + string memory object; + + for (uint256 j = 0; j < receiverConfig[i].receiverAdapters.length; j++) { + if (j == receiverConfig[i].receiverAdapters.length - 1) { + object = vm.serializeString( + key, + vm.toString(receiverConfig[i].receiverAdapters[j]), + vm.toString(true) + ); + } else { + vm.serializeString( + key, + vm.toString(receiverConfig[i].receiverAdapters[j]), + vm.toString(true) + ); + } + } + content = vm.serializeString(receiverAdaptersKey, key, object); + } + string memory output = vm.serializeString('root', 'receiverAdaptersByChain', content); + vm.writeJson(output, path); + } + + function _writeReceiverConfigs(string memory path, CCCConfig memory configs) internal { + // keys for json stringification + string memory receiverConfigsKey = 'receiverConfigs'; + string memory content = '{}'; + vm.serializeJson(receiverConfigsKey, '{}'); + ReceiverConfigByChain[] memory receiverConfig = configs.receiverConfigs; + for (uint256 i = 0; i < receiverConfig.length; i++) { + uint256 chainId = receiverConfig[i].chainId; + string memory key = vm.toString(chainId); + vm.serializeJson(key, '{}'); + string memory object; + vm.serializeString( + key, + 'requiredConfirmations', + vm.toString(receiverConfig[i].requiredConfirmations) + ); + object = vm.serializeString( + key, + 'validityTimestamp', + vm.toString(receiverConfig[i].validityTimestamp) + ); + + content = vm.serializeString(receiverConfigsKey, key, object); + } + string memory output = vm.serializeString('root', 'receiverConfigs', content); + vm.writeJson(output, path); + } + + function _getCCCConfig(address ccc) internal view returns (CCCConfig memory) { + CCCConfig memory config; + + // get crossChainController implementation + config.crossChainControllerImpl = ProxyHelpers + .getInitializableAdminUpgradeabilityProxyImplementation(vm, ccc); + // get supported networks + uint256[] memory receiverSupportedChains = ICrossChainReceiver(ccc).getSupportedChains(); + ReceiverConfigByChain[] memory receiverConfigs = new ReceiverConfigByChain[]( + receiverSupportedChains.length + ); + ReceiverAdaptersByChain[] memory receiverAdaptersConfig = new ReceiverAdaptersByChain[]( + receiverSupportedChains.length + ); + for (uint256 i = 0; i < receiverSupportedChains.length; i++) { + uint256 chainId = receiverSupportedChains[i]; + ICrossChainReceiver.ReceiverConfiguration memory receiverConfig = ICrossChainReceiver(ccc) + .getConfigurationByChain(chainId); + receiverConfigs[i] = ReceiverConfigByChain({ + chainId: chainId, + requiredConfirmations: receiverConfig.requiredConfirmation, + validityTimestamp: receiverConfig.validityTimestamp + }); + receiverAdaptersConfig[i] = ReceiverAdaptersByChain({ + chainId: chainId, + receiverAdapters: ICrossChainReceiver(ccc).getReceiverBridgeAdaptersByChain(chainId) + }); + } + + config.receiverAdaptersConfig = receiverAdaptersConfig; + config.receiverConfigs = receiverConfigs; + + // get receiver configs by network + uint256[] memory supportedForwardingNetworks = _getForwarderSupportedChainsByChainId( + block.chainid + ); + ForwarderAdaptersByChain[] memory forwardersByChain = new ForwarderAdaptersByChain[]( + supportedForwardingNetworks.length + ); + for (uint256 i = 0; i < supportedForwardingNetworks.length; i++) { + uint256 chainId = supportedForwardingNetworks[i]; + forwardersByChain[i] = ForwarderAdaptersByChain({ + chainId: chainId, + forwarders: ICrossChainForwarder(ccc).getForwarderBridgeAdaptersByChain(chainId) + }); + } + config.forwarderAdaptersConfig = forwardersByChain; + + return config; + } + + /// @dev Update when supporting new forwarding networks + function _getForwarderSupportedChainsByChainId( + uint256 chainId + ) internal pure returns (uint256[] memory) { + if (chainId == ChainIds.MAINNET) { + uint256[] memory chainIds = new uint256[](10); + chainIds[0] = ChainIds.MAINNET; + chainIds[1] = ChainIds.POLYGON; + chainIds[2] = ChainIds.AVALANCHE; + chainIds[3] = ChainIds.BNB; + chainIds[4] = ChainIds.GNOSIS; + chainIds[5] = ChainIds.ARBITRUM; + chainIds[6] = ChainIds.OPTIMISM; + chainIds[7] = ChainIds.METIS; + chainIds[8] = ChainIds.BASE; + chainIds[9] = ChainIds.SCROLL; + + return chainIds; + } else if (chainId == ChainIds.POLYGON) { + uint256[] memory chainIds = new uint256[](1); + chainIds[0] = ChainIds.MAINNET; + + return chainIds; + } else if (chainId == ChainIds.AVALANCHE) { + uint256[] memory chainIds = new uint256[](1); + chainIds[0] = ChainIds.MAINNET; + + return chainIds; + } else { + return new uint256[](0); + } + } + + function _getCurrentForwarderAdaptersByChain( + address crossChainController, + uint256 chainId + ) internal view returns (ForwarderAdapters[] memory) { + uint256[] memory supportedChains = _getForwarderSupportedChainsByChainId(chainId); + + ForwarderAdapters[] memory forwarderAdapters = new ForwarderAdapters[](supportedChains.length); + + for (uint256 i = 0; i < supportedChains.length; i++) { + ICrossChainForwarder.ChainIdBridgeConfig[] memory forwarders = ICrossChainForwarder( + crossChainController + ).getForwarderBridgeAdaptersByChain(supportedChains[i]); + + forwarderAdapters[i] = ForwarderAdapters({adapters: forwarders, chainId: supportedChains[i]}); + } + return forwarderAdapters; + } + + function _getCurrentReceiverAdaptersByChain( + address crossChainController + ) internal view returns (AdaptersByChain[] memory) { + uint256[] memory supportedChains = ICrossChainReceiver(crossChainController) + .getSupportedChains(); + + AdaptersByChain[] memory receiverAdapters = new AdaptersByChain[](supportedChains.length); + + for (uint256 i = 0; i < supportedChains.length; i++) { + address[] memory receivers = ICrossChainReceiver(crossChainController) + .getReceiverBridgeAdaptersByChain(supportedChains[i]); + + receiverAdapters[i] = AdaptersByChain({adapters: receivers, chainId: supportedChains[i]}); + } + + return receiverAdapters; + } + + /// @dev add new chains t + function getCCCByChainId(uint256 chainId) public pure returns (address) { + if (chainId == ChainIds.MAINNET) { + return GovernanceV3Ethereum.CROSS_CHAIN_CONTROLLER; + } else if (chainId == ChainIds.POLYGON) { + return GovernanceV3Polygon.CROSS_CHAIN_CONTROLLER; + } else if (chainId == ChainIds.AVALANCHE) { + return GovernanceV3Avalanche.CROSS_CHAIN_CONTROLLER; + } else if (chainId == ChainIds.OPTIMISM) { + return GovernanceV3Optimism.CROSS_CHAIN_CONTROLLER; + } else if (chainId == ChainIds.BNB) { + return GovernanceV3BNB.CROSS_CHAIN_CONTROLLER; + } else if (chainId == ChainIds.METIS) { + return GovernanceV3Metis.CROSS_CHAIN_CONTROLLER; + } else if (chainId == ChainIds.BASE) { + return GovernanceV3Base.CROSS_CHAIN_CONTROLLER; + } else if (chainId == ChainIds.ARBITRUM) { + return GovernanceV3Arbitrum.CROSS_CHAIN_CONTROLLER; + } else if (chainId == ChainIds.GNOSIS) { + return GovernanceV3Gnosis.CROSS_CHAIN_CONTROLLER; + } else if (chainId == ChainIds.SCROLL) { + return GovernanceV3Scroll.CROSS_CHAIN_CONTROLLER; + } + revert(); + } +} diff --git a/tests/ccc/shuffle/ShufflePayloadTests.t.sol b/tests/ccc/shuffle/ShufflePayloadTests.t.sol index d4b0c3b..c576fbd 100644 --- a/tests/ccc/shuffle/ShufflePayloadTests.t.sol +++ b/tests/ccc/shuffle/ShufflePayloadTests.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; import {Addresses, Ethereum, Polygon, Avalanche, Arbitrum, Optimism, Metis, Binance, Base, Gnosis, Scroll} from '../../../scripts/payloads/ccc/shuffle/Network_Deployments.s.sol'; -import 'aave-helpers/adi/test/ADITestBase.sol'; +import '../../adi/ADITestBase.sol'; import 'forge-std/console.sol'; abstract contract BaseShufflePayloadTest is ADITestBase { diff --git a/tests/payloads/zksync/AddZkSyncPathTest.t.sol b/tests/payloads/zksync/AddZkSyncPathTest.t.sol index 6a7e530..e28bef8 100644 --- a/tests/payloads/zksync/AddZkSyncPathTest.t.sol +++ b/tests/payloads/zksync/AddZkSyncPathTest.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; import 'forge-std/console.sol'; -import {ADITestBase} from 'aave-helpers/adi/test/ADITestBase.sol'; +import {ADITestBase} from '../../adi/ADITestBase.sol'; import {Addresses, Ethereum as PayloadEthereumScript} from '../../../scripts/payloads/adapters/zksync/Network_Deployments.s.sol'; import '../../../src/templates/SimpleAddForwarderAdapter.sol';