Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: simulation support in deploy-cli #406

Merged
merged 5 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 contracts/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ coverage.json
mochaOutput.json
testMatrix.json
/deployment-context-latest.json
/deployment-manifest.json
5 changes: 4 additions & 1 deletion contracts/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ out = "out"
libs = ["lib"]
evm_version = 'shanghai'
ignored_error_codes = [5574] # contract-size
fs_permissions = [{access = "read", path = "./utils/assets/"}]
fs_permissions = [
{ access = "read", path = "./utils/assets/" },
{ access = "write", path = "./deployment-manifest.json" }
]

[invariant]
call_override = false
Expand Down
116 changes: 85 additions & 31 deletions contracts/src/scripts/DeployLiquity2.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ pragma solidity 0.8.18;
import {Script} from "forge-std/Script.sol";
import {StdCheats} from "forge-std/StdCheats.sol";
import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol";
import {StringFormatting} from "../test/Utils/StringFormatting.sol";
import {Accounts} from "../test/TestContracts/Accounts.sol";
import {ERC20Faucet} from "../test/TestContracts/ERC20Faucet.sol";
import {ETH_GAS_COMPENSATION} from "../Dependencies/Constants.sol";
Expand Down Expand Up @@ -31,8 +33,10 @@ import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol";
import "forge-std/console.sol";

