Skip to content

Commit

Permalink
Merge pull request #4 from yieldnest/scripts
Browse files Browse the repository at this point in the history
Deployment Scripts
  • Loading branch information
dan13ram authored Sep 6, 2024
2 parents 69d2fbe + 4f34e01 commit de64bce
Show file tree
Hide file tree
Showing 24 changed files with 558 additions and 404 deletions.
3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

22 changes: 20 additions & 2 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,29 @@ libs = ["lib"]
test = 'test'
cache_path = 'cache'
fs_permissions = [
{ access = "read-write", path = "./deployments" },
{ access = "read", path = "./" },
{ access = "read-write", path = "./deployments" },
{ access = "read", path = "./" },
]
optimizer = true
optimizer-runs = 200
evm_version = "cancun"
solc_version = "0.8.24"
prompt_timeout = 120

[rpc_endpoints]
mainnet = "${MAINNET_RPC_URL}"
arbitrum = "${ARBITRUM_RPC_URL}"
optimism = "${OPTIMISM_RPC_URL}"
base = "${BASE_RPC_URL}"
fraxtal = "${FRAXTAL_RPC_URL}"
holesky = "${HOLESKY_RPC_URL}"
fraxtal_testnet = "${FRAXTAL_TESTNET_RPC_URL}"

[etherscan]
mainnet = { key = "${ETHERSCAN_API_KEY}" }
arbitrum = { key = "${ARBISCAN_API_KEY}" }
optimism = { key = "${OPTIMISTIC_ETHERSCAN_API_KEY}" }
base = { key = "${BASESCAN_API_KEY}", url = "https://api.basescan.org/api/" }
holesky = { key = "${ETHERSCAN_API_KEY}" }
fraxtal = { key = "${FRAXSCAN_API_KEY}", url = "https://api.fraxscan.io/api/" }
fraxtal_testnet = { key = "${FRAXSCAN_API_KEY}", url = "https://api-holesky.fraxscan.io/api/" }
1 change: 0 additions & 1 deletion lib/solmate
Submodule solmate deleted from 97bdb2
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"dependencies": {
"@layerzerolabs/lz-evm-v1-0.7": "^2.3.40",
"hardhat-deploy": "^0.12.4",
"lint-staged": "^15.2.10"
"lint-staged": "^15.2.10",
"solmate": "^6.2.0"
}
}
4 changes: 2 additions & 2 deletions remappings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ forge-std/=node_modules/forge-std/src/
@layerzerolabs/lz-evm-v1-0.7/=node_modules/@layerzerolabs/lz-evm-v1-0.7/
@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/
@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/
@solmate/=lib/solmate/src/
@adapters/=src/
@solmate/=node_modules/solmate/src/
@/=src/
@factory/=src/factory/
@interfaces/=src/interfaces/
solidity-bytes-utils/=node_modules/solidity-bytes-utils/
Expand Down
85 changes: 85 additions & 0 deletions script/BaseData.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {Script} from "forge-std/Script.sol";

