Skip to content
Open
Show file tree
Hide file tree
Changes from 10 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
55 changes: 53 additions & 2 deletions deployments/protocol/v1.5.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,54 @@
{

}
"1": {
"categoryRegistry": "0xbB2168d5546A94AE2DA9254e63D88F7f137B2534",
"chainlinkFeedRegistry": "0x8D5e90706E52a52853dA9A14fA1c63889a412851",
"config": "0xd52a2898d61636bB3eEF0d145f05352FF543bdCC",
"configSingleton": "0x1f5febF0efA3aD487508b6Cc7f39a0a54DE9De72",
"crowdsourceLenderVault": "0x41dCf7E9ECDBd3f0bc69cba50b49f1B37ae65Ca2",
"hooks": {
"compoundLender": "",
"directLenderRepayment": "",
"refinanceBorrowerCreate": "",
"vaultLender": "",
"aaveLender": ""
},
"hub": "0x37807A2F031b3B44081F4b21500E5D70EbaDAdd5",
"loan": "0xc58791ec351349a82036aE712976109C10e34217",
"loanToken": "0x4440C069272cC34b80C7B11bEE657D0349Ba9C23",
"products": {
"stable": "",
"installments": "0x59Fd11B2518238E363bd4CC2aBb50455d1587966",
"fixed": "",
"uniswapV3Individual": "",
"uniswapV3Set": ""
},
"revokedNonce": "0x972204fF33348ee6889B2d0A3967dB67d7b08e4c",
"utilizedCredit": "0x8E6F44DEa3c11d69C63655BDEcbA25Fa986BCE9D"
},
"11155111": {
"categoryRegistry": "0xbB2168d5546A94AE2DA9254e63D88F7f137B2534",
"chainlinkFeedRegistry": "0x8D5e90706E52a52853dA9A14fA1c63889a412851",
"config": "0xd52a2898d61636bB3eEF0d145f05352FF543bdCC",
"configSingleton": "0x1f5febF0efA3aD487508b6Cc7f39a0a54DE9De72",
"crowdsourceLenderVault": "0x2474d856d1463435932866de8118CC40Ed3c01d8",
"hooks": {
"compoundLender": "",
"directLenderRepayment": "",
"refinanceBorrowerCreate": "",
"vaultLender": "",
"aaveLender": ""
},
"hub": "0x37807A2F031b3B44081F4b21500E5D70EbaDAdd5",
"loan": "0xc58791ec351349a82036aE712976109C10e34217",
"loanToken": "0x4440C069272cC34b80C7B11bEE657D0349Ba9C23",
"products": {
"stable": "",
"installments": "0x68669e7ec29070e3dfa684cb4893282Cd4C9E608",
"fixed": "",
"uniswapV3Individual": "",
"uniswapV3Set": ""
},
"revokedNonce": "0x972204fF33348ee6889B2d0A3967dB67d7b08e4c",
"utilizedCredit": "0x8E6F44DEa3c11d69C63655BDEcbA25Fa986BCE9D"
}
}
20 changes: 20 additions & 0 deletions foundry.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"lib/MultiToken": {
"rev": "863dcd8b4c60494d1deda231fb95b48073d85659"
},
"lib/forge-std": {
"rev": "ae570fec082bfe1c1f45b0acca4a2b4f84d345ce"
},
"lib/openzeppelin-contracts": {
"rev": "bd325d56b4c62c9c5c1aff048c37c6bb18ac0290"
},
"lib/openzeppelin-contracts-upgradeable": {
"rev": "a40cb0bda838c2ef3dfc252c179f5c37c32e80c4"
},
"lib/v3-core": {
"rev": "6562c52e8f75f0c10f9deaf44861847585fc8129"
},
"lib/v3-periphery": {
"rev": "50c696768e1e6cf13aa4d4d382ab3fec0c7d3b2e"
}
}
104 changes: 94 additions & 10 deletions script/PWN.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ import {
MultiTokenCategoryRegistry,
IChainlinkFeedRegistryLike,
PWNStableProduct,
PWNWorldStableProduct
PWNInstallmentsProduct,
IAaveLike
} from "pwn/Deployments.sol";

