Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ polygon_pos = "https://polygon-mainnet.infura.io/v3/${INFURA_TOKEN}"
polygon_zkevm = "https://zkevm-rpc.com"
polygon_zkevm_testnet = "https://rpc.public.zkevm-test.net"
tatara = "https://rpc.tatara.katanarpc.com/${TATARA_TOKEN}"
katana = "https://rpc.katanarpc.com/${KATANA_TOKEN}"

[etherscan]
mainnet = { key = "${API_KEY}" }
Expand Down
101 changes: 101 additions & 0 deletions script/DeployLayerY.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// SPDX-License-Identifier: LicenseRef-PolygonLabs-Open-Attribution OR LicenseRef-PolygonLabs-Source-Available
pragma solidity ^0.8.29;

import "forge-std/Script.sol";
import "../src/custom-tokens/GenericCustomToken.sol";
import "../src/custom-tokens/GenericNativeConverter.sol";
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {ERC1967Proxy, ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

contract DeployLayerY is Script {
using stdJson for string;

uint256 deployerPrivateKey = uint256(uint160(address(this))); // default placeholder for tests

function run() public {
deployerPrivateKey = vm.promptSecretUint("PRIVATE_KEY");

deployLayerY();
}

function deployLayerY() public {
vm.startBroadcast(deployerPrivateKey);

string memory input = vm.readFile("script/input.json");

string memory slug = string(abi.encodePacked('["', vm.toString(block.chainid), '"]'));

address polygonEngineeringMultisig = input.readAddress(string.concat(slug, ".polygonEngineeringMultisig"));
address migrationManagerAddress = input.readAddress(string.concat(slug, ".migrationManager"));
address lxlyBridge = input.readAddress(string.concat(slug, ".lxlyBridge"));

GenericNativeConverter[] memory nativeConverters = new GenericNativeConverter[](5);

string[] memory vbTokens = new string[](4);
vbTokens[0] = "vbUSDC";
vbTokens[1] = "vbUSDT";
vbTokens[2] = "vbWBTC";
vbTokens[3] = "vbUSDS";

// deploy token impl
GenericCustomToken customTokenImpl = new GenericCustomToken();
GenericNativeConverter nativeConverterImpl = new GenericNativeConverter();

for (uint256 i = 0; i < vbTokens.length; i++) {
string memory vbSlug =
string(abi.encodePacked('["', vm.toString(block.chainid), '"]', '.["', vbTokens[i], '"]'));

address customToken = input.readAddress(string.concat(vbSlug, ".customToken"));
address underlyingToken = input.readAddress(string.concat(vbSlug, ".underlyingToken"));
string memory name = input.readString(string.concat(vbSlug, ".name"));
string memory symbol = input.readString(string.concat(vbSlug, ".symbol"));
uint8 decimals = uint8(input.readUint(string.concat(vbSlug, ".decimals")));
uint256 nonMigratableBackingPercentage =
input.readUint(string.concat(vbSlug, ".nonMigratableBackingPercentage"));

bytes memory initNativeConverter = abi.encodeCall(
GenericNativeConverter.initialize,
(
polygonEngineeringMultisig,
decimals,
customToken,
underlyingToken,
lxlyBridge,
0,
nonMigratableBackingPercentage,
migrationManagerAddress
)
);
address nativeConverter =
_proxify(address(nativeConverterImpl), polygonEngineeringMultisig, initNativeConverter);

nativeConverters[i] = GenericNativeConverter(nativeConverter);

console.log("Native converter ", vbTokens[i], " deployed at: ", nativeConverter);

// update custom token
bytes memory data = abi.encodeCall(
GenericCustomToken.reinitialize,
(polygonEngineeringMultisig, name, symbol, decimals, lxlyBridge, nativeConverter)
);

IERC1967Proxy customTokenProxy = IERC1967Proxy(payable(customToken));
bytes memory payload = abi.encodeCall(customTokenProxy.upgradeToAndCall, (address(customTokenImpl), data));

console.log("Payload for upgrading custom token", vbTokens[i]);
console.logBytes(payload);
}

console.log("Use this multisig: ", polygonEngineeringMultisig);

vm.stopBroadcast();
}

function _proxify(address logic, address admin, bytes memory initData) internal returns (address payable proxy) {
proxy = payable(new TransparentUpgradeableProxy(logic, admin, initData));
}
}

interface IERC1967Proxy {
function upgradeToAndCall(address newImplementation, bytes calldata data) external;
}
88 changes: 88 additions & 0 deletions script/DeployLayerY_WETH.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// SPDX-License-Identifier: LicenseRef-PolygonLabs-Open-Attribution OR LicenseRef-PolygonLabs-Source-Available
pragma solidity ^0.8.29;

import "forge-std/Script.sol";
import "../src/custom-tokens/WETH/WETH.sol";
import "../src/custom-tokens/WETH/WETHNativeConverter.sol";
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {ERC1967Proxy, ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

contract DeployLayerY_WETH is Script {
using stdJson for string;

uint256 deployerPrivateKey = uint256(uint160(address(this))); // default placeholder for tests

function run() public {
deployerPrivateKey = vm.promptSecretUint("PRIVATE_KEY");

deployLayerY_WETH();
}

function deployLayerY_WETH() public {
vm.startBroadcast(deployerPrivateKey);

string memory input = vm.readFile("script/input.json");

string memory slug = string(abi.encodePacked('["', vm.toString(block.chainid), '"]'));

address polygonEngineeringMultisig = input.readAddress(string.concat(slug, ".polygonEngineeringMultisig"));
address migrationManagerAddress = input.readAddress(string.concat(slug, ".migrationManager"));
address lxlyBridge = input.readAddress(string.concat(slug, ".lxlyBridge"));

string memory vbETHSlug = string(abi.encodePacked('["', vm.toString(block.chainid), '"]', '.["vbETH"]'));

address vbWETH = input.readAddress(string.concat(vbETHSlug, ".customToken"));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommended to Use CustomToken and underlying token. Using vbETH for W-vbETH and WETH for W-WETH is misleading.

address wETH = input.readAddress(string.concat(vbETHSlug, ".underlyingToken"));
string memory name = input.readString(string.concat(vbETHSlug, ".name"));
string memory symbol = input.readString(string.concat(vbETHSlug, ".symbol"));
uint8 decimals = uint8(input.readUint(string.concat(vbETHSlug, ".decimals")));
uint256 nonMigratableGasBackingPercentage =
input.readUint(string.concat(vbETHSlug, ".nonMigratableGasBackingPercentage"));

WETHNativeConverter nativeConverterImpl = new WETHNativeConverter();

bytes memory initNativeConverter = abi.encodeCall(
WETHNativeConverter.initialize,
(
polygonEngineeringMultisig,
decimals,
vbWETH,
wETH,
lxlyBridge,
0,
0,
migrationManagerAddress,
nonMigratableGasBackingPercentage
)
);
address wethNativeConverter =
_proxify(address(nativeConverterImpl), polygonEngineeringMultisig, initNativeConverter);

// deploy vbWETH impl
WETH wethImpl = new WETH();

// update vbWETH
bytes memory data = abi.encodeCall(
WETH.reinitialize, (polygonEngineeringMultisig, name, symbol, decimals, lxlyBridge, wethNativeConverter)
);

IERC1967Proxy vbWethProxy = IERC1967Proxy(payable(vbWETH));
bytes memory payload = abi.encodeCall(vbWethProxy.upgradeToAndCall, (address(wethImpl), data));

console.log("Payload for upgrading vbWETH", "use this multisig: ", polygonEngineeringMultisig);
console.logBytes(payload);

/* bytes32 implementation = vm.load(vbWETH, 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc);
vm.assertEq(implementation, bytes32(uint256(uint160(address(wethImpl))))); */

vm.stopBroadcast();
}

function _proxify(address logic, address admin, bytes memory initData) internal returns (address payable proxy) {
proxy = payable(new TransparentUpgradeableProxy(logic, admin, initData));
}
}

interface IERC1967Proxy {
function upgradeToAndCall(address newImplementation, bytes calldata data) external;
}
33 changes: 33 additions & 0 deletions script/DepositAndBridge.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: LicenseRef-PolygonLabs-Open-Attribution OR LicenseRef-PolygonLabs-Source-Available
pragma solidity ^0.8.29;

import "forge-std/Script.sol";
import "../src/vault-bridge-tokens/vbETH/VbETH.sol";

/// @dev this can be used to send some initial ETH to LayerY. Needs to be replicated for other tokens as well,
/// @dev but can also be done manually. Ly token addresses are necessary for the rest of the deployment process.
contract DepositAndBridge is Script {
using stdJson for string;

uint256 deployerPrivateKey = uint256(uint160(address(this))); // default placeholder for tests

uint256 depositAmount = 0.001 ether;
uint32 NETWORK_ID_L2 = 20;
address receiver = 0x32bdc6A4e8C654dF65503CBb0eDc82B4Ce9158e6;

function run() public {
deployerPrivateKey = vm.promptSecretUint("PRIVATE_KEY");

vm.startBroadcast(deployerPrivateKey);

console.log(receiver);

VbETH vbETH = VbETH(payable(0x2DC70fb75b88d2eB4715bc06E1595E6D97c34DFF));

uint256 shares = vbETH.depositGasTokenAndBridge{value: depositAmount}(receiver, NETWORK_ID_L2, true);

console.log(shares);

vm.stopBroadcast();
}
}
73 changes: 73 additions & 0 deletions script/RegisterNativeConverters.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// SPDX-License-Identifier: LicenseRef-PolygonLabs-Open-Attribution OR LicenseRef-PolygonLabs-Source-Available
pragma solidity ^0.8.29;

import "forge-std/Script.sol";
import "../src/MigrationManager.sol";

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract RegisterNativeConverters is Script {
using stdJson for string;

uint32 NETWORK_ID_Y = 20;

address polygonSecurityMultisig = 0x9d851f8b8751c5FbC09b9E74E6e68E9950949052;

function run() public {
string memory input = vm.readFile("script/input.json");

string memory migrationManagerSlug =
string(abi.encodePacked('["', vm.toString(block.chainid), '"]', '.["migrationManager"]'));

// Read from input.json based on current chain ID
address migrationManagerAddress = input.readAddress(string.concat(migrationManagerSlug, ".address"));

MigrationManager migrationManager = MigrationManager(payable(migrationManagerAddress));

string[] memory vbTokens = new string[](5);
vbTokens[0] = "vbUSDS";
vbTokens[1] = "vbUSDT";
vbTokens[2] = "vbUSDC";
vbTokens[3] = "vbWBTC";
vbTokens[4] = "vbETH";

vm.startBroadcast(polygonSecurityMultisig);

// register NativeConverters

for (uint256 i = 0; i < vbTokens.length; i++) {
address nativeConverter =
input.readAddress(string.concat(migrationManagerSlug, ".", vbTokens[i], "NativeConverter"));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Beware that all input.json "vbTokens[i].NativeConverters" are still fake (all of them are using address 0x000059dE96F9C28e3a343b831cbDC2B93c8C4855) , so we MUST update them once we have each of the NativeConverters deployed. Count with us to review before executing.

address vbToken = input.readAddress(string.concat(migrationManagerSlug, ".", vbTokens[i]));

uint32[] memory layerYLxlyIds = new uint32[](1);
layerYLxlyIds[0] = NETWORK_ID_Y;
address[] memory nativeConverters = new address[](1);
nativeConverters[0] = nativeConverter;

// migrationManager.configureNativeConverters(layerYLxlyIds, nativeConverters, payable(address(vbToken)));
bytes memory payload = abi.encodeCall(
migrationManager.configureNativeConverters, (layerYLxlyIds, nativeConverters, payable(address(vbToken)))
);

console.log("Payload to be sent from", polygonSecurityMultisig);
console.logBytes(payload);

/* MigrationManager.TokenPair memory tokenPair =
migrationManager.nativeConvertersConfiguration(NETWORK_ID_Y, nativeConverter);
string memory vbTokenSlug =
string(abi.encodePacked('["', vm.toString(block.chainid), '"]', '.["', vbTokens[i], '"]'));
address underlyingToken = input.readAddress(string.concat(vbTokenSlug, ".underlyingToken"));
vm.assertEq(address(tokenPair.vbToken), address(vbToken));
vm.assertEq(address(tokenPair.underlyingToken), address(underlyingToken));
vm.assertEq(
IERC20(underlyingToken).allowance(address(migrationManager), address(vbToken)), type(uint256).max
); */
}

vm.stopBroadcast();
}
}
63 changes: 61 additions & 2 deletions script/input.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,19 @@
"migrationManager": {
"proxyAdmin": "0x9d851f8b8751c5FbC09b9E74E6e68E9950949052",
"ownerMigrationManager": "0x9d851f8b8751c5FbC09b9E74E6e68E9950949052",
"lxlyBridge": "0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe"
"lxlyBridge": "0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe",
"address": "0x417d01B64Ea30C4E163873f3a1f77b727c689e02",
"layerYNetworkId": 20,
"vbUSDSNativeConverter": "0x000059dE96F9C28e3a343b831cbDC2B93c8C4855",
"vbUSDTNativeConverter": "0x000059dE96F9C28e3a343b831cbDC2B93c8C4855",
"vbUSDCNativeConverter": "0x000059dE96F9C28e3a343b831cbDC2B93c8C4855",
"vbWBTCNativeConverter": "0x000059dE96F9C28e3a343b831cbDC2B93c8C4855",
"vbETHNativeConverter": "0x000059dE96F9C28e3a343b831cbDC2B93c8C4855",
Comment on lines +9 to +13

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update them before executing the RegisterNativeConverters.s.sol script

"vbUSDS": "0x3DD459dE96F9C28e3a343b831cbDC2B93c8C4855",
"vbUSDT": "0x6d4f9f9f8f0155509ecd6Ac6c544fF27999845CC",
"vbUSDC": "0x53E82ABbb12638F09d9e624578ccB666217a765e",
"vbWBTC": "0x2C24B57e2CCd1f273045Af6A5f632504C432374F",
"vbETH": "0x2DC70fb75b88d2eB4715bc06E1595E6D97c34DFF"
},
"vbUSDS": {
"proxyAdmin": "0xA8C31B2edd84c654d06d626383f4154D1E40C5Ff",
Expand Down Expand Up @@ -77,7 +89,54 @@
}
},
"747474": {

"vbUSDS": {
"customToken": "0x62D6A123E8D19d06d68cf0d2294F9A3A0362c6b3",
"underlyingToken": "0x2134866886ce784fE2E0DE819118E4D32b4Be32C",
"owner": "0x2De242e27386e224E5fbF110EA8406d5B70740ec",
"name": "Vault Bridge USDS",
"symbol": "vbUSDS",
"decimals": 18,
"nonMigratableBackingPercentage": 0.01e18
},
"vbUSDT": {
"customToken": "0x2DCa96907fde857dd3D816880A0df407eeB2D2F2",
"underlyingToken": "0xf44e3BCB7A2461CC08185E127B324f2486a74E20",
"owner": "0x2De242e27386e224E5fbF110EA8406d5B70740ec",
"name": "Vault Bridge USDT",
"symbol": "vbUSDT",
"decimals": 6,
"nonMigratableBackingPercentage": 0.02e18
},
"vbUSDC": {
"customToken": "0x203A662b0BD271A6ed5a60EdFbd04bFce608FD36",
"underlyingToken": "0xfd415D011FfaA8e6f17fa753CdB080d1dE266784",
"owner": "0x2De242e27386e224E5fbF110EA8406d5B70740ec",
"name": "Vault Bridge USDC",
"symbol": "vbUSDC",
"decimals": 6,
"nonMigratableBackingPercentage": 0.02e18
},
"vbWBTC": {
"customToken": "0x0913DA6Da4b42f538B445599b46Bb4622342Cf52",
"underlyingToken": "0xB33e43A3F276e8e75792b941bccC996EcB2c0bBD",
"owner": "0x2De242e27386e224E5fbF110EA8406d5B70740ec",
"name": "Vault Bridge WBTC",
"symbol": "vbWBTC",
"decimals": 8,
"nonMigratableBackingPercentage": 0.01e18
},
"vbETH": {
"customToken": "0xEE7D8BCFb72bC1880D0Cf19822eB0A2e6577aB62",
"underlyingToken": "0x815955d051C6262C16c720b19D735426254Bec5B",
"owner": "0x2De242e27386e224E5fbF110EA8406d5B70740ec",
"name": "Vault Bridge Wrapped Ether",
"symbol": "WETH",
"decimals": 18,
"nonMigratableGasBackingPercentage": 0.01e18
},
"migrationManager": "0x417d01B64Ea30C4E163873f3a1f77b727c689e02",
"polygonEngineeringMultisig": "0x4e981bAe8E3cd06Ca911ffFE5504B2653ac1C38a",
"lxlyBridge": "0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe"
},
"31337": {
"proxyAdmin": "0x0000c6A4e8C654dF65503CBb0eDc82B4Ce9158e6",
Expand Down
4 changes: 4 additions & 0 deletions src/CustomToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ abstract contract CustomToken is
onlyLxlyBridgeAndNativeConverter
nonReentrant
{
// When we migrate backing to Lx, we end up sending tokens to address(0) here.
// These need to be claimable so the bridge accounting is correct and we allow it here by not reverting.
if (account == address(0)) return;

_mint(account, value);
}

Expand Down