contract BaseData is Script {
struct Actors {
address OFT_DELEGATE;
address TOKEN_ADMIN;
address PROXY_ADMIN;
}

struct ChainAddresses {
address lzEndpoint;
}

struct ChainIds {
uint256 mainnet;
uint256 base;
uint256 optimism;
uint256 arbitrum;
uint256 fraxtal;
uint256 holesky;
uint256 fraxtalTestnet;
}

mapping(uint256 => Actors) public actors;
mapping(uint256 => ChainAddresses) public addresses;

ChainIds public chainIds = ChainIds({
mainnet: 1,
base: 8453,
optimism: 10,
arbitrum: 42161,
fraxtal: 252,
holesky: 17000,
fraxtalTestnet: 2522
});

function setUp() public virtual {
addresses[chainIds.mainnet] = ChainAddresses({lzEndpoint: 0x1a44076050125825900e736c501f859c50fE728c});
actors[chainIds.mainnet] = Actors({
OFT_DELEGATE: 0xfcad670592a3b24869C0b51a6c6FDED4F95D6975, // yn security council
TOKEN_ADMIN: 0xfcad670592a3b24869C0b51a6c6FDED4F95D6975,
PROXY_ADMIN: 0xfcad670592a3b24869C0b51a6c6FDED4F95D6975
});

addresses[chainIds.fraxtal] = ChainAddresses({lzEndpoint: 0x1a44076050125825900e736c501f859c50fE728c});
actors[chainIds.fraxtal] = Actors({OFT_DELEGATE: address(0), TOKEN_ADMIN: address(0), PROXY_ADMIN: address(0)});

addresses[chainIds.optimism] = ChainAddresses({lzEndpoint: 0x1a44076050125825900e736c501f859c50fE728c});
actors[chainIds.optimism] = Actors({OFT_DELEGATE: address(0), TOKEN_ADMIN: address(0), PROXY_ADMIN: address(0)});

addresses[chainIds.arbitrum] = ChainAddresses({lzEndpoint: 0x1a44076050125825900e736c501f859c50fE728c});
actors[chainIds.arbitrum] = Actors({OFT_DELEGATE: address(0), TOKEN_ADMIN: address(0), PROXY_ADMIN: address(0)});

addresses[chainIds.base] = ChainAddresses({lzEndpoint: 0x1a44076050125825900e736c501f859c50fE728c});
actors[chainIds.base] = Actors({OFT_DELEGATE: address(0), TOKEN_ADMIN: address(0), PROXY_ADMIN: address(0)});

addresses[chainIds.holesky] = ChainAddresses({lzEndpoint: 0x6EDCE65403992e310A62460808c4b910D972f10f});
actors[chainIds.holesky] = Actors({
OFT_DELEGATE: 0x743b91CDB1C694D4F51bCDA3a4A59DcC0d02b913, // yn security council
TOKEN_ADMIN: 0x743b91CDB1C694D4F51bCDA3a4A59DcC0d02b913,
PROXY_ADMIN: 0x743b91CDB1C694D4F51bCDA3a4A59DcC0d02b913
});

addresses[chainIds.fraxtalTestnet] = ChainAddresses({lzEndpoint: 0x6EDCE65403992e310A62460808c4b910D972f10f});
actors[chainIds.fraxtalTestnet] =
Actors({OFT_DELEGATE: address(0), TOKEN_ADMIN: address(0), PROXY_ADMIN: address(0)});
}

function getActors(uint256 chainId) public view returns (Actors memory) {
return actors[chainId];
}

function getChainAddresses(uint256 chainId) public view returns (ChainAddresses memory) {
return addresses[chainId];
}

function isSupportedChainId(uint256 chainId) public view returns (bool) {
return chainId == chainIds.mainnet || chainId == chainIds.base || chainId == chainIds.fraxtal
|| chainId == chainIds.optimism || chainId == chainIds.arbitrum || chainId == chainIds.holesky
|| chainId == chainIds.fraxtalTestnet;
}
}
127 changes: 127 additions & 0 deletions script/BaseScript.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {BaseData} from "./BaseData.sol";
import {ImmutableMultiChainDeployer} from "@factory/ImmutableMultiChainDeployer.sol";
import {RateLimiter} from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/utils/RateLimiter.sol";
import {EndpointV2} from "@layerzerolabs/lz-evm-protocol-v2/contracts/EndpointV2.sol";
import "forge-std/console.sol";

struct L2YnOFTAdapterInput {
address adapterImplementation;
uint256 chainId;
address erc20Address;
RateLimitConfig[] rateLimitConfigs;
}

struct L1YnOFTAdapterInput {
uint256 chainId;
address erc20Address;
RateLimitConfig[] rateLimitConfigs;
}

struct RateLimitConfig {
uint256 limit;
uint256 window;
}

struct YnERC20Input {
uint256 chainId;
address erc20Address;
string name;
string symbol;
}
//forge script script/DeployMainnetImplementations.s.sol:DeployMainnetImplementations --rpc-url ${rpc} --account ${deployerAccountName} --sender ${deployer} --broadcast --etherscan-api-key ${api} --verify