import { PWNCrowdsourceLenderVault } from "pwn/periphery/crowdsource/PWNCrowdsourceLenderVault.sol";


library PWNContractDeployerSalt {

Expand All @@ -44,7 +47,10 @@ library PWNContractDeployerSalt {
bytes32 internal constant FIXED_PRODUCT = keccak256("PWNFixedProduct");
bytes32 internal constant UNISWAP_V3_INDIVIDUAL_PRODUCT = keccak256("PWNUniswapV3IndividualProduct");
bytes32 internal constant UNISWAP_V3_SET_PRODUCT = keccak256("PWNUniswapV3SetProduct");
bytes32 internal constant INSTALLMENTS_PRODUCT = keccak256("PWNInstallmentsProduct");

// Others
bytes32 internal constant CROWDSOURCE_LENDER_VAULT = keccak256("PWNCrowdsourceLenderVault");
}

using GnosisSafeUtils for GnosisSafeLike;
Expand Down Expand Up @@ -95,41 +101,119 @@ forge script script/PWN.s.sol:Deploy --sig "deploy()" \
_loadDeployedAddresses();
vm.startBroadcast();

// !!! TODO LOADING ADDRESSES FROM JSON DOES NOT WORK SOMEHOW, SO I AM JUST HARDCODING THE ADDRESSES HERE !!!

__d.loanToken = PWNLOAN(0x4440C069272cC34b80C7B11bEE657D0349Ba9C23);
__d.config = PWNConfig(0xd52a2898d61636bB3eEF0d145f05352FF543bdCC);
__d.categoryRegistry = MultiTokenCategoryRegistry(0xbB2168d5546A94AE2DA9254e63D88F7f137B2534);

__d.loan = PWNLoan(
_deploy(
PWNContractDeployerSalt.LOAN,
abi.encodePacked(
type(PWNLoan).creationCode,
abi.encode(address(__d.hub), address(__d.loanToken), address(__d.config), address(__d.categoryRegistry), __e.permit2)
abi.encode(
address(__d.loanToken),
address(__d.config),
address(__d.categoryRegistry)
)
)
)
);

__d.products.stable = PWNStableProduct(
console2.log("PWNLoan:", address(__d.loan));

__d.hub = PWNHub(0x37807A2F031b3B44081F4b21500E5D70EbaDAdd5);
__d.revokedNonce = PWNRevokedNonce(0x972204fF33348ee6889B2d0A3967dB67d7b08e4c);
__d.utilizedCredit = PWNUtilizedCredit(0x8E6F44DEa3c11d69C63655BDEcbA25Fa986BCE9D);
__d.chainlinkFeedRegistry = IChainlinkFeedRegistryLike(0x8D5e90706E52a52853dA9A14fA1c63889a412851);
__e.chainlinkL2SequencerUptimeFeed = address(0x0000000000000000000000000000000000000000);
__e.weth = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);

__d.products.installments = PWNInstallmentsProduct(
_deploy(
PWNContractDeployerSalt.STABLE_PRODUCT,
PWNContractDeployerSalt.INSTALLMENTS_PRODUCT,
abi.encodePacked(
type(PWNWorldStableProduct).creationCode,
abi.encode(address(__d.hub), address(__d.revokedNonce), address(__d.utilizedCredit), address(__d.chainlinkFeedRegistry), __e.chainlinkL2SequencerUptimeFeed, __e.weth, 0x17B354dD2595411ff79041f930e491A4Df39A278, "app_17abe44eaf47c99566f5378aa4e19463", "verify-humanness")
type(PWNInstallmentsProduct).creationCode,
abi.encode(
address(__d.hub),
address(__d.revokedNonce),
address(__d.utilizedCredit),
address(__d.chainlinkFeedRegistry),
__e.chainlinkL2SequencerUptimeFeed,
__e.weth
)
)
)
);

console2.log("PWNLoan:", address(__d.loan));
console2.log("PWNStableProduct:", address(__d.products.stable));
console2.log("PWNInstallmentsProduct:", address(__d.products.installments));

address[] memory addrs = new address[](3);
addrs[0] = address(__d.loan);
addrs[1] = address(__d.products.stable);
addrs[2] = address(__d.products.stable);
addrs[1] = address(__d.products.installments);
addrs[2] = address(__d.products.installments);

bytes32[] memory tags = new bytes32[](3);
tags[0] = PWNHubTags.ACTIVE_LOAN;
tags[1] = PWNHubTags.LOAN_PROPOSAL;
tags[2] = PWNHubTags.NONCE_MANAGER;

// note: this should be called on the protocolTimelock contract and use `schedule` and then `execute`
// functions where the target arg is the PWNHub and the data is the encoded bytes logged below
// note 2: when setting tags for proposal, it needs to have both LOAN_PROPOSAL and NONCE_MANAGER
// tags in order to work fully correctly
console2.logBytes(abi.encodeWithSignature("setTags(address[],bytes32[],bool)", addrs, tags, true));

/*
USDC --> weETH route
1) USDC --> USD ( 0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6 , non inverted )
2) USD --> ETH ( 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419 , inverted )
3) eth --> weETH ( 0x5c9C449BbC9a6075A2c061dF312a35fd1E05fF22 , inverted )
*/

address[] memory feedIntermediaryDenominations = new address[](2);
feedIntermediaryDenominations[0] = address(0x0000000000000000000000000000000000000348); // USD
feedIntermediaryDenominations[1] = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); // ETH
bool[] memory feedInvertFlags = new bool[](3);
feedInvertFlags[0] = false;
feedInvertFlags[1] = true;
feedInvertFlags[2] = true;

