From e5fe6f15b4d22568caaa44dffc92df3d7607f46a Mon Sep 17 00:00:00 2001 From: epoon-circle Date: Wed, 13 Nov 2024 13:32:41 -0700 Subject: [PATCH] Stable 7722 v2 deployment scripts (#43) # Overview Updated deployment scripts and process documentation for V2 contracts as [documented](https://docs.google.com/document/d/1ayFWGNVmaO6jlLwgZsa0Yk-490CTBdiFASuY4jJzkE0/edit?usp=sharing). # Changes - Added new scripts for deploying and configuring the V2 contracts. - Added tests for the new scripts. - Updated the readme and Makefile for V2 deployment process. # Tests - Added new script tests. - Manually followed the deployment process locally. # Review - Help take a look to make sure all the env vars make sense. (Especially regarding all the owners/pks.) - Optionally, run through the process locally. --- Makefile | 46 ++- README.md | 175 +++++---- scripts/v2/1_deploy.s.sol | 274 ------------- scripts/v2/2_setupSecondAttester.s.sol | 63 --- scripts/v2/3_setupRemoteResources.s.sol | 108 ------ scripts/v2/4_rotateKeys.s.sol | 114 ------ scripts/v2/DeployAddressUtilsExternal.s.sol | 53 +++ scripts/v2/DeployImplementationsV2.s.sol | 108 ++++++ scripts/v2/DeployProxiesV2.s.sol | 364 ++++++++++++++++++ scripts/v2/RotateKeysV2.s.sol | 133 +++++++ scripts/v2/SetupRemoteResourcesV2.s.sol | 123 ++++++ test/scripts/1_deploy.t.sol | 105 ----- test/scripts/2_setupSecondAttester.t.sol | 37 -- test/scripts/ScriptV2TestUtils.sol | 171 -------- test/scripts/v2/DeployImplementationsV2.t.sol | 51 +++ test/scripts/v2/DeployProxiesV2.t.sol | 149 +++++++ .../RotateKeysV2.t.sol} | 19 +- test/scripts/v2/ScriptV2TestUtils.sol | 317 +++++++++++++++ .../SetupRemoteResourcesV2.t.sol} | 11 +- 19 files changed, 1433 insertions(+), 988 deletions(-) delete mode 100644 scripts/v2/1_deploy.s.sol delete mode 100644 scripts/v2/2_setupSecondAttester.s.sol delete mode 100644 scripts/v2/3_setupRemoteResources.s.sol delete mode 100644 scripts/v2/4_rotateKeys.s.sol create mode 100644 scripts/v2/DeployAddressUtilsExternal.s.sol create mode 100644 scripts/v2/DeployImplementationsV2.s.sol create mode 100644 scripts/v2/DeployProxiesV2.s.sol create mode 100644 scripts/v2/RotateKeysV2.s.sol create mode 100644 scripts/v2/SetupRemoteResourcesV2.s.sol delete mode 100644 test/scripts/1_deploy.t.sol delete mode 100644 test/scripts/2_setupSecondAttester.t.sol delete mode 100644 test/scripts/ScriptV2TestUtils.sol create mode 100644 test/scripts/v2/DeployImplementationsV2.t.sol create mode 100644 test/scripts/v2/DeployProxiesV2.t.sol rename test/scripts/{4_rotateKeys.t.sol => v2/RotateKeysV2.t.sol} (62%) create mode 100644 test/scripts/v2/ScriptV2TestUtils.sol rename test/scripts/{3_setupRemoteResources.t.sol => v2/SetupRemoteResourcesV2.t.sol} (79%) diff --git a/Makefile b/Makefile index a146992..cba6c8b 100644 --- a/Makefile +++ b/Makefile @@ -15,35 +15,41 @@ simulate-deploy: deploy: forge script scripts/v1/deploy.s.sol:DeployScript --rpc-url ${RPC_URL} --sender ${SENDER} --broadcast -simulate-deploy-proxy-factory: - forge script scripts/DeployProxyFactory.s.sol:DeployProxyFactoryScript --rpc-url ${RPC_URL} --sender ${SENDER} +simulate-deploy-implementations-v2: + forge script scripts/v2/DeployImplementationsV2.s.sol:DeployImplementationsV2Script --rpc-url ${RPC_URL} --sender ${SENDER} -deploy-proxy-factory: - forge script scripts/DeployProxyFactory.s.sol:DeployProxyFactoryScript --rpc-url ${RPC_URL} --sender ${SENDER} --broadcast +deploy-implementations-v2: + forge script scripts/v2/DeployImplementationsV2.s.sol:DeployImplementationsV2Script --rpc-url ${RPC_URL} --sender ${SENDER} --broadcast -simulate-deployv2: - forge script scripts/v2/1_deploy.s.sol:DeployV2Script --rpc-url ${RPC_URL} --sender ${SENDER} +simulate-deploy-create2-factory: + forge script scripts/DeployCreate2Factory.s.sol:DeployCreate2FactoryScript --rpc-url ${RPC_URL} --sender ${SENDER} -deployv2: - forge script scripts/v2/1_deploy.s.sol:DeployV2Script --rpc-url ${RPC_URL} --sender ${SENDER} --broadcast +deploy-create2-factory: + forge script scripts/DeployCreate2Factory.s.sol:DeployCreate2FactoryScript --rpc-url ${RPC_URL} --sender ${SENDER} --broadcast -simulate-setup-second-attester: - forge script scripts/v2/2_setupSecondAttester.s.sol:SetupSecondAttesterScript --rpc-url ${RPC_URL} --sender ${SENDER} +simulate-deploy-proxies-v2: + forge script scripts/v2/DeployProxiesV2.s.sol:DeployProxiesV2Script --rpc-url ${RPC_URL} --sender ${SENDER} -setup-second-attester: - forge script scripts/v2/2_setupSecondAttester.s.sol:SetupSecondAttesterScript --rpc-url ${RPC_URL} --sender ${SENDER} --broadcast +deploy-proxies-v2: + forge script scripts/v2/DeployProxiesV2.s.sol:DeployProxiesV2Script --rpc-url ${RPC_URL} --sender ${SENDER} --broadcast -simulate-setup-remote-resources: - forge script scripts/v2/3_setupRemoteResources.s.sol:SetupRemoteResourcesScript --rpc-url ${RPC_URL} --sender ${SENDER} +simulate-setup-remote-resources-v2: + forge script scripts/v2/SetupRemoteResourcesV2.s.sol:SetupRemoteResourcesV2Script --rpc-url ${RPC_URL} --sender ${SENDER} -setup-remote-resources: - forge script scripts/v2/3_setupRemoteResources.s.sol:SetupRemoteResourcesScript --rpc-url ${RPC_URL} --sender ${SENDER} --broadcast +setup-remote-resources-v2: + forge script scripts/v2/SetupRemoteResourcesV2.s.sol:SetupRemoteResourcesV2Script --rpc-url ${RPC_URL} --sender ${SENDER} --broadcast -simulate-rotate-keys: - forge script scripts/v2/4_rotateKeys.s.sol:RotateKeysScript --rpc-url ${RPC_URL} --sender ${SENDER} +simulate-rotate-keys-v2: + forge script scripts/v2/RotateKeysV2.s.sol:RotateKeysV2Script --rpc-url ${RPC_URL} --sender ${SENDER} -rotate-keys: - forge script scripts/v2/4_rotateKeys.s.sol:RotateKeysScript --rpc-url ${RPC_URL} --sender ${SENDER} --broadcast +rotate-keys-v2: + forge script scripts/v2/RotateKeysV2.s.sol:RotateKeysV2Script --rpc-url ${RPC_URL} --sender ${SENDER} --broadcast + +simulate-deploy-address-utils-external: + forge script scripts/v2/DeployAddressUtilsExternal.s.sol:DeployAddressUtilsExternalScript --rpc-url ${RPC_URL} --sender ${SENDER} + +deploy-address-utils-external: + forge script scripts/v2/DeployAddressUtilsExternal.s.sol:DeployAddressUtilsExternalScript --rpc-url ${RPC_URL} --sender ${SENDER} --broadcast anvil: docker rm -f anvil || true diff --git a/README.md b/README.md index 84239d7..be7f29a 100644 --- a/README.md +++ b/README.md @@ -96,117 +96,128 @@ The contracts are deployed using [Forge Scripts](https://book.getfoundry.sh/tuto ### V2 +#### Create2Factory + Deploy Create2Factory first if not yet deployed. -
    -
  1. - - Add the below environment variable to your [env](.env) file: - - `CREATE2_FACTORY_DEPLOYER_KEY`
  2. -
  3. - - Run `make simulate-deploy-create2-factory RPC_URL= SENDER=` to perform a dry run.
  4. -
  5. - - Run +1. Add the environment variable `CREATE2_FACTORY_DEPLOYER_KEY` to your [env](.env) file. +2. Run `make simulate-deploy-create2-factory RPC_URL= SENDER=` to perform a dry run. +3. Run ```make deploy-create2-factory RPC_URL= SENDER=``` - to deploy the Create2Factory.
  6. -
+ to deploy the Create2Factory. -The contracts are deployed via `CREATE2` through Create2Factory. Follow the below steps to deploy the contracts: +#### V2 Implementation Contracts -1. Replace the environment variables in your [env](.env) file with the following: +Deploy the implementation contracts. - - `MESSAGE_TRANSMITTER_DEPLOYER_KEY` - - `TOKEN_MESSENGER_DEPLOYER_KEY` - - `TOKEN_MINTER_DEPLOYER_KEY` - - `TOKEN_CONTROLLER_DEPLOYER_KEY` - - `ATTESTER_ADDRESS` - - `USDC_CONTRACT_ADDRESS` - - `REMOTE_USDC_CONTRACT_ADDRESS` - - `MESSAGE_TRANSMITTER_PAUSER_ADDRESS` - - `TOKEN_MINTER_PAUSER_ADDRESS` - - `MESSAGE_TRANSMITTER_RESCUER_ADDRESS` - - `TOKEN_MESSENGER_RESCUER_ADDRESS` - - `TOKEN_MINTER_RESCUER_ADDRESS` - - `TOKEN_CONTROLLER_ADDRESS` - - `DOMAIN` - - `REMOTE_DOMAIN` - - `BURN_LIMIT_PER_MESSAGE` - - `CREATE2_FACTORY_ADDRESS` +1. Add the following [env](.env) variables + + - `CREATE2_FACTORY_CONTRACT_ADDRESS` + - `TOKEN_CONTROLLER_ADDRESS` + - `DOMAIN` + - `MESSAGE_BODY_VERSION` + - `VERSION` + - `IMPLEMENTATION_DEPLOYER_PRIVATE_KEY` + +2. Run `make simulate-deploy-implementations-v2 RPC_URL= SENDER=` to perform a dry run. - In addition, to link the remote bridge, one of two steps needs to be followed: +3. Run + ```make deploy-implementations-v2 RPC_URL= SENDER=``` + to deploy MessageTransmitterV2, TokenMinterV2, and TokenMessengerV2. - - Add the `REMOTE_TOKEN_MESSENGER_DEPLOYER` address to your [env](.env) file and run [scripts/precomputeRemoteMessengerAddress.py](/scripts/precomputeRemoteMessengerAddress.py) with argument `--REMOTE_RPC_URL` for the remote chain, which will automatically add the `REMOTE_TOKEN_MESSENGER_ADDRESS` to the .env file - - Manually add the `REMOTE_TOKEN_MESSENGER_ADDRESS` to your .env file. +#### V2 Proxies -2. Run `make simulate-deployv2 RPC_URL= SENDER=` to perform a dry run. _Note: Use address from one of the private keys (used for deploying) above as `sender`. It is used to deploy the shared libraries that contracts use_ -3. Run `make deployv2 RPC_URL= SENDER=` to deploy the contracts +The proxies are deployed via `CREATE2` through Create2Factory. The scripts assumes the remote chains are EVM compatible and predicts that remote contracts will be deployed at the same addresses. Follow the below steps to deploy the contracts: + +1. Replace the environment variables in your [env](.env) file with the following: + + Note: `REMOTE_DOMAINS`, `REMOTE_USDC_CONTRACT_ADDRESSES`, and `REMOTE_TOKEN_MESSENGER_V2_ADDRESSES` must all correspond 1:1:1 in order. + + - `USDC_CONTRACT_ADDRESS` + - `TOKEN_CONTROLLER_ADDRESS` + - `REMOTE_DOMAINS` + - `REMOTE_USDC_CONTRACT_ADDRESSES` + - `REMOTE_TOKEN_MESSENGER_V2_ADDRESSES` + - `CREATE2_FACTORY_CONTRACT_ADDRESS` + + - `MESSAGE_TRANSMITTER_V2_IMPLEMENTATION_ADDRESS` + - `MESSAGE_TRANSMITTER_V2_OWNER_ADDRESS` + - `MESSAGE_TRANSMITTER_V2_PAUSER_ADDRESS` + - `MESSAGE_TRANSMITTER_V2_RESCUER_ADDRESS` + - `MESSAGE_TRANSMITTER_V2_ATTESTER_MANAGER_ADDRESS` + - `MESSAGE_TRANSMITTER_V2_ATTESTER_1_ADDRESS` + - `MESSAGE_TRANSMITTER_V2_ATTESTER_2_ADDRESS` + - `MESSAGE_TRANSMITTER_V2_PROXY_ADMIN_ADDRESS` + + - `TOKEN_MINTER_V2_CONTRACT_ADDRESS` + - `TOKEN_MINTER_V2_PAUSER_ADDRESS` + - `TOKEN_MINTER_V2_RESCUER_ADDRESS` + + - `TOKEN_MESSENGER_V2_IMPLEMENTATION_ADDRESS` + - `TOKEN_MESSENGER_V2_OWNER_ADDRESS` + - `TOKEN_MESSENGER_V2_RESCUER_ADDRESS` + - `TOKEN_MESSENGER_V2_FEE_RECIPIENT_ADDRESS` + - `TOKEN_MESSENGER_V2_DENYLISTER_ADDRESS` + - `TOKEN_MESSENGER_V2_PROXY_ADMIN_ADDRESS` + + - `DOMAIN` + - `BURN_LIMIT_PER_MESSAGE` -4. Replace the environment variables in your [env](.env) file with: + - `CREATE2_FACTORY_OWNER_KEY` + - `TOKEN_MINTER_V2_DEPLOYER_KEY` + - `TOKEN_CONTROLLER_KEY` - - `MESSAGE_TRANSMITTER_CONTRACT_ADDRESS` - - `MESSAGE_TRANSMITTER_DEPLOYER_KEY` - - `NEW_ATTESTER_MANAGER_ADDRESS` - - `SECOND_ATTESTER_ADDRESS` +2. Run `make simulate-deploy-proxies-v2 RPC_URL= SENDER=` to perform a dry run. -5. Run `make simulate-setup-second-attester RPC_URL= SENDER=` to perform a dry run of setting up the second attester. +3. Run `make deploy-proxies-v2 RPC_URL= SENDER=` to deploy the contracts -6. Run `make setup-second-attester RPC_URL= SENDER=` to setup the second attester. +4. ONLY perform steps 5-7 for additional remote resources NOT already configured above. -7. Replace the environment variables in your [env](.env) file with the following. We'll just add one remote resource (e.g. adding remote token messenger and remote usdc contract addresses) at a time, so just pick any and then repeat these steps. This will need to be repeated for each remote chain: +5. Replace the environment variables in your [env](.env) file with the following. We'll just add one remote resource (e.g. adding remote token messenger and remote usdc contract addresses) at a time, so just pick any and then repeat these steps. This will need to be repeated for each remote chain: - - `TOKEN_MESSENGER_DEPLOYER_KEY` + - `TOKEN_MESSENGER_V2_OWNER_KEY` - `TOKEN_CONTROLLER_KEY` - - `REMOTE_TOKEN_MESSENGER_ADDRESS` - - `TOKEN_MINTER_CONTRACT_ADDRESS` - - `TOKEN_MESSENGER_CONTRACT_ADDRESS` - - `REMOTE_USDC_CONTRACT_ADDRESS` + - `TOKEN_MESSENGER_V2_CONTRACT_ADDRESS` + - `TOKEN_MINTER_V2_CONTRACT_ADDRESS` - `USDC_CONTRACT_ADDRESS` + - `REMOTE_USDC_CONTRACT_ADDRESS` - `REMOTE_DOMAIN` -8. Run `make simulate-setup-remote-resources RPC_URL= SENDER=` to perform a dry run of adding remote resources. +6. Run `make simulate-setup-remote-resources-v2 RPC_URL= SENDER=` to perform a dry run of adding remote resources. -9. Run `make setup-remote-resources RPC_URL= SENDER=` to setup the remote resources. +7. Run `make setup-remote-resources-v2 RPC_URL= SENDER=` to setup the remote resources. -10. Repeat steps 7-9 for all remote resources. This needs to be done for all existing remote chains at - contract setup except for the initial remote chain used in `1_deploy.s.sol`. +**[Remaining steps are only for mainnet]** -**[Only execute the following if replacing remote resources for an existing chain]** +8. Replace the environment variables in your [env](.env) file with: + + - `MESSAGE_TRANSMITTER_V2_CONTRACT_ADDRESS` + - `TOKEN_MESSENGER_V2_CONTRACT_ADDRESS` + - `TOKEN_MINTER_V2_CONTRACT_ADDRESS` + - `MESSAGE_TRANSMITTER_V2_OWNER_KEY` + - `TOKEN_MESSENGER_V2_OWNER_KEY` + - `TOKEN_MINTER_V2_OWNER_KEY` + - `MESSAGE_TRANSMITTER_V2_NEW_OWNER_ADDRESS` + - `TOKEN_MESSENGER_V2_NEW_OWNER_ADDRESS` + - `TOKEN_MINTER_V2_NEW_OWNER_ADDRESS` + - `NEW_TOKEN_CONTROLLER_ADDRESS` -11. Replace the environment variables in your [env](.env) file with the following. We'll replace one set of remote resources for a given chain (e.g. changing the remote token messenger and remote usdc contract addresses) at a time so it will need to be repeated for each applicable chain. - - `TOKEN_MESSENGER_DEPLOYER_KEY` - - `TOKEN_CONTROLLER_KEY` - - `REMOTE_TOKEN_MESSENGER_ADDRESS` - - `REMOTE_TOKEN_MESSENGER_ADDRESS_DEPRECATED` - - `TOKEN_MINTER_CONTRACT_ADDRESS` - - `TOKEN_MESSENGER_CONTRACT_ADDRESS` - - `REMOTE_USDC_CONTRACT_ADDRESS` - - `REMOTE_USDC_CONTRACT_ADDRESS_DEPRECATED` - - `USDC_CONTRACT_ADDRESS` - - `REMOTE_DOMAIN` -12. Run `make simulate-replace-remote-resources RPC_URL= SENDER=` to perform a dry run of replacing remote resources. +9. Run `make simulate-rotate-keys-v2 RPC_URL= SENDER=` to perform a dry run of rotating the keys. -13. Run `make replace-remote-resources RPC_URL= SENDER=` to replace the remote resources. +10. Run `make rotate-keys-v2 RPC_URL= SENDER=` to rotate keys. -**[Remaining steps are only for mainnet]** +#### AddressUtilsExternal -14. Replace the environment variables in your [env](.env) file with: +Use Create2Factory to deploy the helper library to a deterministic address for easy integration. - - `MESSAGE_TRANSMITTER_CONTRACT_ADDRESS` - - `TOKEN_MESSENGER_CONTRACT_ADDRESS` - - `TOKEN_MINTER_CONTRACT_ADDRESS` - - `MESSAGE_TRANSMITTER_DEPLOYER_KEY` - - `TOKEN_MESSENGER_DEPLOYER_KEY` - - `TOKEN_MINTER_DEPLOYER_KEY` - - `MESSAGE_TRANSMITTER_NEW_OWNER_ADDRESS` - - `TOKEN_MESSENGER_NEW_OWNER_ADDRESS` - - `TOKEN_MINTER_NEW_OWNER_ADDRESS` - - `NEW_TOKEN_CONTROLLER_ADDRESS` +1. Set the following [env](.env) variables: + + - `CREATE2_FACTORY_CONTRACT_ADDRESS` + - `CREATE2_FACTORY_OWNER_KEY` -15. Run `make simulate-rotate-keys RPC_URL= SENDER=` to perform a dry run of rotating the keys. +2. Run `make simulate-deploy-address-utils-external RPC_URL= SENDER=` to perform a dry run. -16. Run `make rotate-keys RPC_URL= SENDER=` to rotate keys. +3. Run `make deploy-address-utils-external RPC_URL= SENDER=` to deploy. ## License diff --git a/scripts/v2/1_deploy.s.sol b/scripts/v2/1_deploy.s.sol deleted file mode 100644 index 0bf07bd..0000000 --- a/scripts/v2/1_deploy.s.sol +++ /dev/null @@ -1,274 +0,0 @@ -pragma solidity 0.7.6; - -import "forge-std/Script.sol"; -import "../../src/TokenMessenger.sol"; -import "../../src/TokenMinter.sol"; -import "../../src/MessageTransmitter.sol"; -import "../../src/messages/Message.sol"; - -contract DeployV2Script is Script { - // Expose for tests - MessageTransmitter public messageTransmitter; - TokenMessenger public tokenMessenger; - TokenMinter public tokenMinter; - - address private attesterAddress; - address private usdcContractAddress; - address private usdcRemoteContractAddress; - address private remoteTokenMessengerAddress; - address private tokenControllerAddress; - address private messageTransmitterPauserAddress; - address private tokenMinterPauserAddress; - address private messageTransmitterRescuerAddress; - address private tokenMessengerRescuerAddress; - address private tokenMinterRescuerAddress; - - uint32 private messageBodyVersion = 0; - uint32 private version = 0; - uint32 private domain; - uint32 private remoteDomain; - uint32 private maxMessageBodySize = 8192; - uint256 private burnLimitPerMessage; - - uint256 private messageTransmitterDeployerPrivateKey; - uint256 private tokenMessengerDeployerPrivateKey; - uint256 private tokenMinterDeployerPrivateKey; - uint256 private tokenControllerPrivateKey; - - /** - * @notice deploys Message Transmitter - * @param privateKey Private Key for signing the transactions - * @return MessageTransmitter instance - */ - function deployMessageTransmitter( - uint256 privateKey - ) private returns (MessageTransmitter) { - // Start recording transactions - vm.startBroadcast(privateKey); - - // Deploy MessageTransmitter - MessageTransmitter _messageTransmitter = new MessageTransmitter( - domain, - attesterAddress, - maxMessageBodySize, - version - ); - - // Add Pauser - _messageTransmitter.updatePauser(messageTransmitterPauserAddress); - - // Add Rescuer - _messageTransmitter.updateRescuer(messageTransmitterRescuerAddress); - - // Stop recording transactions - vm.stopBroadcast(); - return _messageTransmitter; - } - - /** - * @notice deploys TokenMessenger - * @param privateKey Private Key for signing the transactions - * @param messageTransmitterAddress Message Transmitter Contract address - * @return TokenMessenger instance - */ - function deployTokenMessenger( - uint256 privateKey, - address messageTransmitterAddress - ) private returns (TokenMessenger) { - // Start recording transations - vm.startBroadcast(privateKey); - - // Deploy TokenMessenger - TokenMessenger _tokenMessenger = new TokenMessenger( - messageTransmitterAddress, - messageBodyVersion - ); - - // Add Rescuer - _tokenMessenger.updateRescuer(tokenMessengerRescuerAddress); - - // Stop recording transations - vm.stopBroadcast(); - - return _tokenMessenger; - } - - /** - * @notice deploys TokenMinter - * @param privateKey Private Key for signing the transactions - * @param tokenMessengerAddress TokenMessenger Contract address - * @return TokenMinter instance - */ - function deployTokenMinter( - uint256 privateKey, - address tokenMessengerAddress - ) private returns (TokenMinter) { - // Start recording transations - vm.startBroadcast(privateKey); - - // Deploy TokenMinter - TokenMinter _tokenMinter = new TokenMinter(tokenControllerAddress); - - // Add Local TokenMessenger - _tokenMinter.addLocalTokenMessenger(tokenMessengerAddress); - - // Add Pauser - _tokenMinter.updatePauser(tokenMinterPauserAddress); - - // Add Rescuer - _tokenMinter.updateRescuer(tokenMinterRescuerAddress); - - // Stop recording transations - vm.stopBroadcast(); - - return _tokenMinter; - } - - /** - * @notice add local minter to the TokenMessenger - */ - function addMinterAddressToTokenMessenger( - TokenMessenger _tokenMessenger, - uint256 privateKey, - address minterAddress - ) private { - // Start recording transations - vm.startBroadcast(privateKey); - - _tokenMessenger.addLocalMinter(minterAddress); - - // Stop recording transations - vm.stopBroadcast(); - } - - /** - * @notice link current chain and remote chain tokens - */ - function linkTokenPair( - TokenMinter _tokenMinter, - uint256 privateKey - ) private { - // Start recording transations - vm.startBroadcast(privateKey); - - bytes32 remoteUsdcContractAddressInBytes32 = Message.addressToBytes32( - usdcRemoteContractAddress - ); - - _tokenMinter.setMaxBurnAmountPerMessage( - usdcContractAddress, - burnLimitPerMessage - ); - - _tokenMinter.linkTokenPair( - usdcContractAddress, - remoteDomain, - remoteUsdcContractAddressInBytes32 - ); - - // Stop recording transations - vm.stopBroadcast(); - } - - /** - * @notice add address of TokenMessenger deployed on another chain - */ - function addRemoteTokenMessenger( - TokenMessenger _tokenMessenger, - uint256 privateKey - ) private { - // Start recording transations - vm.startBroadcast(privateKey); - bytes32 remoteTokenMessengerAddressInBytes32 = Message.addressToBytes32( - remoteTokenMessengerAddress - ); - _tokenMessenger.addRemoteTokenMessenger( - remoteDomain, - remoteTokenMessengerAddressInBytes32 - ); - - // Stop recording transations - vm.stopBroadcast(); - } - - /** - * @notice initialize variables from environment - */ - function setUp() public { - messageTransmitterDeployerPrivateKey = vm.envUint( - "MESSAGE_TRANSMITTER_DEPLOYER_KEY" - ); - tokenMessengerDeployerPrivateKey = vm.envUint( - "TOKEN_MESSENGER_DEPLOYER_KEY" - ); - tokenMinterDeployerPrivateKey = vm.envUint("TOKEN_MINTER_DEPLOYER_KEY"); - tokenControllerPrivateKey = vm.envUint("TOKEN_CONTROLLER_DEPLOYER_KEY"); - - attesterAddress = vm.envAddress("ATTESTER_ADDRESS"); - usdcContractAddress = vm.envAddress("USDC_CONTRACT_ADDRESS"); - tokenControllerAddress = vm.envAddress("TOKEN_CONTROLLER_ADDRESS"); - burnLimitPerMessage = vm.envUint("BURN_LIMIT_PER_MESSAGE"); - - usdcRemoteContractAddress = vm.envAddress( - "REMOTE_USDC_CONTRACT_ADDRESS" - ); - - remoteTokenMessengerAddress = vm.envAddress( - "REMOTE_TOKEN_MESSENGER_ADDRESS" - ); - - domain = uint32(vm.envUint("DOMAIN")); - remoteDomain = uint32(vm.envUint("REMOTE_DOMAIN")); - - messageTransmitterPauserAddress = vm.envAddress( - "MESSAGE_TRANSMITTER_PAUSER_ADDRESS" - ); - tokenMinterPauserAddress = vm.envAddress("TOKEN_MINTER_PAUSER_ADDRESS"); - - messageTransmitterRescuerAddress = vm.envAddress( - "MESSAGE_TRANSMITTER_RESCUER_ADDRESS" - ); - tokenMessengerRescuerAddress = vm.envAddress( - "TOKEN_MESSENGER_RESCUER_ADDRESS" - ); - tokenMinterRescuerAddress = vm.envAddress( - "TOKEN_MINTER_RESCUER_ADDRESS" - ); - } - - /** - * @notice main function that will be run by forge - */ - function run() public { - // Deploy MessageTransmitter - messageTransmitter = deployMessageTransmitter( - messageTransmitterDeployerPrivateKey - ); - - // Deploy TokenMessenger - tokenMessenger = deployTokenMessenger( - tokenMessengerDeployerPrivateKey, - address(messageTransmitter) - ); - - // Deploy TokenMinter - tokenMinter = deployTokenMinter( - tokenMinterDeployerPrivateKey, - address(tokenMessenger) - ); - - // Add Local Minter - addMinterAddressToTokenMessenger( - tokenMessenger, - tokenMessengerDeployerPrivateKey, - address(tokenMinter) - ); - - // Link token pair and add remote token messenger - linkTokenPair(tokenMinter, tokenControllerPrivateKey); - addRemoteTokenMessenger( - tokenMessenger, - tokenMessengerDeployerPrivateKey - ); - } -} diff --git a/scripts/v2/2_setupSecondAttester.s.sol b/scripts/v2/2_setupSecondAttester.s.sol deleted file mode 100644 index 65fbc86..0000000 --- a/scripts/v2/2_setupSecondAttester.s.sol +++ /dev/null @@ -1,63 +0,0 @@ -pragma solidity 0.7.6; - -import "forge-std/Script.sol"; -import "../../src/MessageTransmitter.sol"; - -contract SetupSecondAttesterScript is Script { - address private secondAttesterAddress; - address private newAttesterManagerAddress; - address private messageTransmitterContractAddress; - - uint256 private attesterManagerPrivateKey; - - function configureSecondAttesterThenRotateAttesterManager( - uint256 privateKey - ) public { - MessageTransmitter messageTransmitter = MessageTransmitter( - messageTransmitterContractAddress - ); - - vm.startBroadcast(privateKey); - - // enable second attester - messageTransmitter.enableAttester(secondAttesterAddress); - - // setSignatureThreshold to 2 - messageTransmitter.setSignatureThreshold(2); - - // updateAttesterManager - messageTransmitter.updateAttesterManager(newAttesterManagerAddress); - - vm.stopBroadcast(); - } - - /** - * @notice initialize variables from environment - */ - function setUp() public { - messageTransmitterContractAddress = vm.envAddress( - "MESSAGE_TRANSMITTER_CONTRACT_ADDRESS" - ); - - attesterManagerPrivateKey = vm.envUint( - "MESSAGE_TRANSMITTER_DEPLOYER_KEY" - ); - - newAttesterManagerAddress = vm.envAddress( - "NEW_ATTESTER_MANAGER_ADDRESS" - ); - - secondAttesterAddress = vm.envAddress("SECOND_ATTESTER_ADDRESS"); - } - - /** - * @notice main function that will be run by forge - */ - function run() public { - setUp(); - - configureSecondAttesterThenRotateAttesterManager( - attesterManagerPrivateKey - ); - } -} diff --git a/scripts/v2/3_setupRemoteResources.s.sol b/scripts/v2/3_setupRemoteResources.s.sol deleted file mode 100644 index 3645278..0000000 --- a/scripts/v2/3_setupRemoteResources.s.sol +++ /dev/null @@ -1,108 +0,0 @@ -pragma solidity 0.7.6; - -import "forge-std/Script.sol"; -import "../../src/TokenMessenger.sol"; -import "../../src/TokenMinter.sol"; -import "../../src/messages/Message.sol"; - -contract SetupRemoteResourcesScript is Script { - address private usdcRemoteContractAddress; - address private usdcContractAddress; - address private remoteTokenMessengerAddress; - address private tokenMessengerContractAddress; - address private tokenMinterContractAddress; - - uint32 private remoteDomain; - - uint256 private tokenMessengerDeployerPrivateKey; - uint256 private tokenControllerPrivateKey; - - /** - * @notice link current chain and remote chain tokens - */ - function linkTokenPair( - TokenMinter tokenMinter, - uint256 privateKey - ) private { - // Start recording transactions - vm.startBroadcast(privateKey); - - bytes32 remoteUsdcContractAddressInBytes32 = Message.addressToBytes32( - usdcRemoteContractAddress - ); - - tokenMinter.linkTokenPair( - usdcContractAddress, - remoteDomain, - remoteUsdcContractAddressInBytes32 - ); - - // Stop recording transactions - vm.stopBroadcast(); - } - - /** - * @notice add address of TokenMessenger deployed on another chain - */ - function addRemoteTokenMessenger( - TokenMessenger tokenMessenger, - uint256 privateKey - ) private { - // Start recording transactions - vm.startBroadcast(privateKey); - bytes32 remoteTokenMessengerAddressInBytes32 = Message.addressToBytes32( - remoteTokenMessengerAddress - ); - tokenMessenger.addRemoteTokenMessenger( - remoteDomain, - remoteTokenMessengerAddressInBytes32 - ); - - // Stop recording transactions - vm.stopBroadcast(); - } - - /** - * @notice initialize variables from environment - */ - function setUp() public { - tokenMessengerDeployerPrivateKey = vm.envUint( - "TOKEN_MESSENGER_DEPLOYER_KEY" - ); - tokenControllerPrivateKey = vm.envUint("TOKEN_CONTROLLER_KEY"); - - tokenMessengerContractAddress = vm.envAddress( - "TOKEN_MESSENGER_CONTRACT_ADDRESS" - ); - tokenMinterContractAddress = vm.envAddress( - "TOKEN_MINTER_CONTRACT_ADDRESS" - ); - usdcContractAddress = vm.envAddress("USDC_CONTRACT_ADDRESS"); - usdcRemoteContractAddress = vm.envAddress( - "REMOTE_USDC_CONTRACT_ADDRESS" - ); - remoteTokenMessengerAddress = vm.envAddress( - "REMOTE_TOKEN_MESSENGER_ADDRESS" - ); - - remoteDomain = uint32(vm.envUint("REMOTE_DOMAIN")); - } - - /** - * @notice main function that will be run by forge - * this links the remote usdc token and the remote token messenger - */ - function run() public { - TokenMessenger tokenMessenger = TokenMessenger( - tokenMessengerContractAddress - ); - TokenMinter tokenMinter = TokenMinter(tokenMinterContractAddress); - - // Link token pair and add remote token messenger - linkTokenPair(tokenMinter, tokenControllerPrivateKey); - addRemoteTokenMessenger( - tokenMessenger, - tokenMessengerDeployerPrivateKey - ); - } -} diff --git a/scripts/v2/4_rotateKeys.s.sol b/scripts/v2/4_rotateKeys.s.sol deleted file mode 100644 index 591f4a2..0000000 --- a/scripts/v2/4_rotateKeys.s.sol +++ /dev/null @@ -1,114 +0,0 @@ -pragma solidity 0.7.6; - -import "forge-std/Script.sol"; -import "../../src/TokenMessenger.sol"; -import "../../src/TokenMinter.sol"; -import "../../src/MessageTransmitter.sol"; - -contract RotateKeysScript is Script { - address private messageTransmitterContractAddress; - address private tokenMessengerContractAddress; - address private tokenMinterContractAddress; - address private newTokenControllerAddress; - - uint256 private messageTransmitterDeployerPrivateKey; - uint256 private tokenMessengerDeployerPrivateKey; - uint256 private tokenMinterDeployerPrivateKey; - - address private messageTransmitterNewOwnerAddress; - address private tokenMessengerNewOwnerAddress; - address private tokenMinterNewOwnerAddress; - - function rotateMessageTransmitterOwner(uint256 privateKey) public { - // load messageTransmitter - MessageTransmitter messageTransmitter = MessageTransmitter( - messageTransmitterContractAddress - ); - - vm.startBroadcast(privateKey); - - messageTransmitter.transferOwnership(messageTransmitterNewOwnerAddress); - - vm.stopBroadcast(); - } - - function rotateTokenMessengerOwner(uint256 privateKey) public { - TokenMessenger tokenMessenger = TokenMessenger( - tokenMessengerContractAddress - ); - - vm.startBroadcast(privateKey); - - tokenMessenger.transferOwnership(tokenMessengerNewOwnerAddress); - - vm.stopBroadcast(); - } - - function rotateTokenControllerThenTokenMinterOwner( - uint256 privateKey - ) public { - TokenMinter tokenMinter = TokenMinter(tokenMinterContractAddress); - - vm.startBroadcast(privateKey); - - tokenMinter.setTokenController(newTokenControllerAddress); - - tokenMinter.transferOwnership(tokenMinterNewOwnerAddress); - - vm.stopBroadcast(); - } - - /** - * @notice initialize variables from environment - */ - function setUp() public { - messageTransmitterContractAddress = vm.envAddress( - "MESSAGE_TRANSMITTER_CONTRACT_ADDRESS" - ); - - tokenMessengerContractAddress = vm.envAddress( - "TOKEN_MESSENGER_CONTRACT_ADDRESS" - ); - - tokenMinterContractAddress = vm.envAddress( - "TOKEN_MINTER_CONTRACT_ADDRESS" - ); - - messageTransmitterDeployerPrivateKey = vm.envUint( - "MESSAGE_TRANSMITTER_DEPLOYER_KEY" - ); - tokenMessengerDeployerPrivateKey = vm.envUint( - "TOKEN_MESSENGER_DEPLOYER_KEY" - ); - tokenMinterDeployerPrivateKey = vm.envUint("TOKEN_MINTER_DEPLOYER_KEY"); - - messageTransmitterNewOwnerAddress = vm.envAddress( - "MESSAGE_TRANSMITTER_NEW_OWNER_ADDRESS" - ); - - tokenMessengerNewOwnerAddress = vm.envAddress( - "TOKEN_MESSENGER_NEW_OWNER_ADDRESS" - ); - - tokenMinterNewOwnerAddress = vm.envAddress( - "TOKEN_MINTER_NEW_OWNER_ADDRESS" - ); - - newTokenControllerAddress = vm.envAddress( - "NEW_TOKEN_CONTROLLER_ADDRESS" - ); - } - - /** - * @notice main function that will be run by forge - */ - function run() public { - setUp(); - - rotateMessageTransmitterOwner(messageTransmitterDeployerPrivateKey); - rotateTokenMessengerOwner(tokenMessengerDeployerPrivateKey); - rotateTokenControllerThenTokenMinterOwner( - tokenMinterDeployerPrivateKey - ); - } -} diff --git a/scripts/v2/DeployAddressUtilsExternal.s.sol b/scripts/v2/DeployAddressUtilsExternal.s.sol new file mode 100644 index 0000000..06b5bd9 --- /dev/null +++ b/scripts/v2/DeployAddressUtilsExternal.s.sol @@ -0,0 +1,53 @@ +/* + * Copyright 2024 Circle Internet Group, Inc. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +pragma solidity 0.7.6; + +import {Script} from "forge-std/Script.sol"; +import {AddressUtilsExternal} from "../../src/messages/v2/AddressUtilsExternal.sol"; +import {Create2Factory} from "../../src/v2/Create2Factory.sol"; + +contract DeployAddressUtilsExternalScript is Script { + Create2Factory private create2Factory; + uint256 private create2FactoryOwnerKey; + + function deployAddressUtilsExternalScript() + private + returns (AddressUtilsExternal _addressUtilsExternal) + { + vm.startBroadcast(create2FactoryOwnerKey); + _addressUtilsExternal = AddressUtilsExternal( + create2Factory.deploy( + 0, + bytes32(0), + type(AddressUtilsExternal).creationCode + ) + ); + vm.stopBroadcast(); + } + + function setUp() public { + create2Factory = Create2Factory( + vm.envAddress("CREATE2_FACTORY_CONTRACT_ADDRESS") + ); + create2FactoryOwnerKey = vm.envUint("CREATE2_FACTORY_OWNER_KEY"); + } + + function run() public { + deployAddressUtilsExternalScript(); + } +} diff --git a/scripts/v2/DeployImplementationsV2.s.sol b/scripts/v2/DeployImplementationsV2.s.sol new file mode 100644 index 0000000..4e9cb98 --- /dev/null +++ b/scripts/v2/DeployImplementationsV2.s.sol @@ -0,0 +1,108 @@ +/* + * Copyright 2024 Circle Internet Group, Inc. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +pragma solidity 0.7.6; + +import {Script} from "forge-std/Script.sol"; +import {AdminUpgradableProxy} from "../../src/proxy/AdminUpgradableProxy.sol"; +import {TokenMessengerV2} from "../../src/v2/TokenMessengerV2.sol"; +import {TokenMinterV2} from "../../src/v2/TokenMinterV2.sol"; +import {MessageTransmitterV2} from "../../src/v2/MessageTransmitterV2.sol"; + +contract DeployImplementationsV2Script is Script { + // Expose for tests + MessageTransmitterV2 public messageTransmitterV2; + TokenMessengerV2 public tokenMessengerV2; + TokenMinterV2 public tokenMinterV2; + address public expectedMessageTransmitterV2ProxyAddress; + + address private factoryAddress; + address private tokenControllerAddress; + uint32 private messageBodyVersion; + uint32 private version; + uint32 private domain; + uint256 private implementationDeployerPrivateKey; + + function deployImplementationsV2( + uint256 privateKey + ) private returns (MessageTransmitterV2, TokenMinterV2, TokenMessengerV2) { + // Calculate MessageTransmitterV2 proxy address + expectedMessageTransmitterV2ProxyAddress = vm.computeCreate2Address( + keccak256(type(MessageTransmitterV2).creationCode), + keccak256( + abi.encodePacked( + type(AdminUpgradableProxy).creationCode, + abi.encode(factoryAddress, factoryAddress, "") + ) + ), + factoryAddress + ); + + // Start recording transactions + vm.startBroadcast(privateKey); + + // Deploy MessageTransmitterV2 implementation + MessageTransmitterV2 messageTransmitterV2Implementation = new MessageTransmitterV2( + domain, + version + ); + + // Deploy TokenMinter + TokenMinterV2 tokenMinterV2Implementation = new TokenMinterV2( + tokenControllerAddress + ); + + // Deploy TokenMessengerV2 + TokenMessengerV2 tokenMessengerV2Implementation = new TokenMessengerV2( + expectedMessageTransmitterV2ProxyAddress, + messageBodyVersion + ); + + // Stop recording transactions + vm.stopBroadcast(); + return ( + messageTransmitterV2Implementation, + tokenMinterV2Implementation, + tokenMessengerV2Implementation + ); + } + + /** + * @notice initialize variables from environment + */ + function setUp() public { + factoryAddress = vm.envAddress("CREATE2_FACTORY_CONTRACT_ADDRESS"); + tokenControllerAddress = vm.envAddress("TOKEN_CONTROLLER_ADDRESS"); + domain = uint32(vm.envUint("DOMAIN")); + messageBodyVersion = uint32(vm.envUint("MESSAGE_BODY_VERSION")); + version = uint32(vm.envUint("VERSION")); + implementationDeployerPrivateKey = vm.envUint( + "IMPLEMENTATION_DEPLOYER_PRIVATE_KEY" + ); + } + + /** + * @notice main function that will be run by forge + */ + function run() public { + ( + messageTransmitterV2, + tokenMinterV2, + tokenMessengerV2 + ) = deployImplementationsV2(implementationDeployerPrivateKey); + } +} diff --git a/scripts/v2/DeployProxiesV2.s.sol b/scripts/v2/DeployProxiesV2.s.sol new file mode 100644 index 0000000..19b9be4 --- /dev/null +++ b/scripts/v2/DeployProxiesV2.s.sol @@ -0,0 +1,364 @@ +/* + * Copyright 2024 Circle Internet Group, Inc. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +pragma solidity 0.7.6; +pragma abicoder v2; + +import {Script} from "forge-std/Script.sol"; +import {Create2Factory} from "../../src/v2/Create2Factory.sol"; +import {AdminUpgradableProxy} from "../../src/proxy/AdminUpgradableProxy.sol"; +import {TokenMessengerV2} from "../../src/v2/TokenMessengerV2.sol"; +import {TokenMinterV2} from "../../src/v2/TokenMinterV2.sol"; +import {MessageTransmitterV2} from "../../src/v2/MessageTransmitterV2.sol"; + +contract DeployProxiesV2Script is Script { + // Expose for tests + MessageTransmitterV2 public messageTransmitterV2; + TokenMessengerV2 public tokenMessengerV2; + + address private usdcContractAddress; + address private create2Factory; + uint32[] private remoteDomains; + bytes32[] private usdcRemoteContractAddresses; + bytes32[] private remoteTokenMessengerV2Addresses; + + address private messageTransmitterV2Implementation; + address private messageTransmitterV2OwnerAddress; + address private messageTransmitterV2PauserAddress; + address private messageTransmitterV2RescuerAddress; + address private messageTransmitterV2AttesterManagerAddress; + address private messageTransmitterV2Attester1Address; + address private messageTransmitterV2Attester2Address; + uint256 private messageTransmitterV2SignatureThreshold = 2; + address private messageTransmitterV2AdminAddress; + + TokenMinterV2 private tokenMinterV2; + address private tokenMinterV2PauserAddress; + address private tokenMinterV2RescuerAddress; + + address private tokenMessengerV2Implementation; + address private tokenMessengerV2OwnerAddress; + address private tokenMessengerV2PauserAddress; + address private tokenMessengerV2RescuerAddress; + address private tokenMessengerV2FeeRecipientAddress; + address private tokenMessengerV2DenylisterAddress; + address private tokenMessengerV2AdminAddress; + + uint32 private domain; + uint32 private maxMessageBodySize = 8192; + uint256 private burnLimitPerMessage; + + uint256 private create2FactoryOwnerPrivateKey; + uint256 private tokenMinterV2DeployerPrivateKey; + uint256 private tokenControllerPrivateKey; + + function getProxyCreationCode( + address _implementation, + address _admin, + bytes memory _data + ) public pure returns (bytes memory) { + return + abi.encodePacked( + type(AdminUpgradableProxy).creationCode, + abi.encode(_implementation, _admin, _data) + ); + } + + function deployMessageTransmitterV2( + address factory, + uint256 privateKey + ) private returns (MessageTransmitterV2) { + // Get proxy creation code + bytes memory proxyCreateCode = getProxyCreationCode( + factory, + factory, + "" + ); + + // Construct initializer + address[] memory attesters = new address[](2); + attesters[0] = messageTransmitterV2Attester1Address; + attesters[1] = messageTransmitterV2Attester2Address; + bytes memory initializer = abi.encodeWithSelector( + MessageTransmitterV2.initialize.selector, + messageTransmitterV2OwnerAddress, + messageTransmitterV2PauserAddress, + messageTransmitterV2RescuerAddress, + messageTransmitterV2AttesterManagerAddress, + attesters, + messageTransmitterV2SignatureThreshold, + maxMessageBodySize + ); + + // Construct upgrade and initialize data + bytes memory upgradeAndInitializeData = abi.encodeWithSelector( + AdminUpgradableProxy.upgradeToAndCall.selector, + messageTransmitterV2Implementation, + initializer + ); + + // Construct admin rotation data + bytes memory adminRotationData = abi.encodeWithSelector( + AdminUpgradableProxy.changeAdmin.selector, + messageTransmitterV2AdminAddress + ); + + bytes[] memory multiCallData = new bytes[](2); + multiCallData[0] = upgradeAndInitializeData; + multiCallData[1] = adminRotationData; + + // Start recording transactions + vm.startBroadcast(privateKey); + + // Deploy and multicall proxy + address messageTransmitterV2ProxyAddress = Create2Factory(factory) + .deployAndMultiCall( + 0, + keccak256(type(MessageTransmitterV2).creationCode), // TODO: Verify salt + proxyCreateCode, + multiCallData + ); + + // Stop recording transactions + vm.stopBroadcast(); + return MessageTransmitterV2(messageTransmitterV2ProxyAddress); + } + + function deployTokenMessengerV2( + address factory, + uint256 privateKey, + address tokenMinterV2Address + ) private returns (TokenMessengerV2) { + // Get proxy creation code + bytes memory proxyCreateCode = getProxyCreationCode( + factory, + factory, + "" + ); + + // Construct initializer + bytes32[] memory remoteTokenMessengerAddresses = new bytes32[]( + remoteDomains.length + ); + uint256 remoteDomainsLength = remoteDomains.length; + for (uint256 i = 0; i < remoteDomainsLength; ++i) { + remoteTokenMessengerAddresses[i] = remoteTokenMessengerV2Addresses[ + i + ]; + } + bytes memory initializer = abi.encodeWithSelector( + TokenMessengerV2.initialize.selector, + tokenMessengerV2OwnerAddress, + tokenMessengerV2RescuerAddress, + tokenMessengerV2FeeRecipientAddress, + tokenMessengerV2DenylisterAddress, + tokenMinterV2Address, + remoteDomains, + remoteTokenMessengerAddresses + ); + + // Construct upgrade and initialize data + bytes memory upgradeAndInitializeData = abi.encodeWithSelector( + AdminUpgradableProxy.upgradeToAndCall.selector, + tokenMessengerV2Implementation, + initializer + ); + + // Construct admin rotation data + bytes memory adminRotationData = abi.encodeWithSelector( + AdminUpgradableProxy.changeAdmin.selector, + tokenMessengerV2AdminAddress + ); + + bytes[] memory multiCallData = new bytes[](2); + multiCallData[0] = upgradeAndInitializeData; + multiCallData[1] = adminRotationData; + + // Start recording transations + vm.startBroadcast(privateKey); + + // Deploy proxy + address tokenMessengerV2ProxyAddress = Create2Factory(factory) + .deployAndMultiCall( + 0, + keccak256(type(TokenMessengerV2).creationCode), // TODO: Verify salt + proxyCreateCode, + multiCallData + ); + + // Stop recording transations + vm.stopBroadcast(); + + return TokenMessengerV2(tokenMessengerV2ProxyAddress); + } + + function addMessengerPauserRescuerToTokenMinterV2( + uint256 tokenMinterV2OwnerPrivateKey, + uint256 _tokenControllerPrivateKey, + TokenMinterV2 _tokenMinterV2, + address tokenMessengerV2Address + ) private { + // Start recording transations + vm.startBroadcast(tokenMinterV2OwnerPrivateKey); + + _tokenMinterV2.addLocalTokenMessenger(tokenMessengerV2Address); + _tokenMinterV2.updatePauser(tokenMinterV2PauserAddress); + _tokenMinterV2.updateRescuer(tokenMinterV2RescuerAddress); + + // Stop recording transations + vm.stopBroadcast(); + + // Start recording transations + vm.startBroadcast(_tokenControllerPrivateKey); + + _tokenMinterV2.setMaxBurnAmountPerMessage( + usdcContractAddress, + burnLimitPerMessage + ); + + uint256 remoteDomainsLength = remoteDomains.length; + for (uint256 i = 0; i < remoteDomainsLength; ++i) { + _tokenMinterV2.linkTokenPair( + usdcContractAddress, + remoteDomains[i], + usdcRemoteContractAddresses[i] + ); + } + + // Stop recording transations + vm.stopBroadcast(); + } + + /** + * @notice initialize variables from environment + */ + function setUp() public { + usdcContractAddress = vm.envAddress("USDC_CONTRACT_ADDRESS"); + bytes32[] memory usdcRemoteContractAddressesMemory = vm.envBytes32( + "REMOTE_USDC_CONTRACT_ADDRESSES", + "," + ); + uint256 usdcRemoteContractAddressesMemoryLength = usdcRemoteContractAddressesMemory + .length; + for (uint256 i = 0; i < usdcRemoteContractAddressesMemoryLength; ++i) { + usdcRemoteContractAddresses.push( + usdcRemoteContractAddressesMemory[i] + ); + } + create2Factory = vm.envAddress("CREATE2_FACTORY_CONTRACT_ADDRESS"); + + messageTransmitterV2Implementation = vm.envAddress( + "MESSAGE_TRANSMITTER_V2_IMPLEMENTATION_ADDRESS" + ); + messageTransmitterV2OwnerAddress = vm.envAddress( + "MESSAGE_TRANSMITTER_V2_OWNER_ADDRESS" + ); + messageTransmitterV2PauserAddress = vm.envAddress( + "MESSAGE_TRANSMITTER_V2_PAUSER_ADDRESS" + ); + messageTransmitterV2RescuerAddress = vm.envAddress( + "MESSAGE_TRANSMITTER_V2_RESCUER_ADDRESS" + ); + messageTransmitterV2AttesterManagerAddress = vm.envAddress( + "MESSAGE_TRANSMITTER_V2_ATTESTER_MANAGER_ADDRESS" + ); + messageTransmitterV2Attester1Address = vm.envAddress( + "MESSAGE_TRANSMITTER_V2_ATTESTER_1_ADDRESS" + ); + messageTransmitterV2Attester2Address = vm.envAddress( + "MESSAGE_TRANSMITTER_V2_ATTESTER_2_ADDRESS" + ); + messageTransmitterV2AdminAddress = vm.envAddress( + "MESSAGE_TRANSMITTER_V2_PROXY_ADMIN_ADDRESS" + ); + + tokenMinterV2 = TokenMinterV2( + vm.envAddress("TOKEN_MINTER_V2_CONTRACT_ADDRESS") + ); + tokenMinterV2PauserAddress = vm.envAddress( + "TOKEN_MINTER_V2_PAUSER_ADDRESS" + ); + tokenMinterV2RescuerAddress = vm.envAddress( + "TOKEN_MINTER_V2_RESCUER_ADDRESS" + ); + + tokenMessengerV2Implementation = vm.envAddress( + "TOKEN_MESSENGER_V2_IMPLEMENTATION_ADDRESS" + ); + tokenMessengerV2OwnerAddress = vm.envAddress( + "TOKEN_MESSENGER_V2_OWNER_ADDRESS" + ); + tokenMessengerV2RescuerAddress = vm.envAddress( + "TOKEN_MESSENGER_V2_RESCUER_ADDRESS" + ); + tokenMessengerV2FeeRecipientAddress = vm.envAddress( + "TOKEN_MESSENGER_V2_FEE_RECIPIENT_ADDRESS" + ); + tokenMessengerV2DenylisterAddress = vm.envAddress( + "TOKEN_MESSENGER_V2_DENYLISTER_ADDRESS" + ); + tokenMessengerV2AdminAddress = vm.envAddress( + "TOKEN_MESSENGER_V2_PROXY_ADMIN_ADDRESS" + ); + + domain = uint32(vm.envUint("DOMAIN")); + + uint256[] memory remoteDomainsUint256 = vm.envUint( + "REMOTE_DOMAINS", + "," + ); + uint256 remoteDomainsUint256Length = remoteDomainsUint256.length; + for (uint256 i = 0; i < remoteDomainsUint256Length; ++i) { + remoteDomains.push(uint32(remoteDomainsUint256[i])); + } + burnLimitPerMessage = vm.envUint("BURN_LIMIT_PER_MESSAGE"); + + create2FactoryOwnerPrivateKey = vm.envUint("CREATE2_FACTORY_OWNER_KEY"); + tokenMinterV2DeployerPrivateKey = vm.envUint( + "TOKEN_MINTER_V2_DEPLOYER_KEY" + ); + tokenControllerPrivateKey = vm.envUint("TOKEN_CONTROLLER_KEY"); + + remoteTokenMessengerV2Addresses = vm.envBytes32( + "REMOTE_TOKEN_MESSENGER_V2_ADDRESSES", + "," + ); + } + + /** + * @notice main function that will be run by forge + */ + function run() public { + messageTransmitterV2 = deployMessageTransmitterV2( + create2Factory, + create2FactoryOwnerPrivateKey + ); + + tokenMessengerV2 = deployTokenMessengerV2( + create2Factory, + create2FactoryOwnerPrivateKey, + address(tokenMinterV2) + ); + + addMessengerPauserRescuerToTokenMinterV2( + tokenMinterV2DeployerPrivateKey, + tokenControllerPrivateKey, + tokenMinterV2, + address(tokenMessengerV2) + ); + } +} diff --git a/scripts/v2/RotateKeysV2.s.sol b/scripts/v2/RotateKeysV2.s.sol new file mode 100644 index 0000000..c305765 --- /dev/null +++ b/scripts/v2/RotateKeysV2.s.sol @@ -0,0 +1,133 @@ +/* + * Copyright 2024 Circle Internet Group, Inc. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +pragma solidity 0.7.6; + +import "forge-std/Script.sol"; +import {TokenMessengerV2} from "../../src/v2/TokenMessengerV2.sol"; +import {TokenMinterV2} from "../../src/v2/TokenMinterV2.sol"; +import {MessageTransmitterV2} from "../../src/v2/MessageTransmitterV2.sol"; + +contract RotateKeysV2Script is Script { + address private messageTransmitterV2ContractAddress; + address private tokenMessengerV2ContractAddress; + address private tokenMinterV2ContractAddress; + address private newTokenControllerAddress; + + uint256 private messageTransmitterV2OwnerPrivateKey; + uint256 private tokenMessengerV2OwnerPrivateKey; + uint256 private tokenMinterV2OwnerPrivateKey; + + address private messageTransmitterV2NewOwnerAddress; + address private tokenMessengerV2NewOwnerAddress; + address private tokenMinterV2NewOwnerAddress; + + function rotateMessageTransmitterV2Owner(uint256 privateKey) public { + // load messageTransmitter + MessageTransmitterV2 messageTransmitterV2 = MessageTransmitterV2( + messageTransmitterV2ContractAddress + ); + + vm.startBroadcast(privateKey); + + messageTransmitterV2.transferOwnership( + messageTransmitterV2NewOwnerAddress + ); + + vm.stopBroadcast(); + } + + function rotateTokenMessengerV2Owner(uint256 privateKey) public { + TokenMessengerV2 tokenMessengerV2 = TokenMessengerV2( + tokenMessengerV2ContractAddress + ); + + vm.startBroadcast(privateKey); + + tokenMessengerV2.transferOwnership(tokenMessengerV2NewOwnerAddress); + + vm.stopBroadcast(); + } + + function rotateTokenControllerThenTokenMinterV2Owner( + uint256 privateKey + ) public { + TokenMinterV2 tokenMinterV2 = TokenMinterV2( + tokenMinterV2ContractAddress + ); + + vm.startBroadcast(privateKey); + + tokenMinterV2.setTokenController(newTokenControllerAddress); + + tokenMinterV2.transferOwnership(tokenMinterV2NewOwnerAddress); + + vm.stopBroadcast(); + } + + /** + * @notice initialize variables from environment + */ + function setUp() public { + messageTransmitterV2ContractAddress = vm.envAddress( + "MESSAGE_TRANSMITTER_V2_CONTRACT_ADDRESS" + ); + + tokenMessengerV2ContractAddress = vm.envAddress( + "TOKEN_MESSENGER_V2_CONTRACT_ADDRESS" + ); + + tokenMinterV2ContractAddress = vm.envAddress( + "TOKEN_MINTER_V2_CONTRACT_ADDRESS" + ); + + messageTransmitterV2OwnerPrivateKey = vm.envUint( + "MESSAGE_TRANSMITTER_V2_OWNER_KEY" + ); + tokenMessengerV2OwnerPrivateKey = vm.envUint( + "TOKEN_MESSENGER_V2_OWNER_KEY" + ); + tokenMinterV2OwnerPrivateKey = vm.envUint("TOKEN_MINTER_V2_OWNER_KEY"); + + messageTransmitterV2NewOwnerAddress = vm.envAddress( + "MESSAGE_TRANSMITTER_V2_NEW_OWNER_ADDRESS" + ); + + tokenMessengerV2NewOwnerAddress = vm.envAddress( + "TOKEN_MESSENGER_V2_NEW_OWNER_ADDRESS" + ); + + tokenMinterV2NewOwnerAddress = vm.envAddress( + "TOKEN_MINTER_V2_NEW_OWNER_ADDRESS" + ); + + newTokenControllerAddress = vm.envAddress( + "NEW_TOKEN_CONTROLLER_ADDRESS" + ); + } + + /** + * @notice main function that will be run by forge + */ + function run() public { + rotateMessageTransmitterV2Owner(messageTransmitterV2OwnerPrivateKey); + rotateTokenMessengerV2Owner(tokenMessengerV2OwnerPrivateKey); + rotateTokenControllerThenTokenMinterV2Owner( + tokenMinterV2OwnerPrivateKey + ); + } +} diff --git a/scripts/v2/SetupRemoteResourcesV2.s.sol b/scripts/v2/SetupRemoteResourcesV2.s.sol new file mode 100644 index 0000000..058b4bc --- /dev/null +++ b/scripts/v2/SetupRemoteResourcesV2.s.sol @@ -0,0 +1,123 @@ +/* + * Copyright 2024 Circle Internet Group, Inc. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +pragma solidity 0.7.6; + +import {Script} from "forge-std/Script.sol"; +import {TokenMessengerV2} from "../../src/v2/TokenMessengerV2.sol"; +import {TokenMinterV2} from "../../src/v2/TokenMinterV2.sol"; +import {Message} from "../../src/messages/Message.sol"; + +contract SetupRemoteResourcesV2Script is Script { + address private usdcRemoteContractAddress; + address private usdcContractAddress; + address private tokenMessengerV2ContractAddress; + address private tokenMinterV2ContractAddress; + + uint32 private remoteDomain; + + uint256 private tokenMessengerV2OwnerPrivateKey; + uint256 private tokenControllerPrivateKey; + + /** + * @notice link current chain and remote chain tokens + */ + function linkTokenPairV2( + TokenMinterV2 tokenMinterV2, + uint256 privateKey + ) private { + // Start recording transactions + vm.startBroadcast(privateKey); + + bytes32 remoteUsdcContractAddressInBytes32 = Message.addressToBytes32( + usdcRemoteContractAddress + ); + + tokenMinterV2.linkTokenPair( + usdcContractAddress, + remoteDomain, + remoteUsdcContractAddressInBytes32 + ); + + // Stop recording transactions + vm.stopBroadcast(); + } + + /** + * @notice add address of TokenMessenger deployed on another chain + */ + function addRemoteTokenMessengerV2( + TokenMessengerV2 tokenMessengerV2, + uint256 privateKey + ) private { + // Start recording transactions + vm.startBroadcast(privateKey); + bytes32 remoteTokenMessengerAddressInBytes32 = Message.addressToBytes32( + address(tokenMessengerV2) + ); + tokenMessengerV2.addRemoteTokenMessenger( + remoteDomain, + remoteTokenMessengerAddressInBytes32 + ); + + // Stop recording transactions + vm.stopBroadcast(); + } + + /** + * @notice initialize variables from environment + */ + function setUp() public { + tokenMessengerV2OwnerPrivateKey = vm.envUint( + "TOKEN_MESSENGER_V2_OWNER_KEY" + ); + tokenControllerPrivateKey = vm.envUint("TOKEN_CONTROLLER_KEY"); + + tokenMessengerV2ContractAddress = vm.envAddress( + "TOKEN_MESSENGER_V2_CONTRACT_ADDRESS" + ); + tokenMinterV2ContractAddress = vm.envAddress( + "TOKEN_MINTER_V2_CONTRACT_ADDRESS" + ); + usdcContractAddress = vm.envAddress("USDC_CONTRACT_ADDRESS"); + usdcRemoteContractAddress = vm.envAddress( + "REMOTE_USDC_CONTRACT_ADDRESS" + ); + + remoteDomain = uint32(vm.envUint("REMOTE_DOMAIN")); + } + + /** + * @notice main function that will be run by forge + * this links the remote usdc token and the remote token messenger + */ + function run() public { + TokenMessengerV2 tokenMessengerV2 = TokenMessengerV2( + tokenMessengerV2ContractAddress + ); + TokenMinterV2 tokenMinterV2 = TokenMinterV2( + tokenMinterV2ContractAddress + ); + + // Link token pair and add remote token messenger + linkTokenPairV2(tokenMinterV2, tokenControllerPrivateKey); + addRemoteTokenMessengerV2( + tokenMessengerV2, + tokenMessengerV2OwnerPrivateKey + ); + } +} diff --git a/test/scripts/1_deploy.t.sol b/test/scripts/1_deploy.t.sol deleted file mode 100644 index a9747ff..0000000 --- a/test/scripts/1_deploy.t.sol +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2024, Circle Internet Financial Limited. - * - * 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. - */ -pragma solidity 0.7.6; -pragma abicoder v2; - -import {ScriptV2TestUtils} from "./ScriptV2TestUtils.sol"; - -contract DeployTest is ScriptV2TestUtils { - function setUp() public { - _deploy(); - } - - function testDeployMessageTransmitter() public { - // domain - assertEq(messageTransmitter.localDomain(), uint256(sourceDomain)); - - // attester - assertEq(messageTransmitter.attesterManager(), deployer); - assertTrue(messageTransmitter.isEnabledAttester(deployer)); - - // maxMessageBodySize - assertEq(messageTransmitter.maxMessageBodySize(), maxMessageBodySize); - - // version - assertEq(messageTransmitter.version(), uint256(version)); - - // pauser - assertEq(messageTransmitter.pauser(), pauser); - - // rescuer - assertEq(messageTransmitter.rescuer(), rescuer); - } - - function testDeployTokenMessenger() public { - // message transmitter - assertEq( - address(tokenMessenger.localMessageTransmitter()), - address(messageTransmitter) - ); - - // message body version - assertEq( - tokenMessenger.messageBodyVersion(), - uint256(_messageBodyVersion) - ); - - // rescuer - assertEq(tokenMessenger.rescuer(), rescuer); - } - - function testDeployTokenMinter() public { - // token controller - assertEq(tokenMinter.tokenController(), deployer); - - // token messenger - assertEq(tokenMinter.localTokenMessenger(), address(tokenMessenger)); - - // pauser - assertEq(tokenMinter.pauser(), pauser); - - // rescuer - assertEq(tokenMinter.rescuer(), rescuer); - } - - function testAddMinterAddressToTokenMessenger() public { - assertEq(address(tokenMessenger.localMinter()), address(tokenMinter)); - } - - function testLinkTokenPair() public { - // max burn per msg - assertEq( - tokenMinter.burnLimitsPerMessage(token), - maxBurnAmountPerMessage - ); - - // linked token pair - bytes32 remoteKey = keccak256( - abi.encodePacked( - destinationDomain, - bytes32(uint256(uint160(remoteToken))) - ) - ); - assertEq(tokenMinter.remoteTokensToLocalTokens(remoteKey), token); - } - - function testAddRemoteTokenMessenger() public { - assertEq( - tokenMessenger.remoteTokenMessengers(destinationDomain), - bytes32(uint256(uint160(remoteTokenMessengerAddress))) - ); - } -} diff --git a/test/scripts/2_setupSecondAttester.t.sol b/test/scripts/2_setupSecondAttester.t.sol deleted file mode 100644 index 7310ffb..0000000 --- a/test/scripts/2_setupSecondAttester.t.sol +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2024, Circle Internet Financial Limited. - * - * 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. - */ -pragma solidity 0.7.6; -pragma abicoder v2; - -import {ScriptV2TestUtils} from "./ScriptV2TestUtils.sol"; - -contract SetupSecondAttesterTest is ScriptV2TestUtils { - function setUp() public { - _deploy(); - _setupSecondAttester(); - } - - function testConfigureSecondAttester() public { - // second attester enabled - assertTrue(messageTransmitter.isEnabledAttester(secondAttester)); - - // sig threshold - assertEq(messageTransmitter.signatureThreshold(), 2); - - // attester manager, didn't change - assertEq(messageTransmitter.attesterManager(), deployer); - } -} diff --git a/test/scripts/ScriptV2TestUtils.sol b/test/scripts/ScriptV2TestUtils.sol deleted file mode 100644 index 167dc6d..0000000 --- a/test/scripts/ScriptV2TestUtils.sol +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2024, Circle Internet Financial Limited. - * - * 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. - */ -pragma solidity 0.7.6; -pragma abicoder v2; - -import {DeployV2Script} from "../../scripts/v2/1_deploy.s.sol"; -import {SetupSecondAttesterScript} from "../../scripts/v2/2_setupSecondAttester.s.sol"; -import {SetupRemoteResourcesScript} from "../../scripts/v2/3_setupRemoteResources.s.sol"; -import {RotateKeysScript} from "../../scripts/v2/4_rotateKeys.s.sol"; -import {MessageTransmitter} from "../../src/MessageTransmitter.sol"; -import {TokenMessenger} from "../../src/TokenMessenger.sol"; -import {TokenMinter} from "../../src/TokenMinter.sol"; -import {MockMintBurnToken} from "../mocks/MockMintBurnToken.sol"; -import {TestUtils} from "../TestUtils.sol"; - -contract ScriptV2TestUtils is TestUtils { - uint32 _messageBodyVersion = 0; - address token; - address remoteToken; - address remoteTokenMessengerAddress; - uint256 deployerPK; - address deployer; - address pauser; - address rescuer; - MessageTransmitter messageTransmitter; - TokenMessenger tokenMessenger; - TokenMinter tokenMinter; - - uint32 anotherRemoteDomain = 2; - address anotherRemoteToken; - address anotherRemoteTokenMessengerAddress; - - uint256 newOwnerPK; - address newOwner; - - function _deploy() internal { - token = address(new MockMintBurnToken()); - remoteToken = address(new MockMintBurnToken()); - - deployerPK = uint256(keccak256("DEPLOYTEST_DEPLOYER_PK")); - deployer = vm.addr(deployerPK); - pauser = vm.addr(uint256(keccak256("DEPLOYTEST_PAUSER_PK"))); - rescuer = vm.addr(uint256(keccak256("DEPLOYTEST_RESCUER_PK"))); - - // Override env vars - vm.setEnv("MESSAGE_TRANSMITTER_DEPLOYER_KEY", vm.toString(deployerPK)); - vm.setEnv("TOKEN_MESSENGER_DEPLOYER_KEY", vm.toString(deployerPK)); - vm.setEnv("TOKEN_MINTER_DEPLOYER_KEY", vm.toString(deployerPK)); - vm.setEnv("TOKEN_CONTROLLER_DEPLOYER_KEY", vm.toString(deployerPK)); - - vm.setEnv("ATTESTER_ADDRESS", vm.toString(deployer)); - vm.setEnv("USDC_CONTRACT_ADDRESS", vm.toString(token)); - vm.setEnv("TOKEN_CONTROLLER_ADDRESS", vm.toString(deployer)); - vm.setEnv( - "BURN_LIMIT_PER_MESSAGE", - vm.toString(maxBurnAmountPerMessage) - ); - - vm.setEnv("REMOTE_USDC_CONTRACT_ADDRESS", vm.toString(remoteToken)); - - remoteTokenMessengerAddress = vm.addr( - uint256(keccak256("REMOTE_TOKEN_MESSENGER_ADDRESS")) - ); - vm.setEnv( - "REMOTE_TOKEN_MESSENGER_ADDRESS", - vm.toString(remoteTokenMessengerAddress) - ); - - vm.setEnv("DOMAIN", vm.toString(uint256(sourceDomain))); - vm.setEnv("REMOTE_DOMAIN", vm.toString(uint256(destinationDomain))); - - vm.setEnv("MESSAGE_TRANSMITTER_PAUSER_ADDRESS", vm.toString(pauser)); - vm.setEnv("TOKEN_MINTER_PAUSER_ADDRESS", vm.toString(pauser)); - - vm.setEnv("MESSAGE_TRANSMITTER_RESCUER_ADDRESS", vm.toString(rescuer)); - vm.setEnv("TOKEN_MESSENGER_RESCUER_ADDRESS", vm.toString(rescuer)); - vm.setEnv("TOKEN_MINTER_RESCUER_ADDRESS", vm.toString(rescuer)); - - DeployV2Script deployScript = new DeployV2Script(); - deployScript.setUp(); - deployScript.run(); - - messageTransmitter = deployScript.messageTransmitter(); - tokenMessenger = deployScript.tokenMessenger(); - tokenMinter = deployScript.tokenMinter(); - } - - function _setupSecondAttester() internal { - vm.setEnv( - "MESSAGE_TRANSMITTER_CONTRACT_ADDRESS", - vm.toString(address(messageTransmitter)) - ); - // [SKIP] Use same MESSAGE_TRANSMITTER_DEPLOYER_KEY - // Use same attester manager, deployer - vm.setEnv("NEW_ATTESTER_MANAGER_ADDRESS", vm.toString(deployer)); - vm.setEnv("SECOND_ATTESTER_ADDRESS", vm.toString(secondAttester)); - - SetupSecondAttesterScript setupSecondAttesterScript = new SetupSecondAttesterScript(); - setupSecondAttesterScript.setUp(); - setupSecondAttesterScript.run(); - } - - function _setupRemoteResources() internal { - // [SKIP] Use same TOKEN_MESSENGER_DEPLOYER_KEY - // Use same TOKEN_CONTROLLER_DEPLOYER_KEY as TOKEN_CONTROLLER_KEY - vm.setEnv("TOKEN_CONTROLLER_KEY", vm.toString(deployerPK)); - vm.setEnv( - "TOKEN_MESSENGER_CONTRACT_ADDRESS", - vm.toString(address(tokenMessenger)) - ); - vm.setEnv( - "TOKEN_MINTER_CONTRACT_ADDRESS", - vm.toString(address(tokenMinter)) - ); - vm.setEnv("USDC_CONTRACT_ADDRESS", vm.toString(token)); - vm.setEnv( - "REMOTE_USDC_CONTRACT_ADDRESS", - vm.toString(anotherRemoteToken) - ); - - anotherRemoteTokenMessengerAddress = vm.addr( - uint256(keccak256("ANOTHER_REMOTE_TOKEN_MESSENGER_ADDRESS")) - ); - vm.setEnv( - "REMOTE_TOKEN_MESSENGER_ADDRESS", - vm.toString(anotherRemoteTokenMessengerAddress) - ); - vm.setEnv("REMOTE_DOMAIN", vm.toString(uint256(anotherRemoteDomain))); - - SetupRemoteResourcesScript setupRemoteResourcesScript = new SetupRemoteResourcesScript(); - setupRemoteResourcesScript.setUp(); - setupRemoteResourcesScript.run(); - } - - function _rotateKeys() internal { - // [SKIP] Use same MESSAGE_TRANSMITTER_CONTRACT_ADDRESS - // [SKIP] Use same TOKEN_MESSENGER_CONTRACT_ADDRESS - // [SKIP] Use same TOKEN_MINTER_CONTRACT_ADDRESS - // [SKIP] Use same MESSAGE_TRANSMITTER_DEPLOYER_KEY - // [SKIP] Use same TOKEN_MESSENGER_DEPLOYER_KEY - // [SKIP] Use same TOKEN_MINTER_DEPLOYER_KEY - - newOwnerPK = uint256(keccak256("ROTATEKEYSTEST_NEW_OWNER")); - newOwner = vm.addr(newOwnerPK); - - vm.setEnv( - "MESSAGE_TRANSMITTER_NEW_OWNER_ADDRESS", - vm.toString(newOwner) - ); - vm.setEnv("TOKEN_MESSENGER_NEW_OWNER_ADDRESS", vm.toString(newOwner)); - vm.setEnv("TOKEN_MINTER_NEW_OWNER_ADDRESS", vm.toString(newOwner)); - vm.setEnv("NEW_TOKEN_CONTROLLER_ADDRESS", vm.toString(newOwner)); - - RotateKeysScript rotateKeysScript = new RotateKeysScript(); - rotateKeysScript.setUp(); - rotateKeysScript.run(); - } -} diff --git a/test/scripts/v2/DeployImplementationsV2.t.sol b/test/scripts/v2/DeployImplementationsV2.t.sol new file mode 100644 index 0000000..29a79d6 --- /dev/null +++ b/test/scripts/v2/DeployImplementationsV2.t.sol @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024, Circle Internet Financial Limited. + * + * 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. + */ +pragma solidity 0.7.6; +pragma abicoder v2; + +import {ScriptV2TestUtils} from "./ScriptV2TestUtils.sol"; +import {DeployImplementationsV2Script} from "../../../scripts/v2/DeployImplementationsV2.s.sol"; +import {MessageTransmitterV2} from "../../../src/v2/MessageTransmitterV2.sol"; +import {TokenMessengerV2} from "../../../src/v2/TokenMessengerV2.sol"; + +contract DeployImplementationsV2Test is ScriptV2TestUtils { + DeployImplementationsV2Script deployImplementationsV2Script; + + function setUp() public { + _deployCreate2Factory(); + _deployImplementations(); + deployImplementationsV2Script = new DeployImplementationsV2Script(); + } + + function testDeployImplementationsV2() public { + // MessageTransmitterV2 + assertEq(messageTransmitterV2Impl.localDomain(), uint256(sourceDomain)); + assertEq(messageTransmitterV2Impl.version(), uint256(_version)); + + // TokenMinterV2 + assertEq(tokenMinterV2.tokenController(), deployer); + + // TokenMessengerV2 + assertEq( + address(tokenMessengerV2Impl.localMessageTransmitter()), + address(expectedMessageTransmitterV2ProxyAddress) + ); + assertEq( + tokenMessengerV2Impl.messageBodyVersion(), + uint256(_messageBodyVersion) + ); + } +} diff --git a/test/scripts/v2/DeployProxiesV2.t.sol b/test/scripts/v2/DeployProxiesV2.t.sol new file mode 100644 index 0000000..8ea2395 --- /dev/null +++ b/test/scripts/v2/DeployProxiesV2.t.sol @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2024, Circle Internet Financial Limited. + * + * 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. + */ +pragma solidity 0.7.6; +pragma abicoder v2; + +import {ScriptV2TestUtils} from "./ScriptV2TestUtils.sol"; +import {AdminUpgradableProxy} from "../../../src/proxy/AdminUpgradableProxy.sol"; +import {DeployImplementationsV2Script} from "../../../scripts/v2/DeployImplementationsV2.s.sol"; +import {DeployProxiesV2Script} from "../../../scripts/v2/DeployProxiesV2.s.sol"; +import {MessageTransmitterV2} from "../../../src/v2/MessageTransmitterV2.sol"; +import {TokenMessengerV2} from "../../../src/v2/TokenMessengerV2.sol"; + +contract DeployProxiesV2Test is ScriptV2TestUtils { + DeployProxiesV2Script deployProxiesV2Script; + + function setUp() public { + _deployCreate2Factory(); + _deployImplementations(); + _deployProxies(); + deployProxiesV2Script = new DeployProxiesV2Script(); + } + + function testDeployMessageTransmitterV2() public { + // create2 address + address predicted = create2Factory.computeAddress( + keccak256(type(MessageTransmitterV2).creationCode), + keccak256( + deployProxiesV2Script.getProxyCreationCode( + address(create2Factory), + address(create2Factory), + "" + ) + ) + ); + assertEq(address(messageTransmitterV2), predicted); + // owner + assertEq(messageTransmitterV2.owner(), deployer); + // domain + assertEq(messageTransmitterV2.localDomain(), uint256(sourceDomain)); + // attester + assertEq(messageTransmitterV2.attesterManager(), deployer); + assertTrue(messageTransmitterV2.isEnabledAttester(attester1)); + assertTrue(messageTransmitterV2.isEnabledAttester(attester2)); + assertEq(messageTransmitterV2.signatureThreshold(), 2); + // maxMessageBodySize + assertEq(messageTransmitterV2.maxMessageBodySize(), maxMessageBodySize); + // version + assertEq(messageTransmitterV2.version(), uint256(1)); + // pauser + assertEq(messageTransmitterV2.pauser(), pauser); + // rescuer + assertEq(messageTransmitterV2.rescuer(), rescuer); + // admin + assertEq( + AdminUpgradableProxy(payable(address(messageTransmitterV2))) + .admin(), + messageTransmitterV2AdminAddress + ); + } + + function testDeployTokenMessengerV2() public { + // create2 address + address predicted = create2Factory.computeAddress( + keccak256(type(TokenMessengerV2).creationCode), + keccak256( + deployProxiesV2Script.getProxyCreationCode( + address(create2Factory), + address(create2Factory), + "" + ) + ) + ); + assertEq(address(tokenMessengerV2), predicted); + // message transmitter + assertEq( + address(tokenMessengerV2.localMessageTransmitter()), + address(messageTransmitterV2) + ); + // message body version + assertEq( + tokenMessengerV2.messageBodyVersion(), + uint256(_messageBodyVersion) + ); + // owner + assertEq(tokenMessengerV2.owner(), deployer); + // rescuer + assertEq(tokenMessengerV2.rescuer(), rescuer); + // fee recipient + assertEq(tokenMessengerV2.feeRecipient(), feeRecipient); + // deny lister + assertEq(tokenMessengerV2.denylister(), denyLister); + // remote token messengers + for (uint256 i = 0; i < remoteDomains.length; i++) { + uint32 remoteDomain = remoteDomains[i]; + assertEq( + tokenMessengerV2.remoteTokenMessengers(remoteDomain), + bytes32(uint256(uint160(address(remoteTokenMessengerV2s[i])))) + ); + } + // admin + assertEq( + AdminUpgradableProxy(payable(address(tokenMessengerV2))).admin(), + tokenMessengerV2AdminAddress + ); + } + + function testConfigureTokenMinterV2() public { + // token controller + assertEq(tokenMinterV2.tokenController(), deployer); + // token messenger + assertEq( + tokenMinterV2.localTokenMessenger(), + address(tokenMessengerV2) + ); + // pauser + assertEq(tokenMinterV2.pauser(), pauser); + // rescuer + assertEq(tokenMinterV2.rescuer(), rescuer); + // max burn per msg + assertEq( + tokenMinterV2.burnLimitsPerMessage(token), + maxBurnAmountPerMessage + ); + // linked token pairs + for (uint256 i = 0; i < remoteDomains.length; i++) { + address remoteToken = remoteTokens[i]; + bytes32 remoteKey = keccak256( + abi.encodePacked( + remoteDomains[i], + bytes32(uint256(uint160(remoteToken))) + ) + ); + assertEq(tokenMinterV2.remoteTokensToLocalTokens(remoteKey), token); + } + } +} diff --git a/test/scripts/4_rotateKeys.t.sol b/test/scripts/v2/RotateKeysV2.t.sol similarity index 62% rename from test/scripts/4_rotateKeys.t.sol rename to test/scripts/v2/RotateKeysV2.t.sol index 64fdc1b..edfe9c6 100644 --- a/test/scripts/4_rotateKeys.t.sol +++ b/test/scripts/v2/RotateKeysV2.t.sol @@ -20,22 +20,23 @@ import {ScriptV2TestUtils} from "./ScriptV2TestUtils.sol"; contract RotateKeysTest is ScriptV2TestUtils { function setUp() public { - _deploy(); - _setupSecondAttester(); + _deployCreate2Factory(); + _deployImplementations(); + _deployProxies(); _setupRemoteResources(); _rotateKeys(); } - function testRotateMessageTransmitterOwner() public { - assertEq(messageTransmitter.pendingOwner(), newOwner); + function testRotateMessageTransmitterV2Owner() public { + assertEq(messageTransmitterV2.pendingOwner(), newOwner); } - function testRotateTokenMessengerOwner() public { - assertEq(tokenMessenger.pendingOwner(), newOwner); + function testRotateTokenMessengerV2Owner() public { + assertEq(tokenMessengerV2.pendingOwner(), newOwner); } - function testRotateTokenControllerThenTokenMinterOwner() public { - assertEq(tokenMinter.tokenController(), newOwner); - assertEq(tokenMinter.pendingOwner(), newOwner); + function testRotateTokenControllerThenTokenMinterV2Owner() public { + assertEq(tokenMinterV2.tokenController(), newOwner); + assertEq(tokenMinterV2.pendingOwner(), newOwner); } } diff --git a/test/scripts/v2/ScriptV2TestUtils.sol b/test/scripts/v2/ScriptV2TestUtils.sol new file mode 100644 index 0000000..fac4ca1 --- /dev/null +++ b/test/scripts/v2/ScriptV2TestUtils.sol @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2024, Circle Internet Financial Limited. + * + * 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. + */ +pragma solidity 0.7.6; +pragma abicoder v2; + +import {DeployImplementationsV2Script} from "../../../scripts/v2/DeployImplementationsV2.s.sol"; +import {DeployProxiesV2Script} from "../../../scripts/v2/DeployProxiesV2.s.sol"; +import {SetupRemoteResourcesV2Script} from "../../../scripts/v2/SetupRemoteResourcesV2.s.sol"; +import {RotateKeysV2Script} from "../../../scripts/v2/RotateKeysV2.s.sol"; +import {MessageTransmitterV2} from "../../../src/v2/MessageTransmitterV2.sol"; +import {TokenMessengerV2} from "../../../src/v2/TokenMessengerV2.sol"; +import {TokenMinterV2} from "../../../src/v2/TokenMinterV2.sol"; +import {MockMintBurnToken} from "../../mocks/MockMintBurnToken.sol"; +import {TestUtils} from "../../TestUtils.sol"; +import {Create2Factory} from "../../../src/v2/Create2Factory.sol"; +import {Message} from "../../../src/messages/Message.sol"; + +contract ScriptV2TestUtils is TestUtils { + uint32 _messageBodyVersion = 1; + uint32 _version = 1; + address token; + uint256 implDeployerPK; + uint256 deployerPK; + address deployer; + address attester1; + address attester2; + address pauser; + address rescuer; + address feeRecipient; + address denyLister; + + Create2Factory create2Factory; + MessageTransmitterV2 messageTransmitterV2; + TokenMessengerV2 tokenMessengerV2; + TokenMinterV2 tokenMinterV2; + + address expectedMessageTransmitterV2ProxyAddress; + MessageTransmitterV2 messageTransmitterV2Impl; + TokenMessengerV2 tokenMessengerV2Impl; + + address[] remoteTokens; + uint32[] remoteDomains; + address[] remoteTokenMessengerV2s; + uint32 anotherRemoteDomain = 5; + address anotherRemoteToken; + + uint256 newOwnerPK; + address newOwner; + address messageTransmitterV2AdminAddress; + address tokenMessengerV2AdminAddress; + + function _deployCreate2Factory() internal { + deployerPK = uint256(keccak256("DEPLOYTEST_DEPLOYER_PK")); + deployer = vm.addr(deployerPK); + vm.startBroadcast(deployerPK); + create2Factory = new Create2Factory(); + vm.stopBroadcast(); + } + + function _deployImplementations() internal { + implDeployerPK = uint256(keccak256("DEPLOYTEST_IMPL_DEPLOYER_PK")); + + vm.setEnv( + "CREATE2_FACTORY_CONTRACT_ADDRESS", + vm.toString(address(create2Factory)) + ); + vm.setEnv("TOKEN_CONTROLLER_ADDRESS", vm.toString(deployer)); + vm.setEnv("DOMAIN", vm.toString(uint256(sourceDomain))); + vm.setEnv( + "MESSAGE_BODY_VERSION", + vm.toString(uint256(_messageBodyVersion)) + ); + vm.setEnv("VERSION", vm.toString(uint256(_version))); + vm.setEnv( + "IMPLEMENTATION_DEPLOYER_PRIVATE_KEY", + vm.toString(implDeployerPK) + ); + + DeployImplementationsV2Script deployImplScript = new DeployImplementationsV2Script(); + deployImplScript.setUp(); + deployImplScript.run(); + + messageTransmitterV2Impl = deployImplScript.messageTransmitterV2(); + tokenMinterV2 = deployImplScript.tokenMinterV2(); + tokenMessengerV2Impl = deployImplScript.tokenMessengerV2(); + expectedMessageTransmitterV2ProxyAddress = deployImplScript + .expectedMessageTransmitterV2ProxyAddress(); + } + + function _deployProxies() internal { + token = address(new MockMintBurnToken()); + remoteTokens.push(address(new MockMintBurnToken())); + remoteTokens.push(address(new MockMintBurnToken())); + remoteTokens.push(address(new MockMintBurnToken())); + remoteDomains.push(1); + remoteDomains.push(2); + remoteDomains.push(3); + remoteTokenMessengerV2s.push( + vm.addr(uint256(keccak256("REMOTE_TOKEN_MESSENGER_V2_ADDRESS_1"))) + ); + remoteTokenMessengerV2s.push( + vm.addr(uint256(keccak256("REMOTE_TOKEN_MESSENGER_V2_ADDRESS_2"))) + ); + remoteTokenMessengerV2s.push( + vm.addr(uint256(keccak256("REMOTE_TOKEN_MESSENGER_V2_ADDRESS_3"))) + ); + anotherRemoteToken = address(new MockMintBurnToken()); + + attester1 = vm.addr(uint256(keccak256("DEPLOYTEST_ATTESTER_1_PK"))); + attester2 = vm.addr(uint256(keccak256("DEPLOYTEST_ATTESTER_2_PK"))); + pauser = vm.addr(uint256(keccak256("DEPLOYTEST_PAUSER_PK"))); + rescuer = vm.addr(uint256(keccak256("DEPLOYTEST_RESCUER_PK"))); + feeRecipient = vm.addr( + uint256(keccak256("DEPLOYTEST_FEE_RECIPIENT_PK")) + ); + denyLister = vm.addr(uint256(keccak256("DEPLOYTEST_DENY_LISTER_PK"))); + + messageTransmitterV2AdminAddress = vm.addr( + uint256(keccak256("MESSAGE_TRANSMITTER_V2_ADMIN")) + ); + tokenMessengerV2AdminAddress = vm.addr( + uint256(keccak256("TOKEN_MESSENGER_V2_ADMIN")) + ); + + // Override env vars + vm.setEnv("USDC_CONTRACT_ADDRESS", vm.toString(token)); + vm.setEnv("TOKEN_CONTROLLER_ADDRESS", vm.toString(deployer)); + vm.setEnv( + "CREATE2_FACTORY_CONTRACT_ADDRESS", + vm.toString(address(create2Factory)) + ); + vm.setEnv( + "REMOTE_DOMAINS", + string( + abi.encodePacked( + vm.toString(uint256(remoteDomains[0])), + ",", + vm.toString(uint256(remoteDomains[1])), + ",", + vm.toString(uint256(remoteDomains[2])) + ) + ) + ); + vm.setEnv( + "REMOTE_USDC_CONTRACT_ADDRESSES", + string( + abi.encodePacked( + vm.toString(Message.addressToBytes32(remoteTokens[0])), + ",", + vm.toString(Message.addressToBytes32(remoteTokens[1])), + ",", + vm.toString(Message.addressToBytes32(remoteTokens[2])) + ) + ) + ); + vm.setEnv( + "REMOTE_TOKEN_MESSENGER_V2_ADDRESSES", + string( + abi.encodePacked( + vm.toString( + Message.addressToBytes32(remoteTokenMessengerV2s[0]) + ), + ",", + vm.toString( + Message.addressToBytes32(remoteTokenMessengerV2s[1]) + ), + ",", + vm.toString( + Message.addressToBytes32(remoteTokenMessengerV2s[2]) + ) + ) + ) + ); + + vm.setEnv( + "MESSAGE_TRANSMITTER_V2_IMPLEMENTATION_ADDRESS", + vm.toString(address(messageTransmitterV2Impl)) + ); + vm.setEnv( + "MESSAGE_TRANSMITTER_V2_OWNER_ADDRESS", + vm.toString(deployer) + ); + vm.setEnv("MESSAGE_TRANSMITTER_V2_PAUSER_ADDRESS", vm.toString(pauser)); + vm.setEnv( + "MESSAGE_TRANSMITTER_V2_RESCUER_ADDRESS", + vm.toString(rescuer) + ); + vm.setEnv( + "MESSAGE_TRANSMITTER_V2_ATTESTER_MANAGER_ADDRESS", + vm.toString(deployer) + ); + vm.setEnv( + "MESSAGE_TRANSMITTER_V2_ATTESTER_1_ADDRESS", + vm.toString(attester1) + ); + vm.setEnv( + "MESSAGE_TRANSMITTER_V2_ATTESTER_2_ADDRESS", + vm.toString(attester2) + ); + vm.setEnv( + "MESSAGE_TRANSMITTER_V2_PROXY_ADMIN_ADDRESS", + vm.toString(messageTransmitterV2AdminAddress) + ); + + vm.setEnv( + "TOKEN_MINTER_V2_CONTRACT_ADDRESS", + vm.toString(address(tokenMinterV2)) + ); + vm.setEnv("TOKEN_MINTER_V2_PAUSER_ADDRESS", vm.toString(pauser)); + vm.setEnv("TOKEN_MINTER_V2_RESCUER_ADDRESS", vm.toString(rescuer)); + + vm.setEnv( + "TOKEN_MESSENGER_V2_IMPLEMENTATION_ADDRESS", + vm.toString(address(tokenMessengerV2Impl)) + ); + vm.setEnv("TOKEN_MESSENGER_V2_OWNER_ADDRESS", vm.toString(deployer)); + vm.setEnv("TOKEN_MESSENGER_V2_RESCUER_ADDRESS", vm.toString(rescuer)); + vm.setEnv( + "TOKEN_MESSENGER_V2_FEE_RECIPIENT_ADDRESS", + vm.toString(feeRecipient) + ); + vm.setEnv( + "TOKEN_MESSENGER_V2_DENYLISTER_ADDRESS", + vm.toString(denyLister) + ); + vm.setEnv( + "TOKEN_MESSENGER_V2_PROXY_ADMIN_ADDRESS", + vm.toString(tokenMessengerV2AdminAddress) + ); + + vm.setEnv("DOMAIN", vm.toString(uint256(sourceDomain))); + vm.setEnv( + "BURN_LIMIT_PER_MESSAGE", + vm.toString(maxBurnAmountPerMessage) + ); + + vm.setEnv("CREATE2_FACTORY_OWNER_KEY", vm.toString(deployerPK)); + vm.setEnv("TOKEN_MINTER_V2_DEPLOYER_KEY", vm.toString(implDeployerPK)); + vm.setEnv("TOKEN_CONTROLLER_KEY", vm.toString(deployerPK)); + + DeployProxiesV2Script deployProxiesV2Script = new DeployProxiesV2Script(); + deployProxiesV2Script.setUp(); + deployProxiesV2Script.run(); + + messageTransmitterV2 = deployProxiesV2Script.messageTransmitterV2(); + tokenMessengerV2 = deployProxiesV2Script.tokenMessengerV2(); + } + + function _setupRemoteResources() internal { + vm.setEnv("TOKEN_MESSENGER_V2_OWNER_KEY", vm.toString(deployerPK)); + + // Use same TOKEN_CONTROLLER_DEPLOYER_KEY as TOKEN_CONTROLLER_KEY + vm.setEnv("TOKEN_CONTROLLER_KEY", vm.toString(deployerPK)); + vm.setEnv( + "TOKEN_MESSENGER_V2_CONTRACT_ADDRESS", + vm.toString(address(tokenMessengerV2)) + ); + vm.setEnv( + "TOKEN_MINTER_V2_CONTRACT_ADDRESS", + vm.toString(address(tokenMinterV2)) + ); + vm.setEnv("USDC_CONTRACT_ADDRESS", vm.toString(token)); + vm.setEnv( + "REMOTE_USDC_CONTRACT_ADDRESS", + vm.toString(anotherRemoteToken) + ); + + vm.setEnv("REMOTE_DOMAIN", vm.toString(uint256(anotherRemoteDomain))); + + SetupRemoteResourcesV2Script setupRemoteResourcesV2Script = new SetupRemoteResourcesV2Script(); + setupRemoteResourcesV2Script.setUp(); + setupRemoteResourcesV2Script.run(); + } + + function _rotateKeys() internal { + vm.setEnv( + "MESSAGE_TRANSMITTER_V2_CONTRACT_ADDRESS", + vm.toString(address(messageTransmitterV2)) + ); + // [SKIP] Use same TOKEN_MESSENGER_CONTRACT_ADDRESS + // [SKIP] Use same TOKEN_MINTER_CONTRACT_ADDRESS + vm.setEnv("MESSAGE_TRANSMITTER_V2_OWNER_KEY", vm.toString(deployerPK)); + vm.setEnv("TOKEN_MESSENGER_V2_OWNER_KEY", vm.toString(deployerPK)); + vm.setEnv("TOKEN_MINTER_V2_OWNER_KEY", vm.toString(implDeployerPK)); + + newOwnerPK = uint256(keccak256("ROTATEKEYSTEST_NEW_OWNER")); + newOwner = vm.addr(newOwnerPK); + + vm.setEnv( + "MESSAGE_TRANSMITTER_V2_NEW_OWNER_ADDRESS", + vm.toString(newOwner) + ); + vm.setEnv( + "TOKEN_MESSENGER_V2_NEW_OWNER_ADDRESS", + vm.toString(newOwner) + ); + vm.setEnv("TOKEN_MINTER_V2_NEW_OWNER_ADDRESS", vm.toString(newOwner)); + vm.setEnv("NEW_TOKEN_CONTROLLER_ADDRESS", vm.toString(newOwner)); + + RotateKeysV2Script rotateKeysV2Script = new RotateKeysV2Script(); + rotateKeysV2Script.setUp(); + rotateKeysV2Script.run(); + } +} diff --git a/test/scripts/3_setupRemoteResources.t.sol b/test/scripts/v2/SetupRemoteResourcesV2.t.sol similarity index 79% rename from test/scripts/3_setupRemoteResources.t.sol rename to test/scripts/v2/SetupRemoteResourcesV2.t.sol index a5bfc3d..b6b7c2c 100644 --- a/test/scripts/3_setupRemoteResources.t.sol +++ b/test/scripts/v2/SetupRemoteResourcesV2.t.sol @@ -20,8 +20,9 @@ import {ScriptV2TestUtils} from "./ScriptV2TestUtils.sol"; contract SetupRemoteResourcesTest is ScriptV2TestUtils { function setUp() public { - _deploy(); - _setupSecondAttester(); + _deployCreate2Factory(); + _deployImplementations(); + _deployProxies(); _setupRemoteResources(); } @@ -32,13 +33,13 @@ contract SetupRemoteResourcesTest is ScriptV2TestUtils { bytes32(uint256(uint160(anotherRemoteToken))) ) ); - assertEq(tokenMinter.remoteTokensToLocalTokens(remoteKey), token); + assertEq(tokenMinterV2.remoteTokensToLocalTokens(remoteKey), token); } function testAddRemoteTokenMessenger() public { assertEq( - tokenMessenger.remoteTokenMessengers(anotherRemoteDomain), - bytes32(uint256(uint160(anotherRemoteTokenMessengerAddress))) + tokenMessengerV2.remoteTokenMessengers(anotherRemoteDomain), + bytes32(uint256(uint160(address(tokenMessengerV2)))) ); } }