contract DeployLiquity2Script is Script, StdCheats, MetadataDeployment {
bytes32 SALT;
using Strings for *;
using StringFormatting for *;

bytes32 SALT;
address deployer;

struct LiquityContractsTestnet {
Expand All @@ -45,6 +49,7 @@ contract DeployLiquity2Script is Script, StdCheats, MetadataDeployment {
IStabilityPool stabilityPool;
ITroveManager troveManager;
ITroveNFT troveNFT;
MetadataNFT metadataNFT;
IPriceFeedTestnet priceFeed; // Tester
GasPool gasPool;
IInterestRouter interestRouter;
Expand Down Expand Up @@ -94,6 +99,63 @@ contract DeployLiquity2Script is Script, StdCheats, MetadataDeployment {
uint256 annualInterestRate;
}

struct DeploymentResult {
LiquityContractsTestnet[] contractsArray;
ICollateralRegistry collateralRegistry;
IBoldToken boldToken;
HintHelpers hintHelpers;
MultiTroveGetter multiTroveGetter;
}

function _getBranchContractsJson(LiquityContractsTestnet memory c) internal pure returns (string memory) {
return string.concat(
"{",
string.concat(
// Avoid stack too deep by chunking concats
string.concat(
string.concat('"addressesRegistry":"', address(c.addressesRegistry).toHexString(), '",'),
string.concat('"activePool":"', address(c.activePool).toHexString(), '",'),
string.concat('"borrowerOperations":"', address(c.borrowerOperations).toHexString(), '",'),
string.concat('"collSurplusPool":"', address(c.collSurplusPool).toHexString(), '",'),
string.concat('"defaultPool":"', address(c.defaultPool).toHexString(), '",'),
string.concat('"sortedTroves":"', address(c.sortedTroves).toHexString(), '",'),
string.concat('"stabilityPool":"', address(c.stabilityPool).toHexString(), '",'),
string.concat('"troveManager":"', address(c.troveManager).toHexString(), '",')
),
string.concat(
string.concat('"troveNFT":"', address(c.troveNFT).toHexString(), '",'),
string.concat('"metadataNFT":"', address(c.metadataNFT).toHexString(), '",'),
string.concat('"priceFeed":"', address(c.priceFeed).toHexString(), '",'),
string.concat('"gasPool":"', address(c.gasPool).toHexString(), '",'),
string.concat('"interestRouter":"', address(c.interestRouter).toHexString(), '",'),
string.concat('"collToken":"', address(c.collToken).toHexString(), '"') // no comma
)
),
"}"
);
}

function _getManifestJson(DeploymentResult memory deployed) internal pure returns (string memory) {
string[] memory branches = new string[](deployed.contractsArray.length);

// Poor man's .map()
for (uint256 i = 0; i < branches.length; ++i) {
branches[i] = _getBranchContractsJson(deployed.contractsArray[i]);
}

return string.concat(
"{",
string.concat(
string.concat('"collateralRegistry":"', address(deployed.collateralRegistry).toHexString(), '",'),
string.concat('"boldToken":"', address(deployed.boldToken).toHexString(), '",'),
string.concat('"hintHelpers":"', address(deployed.hintHelpers).toHexString(), '",'),
string.concat('"multiTroveGetter":"', address(deployed.multiTroveGetter).toHexString(), '",'),
string.concat('"branches":[', branches.join(","), "]") // no comma
),
"}"
);
}

function run() external {
SALT = keccak256(abi.encodePacked(block.timestamp));

Expand All @@ -114,14 +176,12 @@ contract DeployLiquity2Script is Script, StdCheats, MetadataDeployment {
troveManagerParamsArray[1] = TroveManagerParams(150e16, 120e16, 110e16, 5e16, 10e16); // stETH

// used for gas compensation and as collateral of the first branch
IWETH WETH = new WETHTester(
100 ether, // _tapAmount
1 days // _tapPeriod
);
(LiquityContractsTestnet[] memory contractsArray,,,,) =
_deployAndConnectContracts(troveManagerParamsArray, WETH);
IWETH WETH = new WETHTester({_tapAmount: 100 ether, _tapPeriod: 1 days});
DeploymentResult memory deployed = _deployAndConnectContracts(troveManagerParamsArray, WETH);
vm.stopBroadcast();

vm.writeFile("deployment-manifest.json", _getManifestJson(deployed));

if (vm.envOr("OPEN_DEMO_TROVES", false)) {
// Anvil default accounts
// TODO: get accounts from env
Expand Down Expand Up @@ -157,11 +217,11 @@ contract DeployLiquity2Script is Script, StdCheats, MetadataDeployment {
demoTroves[14] = DemoTroveParams(1, demoAccounts[6], 1, 71e18, 11000e18, 3.3e16);
demoTroves[15] = DemoTroveParams(1, demoAccounts[7], 1, 84e18, 12800e18, 4.4e16);

for (uint256 i = 0; i < contractsArray.length; i++) {
tapFaucet(demoAccounts, contractsArray[i]);
for (uint256 i = 0; i < deployed.contractsArray.length; i++) {
tapFaucet(demoAccounts, deployed.contractsArray[i]);
}

openDemoTroves(demoTroves, contractsArray);
openDemoTroves(demoTroves, deployed.contractsArray);
}
}

Expand Down Expand Up @@ -227,23 +287,17 @@ contract DeployLiquity2Script is Script, StdCheats, MetadataDeployment {

function _deployAndConnectContracts(TroveManagerParams[] memory troveManagerParamsArray, IWETH _WETH)
internal
returns (
LiquityContractsTestnet[] memory contractsArray,
ICollateralRegistry collateralRegistry,
IBoldToken boldToken,
HintHelpers hintHelpers,
MultiTroveGetter multiTroveGetter
)
returns (DeploymentResult memory r)
{
DeploymentVarsTestnet memory vars;
vars.numCollaterals = troveManagerParamsArray.length;
// Deploy Bold
vars.bytecode = abi.encodePacked(type(BoldToken).creationCode, abi.encode(deployer));
vars.boldTokenAddress = vm.computeCreate2Address(SALT, keccak256(vars.bytecode));
boldToken = new BoldToken{salt: SALT}(deployer);
assert(address(boldToken) == vars.boldTokenAddress);
r.boldToken = new BoldToken{salt: SALT}(deployer);
assert(address(r.boldToken) == vars.boldTokenAddress);

contractsArray = new LiquityContractsTestnet[](vars.numCollaterals);
r.contractsArray = new LiquityContractsTestnet[](vars.numCollaterals);
vars.collaterals = new IERC20Metadata[](vars.numCollaterals);
vars.addressesRegistries = new IAddressesRegistry[](vars.numCollaterals);
vars.troveManagers = new ITroveManager[](vars.numCollaterals);
Expand All @@ -269,26 +323,26 @@ contract DeployLiquity2Script is Script, StdCheats, MetadataDeployment {
vars.troveManagers[vars.i] = ITroveManager(troveManagerAddress);
}

collateralRegistry = new CollateralRegistry(boldToken, vars.collaterals, vars.troveManagers);
hintHelpers = new HintHelpers(collateralRegistry);
multiTroveGetter = new MultiTroveGetter(collateralRegistry);
r.collateralRegistry = new CollateralRegistry(r.boldToken, vars.collaterals, vars.troveManagers);
r.hintHelpers = new HintHelpers(r.collateralRegistry);
r.multiTroveGetter = new MultiTroveGetter(r.collateralRegistry);

// Deploy per-branch contracts for each branch
for (vars.i = 0; vars.i < vars.numCollaterals; vars.i++) {
vars.contracts = _deployAndConnectCollateralContractsTestnet(
vars.collaterals[vars.i],
boldToken,
collateralRegistry,
r.boldToken,
r.collateralRegistry,
_WETH,
vars.addressesRegistries[vars.i],
address(vars.troveManagers[vars.i]),
hintHelpers,
multiTroveGetter
r.hintHelpers,
r.multiTroveGetter
);
contractsArray[vars.i] = vars.contracts;
r.contractsArray[vars.i] = vars.contracts;
}

boldToken.setCollateralRegistry(address(collateralRegistry));
r.boldToken.setCollateralRegistry(address(r.collateralRegistry));
}

function _deployAddressesRegistry(TroveManagerParams memory _troveManagerParams)
Expand Down Expand Up @@ -327,11 +381,11 @@ contract DeployLiquity2Script is Script, StdCheats, MetadataDeployment {
contracts.addressesRegistry = _addressesRegistry;

// Deploy Metadata
MetadataNFT metadataNFT = deployMetadata(SALT);
contracts.metadataNFT = deployMetadata(SALT);
addresses.metadataNFT = vm.computeCreate2Address(
SALT, keccak256(getBytecode(type(MetadataNFT).creationCode, address(initializedFixedAssetReader)))
);
assert(address(metadataNFT) == addresses.metadataNFT);
assert(address(contracts.metadataNFT) == addresses.metadataNFT);

contracts.priceFeed = new PriceFeedTestnet();
contracts.interestRouter = new MockInterestRouter();
Expand Down
Loading
Loading