// __d.loan = PWNLoan(0xc58791ec351349a82036aE712976109C10e34217);
// __d.products.installments = PWNInstallmentsProduct(0x68669e7ec29070e3dfa684cb4893282Cd4C9E608);
__e.aave = IAaveLike(address(0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2));

__d.crowdsourceLenderVault = PWNCrowdsourceLenderVault(
_deploy(
PWNContractDeployerSalt.CROWDSOURCE_LENDER_VAULT,
abi.encodePacked(
type(PWNCrowdsourceLenderVault).creationCode,
abi.encode(
address(__d.loan),
address(__d.products.installments),
address(__e.aave),
"BordelMortgageVaultShare",
"BORDEL",
PWNCrowdsourceLenderVault.Terms({
collateralAddress: address(0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee), // weETH
creditAddress: address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48), // USDC
feedIntermediaryDenominations: feedIntermediaryDenominations,
feedInvertFlags: feedInvertFlags,
loanToValue: 7500, // 75%
interestAPR: 200, // 2%
postponement: 15780000, // 6 months in seconds
duration: 157800000, // 5 years in seconds
minCreditAmount: 180000000000, // 180 000 USDC (6 decimals)
expiration: block.timestamp + 8640000 // 100 days from now
})
)
)
)
);

console2.log("PWNCrowdsourceLenderVault:", address(__d.crowdsourceLenderVault));

vm.stopBroadcast();
}

Expand Down
118 changes: 111 additions & 7 deletions src/Deployments.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import { PWNDirectLenderRepaymentHook } from "pwn/periphery/hook/lender/PWNDirec
import { PWNRevokedNonce } from "pwn/periphery/auxiliary/PWNRevokedNonce.sol";
import { PWNUtilizedCredit } from "pwn/periphery/auxiliary/PWNUtilizedCredit.sol";

import { PWNCrowdsourceLenderVault } from "pwn/periphery/crowdsource/PWNCrowdsourceLenderVault.sol";