contract BaseScript is BaseData {
// TODO: parse token address from json or as input from user
// TODO: setup forks based on if testnet or mainnet deployment as per json
// TODO: setup saving of deployment data in deployments json file
uint256 _chainId;
bytes public data;
L2YnOFTAdapterInput public _ynOFTAdapterInputs;
L1YnOFTAdapterInput public _ynOFTImplementationInputs;
YnERC20Input public _ynERC20Inputs;
RateLimiter.RateLimitConfig[] public _rateLimitConfigs;

function _loadERC20Data(string memory _inputPath) internal {
_loadJson(_inputPath);
_loadYnERC20Inputs();
_verifyChain();
}

function _loadOFTAdapterData(string memory _inputPath) internal {
_loadJson(_inputPath);
_loadYnOFTAdapterInputs();
_verifyChain();
_getRateLimiterConfigs();
}

function _loadOFTImplementationData(string memory _inputPath) internal {
_loadJson(_inputPath);
_loadYnOFTImplementationInputs();
_verifyChain();
_getRateLimiterConfigs();
}

function _loadYnOFTImplementationInputs() internal {
L1YnOFTAdapterInput memory implementationInputs = abi.decode(data, (L1YnOFTAdapterInput));
this.loadImplementationInputs(implementationInputs);
_chainId = _ynOFTImplementationInputs.chainId;
}

function _loadJson(string memory _path) internal {
string memory path = string(abi.encodePacked(vm.projectRoot(), "/", _path));
string memory json = vm.readFile(path);
data = vm.parseJson(json);
}

function _loadYnOFTAdapterInputs() internal {
L2YnOFTAdapterInput memory ynOFTAdapterInputs = abi.decode(data, (L2YnOFTAdapterInput));
this.loadAdapterInputs(ynOFTAdapterInputs);
_chainId = _ynOFTAdapterInputs.chainId;
}

function loadAdapterInputs(L2YnOFTAdapterInput calldata _ynInput) external {
_ynOFTAdapterInputs = _ynInput;
}

function loadImplementationInputs(L1YnOFTAdapterInput calldata _ynImpInput) external {
_ynOFTImplementationInputs = _ynImpInput;
}

function _loadYnERC20Inputs() internal {
_ynERC20Inputs = abi.decode(data, (YnERC20Input));
_chainId = _ynERC20Inputs.chainId;
}

function _getRateLimiterConfigs() internal {
RateLimiter.RateLimitConfig memory _tempConfig;
uint32 tempDstEid = EndpointV2(addresses[_chainId].lzEndpoint).eid();
for (uint256 i; i < _ynOFTAdapterInputs.rateLimitConfigs.length; i++) {
_tempConfig.dstEid = tempDstEid;
_tempConfig.limit = _ynOFTAdapterInputs.rateLimitConfigs[i].limit;
_tempConfig.window = _ynOFTAdapterInputs.rateLimitConfigs[i].window;
_rateLimitConfigs.push(_tempConfig);
}
}

function _serializeOutputs(string memory objectKey) internal virtual {
// left blank on purpose
}

function _verifyChain() internal view returns (bool) {
require(isSupportedChainId(_chainId) && block.chainid == _chainId, "Invalid chain");
return isSupportedChainId(_chainId) && block.chainid == _chainId;
}

function _getOutputPath(string memory _deploymentType) internal view returns (string memory) {
string memory root = vm.projectRoot();
return string.concat(root, "/deployments/", _deploymentType, "-", vm.toString(block.chainid), ".json");
}

function _writeOutput(string memory deploymentType, string memory json) internal {
string memory path = _getOutputPath(deploymentType);
vm.writeFile(path, json);
}
}
27 changes: 27 additions & 0 deletions script/DeployImmutableMultiChainDeployer.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {BaseScript} from "./BaseScript.s.sol";
import {ImmutableMultiChainDeployer} from "@factory/ImmutableMultiChainDeployer.sol";
import "forge-std/console.sol";

