Skip to content

Commit

Permalink
STABLE-8092: Update deployment scripts to use CREATE2 for implementat…
Browse files Browse the repository at this point in the history
…ion contracts (#57)
  • Loading branch information
ams9198 authored Jan 17, 2025
1 parent 8a25c1a commit 8cf3673
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 62 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,13 @@ Deploy the implementation contracts.
1. Add the following [env](.env) variables

- `CREATE2_FACTORY_CONTRACT_ADDRESS`
- `CREATE2_FACTORY_OWNER_KEY`
- `TOKEN_MINTER_V2_OWNER_ADDRESS`
- `TOKEN_MINTER_V2_OWNER_KEY`
- `TOKEN_CONTROLLER_ADDRESS`
- `DOMAIN`
- `MESSAGE_BODY_VERSION`
- `VERSION`
- `IMPLEMENTATION_DEPLOYER_PRIVATE_KEY`

2. Run `make simulate-deploy-implementations-v2 RPC_URL=<RPC_URL> SENDER=<SENDER>` to perform a dry run.

Expand Down Expand Up @@ -170,8 +172,8 @@ The proxies are deployed via `CREATE2` through Create2Factory. The scripts assum
- `BURN_LIMIT_PER_MESSAGE`

- `CREATE2_FACTORY_OWNER_KEY`
- `TOKEN_MINTER_V2_DEPLOYER_KEY`
- `TOKEN_CONTROLLER_KEY`
- `TOKEN_MINTER_V2_OWNER_KEY`

2. Run `make simulate-deploy-proxies-v2 RPC_URL=<RPC_URL> SENDER=<SENDER>` to perform a dry run.

Expand Down
3 changes: 2 additions & 1 deletion scripts/v2/DeployAddressUtilsExternal.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ 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";
import {SALT_ADDRESS_UTILS_EXTERNAL} from "./Salts.sol";

contract DeployAddressUtilsExternalScript is Script {
Create2Factory private create2Factory;
Expand All @@ -33,7 +34,7 @@ contract DeployAddressUtilsExternalScript is Script {
_addressUtilsExternal = AddressUtilsExternal(
create2Factory.deploy(
0,
bytes32(0),
SALT_ADDRESS_UTILS_EXTERNAL,
type(AddressUtilsExternal).creationCode
)
);
Expand Down
97 changes: 71 additions & 26 deletions scripts/v2/DeployImplementationsV2.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@
* limitations under the License.
*/
pragma solidity 0.7.6;
pragma abicoder v2;

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";
import {Create2Factory} from "../../src/v2/Create2Factory.sol";
import {Ownable2Step} from "../../src/roles/Ownable2Step.sol";
import {SALT_MESSAGE_TRANSMITTER, SALT_TOKEN_MESSENGER, SALT_TOKEN_MINTER} from "./Salts.sol";

contract DeployImplementationsV2Script is Script {
// Expose for tests
Expand All @@ -31,18 +35,21 @@ contract DeployImplementationsV2Script is Script {
address public expectedMessageTransmitterV2ProxyAddress;

address private factoryAddress;
address private tokenMinterOwnerAddress;
uint256 private tokenMinterOwnerKey;
address private tokenControllerAddress;
uint32 private messageBodyVersion;
uint32 private version;
uint32 private domain;
uint256 private implementationDeployerPrivateKey;
uint256 private create2FactoryOwnerPrivateKey;

function deployImplementationsV2(
uint256 privateKey
) private returns (MessageTransmitterV2, TokenMinterV2, TokenMessengerV2) {
function deployImplementationsV2()
private
returns (MessageTransmitterV2, TokenMinterV2, TokenMessengerV2)
{
// Calculate MessageTransmitterV2 proxy address
expectedMessageTransmitterV2ProxyAddress = vm.computeCreate2Address(
keccak256(type(MessageTransmitterV2).creationCode),
SALT_MESSAGE_TRANSMITTER,
keccak256(
abi.encodePacked(
type(AdminUpgradableProxy).creationCode,
Expand All @@ -52,47 +59,85 @@ contract DeployImplementationsV2Script is Script {
factoryAddress
);

Create2Factory factory = Create2Factory(factoryAddress);

// Start recording transactions
vm.startBroadcast(privateKey);
vm.startBroadcast(create2FactoryOwnerPrivateKey);

// Deploy MessageTransmitterV2 implementation
MessageTransmitterV2 messageTransmitterV2Implementation = new MessageTransmitterV2(
domain,
version
);
messageTransmitterV2 = MessageTransmitterV2(
factory.deploy(
0,
SALT_MESSAGE_TRANSMITTER,
abi.encodePacked(
type(MessageTransmitterV2).creationCode,
abi.encode(domain, version)
)
)
);

// Deploy TokenMinter
TokenMinterV2 tokenMinterV2Implementation = new TokenMinterV2(
tokenControllerAddress
// Deploy TokenMessengerV2 implementation
tokenMessengerV2 = TokenMessengerV2(
factory.deploy(
0,
SALT_TOKEN_MESSENGER,
abi.encodePacked(
type(TokenMessengerV2).creationCode,
abi.encode(
expectedMessageTransmitterV2ProxyAddress,
messageBodyVersion
)
)
)
);

// Deploy TokenMessengerV2
TokenMessengerV2 tokenMessengerV2Implementation = new TokenMessengerV2(
expectedMessageTransmitterV2ProxyAddress,
messageBodyVersion
// Since the TokenMinter sets the msg.sender of the deployment to be
// the Owner, we'll need to rotate it from the Create2Factory atomically.
bytes memory tokenMinterOwnershipRotation = abi.encodeWithSelector(
Ownable2Step.transferOwnership.selector,
tokenMinterOwnerAddress
);
bytes[] memory tokenMinterMultiCallData = new bytes[](1);
tokenMinterMultiCallData[0] = tokenMinterOwnershipRotation;

// Deploy TokenMinter
tokenMinterV2 = TokenMinterV2(
factory.deployAndMultiCall(
0,
SALT_TOKEN_MINTER,
abi.encodePacked(
type(TokenMinterV2).creationCode,
abi.encode(tokenControllerAddress)
),
tokenMinterMultiCallData
)
);

// Stop recording transactions
vm.stopBroadcast();
return (
messageTransmitterV2Implementation,
tokenMinterV2Implementation,
tokenMessengerV2Implementation
);

// Accept the TokenMinter 2-step ownership
vm.startBroadcast(tokenMinterOwnerKey);
tokenMinterV2.acceptOwnership();
vm.stopBroadcast();

return (messageTransmitterV2, tokenMinterV2, tokenMessengerV2);
}

/**
* @notice initialize variables from environment
*/
function setUp() public {
factoryAddress = vm.envAddress("CREATE2_FACTORY_CONTRACT_ADDRESS");
create2FactoryOwnerPrivateKey = vm.envUint("CREATE2_FACTORY_OWNER_KEY");
tokenMinterOwnerAddress = vm.envAddress(
"TOKEN_MINTER_V2_OWNER_ADDRESS"
);
tokenMinterOwnerKey = vm.envUint("TOKEN_MINTER_V2_OWNER_KEY");
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"
);
}

/**
Expand All @@ -103,6 +148,6 @@ contract DeployImplementationsV2Script is Script {
messageTransmitterV2,
tokenMinterV2,
tokenMessengerV2
) = deployImplementationsV2(implementationDeployerPrivateKey);
) = deployImplementationsV2();
}
}
34 changes: 19 additions & 15 deletions scripts/v2/DeployProxiesV2.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {TokenMessengerV2} from "../../src/v2/TokenMessengerV2.sol";
import {TokenMinterV2} from "../../src/v2/TokenMinterV2.sol";
import {MessageTransmitterV2} from "../../src/v2/MessageTransmitterV2.sol";
import {AddressUtils} from "../../src/messages/v2/AddressUtils.sol";
import {SALT_TOKEN_MESSENGER, SALT_MESSAGE_TRANSMITTER} from "./Salts.sol";

contract DeployProxiesV2Script is Script {
// Expose for tests
Expand Down Expand Up @@ -64,7 +65,7 @@ contract DeployProxiesV2Script is Script {
uint256 private burnLimitPerMessage;

uint256 private create2FactoryOwnerPrivateKey;
uint256 private tokenMinterV2DeployerPrivateKey;
uint256 private tokenMinterV2OwnerPrivateKey;
uint256 private tokenControllerPrivateKey;

function getProxyCreationCode(
Expand Down Expand Up @@ -129,7 +130,7 @@ contract DeployProxiesV2Script is Script {
address messageTransmitterV2ProxyAddress = Create2Factory(factory)
.deployAndMultiCall(
0,
keccak256(type(MessageTransmitterV2).creationCode), // TODO: Verify salt
SALT_MESSAGE_TRANSMITTER,
proxyCreateCode,
multiCallData
);
Expand All @@ -153,14 +154,13 @@ contract DeployProxiesV2Script is Script {

// Calculate TokenMessengerV2 proxy address
address expectedTokenMessengerV2ProxyAddress = vm.computeCreate2Address(
keccak256(type(TokenMessengerV2).creationCode),
keccak256(
proxyCreateCode
),
SALT_TOKEN_MESSENGER,
keccak256(proxyCreateCode),
factory
);

bool remoteTokenMessengerV2FromEnv = remoteTokenMessengerV2Addresses.length > 0;
bool remoteTokenMessengerV2FromEnv = remoteTokenMessengerV2Addresses
.length > 0;

// Construct initializer
bytes32[] memory remoteTokenMessengerAddresses = new bytes32[](
Expand All @@ -169,9 +169,13 @@ contract DeployProxiesV2Script is Script {
uint256 remoteDomainsLength = remoteDomains.length;
for (uint256 i = 0; i < remoteDomainsLength; ++i) {
if (remoteTokenMessengerV2FromEnv) {
remoteTokenMessengerAddresses[i] = remoteTokenMessengerV2Addresses[i];
remoteTokenMessengerAddresses[
i
] = remoteTokenMessengerV2Addresses[i];
} else {
remoteTokenMessengerAddresses[i] = AddressUtils.toBytes32(expectedTokenMessengerV2ProxyAddress);
remoteTokenMessengerAddresses[i] = AddressUtils.toBytes32(
expectedTokenMessengerV2ProxyAddress
);
}
}
bytes memory initializer = abi.encodeWithSelector(
Expand Down Expand Up @@ -209,7 +213,7 @@ contract DeployProxiesV2Script is Script {
address tokenMessengerV2ProxyAddress = Create2Factory(factory)
.deployAndMultiCall(
0,
keccak256(type(TokenMessengerV2).creationCode), // TODO: Verify salt
SALT_TOKEN_MESSENGER,
proxyCreateCode,
multiCallData
);
Expand Down Expand Up @@ -341,12 +345,12 @@ contract DeployProxiesV2Script is Script {
burnLimitPerMessage = vm.envUint("BURN_LIMIT_PER_MESSAGE");

create2FactoryOwnerPrivateKey = vm.envUint("CREATE2_FACTORY_OWNER_KEY");
tokenMinterV2DeployerPrivateKey = vm.envUint(
"TOKEN_MINTER_V2_DEPLOYER_KEY"
);
tokenMinterV2OwnerPrivateKey = vm.envUint("TOKEN_MINTER_V2_OWNER_KEY");
tokenControllerPrivateKey = vm.envUint("TOKEN_CONTROLLER_KEY");

bytes32[] memory emptyRemoteTokenMessengerV2Addresses = new bytes32[](0);
bytes32[] memory emptyRemoteTokenMessengerV2Addresses = new bytes32[](
0
);
remoteTokenMessengerV2Addresses = vm.envOr(
"REMOTE_TOKEN_MESSENGER_V2_ADDRESSES",
",",
Expand All @@ -370,7 +374,7 @@ contract DeployProxiesV2Script is Script {
);

addMessengerPauserRescuerToTokenMinterV2(
tokenMinterV2DeployerPrivateKey,
tokenMinterV2OwnerPrivateKey,
tokenControllerPrivateKey,
tokenMinterV2,
address(tokenMessengerV2)
Expand Down
29 changes: 29 additions & 0 deletions scripts/v2/Salts.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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;

// Salts used for CREATE2 deployments

bytes32 constant SALT_TOKEN_MINTER = keccak256("cctp.v2.tokenminter");
bytes32 constant SALT_TOKEN_MESSENGER = keccak256("cctp.v2.tokenmessenger");
bytes32 constant SALT_MESSAGE_TRANSMITTER = keccak256(
"cctp.v2.messagetransmitter"
);
bytes32 constant SALT_ADDRESS_UTILS_EXTERNAL = keccak256(
"cctp.v2.addressutilsexternal"
);
1 change: 1 addition & 0 deletions test/scripts/v2/DeployImplementationsV2.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ contract DeployImplementationsV2Test is ScriptV2TestUtils {

// TokenMinterV2
assertEq(tokenMinterV2.tokenController(), deployer);
assertEq(tokenMinterV2.owner(), deployer);

// TokenMessengerV2
assertEq(
Expand Down
13 changes: 9 additions & 4 deletions test/scripts/v2/DeployProxiesV2.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {DeployImplementationsV2Script} from "../../../scripts/v2/DeployImplement
import {DeployProxiesV2Script} from "../../../scripts/v2/DeployProxiesV2.s.sol";
import {MessageTransmitterV2} from "../../../src/v2/MessageTransmitterV2.sol";
import {TokenMessengerV2} from "../../../src/v2/TokenMessengerV2.sol";
import {SALT_MESSAGE_TRANSMITTER, SALT_TOKEN_MESSENGER} from "../../../scripts/v2/Salts.sol";

contract DeployProxiesV2Test is ScriptV2TestUtils {
DeployProxiesV2Script deployProxiesV2Script;
Expand All @@ -36,7 +37,7 @@ contract DeployProxiesV2Test is ScriptV2TestUtils {
function testDeployMessageTransmitterV2() public {
// create2 address
address predicted = create2Factory.computeAddress(
keccak256(type(MessageTransmitterV2).creationCode),
SALT_MESSAGE_TRANSMITTER,
keccak256(
deployProxiesV2Script.getProxyCreationCode(
address(create2Factory),
Expand Down Expand Up @@ -74,7 +75,7 @@ contract DeployProxiesV2Test is ScriptV2TestUtils {
function testDeployTokenMessengerV2() public {
// create2 address
address predicted = create2Factory.computeAddress(
keccak256(type(TokenMessengerV2).creationCode),
SALT_TOKEN_MESSENGER,
keccak256(
deployProxiesV2Script.getProxyCreationCode(
address(create2Factory),
Expand Down Expand Up @@ -105,9 +106,13 @@ contract DeployProxiesV2Test is ScriptV2TestUtils {
// remote token messengers
for (uint256 i = 0; i < remoteDomains.length; i++) {
uint32 remoteDomain = remoteDomains[i];
bytes32 remoteTokenMessengerAddress = bytes32(uint256(uint160(address(tokenMessengerV2))));
bytes32 remoteTokenMessengerAddress = bytes32(
uint256(uint160(address(tokenMessengerV2)))
);
if (remoteTokenMessengerV2FromEnv) {
remoteTokenMessengerAddress = bytes32(uint256(uint160(address(remoteTokenMessengerV2s[i]))));
remoteTokenMessengerAddress = bytes32(
uint256(uint160(address(remoteTokenMessengerV2s[i])))
);
}
assertEq(
tokenMessengerV2.remoteTokenMessengers(remoteDomain),
Expand Down
Loading

0 comments on commit 8cf3673

Please sign in to comment.