interface IPWNDeployer {
function owner() external returns (address);
Expand Down Expand Up @@ -72,6 +74,7 @@ abstract contract Deployments is CommonBase {
IChainlinkFeedRegistryLike chainlinkFeedRegistry;
PWNConfig config;
PWNConfig configSingleton;
PWNCrowdsourceLenderVault crowdsourceLenderVault;
Hooks hooks;
PWNHub hub;
PWNLoan loan;
Expand Down Expand Up @@ -113,27 +116,128 @@ abstract contract Deployments is CommonBase {

function _loadDeployedAddresses() internal {
string memory root = vm.projectRoot();
string memory chainIdKey = block.chainid.toString();

// Load creation code
_loadCreationCode(root);

// Load external addresses
_loadExternalAddresses(root, chainIdKey);

// Load deployment addresses
_loadDeploymentAddresses(root, chainIdKey);
}

function _loadCreationCode(string memory root) internal {
string memory creationJson = vm.readFile(string.concat(root, deploymentsSubpath, "/deployments/creation/creationCode.json"));
bytes memory rawCreation = creationJson.parseRaw(".");
__cc = abi.decode(rawCreation, (CreationCode));
__cc.categoryRegistry = creationJson.readBytes(".categoryRegistry");
__cc.chainlinkFeedRegistry = creationJson.readBytes(".chainlinkFeedRegistry");
__cc.config = creationJson.readBytes(".config");
__cc.configSingleton_v1_2 = creationJson.readBytes(".configSingleton_v1_2");
__cc.hub = creationJson.readBytes(".hub");
__cc.loanToken = creationJson.readBytes(".loanToken");
__cc.revokedNonce = creationJson.readBytes(".revokedNonce");
__cc.utilizedCredit = creationJson.readBytes(".utilizedCredit");
}

function _loadExternalAddresses(string memory root, string memory chainIdKey) internal {
string memory externalJson = vm.readFile(string.concat(root, deploymentsSubpath, "/deployments/external/external.json"));
bytes memory rawExternal = externalJson.parseRaw(string.concat(".", block.chainid.toString()));
__e = abi.decode(rawExternal, (External));
string memory externalKey = string.concat(".", chainIdKey);
__e.aave = IAaveLike(externalJson.readAddress(string.concat(externalKey, ".aave")));
__e.adminTimelock = externalJson.readAddress(string.concat(externalKey, ".adminTimelock"));
__e.chainlinkL2SequencerUptimeFeed = externalJson.readAddress(string.concat(externalKey, ".chainlinkL2SequencerUptimeFeed"));
__e.dao = externalJson.readAddress(string.concat(externalKey, ".dao"));
__e.daoSafe = externalJson.readAddress(string.concat(externalKey, ".daoSafe"));
__e.deployer = IPWNDeployer(externalJson.readAddress(string.concat(externalKey, ".deployer")));
__e.deployerSafe = externalJson.readAddress(string.concat(externalKey, ".deployerSafe"));
__e.isL2 = externalJson.readBool(string.concat(externalKey, ".isL2"));
__e.protocolTimelock = externalJson.readAddress(string.concat(externalKey, ".protocolTimelock"));
__e.uniswapV3Factory = externalJson.readAddress(string.concat(externalKey, ".uniswapV3Factory"));
__e.uniswapV3NFTPositionManager = externalJson.readAddress(string.concat(externalKey, ".uniswapV3NFTPositionManager"));
__e.weth = externalJson.readAddress(string.concat(externalKey, ".weth"));
}

function _loadDeploymentAddresses(string memory root, string memory chainIdKey) private {
string memory deploymentsJson = vm.readFile(string.concat(root, deploymentsSubpath, "/deployments/protocol/v1.5.json"));
bytes memory rawDeployment = deploymentsJson.parseRaw(string.concat(".", block.chainid.toString()));

string memory deploymentKey = string.concat(".", chainIdKey);

// Check if deployment exists for this chain by checking if raw bytes exist
bytes memory rawDeployment = deploymentsJson.parseRaw(deploymentKey);

if (rawDeployment.length > 0) {
wasPredeployedOnFork = true;
__d = abi.decode(rawDeployment, (Deployment));
_loadDeploymentTopLevel(deploymentsJson, deploymentKey);
_loadDeploymentProducts(deploymentsJson, deploymentKey);
_loadDeploymentHooks(deploymentsJson, deploymentKey);
} else {
wasPredeployedOnFork = false;
_protocolNotDeployedOnSelectedChain();
}
}

function _safeReadAddress(string memory json, string memory key) private pure returns (address) {
string memory addrStr = json.readString(key);
if (bytes(addrStr).length == 0) {
return address(0);
}
return json.readAddress(key);
}

function _loadDeploymentTopLevel(string memory deploymentsJson, string memory deploymentKey) private {
__d.categoryRegistry = MultiTokenCategoryRegistry(_safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".categoryRegistry")));
__d.chainlinkFeedRegistry = IChainlinkFeedRegistryLike(_safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".chainlinkFeedRegistry")));
__d.config = PWNConfig(_safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".config")));
__d.configSingleton = PWNConfig(_safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".configSingleton")));
__d.hub = PWNHub(_safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".hub")));
__d.loanToken = PWNLOAN(_safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".loanToken")));