//forge script script/DeployImmutableMultiChainDeployer.s.sol:DeployImmutableMultiChainDeployer --rpc-url ${rpc} --sig "run(bytes32)" ${salt} --account ${deployerAccountName} --sender ${deployer} --broadcast --etherscan-api-key ${api} --verify

contract DeployImmutableMultiChainDeployer is BaseScript {
address public multiChainDeployerAddress;

function run(bytes32 _salt) public {
vm.broadcast();
multiChainDeployerAddress = address(new ImmutableMultiChainDeployer{salt: _salt}());

console.log("ImmutableMultiChainDeployer deployed at: ", multiChainDeployerAddress);
_serializeOutputs("ImmutableMultiChainDeployer");
}

function _serializeOutputs(string memory objectKey) internal override {
vm.serializeString(objectKey, "chainid", vm.toString(block.chainid));
string memory finalJson =
vm.serializeAddress(objectKey, "ImmutableMultiChainDeployerAddress", address(multiChainDeployerAddress));
_writeOutput("ImmutableMultiChainDeployer", finalJson);
}
}
37 changes: 37 additions & 0 deletions script/DeployMainnetImplementations.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {BaseScript} from "./BaseScript.s.sol";
import {ImmutableMultiChainDeployer} from "@factory/ImmutableMultiChainDeployer.sol";
import {RateLimiter} from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/utils/RateLimiter.sol";
import {L1YnOFTAdapterUpgradeable} from "@/L1YnOFTAdapterUpgradeable.sol";
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";

// forge script script/DeployMainnetImplementations.s.sol:DeployMainnetImplementations --rpc-url ${rpc} --sig "run(string memory)" ${path} --account ${deployerAccountName} --sender ${deployer} --broadcast --etherscan-api-key ${api} --verify
contract DeployMainnetImplementations is BaseScript {
address public mainnetOFTAdapterImpl;
L1YnOFTAdapterUpgradeable public mainnetOFTAdapter;

function run(string memory __path) public {
_loadOFTImplementationData(__path);

vm.broadcast();

mainnetOFTAdapterImpl =
address(new L1YnOFTAdapterUpgradeable(_ynOFTAdapterInputs.erc20Address, addresses[_chainId].lzEndpoint));
mainnetOFTAdapter =
L1YnOFTAdapterUpgradeable(address(new TransparentUpgradeableProxy(mainnetOFTAdapterImpl, msg.sender, "")));

mainnetOFTAdapter.initialize(msg.sender, _rateLimitConfigs);

_serializeOutputs("MainnetImplementations");
}

function _serializeOutputs(string memory objectKey) internal override {
vm.serializeAddress(objectKey, "erc20", _ynOFTAdapterInputs.erc20Address);
vm.serializeString(objectKey, "chainid", vm.toString(block.chainid));
vm.serializeAddress(objectKey, "OFTAdapterImplementation", address(mainnetOFTAdapterImpl));
string memory finalJson = vm.serializeAddress(objectKey, "OFTAdapter", address(mainnetOFTAdapter));
_writeOutput("MainnetImplementations", finalJson);
}
}
7 changes: 7 additions & 0 deletions script/inputs/L2ERC20DeploymentInput.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"chainId": 17000,
"erc20Address": "0x0000000000000000000000000000000000000000",
"lzEndpoint": "0x0000000000000000000000000000000000000000",
"name": "name",
"symbol": "symbol"
}
14 changes: 14 additions & 0 deletions script/inputs/L2OFTAdapterInput.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"chainId": 17000,
"erc20Address": "0x0000000000000000000000000000000000000000",
"adapterImplementation": "0x0000000000000000000000000000000000000000",
"rateLimiterConfigs": [
{
"limit": "100000000000000000000",
"window": "86400"
}
],
"TOKEN_ADMIN": "0x0000000000000000000000000000000000000000",
"PROXY_ADMIN": "0x0000000000000000000000000000000000000000",
"OFT_DELEGATE": "0x0000000000000000000000000000000000000000"
}
Loading

0 comments on commit de64bce

Please sign in to comment.