address addr = _safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".crowdsourceLenderVault"));
if (addr != address(0)) __d.crowdsourceLenderVault = PWNCrowdsourceLenderVault(addr);

addr = _safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".loan"));
if (addr != address(0)) __d.loan = PWNLoan(addr);

addr = _safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".revokedNonce"));
if (addr != address(0)) __d.revokedNonce = PWNRevokedNonce(addr);

addr = _safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".utilizedCredit"));
if (addr != address(0)) __d.utilizedCredit = PWNUtilizedCredit(addr);
}

function _loadDeploymentProducts(string memory deploymentsJson, string memory deploymentKey) private {
address addr = _safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".products.stable"));
if (addr != address(0)) __d.products.stable = PWNStableProduct(addr);

addr = _safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".products.installments"));
if (addr != address(0)) __d.products.installments = PWNInstallmentsProduct(addr);

addr = _safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".products.fixed"));
if (addr != address(0)) __d.products._fixed = PWNFixedProduct(addr);

addr = _safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".products.uniswapV3Individual"));
if (addr != address(0)) __d.products.uniswapV3Individual = PWNUniswapV3IndividualProduct(addr);

addr = _safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".products.uniswapV3Set"));
if (addr != address(0)) __d.products.uniswapV3Set = PWNUniswapV3SetProduct(addr);
}

function _loadDeploymentHooks(string memory deploymentsJson, string memory deploymentKey) private {
address addr = _safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".hooks.aaveLender"));
if (addr != address(0)) __d.hooks.aaveLender = PWNAaveLenderHook(addr);

addr = _safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".hooks.compoundLender"));
if (addr != address(0)) __d.hooks.compoundLender = PWNCompoundLenderHook(addr);

addr = _safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".hooks.directLenderRepayment"));
if (addr != address(0)) __d.hooks.directLenderRepayment = PWNDirectLenderRepaymentHook(addr);

addr = _safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".hooks.refinanceBorrowerCreate"));
if (addr != address(0)) __d.hooks.refinanceBorrowerCreate = PWNRefinanceBorrowerCreateHook(addr);

addr = _safeReadAddress(deploymentsJson, string.concat(deploymentKey, ".hooks.vaultLender"));
if (addr != address(0)) __d.hooks.vaultLender = PWN4626VaultLenderHook(addr);
}

function _protocolNotDeployedOnSelectedChain() internal virtual {
// Override
}
Expand Down
Loading