From c3c19b039d46914798251c6062476cbe231865ea Mon Sep 17 00:00:00 2001 From: Thor Seldon Date: Tue, 1 Mar 2022 15:26:06 +0800 Subject: [PATCH 1/6] add develop testnet for internal dev testing --- .gitignore | 1 + deployments/deployed-contracts-develop.json | 195 ++++++++++++++++++++ hardhat.config.ts | 1 + helper-hardhat-config.ts | 5 + helpers/contracts-helpers.ts | 4 +- helpers/etherscan-verification.ts | 2 +- helpers/init-helpers.ts | 5 +- helpers/types.ts | 2 + markets/bend/commons.ts | 21 +++ markets/bend/index.ts | 17 ++ package.json | 17 +- tasks/full/initialize.ts | 24 --- tasks/full/lend-pool.ts | 6 +- tasks/migrations/bend.mainnet.ts | 4 + tasks/misc/custom-task.ts | 43 ++++- tasks/misc/oracle-admin.ts | 30 ++- tasks/misc/pool-admin.ts | 14 +- 17 files changed, 334 insertions(+), 57 deletions(-) create mode 100644 deployments/deployed-contracts-develop.json diff --git a/.gitignore b/.gitignore index f913212..6af053e 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ deployed-contracts.json /deployments/* !/deployments/deployed-contracts-main*.json !/deployments/deployed-contracts-rinkeby*.json +!/deployments/deployed-contracts-develop*.json /flattened bend-flattened.* diff --git a/deployments/deployed-contracts-develop.json b/deployments/deployed-contracts-develop.json new file mode 100644 index 0000000..a4cc076 --- /dev/null +++ b/deployments/deployed-contracts-develop.json @@ -0,0 +1,195 @@ +{ + "WETHMocked": { + "address": "0x3C73A32C11E20101be3D5ff2F67Af15a4ACbF298", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "WETH": { + "address": "0x3C73A32C11E20101be3D5ff2F67Af15a4ACbF298", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "MintableERC20": { + "address": "0x5C6105989c5Be5f88b88fD0b2cE15A282d7c9F07", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "DAI": { + "address": "0xcB3b65Fb934d5A49a4738d8c6CC328dc96120ad7", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "USDC": { + "address": "0x5C6105989c5Be5f88b88fD0b2cE15A282d7c9F07", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "CryptoPunksMarket": { + "address": "0xE159fC1226dbCe3e9d511e884a067D09C3290B9E", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "WrappedPunk": { + "address": "0xcDbBC001976F79db2fC1ECfd140031fE970CeaEc", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "WPUNKS": { + "address": "0xcDbBC001976F79db2fC1ECfd140031fE970CeaEc", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "MintableERC721": { + "address": "0x65217942f01E563e5F292ba0C7285D0ce85fDE1e", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "BAYC": { + "address": "0x818674fb778147DC81c85f9af3d5cd73E03545B2", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "DOODLE": { + "address": "0x54Db2bbf13cC6b2073CcDf9A06B7A2862eb8C3cC", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "COOL": { + "address": "0xD83948C3deF2a75F9E4A0c0D9e5E7e050a6c2423", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "MEEBITS": { + "address": "0x0DD78C9209f57088bAB52C953C8bD51BDA3570A2", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "MAYC": { + "address": "0x5EDB2c61d14648D8b2adb559a6AE13F7E3a11678", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "WOW": { + "address": "0xdB5DD4ecBd172BfAc198e617122D00CaD12ee2ae", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "CLONEX": { + "address": "0xA446Ab62fb4bdCEdAF69259354ad0C1C7ccb87ff", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "AZUKI": { + "address": "0x048e8A2738F4d292Cf30e8468066ce930dFBDAfa", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "KONGZ": { + "address": "0x65217942f01E563e5F292ba0C7285D0ce85fDE1e", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "BendProxyAdminPool": { + "address": "0x740A26A9aa27e193C8d15d75A1ca1C19AE735c21" + }, + "BendProxyAdminFund": { + "address": "0x0B815174656df530906CC39E983431f0Ec442C59" + }, + "BendCollectorImpl": { + "address": "0x788406B3b1F9720bF7C4b8E814c2081f05388841" + }, + "BendCollector": { + "address": "0xA9620F4655620863FaC5AD87DcB4e3ab5e1C5b86", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "LendPoolAddressesProvider": { + "address": "0x4eAd42E5aC97E3E81FCC8A9B0E80AfcDa7e630C5", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "LendPoolAddressesProviderRegistry": { + "address": "0x1Db6D93Cc48074A0D0664850508eC76Ca4955951", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "ReserveLogic": { + "address": "0xBb70B549e0c7C75D2D7269AE15C84526febce459", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "NftLogic": { + "address": "0x6E9936c3270d80F3fDCA1Eaee8F7F1fe8ff3D626", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "GenericLogic": { + "address": "0x259d4e7B47A2f46AA25D1BB4249daE4Ce8044924", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "ValidationLogic": { + "address": "0x8A0F9F764949fA4DC30a31e6B1D49455A5b7c37e", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "LendPoolImpl": { + "address": "0x061172D66E3b0d12f35AA5f4aa790d1b82584b81" + }, + "LendPool": { + "address": "0x7273847406a52B949F3E824fce7704E8e74244f5" + }, + "LendPoolLiquidatorImpl": { + "address": "0x0d7FD00F0eB15E2ac6F2A7e2A711EC3cF52C5af7" + }, + "LendPoolLiquidator": { + "address": "0x0d7FD00F0eB15E2ac6F2A7e2A711EC3cF52C5af7", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "LendPoolLoanImpl": { + "address": "0xfC65bB7444E53549ffE2ED019f7808Fa11054aF5" + }, + "LendPoolLoan": { + "address": "0xfD45825533513ABfCa3D767f407C86C1c522a659" + }, + "LendPoolConfiguratorImpl": { + "address": "0x51C7a63628E3020DCf79fB824C7B2EdbBCd19aD5" + }, + "LendPoolConfigurator": { + "address": "0xB941fC3ceC2E83a9Df305Cc8A3285D6E8bc29A01" + }, + "BTokensAndBNFTsHelper": { + "address": "0x4C08584B7CbdEb2912Db3414f6480E4005AcF1E7", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "BToken": { + "address": "0x1E18CDB5b7aBD4eC74C5E30F6E1F1ce356Af3694", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "DebtToken": { + "address": "0x6C76C7e412C8CA560710240BF126B94dA6aCE597", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "ReserveOracleImpl": { + "address": "0x43398385ce07CE08351331A4e7937dD063F97faF" + }, + "ReserveOracle": { + "address": "0xd30179fbB087088a77E1DD0903cCc64510287cB2", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "NFTOracleImpl": { + "address": "0x7f998b4caeeEd21c71ca3CC85c0917f70782a22A" + }, + "NFTOracle": { + "address": "0xE283F4D306517200911F9c378aC68f020acb9f64", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "WETHGateway": { + "address": "0x53EB7c083eFDc7505848263BB481bD93fA7Ad5B6", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "PunkGateway": { + "address": "0x02a23AeD66567bC36C6dABB75959972cC7644bf7", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "InterestRate": { + "address": "0xbBbFaFACaBeEB2B3957eddf87e95434e81aeC25c", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "rateStrategyWETH": { + "address": "0x322534C25175b4ba9d9926808d0C29BE30957541" + }, + "rateStrategyStableTwo": { + "address": "0x653BcA07BaC7c9c6ef55a3b3Af231d2f1F943Cc4" + }, + "rateStrategyStableThree": { + "address": "0xbBbFaFACaBeEB2B3957eddf87e95434e81aeC25c" + }, + "WalletBalanceProvider": { + "address": "0x54028bF245F8b54C037e10DED960f1F10e228cd2", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "BendProtocolDataProvider": { + "address": "0xA8334E9BA1c4E1dD2d72C38258B43C30b6aeDEb0", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "UIPoolDataProvider": { + "address": "0x291451555eF07441f4De67940b967a6B8D4033Df", + "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + } +} \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index f50fda0..61c6224 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -95,6 +95,7 @@ const buidlerConfig: HardhatUserConfig = { chainId: BUIDLEREVM_CHAINID, accounts: accounts.map(({ secretKey, balance }: { secretKey: string; balance: string }) => (secretKey)), }, + develop: getCommonNetworkConfig(eEthereumNetwork.develop, 4), rinkeby: getCommonNetworkConfig(eEthereumNetwork.rinkeby, 4), main: getCommonNetworkConfig(eEthereumNetwork.main, 1), hardhat: { diff --git a/helper-hardhat-config.ts b/helper-hardhat-config.ts index 4fd73af..88ddf9e 100644 --- a/helper-hardhat-config.ts +++ b/helper-hardhat-config.ts @@ -26,6 +26,9 @@ export const buildForkConfig = (): HardhatNetworkForkingUserConfig | undefined = }; export const NETWORKS_RPC_URL: iParamsPerNetwork = { + [eEthereumNetwork.develop]: ALCHEMY_KEY + ? `https://eth-rinkeby.alchemyapi.io/v2/${ALCHEMY_KEY}` + : `https://rinkeby.infura.io/v3/${INFURA_KEY}`, [eEthereumNetwork.rinkeby]: ALCHEMY_KEY ? `https://eth-rinkeby.alchemyapi.io/v2/${ALCHEMY_KEY}` : `https://rinkeby.infura.io/v3/${INFURA_KEY}`, @@ -38,6 +41,7 @@ export const NETWORKS_RPC_URL: iParamsPerNetwork = { }; export const NETWORKS_DEFAULT_GAS: iParamsPerNetwork = { + [eEthereumNetwork.develop]: 65 * GWEI, [eEthereumNetwork.rinkeby]: 65 * GWEI, [eEthereumNetwork.main]: 65 * GWEI, [eEthereumNetwork.coverage]: 65 * GWEI, @@ -48,6 +52,7 @@ export const NETWORKS_DEFAULT_GAS: iParamsPerNetwork = { export const BLOCK_TO_FORK: iParamsPerNetwork = { [eEthereumNetwork.main]: 13623705, [eEthereumNetwork.rinkeby]: 0, + [eEthereumNetwork.develop]: 0, [eEthereumNetwork.coverage]: 0, [eEthereumNetwork.hardhat]: 0, [eEthereumNetwork.localhost]: 0, diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index 368507f..1b4531a 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -171,7 +171,7 @@ export const linkBytecode = (artifact: Artifact, libraries: any) => { }; export const getParamPerNetwork = (param: iParamsPerNetwork, network: eNetwork) => { - const { main, rinkeby, hardhat, coverage, localhost } = param as iEthereumParamsPerNetwork; + const { main, rinkeby, develop, hardhat, coverage, localhost } = param as iEthereumParamsPerNetwork; if (process.env.FORK) { return param[process.env.FORK as eNetwork] as T; } @@ -183,6 +183,8 @@ export const getParamPerNetwork = (param: iParamsPerNetwork, network: eNet return hardhat; case eEthereumNetwork.localhost: return localhost; + case eEthereumNetwork.develop: + return develop; case eEthereumNetwork.rinkeby: return rinkeby; case eEthereumNetwork.main: diff --git a/helpers/etherscan-verification.ts b/helpers/etherscan-verification.ts index 69bb506..c846583 100644 --- a/helpers/etherscan-verification.ts +++ b/helpers/etherscan-verification.ts @@ -14,7 +14,7 @@ const okErrors = [`Contract source code already verified`, `Already Verified`]; const unableVerifyError = "Fail - Unable to verify"; -export const SUPPORTED_ETHERSCAN_NETWORKS = ["main", "ropsten", "kovan", "rinkeby"]; +export const SUPPORTED_ETHERSCAN_NETWORKS = ["main", "ropsten", "kovan", "rinkeby", "develop"]; function delay(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 05e6493..166d7c8 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -129,8 +129,7 @@ export const initReservesByHelper = async ( console.log( ` - Reserve ready for: ${chunkedSymbols[chunkIndex].join(", ")}`, - chunkedInitInputParams[chunkIndex][0].bTokenImpl, - chunkedInitInputParams[chunkIndex][0].underlyingAssetName + chunkedInitInputParams[chunkIndex][0].underlyingAsset ); console.log(" * gasUsed", tx3.gasUsed.toString()); } @@ -152,7 +151,7 @@ export const initNftsByHelper = async ( verify: boolean ) => { const addressProvider = await getLendPoolAddressesProvider(); - const bnftRegistry = await getBNFTRegistryProxy(); + const bnftRegistry = await addressProvider.getBNFTRegistry(); // CHUNK CONFIGURATION const initChunks = 1; diff --git a/helpers/types.ts b/helpers/types.ts index 9c1fc16..900666d 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -10,6 +10,7 @@ export enum eEthereumNetwork { coverage = "coverage", hardhat = "hardhat", localhost = "localhost", + develop = "develop", rinkeby = "rinkeby", main = "main", } @@ -325,6 +326,7 @@ export interface iEthereumParamsPerNetwork { [eEthereumNetwork.coverage]: T; [eEthereumNetwork.hardhat]: T; [eEthereumNetwork.localhost]: T; + [eEthereumNetwork.develop]: T; [eEthereumNetwork.rinkeby]: T; [eEthereumNetwork.main]: T; } diff --git a/markets/bend/commons.ts b/markets/bend/commons.ts index 155bf34..099e4b3 100644 --- a/markets/bend/commons.ts +++ b/markets/bend/commons.ts @@ -53,6 +53,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: undefined, [eEthereumNetwork.hardhat]: undefined, [eEthereumNetwork.localhost]: undefined, + [eEthereumNetwork.develop]: '0x740A26A9aa27e193C8d15d75A1ca1C19AE735c21', [eEthereumNetwork.rinkeby]: '0xC019619F15aF1f96A695aBA39478e64ABcAa474b', [eEthereumNetwork.main]: undefined, }, @@ -60,6 +61,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: undefined, [eEthereumNetwork.hardhat]: undefined, [eEthereumNetwork.localhost]: undefined, + [eEthereumNetwork.develop]: '0x0B815174656df530906CC39E983431f0Ec442C59', [eEthereumNetwork.rinkeby]: '0x64DA9D7651CA78caAB756740C6057e2b7B1E63De', [eEthereumNetwork.main]: undefined, }, @@ -69,6 +71,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: undefined, [eEthereumNetwork.hardhat]: undefined, [eEthereumNetwork.localhost]: undefined, + [eEthereumNetwork.develop]: '0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B', [eEthereumNetwork.rinkeby]: '0xafF5C36642385b6c7Aaf7585eC785aB2316b5db6', [eEthereumNetwork.main]: undefined, }, @@ -77,6 +80,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: undefined, [eEthereumNetwork.coverage]: undefined, [eEthereumNetwork.localhost]: undefined, + [eEthereumNetwork.develop]: '0x14048d069A5E821eB82E01a275fdfC915C5BcfC4', [eEthereumNetwork.rinkeby]: '0xFc6a5b329340719b2693C2c74a5D056cf4f93FB0', [eEthereumNetwork.main]: undefined, }, @@ -86,6 +90,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.localhost]: '0xCE1e5D792d24F62b29D35DeB85eC04b1F66447b1', + [eEthereumNetwork.develop]: '0xf440346C93868879B5D3b8e5f96fEc57D4f2dcdf', [eEthereumNetwork.rinkeby]: '0xB873F088EB721261bc88BbC739B5C794e02e414b', [eEthereumNetwork.main]: '', }, @@ -94,10 +99,12 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.localhost]: '', + [eEthereumNetwork.develop]: '', [eEthereumNetwork.rinkeby]: '', [eEthereumNetwork.main]: '', }, ProviderRegistryOwner: { + [eEthereumNetwork.develop]: '0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B', [eEthereumNetwork.rinkeby]: '0xafF5C36642385b6c7Aaf7585eC785aB2316b5db6', [eEthereumNetwork.main]: '', [eEthereumNetwork.coverage]: '', @@ -109,6 +116,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.localhost]: '', + [eEthereumNetwork.develop]: '', [eEthereumNetwork.rinkeby]: '', [eEthereumNetwork.main]: '', }, @@ -116,6 +124,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.localhost]: '', + [eEthereumNetwork.develop]: '', [eEthereumNetwork.rinkeby]: '', [eEthereumNetwork.main]: '', }, @@ -130,6 +139,11 @@ export const CommonsConfig: ICommonConfiguration = { USDC: '0x2cC3790f7CF280fA898E4913CA980410cF38e53b', USD: '0x6B8dcBD1bb131ED184221902df1Fe21019ccD7dc', }, + [eEthereumNetwork.develop]: { + DAI: '0x74825DbC8BF76CC4e9494d0ecB210f676Efa001D', + USDC: '0xdCA36F27cbC4E38aE16C4E9f99D39b42337F6dcf', + USD: '0x8A753747A1Fa494EC906cE90E9f37563A8AF630e', //ETH - USD + }, [eEthereumNetwork.rinkeby]: { DAI: '0x74825DbC8BF76CC4e9494d0ecB210f676Efa001D', USDC: '0xdCA36F27cbC4E38aE16C4E9f99D39b42337F6dcf', @@ -147,6 +161,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.localhost]: {}, [eEthereumNetwork.main]: {}, [eEthereumNetwork.rinkeby]: {}, + [eEthereumNetwork.develop]: {}, }, ReservesConfig: {}, NftsAssets: { @@ -155,6 +170,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.localhost]: {}, [eEthereumNetwork.main]: {}, [eEthereumNetwork.rinkeby]: {}, + [eEthereumNetwork.develop]: {}, }, NftsConfig: {}, @@ -162,6 +178,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', // deployed in local evm [eEthereumNetwork.hardhat]: '', // deployed in local evm [eEthereumNetwork.localhost]: '0xB4B4ead1A260F1572b88b9D8ABa5A152D166c104', + [eEthereumNetwork.develop]: '0x3C73A32C11E20101be3D5ff2F67Af15a4ACbF298', [eEthereumNetwork.rinkeby]: '0xaD1908f909B5C5D2B1032a215d611773F26f089F', [eEthereumNetwork.main]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', }, @@ -170,6 +187,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', // deployed in local evm [eEthereumNetwork.hardhat]: '', // deployed in local evm [eEthereumNetwork.localhost]: '0xb2f97A3c2E48cd368901657e31Faaa93035CE390', + [eEthereumNetwork.develop]: '0xE159fC1226dbCe3e9d511e884a067D09C3290B9E', [eEthereumNetwork.rinkeby]: '0x6389eA3Cf6dE815ba76d7Cf4C6Db6A7093471bcb', [eEthereumNetwork.main]: '0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb', }, @@ -177,6 +195,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', // deployed in local evm [eEthereumNetwork.hardhat]: '', // deployed in local evm [eEthereumNetwork.localhost]: '0x5a60c5d89A0A0e08ae0CAe73453e3AcC9C335847', + [eEthereumNetwork.develop]: '0xcDbBC001976F79db2fC1ECfd140031fE970CeaEc', [eEthereumNetwork.rinkeby]: '0x74e4418A41169Fb951Ca886976ccd8b36968c4Ab', [eEthereumNetwork.main]: '0xb7F7F6C52F2e2fdb1963Eab30438024864c313F6', }, @@ -185,6 +204,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '0xafF5C36642385b6c7Aaf7585eC785aB2316b5db6', [eEthereumNetwork.hardhat]: '0xafF5C36642385b6c7Aaf7585eC785aB2316b5db6', [eEthereumNetwork.localhost]: '0xafF5C36642385b6c7Aaf7585eC785aB2316b5db6', + [eEthereumNetwork.develop]: '0xA9620F4655620863FaC5AD87DcB4e3ab5e1C5b86', [eEthereumNetwork.rinkeby]: '0x7A02EE743Aadca63d60945971B7eD12c7f26b6d2', [eEthereumNetwork.main]: '', }, @@ -192,6 +212,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: ZERO_ADDRESS, [eEthereumNetwork.hardhat]: ZERO_ADDRESS, [eEthereumNetwork.localhost]: "0x1eaA4a267eDcde0eB5e08D08810Aa1696b123a2D", + [eEthereumNetwork.develop]: '0x602bE80f0Bf54E0AffaCD794dfe3ac0f867F7581', [eEthereumNetwork.rinkeby]: '0xD800e97aE32b06C1e89ca5126c7bF6aEF89D6B24', [eEthereumNetwork.main]: ZERO_ADDRESS, }, diff --git a/markets/bend/index.ts b/markets/bend/index.ts index e6aa83b..ddefe58 100644 --- a/markets/bend/index.ts +++ b/markets/bend/index.ts @@ -48,6 +48,11 @@ export const BendConfig: IBendConfiguration = { DAI: '0xa05ffF82bcC0C599984b0839218DC6ee9328d1Fb', USDC: '0x025FE4760c6f14dE878C22cEb09A3235F16dAe53', }, + [eEthereumNetwork.develop]: { + WETH: '0x3C73A32C11E20101be3D5ff2F67Af15a4ACbF298', + DAI: '0xcB3b65Fb934d5A49a4738d8c6CC328dc96120ad7', + USDC: '0x5C6105989c5Be5f88b88fD0b2cE15A282d7c9F07', + }, [eEthereumNetwork.rinkeby]: { WETH: '0xaD1908f909B5C5D2B1032a215d611773F26f089F', DAI: '0x51EA2fEb1b1EB0891595f846456068D497734ca4', @@ -70,6 +75,18 @@ export const BendConfig: IBendConfiguration = { MEEBITS: '0x69D1108D37825212736aC101B445b6B57a390d13', MAYC: '0x8b89F971cA1A5dE1B7df7f554a3024eE84FeeB05', }, + [eEthereumNetwork.develop]: { + WPUNKS: '0xcDbBC001976F79db2fC1ECfd140031fE970CeaEc', + BAYC: '0x818674fb778147DC81c85f9af3d5cd73E03545B2', + DOODLE: '0x54Db2bbf13cC6b2073CcDf9A06B7A2862eb8C3cC', + COOL: '0xD83948C3deF2a75F9E4A0c0D9e5E7e050a6c2423', + MEEBITS: '0x0DD78C9209f57088bAB52C953C8bD51BDA3570A2', + MAYC: '0x5EDB2c61d14648D8b2adb559a6AE13F7E3a11678', + WOW: '0xdB5DD4ecBd172BfAc198e617122D00CaD12ee2ae', + CLONEX: '0xA446Ab62fb4bdCEdAF69259354ad0C1C7ccb87ff', + AZUKI: '0x048e8A2738F4d292Cf30e8468066ce930dFBDAfa', + KONGZ: '0x65217942f01E563e5F292ba0C7285D0ce85fDE1e', + }, [eEthereumNetwork.rinkeby]: { WPUNKS: '0x74e4418A41169Fb951Ca886976ccd8b36968c4Ab', BAYC: '0x588D1a07ccdb224cB28dCd8E3dD46E16B3a72b5e', diff --git a/package.json b/package.json index 327fddf..5514a64 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "hardhat": "hardhat", "hardhat:node": "hardhat node", "hardhat:localhost": "hardhat --network localhost", + "hardhat:develop": "hardhat --network develop", "hardhat:rinkeby": "hardhat --network rinkeby", "hardhat:main": "hardhat --network main", "compile": "SKIP_LOAD=true hardhat compile", @@ -28,20 +29,24 @@ "bend:hardhat:dev:migration": "npm run compile && npm run hardhat -- bend:dev", "bend:localhost:dev:migration": "npm run compile && npm run hardhat:localhost -- bend:dev", "bend:localhost:full:migration": "npm run compile && npm run hardhat:localhost -- bend:mainnet", + "bend:develop:full:migration": "npm run compile && npm run hardhat:develop -- bend:mainnet", "bend:rinkeby:full:migration": "npm run compile && npm run hardhat:rinkeby -- bend:mainnet", "bend:main:full:migration": "npm run compile && npm run hardhat:main -- bend:mainnet --verify", - "bend:fork:main": "npm run compile && FORK=main hardhat bend:mainnet", - "bend:fork:rinkeby": "npm run compile && FORK=rinkeby hardhat bend:mainnet", + "develop:verify": "npm run hardhat:develop verify:general -- --all --pool Bend", + "develop:verify:reserves": "npm run hardhat:develop verify:reserves -- --pool Bend", + "develop:verify:nfts": "npm run hardhat:develop verify:nfts -- --pool Bend", + "develop:print-contracts": "npm run hardhat:develop -- print-contracts", + "develop:print-config": "hardhat --network develop print-config --pool Bend", "rinkeby:verify": "npm run hardhat:rinkeby verify:general -- --all --pool Bend", "rinkeby:verify:reserves": "npm run hardhat:rinkeby verify:reserves -- --pool Bend", "rinkeby:verify:nfts": "npm run hardhat:rinkeby verify:nfts -- --pool Bend", + "rinkeby:print-contracts": "npm run hardhat:rinkeby -- print-contracts", + "rinkeby:print-config": "hardhat --network rinkeby print-config --pool Bend", "main:verify": "npm run hardhat:main verify:general -- --all --pool Bend", "main:verify:reserves": "npm run hardhat:main verify:reserves -- --pool Bend", "main:verify:nfts": "npm run hardhat:main verify:nfts -- --pool Bend", - "print-contracts:rinkeby": "npm run hardhat:rinkeby -- print-contracts", - "print-contracts:main": "npm run hardhat:main -- print-contracts", - "print-config:rinkeby": "hardhat --network rinkeby print-config --pool Bend", - "print-config:main": "hardhat --network main print-config --pool Bend", + "main:print-contracts": "npm run hardhat:main -- print-contracts", + "main:print-config": "hardhat --network main print-config --pool Bend", "prepublishOnly": "npm run compile" }, "devDependencies": { diff --git a/tasks/full/initialize.ts b/tasks/full/initialize.ts index cf05b3e..c0d9acd 100644 --- a/tasks/full/initialize.ts +++ b/tasks/full/initialize.ts @@ -1,10 +1,5 @@ import { task } from "hardhat/config"; import { getParamPerNetwork } from "../../helpers/contracts-helpers"; -import { - deployBendProtocolDataProvider, - deployWalletBalancerProvider, - deployUiPoolDataProvider, -} from "../../helpers/contracts-deployments"; import { loadPoolConfig, ConfigNames, getTreasuryAddress } from "../../helpers/configuration"; import { getWETHGateway, getPunkGateway } from "../../helpers/contracts-getters"; import { eNetwork, ICommonConfiguration } from "../../helpers/types"; @@ -63,25 +58,6 @@ task("full:initialize-lend-pool", "Initialize lend pool configuration.") await initNftsByHelper(poolConfig.NftsConfig, nftsAssets, admin, pool, verify); await configureNftsByHelper(poolConfig.NftsConfig, nftsAssets, admin); - - ////////////////////////////////////////////////////////////////////////// - console.log("Deploy bend & wallet & ui provider"); - const reserveOracle = await addressesProvider.getReserveOracle(); - const nftOracle = await addressesProvider.getNFTOracle(); - - const walletBalanceProvider = await deployWalletBalancerProvider(verify); - console.log("WalletBalancerProvider deployed at:", walletBalanceProvider.address); - await waitForTx(await addressesProvider.setWalletBalanceProvider(walletBalanceProvider.address)); - - // this contract is not support upgrade, just deploy new contract - const bendProtocolDataProvider = await deployBendProtocolDataProvider(addressesProvider.address, verify); - console.log("BendProtocolDataProvider deployed at:", bendProtocolDataProvider.address); - await waitForTx(await addressesProvider.setBendDataProvider(bendProtocolDataProvider.address)); - - // this contract is not support upgrade, just deploy new contract - const uiPoolDataProvider = await deployUiPoolDataProvider(reserveOracle, nftOracle, verify); - console.log("UiPoolDataProvider deployed at:", uiPoolDataProvider.address); - await waitForTx(await addressesProvider.setUIDataProvider(uiPoolDataProvider.address)); } catch (err) { console.error(err); exit(1); diff --git a/tasks/full/lend-pool.ts b/tasks/full/lend-pool.ts index d6ba936..2e93f1d 100644 --- a/tasks/full/lend-pool.ts +++ b/tasks/full/lend-pool.ts @@ -1,5 +1,9 @@ import { task } from "hardhat/config"; -import { getParamPerNetwork, insertContractAddressInDb } from "../../helpers/contracts-helpers"; +import { + getEthersSignerByAddress, + getParamPerNetwork, + insertContractAddressInDb, +} from "../../helpers/contracts-helpers"; import { deployBTokenImplementations, deployBTokensAndBNFTsHelper, diff --git a/tasks/migrations/bend.mainnet.ts b/tasks/migrations/bend.mainnet.ts index 509056b..f3a94aa 100644 --- a/tasks/migrations/bend.mainnet.ts +++ b/tasks/migrations/bend.mainnet.ts @@ -79,6 +79,10 @@ task("bend:mainnet", "Deploy full enviroment") console.log("\n\nInitialize gateway"); await DRE.run("full:initialize-gateway", { pool: POOL_NAME }); + ////////////////////////////////////////////////////////////////////////// + console.log("\n\nDeploy data provider"); + await DRE.run("full:deploy-data-provider", { pool: POOL_NAME, wallet: true, ui: true, protocol: true }); + if (verify) { printContracts(); diff --git a/tasks/misc/custom-task.ts b/tasks/misc/custom-task.ts index cac8d79..22d459c 100644 --- a/tasks/misc/custom-task.ts +++ b/tasks/misc/custom-task.ts @@ -174,7 +174,9 @@ task("dev:withdraw-eth", "Doing custom task") task("dev:borrow-eth-using-bayc", "Doing custom task") .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) - .setAction(async ({ pool }, DRE) => { + .addParam("amount", "Amount to borrow, like 0.01") + .addParam("tokenId", "Token ID of NFT, like 1234") + .setAction(async ({ pool, amount, tokenId }, DRE) => { await DRE.run("set-DRE"); const network = DRE.network.name as eNetwork; @@ -183,22 +185,30 @@ task("dev:borrow-eth-using-bayc", "Doing custom task") const signer = await getDeploySigner(); + const wethAddress = await getContractAddressInDb("WETH"); + const weth = await getMintableERC20(wethAddress); + let amountDecimals: BigNumberish; + if (amount == "-1") { + amountDecimals = MAX_UINT_AMOUNT; + } else { + amountDecimals = await convertToCurrencyDecimals(weth.address, amount); + } + const wethGateway = await getWETHGateway(); const baycAddress = await getContractAddressInDb("BAYC"); const bayc = await getMintableERC721(baycAddress); await waitForTx(await bayc.setApprovalForAll(wethGateway.address, true)); - const tokenId = 5002; await waitForTx(await bayc.mint(tokenId)); - await waitForTx( - await wethGateway.borrowETH("100000000000000000", bayc.address, tokenId, await signer.getAddress(), "0") - ); + await waitForTx(await wethGateway.borrowETH(amountDecimals, bayc.address, tokenId, await signer.getAddress(), "0")); }); task("dev:borrow-usdc-using-bayc", "Doing custom task") .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) - .setAction(async ({ pool }, DRE) => { + .addParam("amount", "Amount to borrow, like 0.01") + .addParam("tokenId", "Token ID of NFT, like 1234") + .setAction(async ({ pool, amount, tokenId }, DRE) => { await DRE.run("set-DRE"); const network = DRE.network.name as eNetwork; @@ -207,6 +217,15 @@ task("dev:borrow-usdc-using-bayc", "Doing custom task") const signer = await getDeploySigner(); + const wethAddress = await getContractAddressInDb("USDC"); + const weth = await getMintableERC20(wethAddress); + let amountDecimals: BigNumberish; + if (amount == "-1") { + amountDecimals = MAX_UINT_AMOUNT; + } else { + amountDecimals = await convertToCurrencyDecimals(weth.address, amount); + } + const lendPool = await getLendPool(await addressesProvider.getLendPool()); const usdcAddress = await getContractAddressInDb("USDC"); @@ -328,6 +347,9 @@ task("dev:repay-eth-using-punk", "Doing repay task") const wpunk = await getWrappedPunk(wpunkAddress); const punkGateway = await getPunkGateway(); + const wethAddress = await getContractAddressInDb("WETH"); + const weth = await getMintableERC20(wethAddress); + let amountDecimals: BigNumberish; if (amount == "-1") { const bendDataProvider = await getBendProtocolDataProvider(await addressesProvider.getBendDataProvider()); @@ -335,7 +357,7 @@ task("dev:repay-eth-using-punk", "Doing repay task") console.log("Loan Borrow Amount:", loanData.currentAmount.toString()); amountDecimals = new BigNumber(loanData.currentAmount.toString()).multipliedBy(1.1).toFixed(0); } else { - amountDecimals = await convertToCurrencyDecimals(wpunk.address, amount); + amountDecimals = await convertToCurrencyDecimals(weth.address, amount); } await waitForTx(await punkGateway.repayETH(id, amountDecimals, { value: amountDecimals })); @@ -359,6 +381,9 @@ task("dev:repay-eth-using-erc721", "Doing repay task") const wethGateway = await getWETHGateway(); + const wethAddress = await getContractAddressInDb("WETH"); + const weth = await getMintableERC20(wethAddress); + let amountDecimals: BigNumberish; if (amount == "-1" || amount == "0") { const bendDataProvider = await getBendProtocolDataProvider(await addressesProvider.getBendDataProvider()); @@ -366,10 +391,10 @@ task("dev:repay-eth-using-erc721", "Doing repay task") console.log("Loan Borrow Amount:", loanData.currentAmount.toString()); amountDecimals = loanData.currentAmount; } else { - amountDecimals = await convertToCurrencyDecimals(token, amount); + amountDecimals = await convertToCurrencyDecimals(weth.address, amount); } - await waitForTx(await wethGateway.redeemETH(token, id, amountDecimals, { value: amountDecimals })); + await waitForTx(await wethGateway.repayETH(token, id, amountDecimals, { value: amountDecimals })); }); task("dev:print-ui-reserve-data", "Doing custom task") diff --git a/tasks/misc/oracle-admin.ts b/tasks/misc/oracle-admin.ts index cbf79c3..dcf9a4d 100644 --- a/tasks/misc/oracle-admin.ts +++ b/tasks/misc/oracle-admin.ts @@ -14,7 +14,22 @@ import { getEthersSignerByAddress, getParamPerNetwork } from "../../helpers/cont import { getNowTimeInSeconds, waitForTx } from "../../helpers/misc-utils"; import { eNetwork } from "../../helpers/types"; -task("oracle-amdin:set-nft-assets", "Set new nft asset to oracle") +task("oracle-admin:set-nft-proxy", "Doing oracle admin task") + .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) + .addParam("proxy", "Address of NFT Oracle proxy contract") + .setAction(async ({ pool, proxy }, DRE) => { + await DRE.run("set-DRE"); + + const network = DRE.network.name as eNetwork; + const poolConfig = loadPoolConfig(pool); + const addressesProvider = await getLendPoolAddressesProvider(); + + await waitForTx(await addressesProvider.setNFTOracle(proxy)); + + console.log("OK"); + }); + +task("oracle-admin:set-nft-assets", "Set new nft asset to oracle") .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .addParam("assets", "Address list of underlying nft asset contract") .setAction(async ({ pool, assets }, DRE) => { @@ -46,7 +61,7 @@ task("oracle-amdin:set-nft-assets", "Set new nft asset to oracle") console.log("OK"); }); -task("oracle-amdin:set-price-feed-admin", "Doing oracle admin task") +task("oracle-admin:set-price-feed-admin", "Doing oracle admin task") .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .addParam("feedAdmin", "Address of price feed") .setAction(async ({ pool, feedAdmin }, DRE) => { @@ -63,7 +78,7 @@ task("oracle-amdin:set-price-feed-admin", "Doing oracle admin task") console.log("New PriceFeedAdmin:", await nftOracleProxy.priceFeedAdmin()); }); -task("oracle-amdin:feed-init-nft-price", "Doing oracle admin task") +task("oracle-admin:feed-init-nft-price", "Doing oracle admin task") .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .setAction(async ({ pool }, DRE) => { await DRE.run("set-DRE"); @@ -76,14 +91,19 @@ task("oracle-amdin:feed-init-nft-price", "Doing oracle admin task") const latestTime = await getNowTimeInSeconds(); const nftsAssets = getParamPerNetwork(poolConfig.NftsAssets, network); + const feedAdminAddress = await nftOracleProxy.priceFeedAdmin(); + const feedAdminSigner = await getEthersSignerByAddress(feedAdminAddress); + for (const nftSymbol of Object.keys(nftsAssets)) { const price = MOCK_NFT_AGGREGATORS_PRICES[nftSymbol]; console.log(`setAssetData:(${nftSymbol}, ${price})`); - await waitForTx(await nftOracleProxy.setAssetData(nftsAssets[nftSymbol], price, latestTime, 1)); + await waitForTx( + await nftOracleProxy.connect(feedAdminSigner).setAssetData(nftsAssets[nftSymbol], price, latestTime, 1) + ); } }); -task("oracle-amdin:add-usd-eth-asset", "Doing oracle admin task") +task("oracle-admin:add-usd-eth-asset", "Doing oracle admin task") .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .setAction(async ({ pool }, DRE) => { await DRE.run("set-DRE"); diff --git a/tasks/misc/pool-admin.ts b/tasks/misc/pool-admin.ts index 952cc7c..c3975f2 100644 --- a/tasks/misc/pool-admin.ts +++ b/tasks/misc/pool-admin.ts @@ -11,7 +11,7 @@ import { configureNftsByHelper, configureReservesByHelper } from "../../helpers/ import { waitForTx } from "../../helpers/misc-utils"; import { eNetwork } from "../../helpers/types"; -task("pool-amdin:set-pause", "Doing lend pool pause task") +task("pool-admin:set-pause", "Doing lend pool pause task") .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .addParam("state", "Admin state of pause, 0-false, 1-true") .setAction(async ({ pool, state }, DRE) => { @@ -46,7 +46,7 @@ task("pool-amdin:set-pause", "Doing lend pool pause task") console.log("LendPool New Pause State:", newPause); }); -task("pool-amdin:update-nfts-config", "Doing lend pool nft config task") +task("pool-admin:update-nfts-config", "Doing lend pool nft config task") .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .setAction(async ({ pool }, DRE) => { await DRE.run("set-DRE"); @@ -65,7 +65,7 @@ task("pool-amdin:update-nfts-config", "Doing lend pool nft config task") await configureNftsByHelper(poolConfig.NftsConfig, nftsAssets, poolAdminAddress); }); -task("pool-amdin:update-reserves-config", "Doing lend pool reserve config task") +task("pool-admin:update-reserves-config", "Doing lend pool reserve config task") .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .setAction(async ({ pool }, DRE) => { await DRE.run("set-DRE"); @@ -84,7 +84,7 @@ task("pool-amdin:update-reserves-config", "Doing lend pool reserve config task") await configureReservesByHelper(poolConfig.ReservesConfig, reservesAssets, poolAdminAddress); }); -task("pool-amdin:set-reserve-active", "Doing Reserve active task") +task("pool-admin:set-reserve-active", "Doing Reserve active task") .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .addParam("asset", "Address of Reserve") .addParam("state", "Active state, 0-false, 1-true") @@ -125,7 +125,7 @@ task("pool-amdin:set-reserve-active", "Doing Reserve active task") console.log("Reserve New Active State:", newReserveConfig.isActive); }); -task("pool-amdin:set-reserve-frozen", "Doing Reserve frozen task") +task("pool-admin:set-reserve-frozen", "Doing Reserve frozen task") .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .addParam("asset", "Address of Reserve") .addParam("state", "Frozen state, 0-false, 1-true") @@ -166,7 +166,7 @@ task("pool-amdin:set-reserve-frozen", "Doing Reserve frozen task") console.log("Reserve New Frozen State:", newReserveConfig.isFrozen); }); -task("pool-amdin:set-nft-active", "Doing NFT active task") +task("pool-admin:set-nft-active", "Doing NFT active task") .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .addParam("asset", "Address of Reserve") .addParam("state", "Admin state of Active, 0-false, 1-true") @@ -207,7 +207,7 @@ task("pool-amdin:set-nft-active", "Doing NFT active task") console.log("NFT New Active State:", newNftConfig.isActive); }); -task("pool-amdin:set-nft-frozen", "Doing NFT frozen task") +task("pool-admin:set-nft-frozen", "Doing NFT frozen task") .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .addParam("asset", "Address of Reserve") .addParam("state", "Frozen state, 0-false, 1-true") From 1483f35cea2d7ef6f227d434924909e04f8cf8ae Mon Sep 17 00:00:00 2001 From: Thor Seldon Date: Mon, 14 Mar 2022 21:34:18 +0800 Subject: [PATCH 2/6] update collector contract for approve and transfer --- contracts/misc/BendCollector.sol | 27 ++++++- deployments/deployed-contracts-rinkeby.json | 5 +- tasks/full/bend-collector.ts | 90 ++++++++++++++++++++- tasks/misc/print-reserve.ts | 28 ++++++- 4 files changed, 140 insertions(+), 10 deletions(-) diff --git a/contracts/misc/BendCollector.sol b/contracts/misc/BendCollector.sol index 6f99945..024c067 100644 --- a/contracts/misc/BendCollector.sol +++ b/contracts/misc/BendCollector.sol @@ -1,6 +1,9 @@ // SPDX-License-Identifier: agpl-3.0 pragma solidity ^0.8.0; +import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; +import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import {SafeERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; /** @@ -9,9 +12,29 @@ import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Ini * systems that will pull BEND funds for their specific use case * @author Bend **/ -contract BendCollector is Initializable { +contract BendCollector is Initializable, OwnableUpgradeable { + using SafeERC20Upgradeable for IERC20Upgradeable; + /** * @dev initializes the contract upon assignment to the BendUpgradeableProxy */ - function initialize() external initializer {} + function initialize() external initializer { + __Ownable_init(); + } + + function approve( + IERC20Upgradeable token, + address recipient, + uint256 amount + ) external onlyOwner { + token.safeApprove(recipient, amount); + } + + function transfer( + IERC20Upgradeable token, + address recipient, + uint256 amount + ) external onlyOwner { + token.safeTransfer(recipient, amount); + } } diff --git a/deployments/deployed-contracts-rinkeby.json b/deployments/deployed-contracts-rinkeby.json index ba2ce1e..da5d37f 100644 --- a/deployments/deployed-contracts-rinkeby.json +++ b/deployments/deployed-contracts-rinkeby.json @@ -183,11 +183,10 @@ "deployer": "0xafF5C36642385b6c7Aaf7585eC785aB2316b5db6" }, "BendCollectorImpl": { - "address": "0x2450b937a42051acf3d7709F9AC04ea407a647dC" + "address": "0x7fa1F11a10C8a9c6A646cA7B3248c244fD8bc69B" }, "BendCollector": { - "address": "0x7A02EE743Aadca63d60945971B7eD12c7f26b6d2", - "deployer": "0xafF5C36642385b6c7Aaf7585eC785aB2316b5db6" + "address": "0x7A02EE743Aadca63d60945971B7eD12c7f26b6d2" }, "WOW": { "address": "0xdfC14f7A536944467834EF7ce7b05a9a79BCDFaD", diff --git a/tasks/full/bend-collector.ts b/tasks/full/bend-collector.ts index b684d2b..beab7e5 100644 --- a/tasks/full/bend-collector.ts +++ b/tasks/full/bend-collector.ts @@ -1,12 +1,24 @@ +import { BigNumber } from "ethers"; import { task } from "hardhat/config"; import { ConfigNames, loadPoolConfig } from "../../helpers/configuration"; +import { MAX_UINT_AMOUNT } from "../../helpers/constants"; import { deployBendCollector, deployBendProxyAdmin, deployBendUpgradeableProxy, } from "../../helpers/contracts-deployments"; -import { getBendProxyAdminById, getBendUpgradeableProxy } from "../../helpers/contracts-getters"; -import { getParamPerNetwork, insertContractAddressInDb } from "../../helpers/contracts-helpers"; +import { + getBendCollectorProxy, + getBendProxyAdminById, + getBendUpgradeableProxy, + getIErc20Detailed, +} from "../../helpers/contracts-getters"; +import { + convertToCurrencyDecimals, + getEthersSignerByAddress, + getParamPerNetwork, + insertContractAddressInDb, +} from "../../helpers/contracts-helpers"; import { notFalsyOrZeroAddress, waitForTx } from "../../helpers/misc-utils"; import { eNetwork, eContractid } from "../../helpers/types"; import { BendCollector, BendUpgradeableProxy } from "../../types"; @@ -30,7 +42,79 @@ task("full:deploy-bend-collector", "Deploy bend collect contract") eContractid.BendCollector, collectorProxyAdmin.address, bendCollectorImpl.address, - initEncodedData + initEncodedData, + verify ); console.log("Bend Collector: proxy %s, implementation %s", bendCollectorProxy.address, bendCollectorImpl.address); }); + +task("full:upgrade-bend-collector", "Upgrade bend collect contract") + .addFlag("verify", "Verify contracts at Etherscan") + .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) + .addParam("proxy", "Contract proxy address") + .addOptionalParam("initFunc", "Name of initialize function") + .setAction(async ({ verify, pool, proxy, initFunc }, DRE) => { + await DRE.run("set-DRE"); + const poolConfig = loadPoolConfig(pool); + const network = DRE.network.name; + + const collectorProxyAdmin = await getBendProxyAdminById(eContractid.BendProxyAdminFund); + const proxyAdminOwnerAddress = await collectorProxyAdmin.owner(); + const proxyAdminOwnerSigner = await getEthersSignerByAddress(proxyAdminOwnerAddress); + console.log("Proxy Admin: address %s, owner %s", collectorProxyAdmin.address, proxyAdminOwnerAddress); + + const bendCollectorProxy = await getBendUpgradeableProxy(proxy); + console.log("Bend Collector: proxy %s", bendCollectorProxy.address); + + const bendCollector = await getBendCollectorProxy(bendCollectorProxy.address); + + const bendCollectorImpl = await deployBendCollector(verify); + console.log("Bend Collector: new implementation %s", bendCollectorImpl.address); + insertContractAddressInDb(eContractid.BendCollector, bendCollectorProxy.address); + + if (initFunc != undefined && initFunc != "") { + const initEncodedData = bendCollectorImpl.interface.encodeFunctionData(initFunc); + + await waitForTx( + await collectorProxyAdmin + .connect(proxyAdminOwnerSigner) + .upgradeAndCall(bendCollectorProxy.address, bendCollectorImpl.address, initEncodedData) + ); + } else { + await waitForTx( + await collectorProxyAdmin + .connect(proxyAdminOwnerSigner) + .upgrade(bendCollectorProxy.address, bendCollectorImpl.address) + ); + } + + await waitForTx(await bendCollector.initialize_v2()); + + console.log("Bend Collector: upgrade ok"); + }); + +task("bend-collector:approve-erc20", "Approve ERC20 token") + .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) + .addParam("proxy", "Contract proxy address") + .addParam("token", "ERC20 token address") + .addParam("to", "Target address, like 0.1") + .addParam("amount", "Amount to approve") + .setAction(async ({ verify, pool, proxy, token, to, amount }, DRE) => { + await DRE.run("set-DRE"); + const poolConfig = loadPoolConfig(pool); + const network = DRE.network.name; + + const bendCollectorProxy = await getBendUpgradeableProxy(proxy); + console.log("Bend Collector: proxy %s", bendCollectorProxy.address); + + const bendCollector = await getBendCollectorProxy(bendCollectorProxy.address); + + let amountDecimals = MAX_UINT_AMOUNT; + if (amount != "-1") { + amountDecimals = (await convertToCurrencyDecimals(token, amount)).toString(); + } + + await waitForTx(await bendCollector.approve(token, to, amountDecimals)); + + console.log("Bend Collector: approve ok"); + }); diff --git a/tasks/misc/print-reserve.ts b/tasks/misc/print-reserve.ts index abad9a9..2234c78 100644 --- a/tasks/misc/print-reserve.ts +++ b/tasks/misc/print-reserve.ts @@ -1,6 +1,13 @@ import { task } from "hardhat/config"; import { ConfigNames, loadPoolConfig } from "../../helpers/configuration"; -import { getBendProtocolDataProvider } from "../../helpers/contracts-getters"; +import { + getBendProtocolDataProvider, + getBToken, + getDebtToken, + getIErc20Detailed, + getLendPoolAddressesProvider, + getUIPoolDataProvider, +} from "../../helpers/contracts-getters"; import { getParamPerNetwork } from "../../helpers/contracts-helpers"; import { DRE } from "../../helpers/misc-utils"; import { eEthereumNetwork, eNetwork } from "../../helpers/types"; @@ -14,7 +21,24 @@ task("print-reserve", "Print data of specified reserve and user") const network = process.env.FORK ? (process.env.FORK as eNetwork) : (localBRE.network.name as eNetwork); const poolConfig = loadPoolConfig(pool); - const protocolDataProvider = await getBendProtocolDataProvider(); + const addressProvider = await getLendPoolAddressesProvider(); + const protocolDataProvider = await getBendProtocolDataProvider(await addressProvider.getBendDataProvider()); + const uiDataProvider = await getUIPoolDataProvider(await addressProvider.getUIDataProvider()); + + const reserveToken = await protocolDataProvider.getReserveTokenData(asset); + const bTokenContract = await getBToken(reserveToken.bTokenAddress); + const bTokenTotalSupply = await bTokenContract.totalSupply(); + const debtTokenContract = await getDebtToken(reserveToken.debtTokenAddress); + const debtTokenTotalSupply = await debtTokenContract.totalSupply(); + const underlyingContract = await getIErc20Detailed(asset); + const underlyingBalance = await underlyingContract.balanceOf(reserveToken.bTokenAddress); + + console.log(`- reserve token`); + console.log(` - underlyingSymbol:`, await underlyingContract.symbol()); + console.log(` - underlyingDecimals:`, await underlyingContract.decimals()); + console.log(` - underlyingBalance:`, underlyingBalance.toString()); + console.log(` - bTokenTotalSupply:`, bTokenTotalSupply.toString()); + console.log(` - debtTokenTotalSupply:`, debtTokenTotalSupply.toString()); const reserveData = await protocolDataProvider.getReserveData(asset); From 1570502aed5ea23fe560c93ee4393f675fa0b5e3 Mon Sep 17 00:00:00 2001 From: Thor Seldon Date: Tue, 15 Mar 2022 16:26:11 +0800 Subject: [PATCH 3/6] add kovan testnet --- .gitignore | 1 + deployments/deployed-contracts-kovan.json | 136 ++++++++++++++++++++++ hardhat.config.ts | 1 + helper-hardhat-config.ts | 5 + helpers/contracts-helpers.ts | 4 +- helpers/types.ts | 2 + markets/bend/commons.ts | 21 ++++ markets/bend/index.ts | 17 +++ package.json | 7 ++ tasks/full/lend-pool.ts | 1 + 10 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 deployments/deployed-contracts-kovan.json diff --git a/.gitignore b/.gitignore index 6af053e..b47371b 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ deployed-contracts.json !/deployments/deployed-contracts-main*.json !/deployments/deployed-contracts-rinkeby*.json !/deployments/deployed-contracts-develop*.json +!/deployments/deployed-contracts-kovan*.json /flattened bend-flattened.* diff --git a/deployments/deployed-contracts-kovan.json b/deployments/deployed-contracts-kovan.json new file mode 100644 index 0000000..b8125d9 --- /dev/null +++ b/deployments/deployed-contracts-kovan.json @@ -0,0 +1,136 @@ +{ + "WETHMocked": { + "address": "0x2F4dA7F22E603aac1A9840D384d63c91a40ddD8D", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "WETH": { + "address": "0x2F4dA7F22E603aac1A9840D384d63c91a40ddD8D", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "MintableERC20": { + "address": "0x0bb5261d7b100bcfAe9976aFFFae50B7dDaBa176", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "DAI": { + "address": "0x02176F918da9E5eBbD42C313713eDD218aFAd52c", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "USDC": { + "address": "0x0bb5261d7b100bcfAe9976aFFFae50B7dDaBa176", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "CryptoPunksMarket": { + "address": "0xc667A10012209D8Fccc85aF7a913d8bBd26c18a7", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "WrappedPunk": { + "address": "0x8Ffc30191AdF56C3Bb06BD03A358fdBfA2C06f63", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "WPUNKS": { + "address": "0x8Ffc30191AdF56C3Bb06BD03A358fdBfA2C06f63", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "MintableERC721": { + "address": "0xb08AD9349f7e38414aDA9CeC0a4A803019cAB795", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "BAYC": { + "address": "0x9131f9809f38FF12E65599530A2cA2Bc9C73Dfef", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "DOODLE": { + "address": "0x3413C9399D5EBEe4A0a9E4DC1a9D750033A1ff99", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "COOL": { + "address": "0x7759b23A458Ff7d4F0a7aBA4D170Cff58D1DccA2", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "MEEBITS": { + "address": "0xfb92ab53d8F72c925BCBdfe1f8F8EddcD89159f8", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "MAYC": { + "address": "0x4427b97F2AD7ceC0FA40b9a54061956E1ADf5927", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "WOW": { + "address": "0xe1700D190C39B934E4402030Fa8bE601Babf724A", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "CLONEX": { + "address": "0x4Ab75F1436D7bDa892DDf1Cd5Fc6774993CF7b05", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "AZUKI": { + "address": "0xd9570f0Fd191598fA10a5766824316B3BD01001a", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "KONGZ": { + "address": "0xb08AD9349f7e38414aDA9CeC0a4A803019cAB795", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "BendProxyAdminPool": { + "address": "0x8da1Cb92f02f5c441A275036Ed26BB03ad6C40Cb" + }, + "BendProxyAdminFund": { + "address": "0x4C8FA526099383508D1AdAE511EaEc7D587DB99b" + }, + "BendCollectorImpl": { + "address": "0xfc0b073F89bC75CDb87d19aAC451b8497E945145" + }, + "BendCollector": { + "address": "0xBC6E81c410FF3b32cDa031267772713f93599077", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "LendPoolAddressesProvider": { + "address": "0xFBcd346b1EeFd2c065be476C8a77262889028977", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "LendPoolAddressesProviderRegistry": { + "address": "0x727FfE709475B5D5004bd97f1F9C438ec2E4C0AE", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "ReserveLogic": { + "address": "0xaE2C9A213Ef74D6c223D25281A53fa6988bf087f", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "NftLogic": { + "address": "0xB2817bcf6042f5250c6Bf46C9c766D1FeAC9A390", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "GenericLogic": { + "address": "0x9678746d351EC6278e7d748D9f93a330aC4a9998", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "ValidationLogic": { + "address": "0x13c33e175a1708201c1D1873536D5EfBb32EC82f", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "LendPoolImpl": { + "address": "0x951891195a945441309483FB7082768A939B9e5C" + }, + "LendPool": { + "address": "0xC76160e4FD4357C823f6687691eA4e2dD5FE827f" + }, + "LendPoolLiquidatorImpl": { + "address": "0xab975d43225B929D2dC80eDa28F8968725139068" + }, + "LendPoolLiquidator": { + "address": "0xab975d43225B929D2dC80eDa28F8968725139068", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "LendPoolLoanImpl": { + "address": "0xB9B3cb27Ea7a8E0f0a70Eb079F2140fA09b87bFd" + }, + "LendPoolLoan": { + "address": "0x89F234249BF78AA0D90947ED19eBD040e53847c8" + }, + "LendPoolConfiguratorImpl": { + "address": "0x83607c42A66deb871758Ff563e0c5454ae129eDF" + }, + "LendPoolConfigurator": { + "address": "0xF07AE7d0c3e5A1397eFa1cCE0334Bb22D1E4AB30" + } +} \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index 61c6224..08e32ec 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -97,6 +97,7 @@ const buidlerConfig: HardhatUserConfig = { }, develop: getCommonNetworkConfig(eEthereumNetwork.develop, 4), rinkeby: getCommonNetworkConfig(eEthereumNetwork.rinkeby, 4), + kovan: getCommonNetworkConfig(eEthereumNetwork.kovan, 42), main: getCommonNetworkConfig(eEthereumNetwork.main, 1), hardhat: { hardfork: "london", diff --git a/helper-hardhat-config.ts b/helper-hardhat-config.ts index 88ddf9e..42ac9ef 100644 --- a/helper-hardhat-config.ts +++ b/helper-hardhat-config.ts @@ -32,6 +32,9 @@ export const NETWORKS_RPC_URL: iParamsPerNetwork = { [eEthereumNetwork.rinkeby]: ALCHEMY_KEY ? `https://eth-rinkeby.alchemyapi.io/v2/${ALCHEMY_KEY}` : `https://rinkeby.infura.io/v3/${INFURA_KEY}`, + [eEthereumNetwork.kovan]: ALCHEMY_KEY + ? `https://eth-kovan.alchemyapi.io/v2/${ALCHEMY_KEY}` + : `https://kovan.infura.io/v3/${INFURA_KEY}`, [eEthereumNetwork.main]: ALCHEMY_KEY ? `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_KEY}` : `https://mainnet.infura.io/v3/${INFURA_KEY}`, @@ -43,6 +46,7 @@ export const NETWORKS_RPC_URL: iParamsPerNetwork = { export const NETWORKS_DEFAULT_GAS: iParamsPerNetwork = { [eEthereumNetwork.develop]: 65 * GWEI, [eEthereumNetwork.rinkeby]: 65 * GWEI, + [eEthereumNetwork.kovan]: 65 * GWEI, [eEthereumNetwork.main]: 65 * GWEI, [eEthereumNetwork.coverage]: 65 * GWEI, [eEthereumNetwork.hardhat]: 65 * GWEI, @@ -52,6 +56,7 @@ export const NETWORKS_DEFAULT_GAS: iParamsPerNetwork = { export const BLOCK_TO_FORK: iParamsPerNetwork = { [eEthereumNetwork.main]: 13623705, [eEthereumNetwork.rinkeby]: 0, + [eEthereumNetwork.kovan]: 0, [eEthereumNetwork.develop]: 0, [eEthereumNetwork.coverage]: 0, [eEthereumNetwork.hardhat]: 0, diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index 1b4531a..4c56bd6 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -171,7 +171,7 @@ export const linkBytecode = (artifact: Artifact, libraries: any) => { }; export const getParamPerNetwork = (param: iParamsPerNetwork, network: eNetwork) => { - const { main, rinkeby, develop, hardhat, coverage, localhost } = param as iEthereumParamsPerNetwork; + const { main, rinkeby, kovan, develop, hardhat, coverage, localhost } = param as iEthereumParamsPerNetwork; if (process.env.FORK) { return param[process.env.FORK as eNetwork] as T; } @@ -185,6 +185,8 @@ export const getParamPerNetwork = (param: iParamsPerNetwork, network: eNet return localhost; case eEthereumNetwork.develop: return develop; + case eEthereumNetwork.kovan: + return kovan; case eEthereumNetwork.rinkeby: return rinkeby; case eEthereumNetwork.main: diff --git a/helpers/types.ts b/helpers/types.ts index 900666d..0f86adc 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -12,6 +12,7 @@ export enum eEthereumNetwork { localhost = "localhost", develop = "develop", rinkeby = "rinkeby", + kovan = "kovan", main = "main", } @@ -328,6 +329,7 @@ export interface iEthereumParamsPerNetwork { [eEthereumNetwork.localhost]: T; [eEthereumNetwork.develop]: T; [eEthereumNetwork.rinkeby]: T; + [eEthereumNetwork.kovan]: T; [eEthereumNetwork.main]: T; } diff --git a/markets/bend/commons.ts b/markets/bend/commons.ts index 099e4b3..42f5c23 100644 --- a/markets/bend/commons.ts +++ b/markets/bend/commons.ts @@ -54,6 +54,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: undefined, [eEthereumNetwork.localhost]: undefined, [eEthereumNetwork.develop]: '0x740A26A9aa27e193C8d15d75A1ca1C19AE735c21', + [eEthereumNetwork.kovan]: '0x8da1Cb92f02f5c441A275036Ed26BB03ad6C40Cb', [eEthereumNetwork.rinkeby]: '0xC019619F15aF1f96A695aBA39478e64ABcAa474b', [eEthereumNetwork.main]: undefined, }, @@ -62,6 +63,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: undefined, [eEthereumNetwork.localhost]: undefined, [eEthereumNetwork.develop]: '0x0B815174656df530906CC39E983431f0Ec442C59', + [eEthereumNetwork.kovan]: '0x4C8FA526099383508D1AdAE511EaEc7D587DB99b', [eEthereumNetwork.rinkeby]: '0x64DA9D7651CA78caAB756740C6057e2b7B1E63De', [eEthereumNetwork.main]: undefined, }, @@ -72,6 +74,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: undefined, [eEthereumNetwork.localhost]: undefined, [eEthereumNetwork.develop]: '0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B', + [eEthereumNetwork.kovan]: '0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B', [eEthereumNetwork.rinkeby]: '0xafF5C36642385b6c7Aaf7585eC785aB2316b5db6', [eEthereumNetwork.main]: undefined, }, @@ -81,6 +84,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: undefined, [eEthereumNetwork.localhost]: undefined, [eEthereumNetwork.develop]: '0x14048d069A5E821eB82E01a275fdfC915C5BcfC4', + [eEthereumNetwork.kovan]: '0x8956D65982Edc6397540d9f2C2be249E98DAFE8b', [eEthereumNetwork.rinkeby]: '0xFc6a5b329340719b2693C2c74a5D056cf4f93FB0', [eEthereumNetwork.main]: undefined, }, @@ -91,6 +95,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.localhost]: '0xCE1e5D792d24F62b29D35DeB85eC04b1F66447b1', [eEthereumNetwork.develop]: '0xf440346C93868879B5D3b8e5f96fEc57D4f2dcdf', + [eEthereumNetwork.kovan]: '0xC5d1624B46db4F3F628400C0F41c49220c210c3F', [eEthereumNetwork.rinkeby]: '0xB873F088EB721261bc88BbC739B5C794e02e414b', [eEthereumNetwork.main]: '', }, @@ -100,11 +105,13 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.localhost]: '', [eEthereumNetwork.develop]: '', + [eEthereumNetwork.kovan]: '', [eEthereumNetwork.rinkeby]: '', [eEthereumNetwork.main]: '', }, ProviderRegistryOwner: { [eEthereumNetwork.develop]: '0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B', + [eEthereumNetwork.kovan]: '0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B', [eEthereumNetwork.rinkeby]: '0xafF5C36642385b6c7Aaf7585eC785aB2316b5db6', [eEthereumNetwork.main]: '', [eEthereumNetwork.coverage]: '', @@ -117,6 +124,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.localhost]: '', [eEthereumNetwork.develop]: '', + [eEthereumNetwork.kovan]: '', [eEthereumNetwork.rinkeby]: '', [eEthereumNetwork.main]: '', }, @@ -125,6 +133,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.localhost]: '', [eEthereumNetwork.develop]: '', + [eEthereumNetwork.kovan]: '', [eEthereumNetwork.rinkeby]: '', [eEthereumNetwork.main]: '', }, @@ -144,6 +153,11 @@ export const CommonsConfig: ICommonConfiguration = { USDC: '0xdCA36F27cbC4E38aE16C4E9f99D39b42337F6dcf', USD: '0x8A753747A1Fa494EC906cE90E9f37563A8AF630e', //ETH - USD }, + [eEthereumNetwork.kovan]: { + DAI: '0x22B58f1EbEDfCA50feF632bD73368b2FdA96D541', + USDC: '0x64EaC61A2DFda2c3Fa04eED49AA33D021AeC8838', + USD: '0x9326BFA02ADD2366b30bacB125260Af641031331', //ETH - USD + }, [eEthereumNetwork.rinkeby]: { DAI: '0x74825DbC8BF76CC4e9494d0ecB210f676Efa001D', USDC: '0xdCA36F27cbC4E38aE16C4E9f99D39b42337F6dcf', @@ -161,6 +175,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.localhost]: {}, [eEthereumNetwork.main]: {}, [eEthereumNetwork.rinkeby]: {}, + [eEthereumNetwork.kovan]: {}, [eEthereumNetwork.develop]: {}, }, ReservesConfig: {}, @@ -170,6 +185,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.localhost]: {}, [eEthereumNetwork.main]: {}, [eEthereumNetwork.rinkeby]: {}, + [eEthereumNetwork.kovan]: {}, [eEthereumNetwork.develop]: {}, }, NftsConfig: {}, @@ -180,6 +196,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.localhost]: '0xB4B4ead1A260F1572b88b9D8ABa5A152D166c104', [eEthereumNetwork.develop]: '0x3C73A32C11E20101be3D5ff2F67Af15a4ACbF298', [eEthereumNetwork.rinkeby]: '0xaD1908f909B5C5D2B1032a215d611773F26f089F', + [eEthereumNetwork.kovan]: '0x2F4dA7F22E603aac1A9840D384d63c91a40ddD8D', [eEthereumNetwork.main]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', }, @@ -189,6 +206,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.localhost]: '0xb2f97A3c2E48cd368901657e31Faaa93035CE390', [eEthereumNetwork.develop]: '0xE159fC1226dbCe3e9d511e884a067D09C3290B9E', [eEthereumNetwork.rinkeby]: '0x6389eA3Cf6dE815ba76d7Cf4C6Db6A7093471bcb', + [eEthereumNetwork.kovan]: '0xc667A10012209D8Fccc85aF7a913d8bBd26c18a7', [eEthereumNetwork.main]: '0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb', }, WrappedPunkToken: { @@ -197,6 +215,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.localhost]: '0x5a60c5d89A0A0e08ae0CAe73453e3AcC9C335847', [eEthereumNetwork.develop]: '0xcDbBC001976F79db2fC1ECfd140031fE970CeaEc', [eEthereumNetwork.rinkeby]: '0x74e4418A41169Fb951Ca886976ccd8b36968c4Ab', + [eEthereumNetwork.kovan]: '0x8Ffc30191AdF56C3Bb06BD03A358fdBfA2C06f63', [eEthereumNetwork.main]: '0xb7F7F6C52F2e2fdb1963Eab30438024864c313F6', }, @@ -206,6 +225,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.localhost]: '0xafF5C36642385b6c7Aaf7585eC785aB2316b5db6', [eEthereumNetwork.develop]: '0xA9620F4655620863FaC5AD87DcB4e3ab5e1C5b86', [eEthereumNetwork.rinkeby]: '0x7A02EE743Aadca63d60945971B7eD12c7f26b6d2', + [eEthereumNetwork.kovan]: '0xBC6E81c410FF3b32cDa031267772713f93599077', [eEthereumNetwork.main]: '', }, IncentivesController: { @@ -214,6 +234,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.localhost]: "0x1eaA4a267eDcde0eB5e08D08810Aa1696b123a2D", [eEthereumNetwork.develop]: '0x602bE80f0Bf54E0AffaCD794dfe3ac0f867F7581', [eEthereumNetwork.rinkeby]: '0xD800e97aE32b06C1e89ca5126c7bF6aEF89D6B24', + [eEthereumNetwork.kovan]: '0x0c5E94DC433A0c67Bbc25801759284A6e1Dd85Bb', [eEthereumNetwork.main]: ZERO_ADDRESS, }, }; diff --git a/markets/bend/index.ts b/markets/bend/index.ts index ddefe58..06ddefc 100644 --- a/markets/bend/index.ts +++ b/markets/bend/index.ts @@ -53,6 +53,11 @@ export const BendConfig: IBendConfiguration = { DAI: '0xcB3b65Fb934d5A49a4738d8c6CC328dc96120ad7', USDC: '0x5C6105989c5Be5f88b88fD0b2cE15A282d7c9F07', }, + [eEthereumNetwork.kovan]: { + WETH: '0x2F4dA7F22E603aac1A9840D384d63c91a40ddD8D', + DAI: '0x02176F918da9E5eBbD42C313713eDD218aFAd52c', + USDC: '0x0bb5261d7b100bcfAe9976aFFFae50B7dDaBa176', + }, [eEthereumNetwork.rinkeby]: { WETH: '0xaD1908f909B5C5D2B1032a215d611773F26f089F', DAI: '0x51EA2fEb1b1EB0891595f846456068D497734ca4', @@ -87,6 +92,18 @@ export const BendConfig: IBendConfiguration = { AZUKI: '0x048e8A2738F4d292Cf30e8468066ce930dFBDAfa', KONGZ: '0x65217942f01E563e5F292ba0C7285D0ce85fDE1e', }, + [eEthereumNetwork.kovan]: { + WPUNKS: '0x8Ffc30191AdF56C3Bb06BD03A358fdBfA2C06f63', + BAYC: '0x9131f9809f38FF12E65599530A2cA2Bc9C73Dfef', + DOODLE: '0x3413C9399D5EBEe4A0a9E4DC1a9D750033A1ff99', + COOL: '0x7759b23A458Ff7d4F0a7aBA4D170Cff58D1DccA2', + MEEBITS: '0xfb92ab53d8F72c925BCBdfe1f8F8EddcD89159f8', + MAYC: '0x4427b97F2AD7ceC0FA40b9a54061956E1ADf5927', + WOW: '0xe1700D190C39B934E4402030Fa8bE601Babf724A', + CLONEX: '0x4Ab75F1436D7bDa892DDf1Cd5Fc6774993CF7b05', + AZUKI: '0xd9570f0Fd191598fA10a5766824316B3BD01001a', + KONGZ: '0xb08AD9349f7e38414aDA9CeC0a4A803019cAB795', + }, [eEthereumNetwork.rinkeby]: { WPUNKS: '0x74e4418A41169Fb951Ca886976ccd8b36968c4Ab', BAYC: '0x588D1a07ccdb224cB28dCd8E3dD46E16B3a72b5e', diff --git a/package.json b/package.json index 5514a64..759d88d 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "hardhat:localhost": "hardhat --network localhost", "hardhat:develop": "hardhat --network develop", "hardhat:rinkeby": "hardhat --network rinkeby", + "hardhat:kovan": "hardhat --network kovan", "hardhat:main": "hardhat --network main", "compile": "SKIP_LOAD=true hardhat compile", "test": "npm run compile && TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test/*.spec.ts", @@ -31,6 +32,7 @@ "bend:localhost:full:migration": "npm run compile && npm run hardhat:localhost -- bend:mainnet", "bend:develop:full:migration": "npm run compile && npm run hardhat:develop -- bend:mainnet", "bend:rinkeby:full:migration": "npm run compile && npm run hardhat:rinkeby -- bend:mainnet", + "bend:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- bend:mainnet", "bend:main:full:migration": "npm run compile && npm run hardhat:main -- bend:mainnet --verify", "develop:verify": "npm run hardhat:develop verify:general -- --all --pool Bend", "develop:verify:reserves": "npm run hardhat:develop verify:reserves -- --pool Bend", @@ -42,6 +44,11 @@ "rinkeby:verify:nfts": "npm run hardhat:rinkeby verify:nfts -- --pool Bend", "rinkeby:print-contracts": "npm run hardhat:rinkeby -- print-contracts", "rinkeby:print-config": "hardhat --network rinkeby print-config --pool Bend", + "kovan:verify": "npm run hardhat:kovan verify:general -- --all --pool Bend", + "kovan:verify:reserves": "npm run hardhat:kovan verify:reserves -- --pool Bend", + "kovan:verify:nfts": "npm run hardhat:kovan verify:nfts -- --pool Bend", + "kovan:print-contracts": "npm run hardhat:kovan -- print-contracts", + "kovan:print-config": "hardhat --network kovan print-config --pool Bend", "main:verify": "npm run hardhat:main verify:general -- --all --pool Bend", "main:verify:reserves": "npm run hardhat:main verify:reserves -- --pool Bend", "main:verify:nfts": "npm run hardhat:main verify:nfts -- --pool Bend", diff --git a/tasks/full/lend-pool.ts b/tasks/full/lend-pool.ts index 2e93f1d..0b9e18e 100644 --- a/tasks/full/lend-pool.ts +++ b/tasks/full/lend-pool.ts @@ -46,6 +46,7 @@ task("full:deploy-lend-pool", "Deploy lend pool for full enviroment") console.log("Setting BNFTRegistry to address provider..."); await waitForTx(await addressesProvider.setBNFTRegistry(bnftRegistryProxy.address)); + // Reserves Init & NFTs Init need IncentivesController const incentivesControllerAddress = getParamPerNetwork(poolConfig.IncentivesController, network); console.log("IncentivesController", poolConfig.IncentivesController); if (incentivesControllerAddress == undefined || !notFalsyOrZeroAddress(incentivesControllerAddress)) { From 68d2c11b720bf2b83e34bd4f8d58a9590e8bd864 Mon Sep 17 00:00:00 2001 From: Thor Seldon Date: Wed, 16 Mar 2022 18:37:55 +0800 Subject: [PATCH 4/6] modify code according certik audit comments. GLOBAL-04 | Unlocked Compiler Version AFL-02 | Function Visibility Optimization BPI-01 | Lack Of msg.sender Validation CKP-01 | Redundant Statements CKP-02 | Variables That Could Be Declared As Immutable CKP-03 | Missing Emit Events CON-02 | Declaration Naming Convention COR-01 | Functions With _ As Name Prefix Are Not private Or internal COT-01 | Any User Can Claim Airdrop Tokens VBC-01 | Usage Of Require Instead Of Assert VBC-02 | Centralization Related Risks VBC-03 | Missing Error Messages WBP-01 | Locked Ether --- .../deployments/BTokensAndBNFTsHelper.sol | 2 +- contracts/interfaces/IBNFT.sol | 2 +- contracts/interfaces/IBNFTRegistry.sol | 2 +- contracts/interfaces/IBToken.sol | 2 +- contracts/interfaces/IDebtToken.sol | 2 +- contracts/interfaces/IERC20Detailed.sol | 2 +- contracts/interfaces/IERC721Detailed.sol | 2 +- contracts/interfaces/IFlashLoanReceiver.sol | 2 +- .../interfaces/IIncentivesController.sol | 2 +- contracts/interfaces/IInterestRate.sol | 2 +- contracts/interfaces/ILendPool.sol | 6 +- .../interfaces/ILendPoolAddressesProvider.sol | 2 +- .../ILendPoolAddressesProviderRegistry.sol | 2 +- .../interfaces/ILendPoolConfigurator.sol | 2 +- contracts/interfaces/ILendPoolLiquidator.sol | 2 +- contracts/interfaces/ILendPoolLoan.sol | 2 +- contracts/interfaces/INFTOracle.sol | 2 +- contracts/interfaces/INFTOracleGetter.sol | 2 +- contracts/interfaces/IPunkGateway.sol | 2 +- contracts/interfaces/IPunks.sol | 2 +- contracts/interfaces/IReserveOracleGetter.sol | 2 +- contracts/interfaces/IScaledBalanceToken.sol | 2 +- contracts/interfaces/IUiPoolDataProvider.sol | 2 +- contracts/interfaces/IWETH.sol | 2 +- contracts/interfaces/IWETHGateway.sol | 2 +- contracts/interfaces/IWrappedPunks.sol | 2 +- .../configuration/NftConfiguration.sol | 2 +- .../configuration/ReserveConfiguration.sol | 2 +- contracts/libraries/helpers/Errors.sol | 2 +- contracts/libraries/logic/GenericLogic.sol | 2 +- contracts/libraries/logic/NftLogic.sol | 2 +- contracts/libraries/logic/ReserveLogic.sol | 2 +- contracts/libraries/logic/ValidationLogic.sol | 2 +- contracts/libraries/math/MathUtils.sol | 2 +- contracts/libraries/math/PercentageMath.sol | 2 +- contracts/libraries/math/WadRayMath.sol | 18 +++--- contracts/libraries/proxy/BendProxyAdmin.sol | 2 +- .../libraries/proxy/BendUpgradeableProxy.sol | 2 +- contracts/libraries/types/DataTypes.sol | 2 +- contracts/misc/BendCollector.sol | 2 +- contracts/misc/BendProtocolDataProvider.sol | 2 +- contracts/misc/UiPoolDataProvider.sol | 2 +- contracts/misc/WalletBalanceProvider.sol | 10 +--- contracts/mock/BNFT/BNFT.sol | 2 +- contracts/mock/BNFT/BNFTRegistry.sol | 2 +- contracts/mock/CryptoPunksMarket.sol | 2 +- contracts/mock/MintableERC20.sol | 2 +- contracts/mock/MintableERC721.sol | 2 +- contracts/mock/MockBTokenVersionN.sol | 2 +- contracts/mock/MockChainlinkOracle.sol | 2 +- contracts/mock/MockDebtTokenVersionN.sol | 2 +- contracts/mock/MockIncentivesController.sol | 2 +- contracts/mock/MockLendPoolVersionN.sol | 2 +- contracts/mock/MockNFTOracle.sol | 2 +- contracts/mock/MockReserveOracle.sol | 2 +- contracts/mock/SelfdestructTransfer.sol | 2 +- contracts/mock/WETH9.sol | 2 +- contracts/mock/WETH9Mocked.sol | 2 +- contracts/mock/WrappedPunk/ICryptoPunk.sol | 2 +- contracts/mock/WrappedPunk/UserProxy.sol | 2 +- contracts/mock/WrappedPunk/WrappedPunk.sol | 2 +- contracts/protocol/BToken.sol | 2 +- contracts/protocol/DebtToken.sol | 2 +- contracts/protocol/EmergencyTokenRecovery.sol | 5 +- contracts/protocol/IncentivizedERC20.sol | 2 +- contracts/protocol/InterestRate.sol | 2 +- contracts/protocol/LendPool.sol | 11 +--- .../protocol/LendPoolAddressesProvider.sol | 2 +- .../LendPoolAddressesProviderRegistry.sol | 2 +- contracts/protocol/LendPoolConfigurator.sol | 11 +--- contracts/protocol/LendPoolLiquidator.sol | 2 +- contracts/protocol/LendPoolLoan.sol | 7 +-- contracts/protocol/LendPoolStorage.sol | 2 +- contracts/protocol/NFTOracle.sol | 4 +- contracts/protocol/PunkGateway.sol | 13 ++-- contracts/protocol/ReserveOracle.sol | 2 +- contracts/protocol/WETHGateway.sol | 2 +- contracts/utils/BlockContext.sol | 2 +- deployments/deployed-contracts-develop.json | 2 +- deployments/deployed-contracts-kovan.json | 59 +++++++++++++++++++ deployments/deployed-contracts-rinkeby.json | 2 +- tasks/misc/print-config.ts | 6 +- test/configurator-nft.spec.ts | 2 +- test/configurator-reserve.spec.ts | 2 +- 84 files changed, 171 insertions(+), 125 deletions(-) diff --git a/contracts/deployments/BTokensAndBNFTsHelper.sol b/contracts/deployments/BTokensAndBNFTsHelper.sol index ce07c64..072cfa0 100644 --- a/contracts/deployments/BTokensAndBNFTsHelper.sol +++ b/contracts/deployments/BTokensAndBNFTsHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {LendPool} from "../protocol/LendPool.sol"; import {LendPoolAddressesProvider} from "../protocol/LendPoolAddressesProvider.sol"; diff --git a/contracts/interfaces/IBNFT.sol b/contracts/interfaces/IBNFT.sol index 8e46973..7b4ddac 100644 --- a/contracts/interfaces/IBNFT.sol +++ b/contracts/interfaces/IBNFT.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {IERC721EnumerableUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721EnumerableUpgradeable.sol"; import {IERC721MetadataUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol"; diff --git a/contracts/interfaces/IBNFTRegistry.sol b/contracts/interfaces/IBNFTRegistry.sol index e858648..3347a72 100644 --- a/contracts/interfaces/IBNFTRegistry.sol +++ b/contracts/interfaces/IBNFTRegistry.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; interface IBNFTRegistry { event Initialized(address genericImpl, string namePrefix, string symbolPrefix); diff --git a/contracts/interfaces/IBToken.sol b/contracts/interfaces/IBToken.sol index 5eda088..5595db2 100644 --- a/contracts/interfaces/IBToken.sol +++ b/contracts/interfaces/IBToken.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {ILendPoolAddressesProvider} from "./ILendPoolAddressesProvider.sol"; import {IIncentivesController} from "./IIncentivesController.sol"; diff --git a/contracts/interfaces/IDebtToken.sol b/contracts/interfaces/IDebtToken.sol index da38967..41aee9e 100644 --- a/contracts/interfaces/IDebtToken.sol +++ b/contracts/interfaces/IDebtToken.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {ILendPoolAddressesProvider} from "../interfaces/ILendPoolAddressesProvider.sol"; import {IIncentivesController} from "./IIncentivesController.sol"; diff --git a/contracts/interfaces/IERC20Detailed.sol b/contracts/interfaces/IERC20Detailed.sol index c1fa676..27a3d43 100644 --- a/contracts/interfaces/IERC20Detailed.sol +++ b/contracts/interfaces/IERC20Detailed.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {IERC20MetadataUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol"; diff --git a/contracts/interfaces/IERC721Detailed.sol b/contracts/interfaces/IERC721Detailed.sol index fbff1d9..92e3261 100644 --- a/contracts/interfaces/IERC721Detailed.sol +++ b/contracts/interfaces/IERC721Detailed.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {IERC721MetadataUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol"; diff --git a/contracts/interfaces/IFlashLoanReceiver.sol b/contracts/interfaces/IFlashLoanReceiver.sol index 37270a2..9d7f14d 100644 --- a/contracts/interfaces/IFlashLoanReceiver.sol +++ b/contracts/interfaces/IFlashLoanReceiver.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; /** * @title IFlashLoanReceiver interface diff --git a/contracts/interfaces/IIncentivesController.sol b/contracts/interfaces/IIncentivesController.sol index 7d1f3b0..3bccd2b 100644 --- a/contracts/interfaces/IIncentivesController.sol +++ b/contracts/interfaces/IIncentivesController.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; interface IIncentivesController { /** diff --git a/contracts/interfaces/IInterestRate.sol b/contracts/interfaces/IInterestRate.sol index d031e68..5a0dc01 100644 --- a/contracts/interfaces/IInterestRate.sol +++ b/contracts/interfaces/IInterestRate.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; /** * @title IInterestRate interface diff --git a/contracts/interfaces/ILendPool.sol b/contracts/interfaces/ILendPool.sol index 4a7ecfc..9c5e473 100644 --- a/contracts/interfaces/ILendPool.sol +++ b/contracts/interfaces/ILendPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {ILendPoolAddressesProvider} from "./ILendPoolAddressesProvider.sol"; import {DataTypes} from "../libraries/types/DataTypes.sol"; @@ -434,7 +434,7 @@ interface ILendPool { function setMaxNumberOfNfts(uint256 val) external; - function MAX_NUMBER_RESERVES() external view returns (uint256); + function getMaxNumberOfReserves() external view returns (uint256); - function MAX_NUMBER_NFTS() external view returns (uint256); + function getMaxNumberOfNfts() external view returns (uint256); } diff --git a/contracts/interfaces/ILendPoolAddressesProvider.sol b/contracts/interfaces/ILendPoolAddressesProvider.sol index 39e92d0..a4b8b45 100644 --- a/contracts/interfaces/ILendPoolAddressesProvider.sol +++ b/contracts/interfaces/ILendPoolAddressesProvider.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; /** * @title LendPoolAddressesProvider contract diff --git a/contracts/interfaces/ILendPoolAddressesProviderRegistry.sol b/contracts/interfaces/ILendPoolAddressesProviderRegistry.sol index d8c5b22..23fbd8e 100644 --- a/contracts/interfaces/ILendPoolAddressesProviderRegistry.sol +++ b/contracts/interfaces/ILendPoolAddressesProviderRegistry.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; /** * @title ILendPoolAddressesProviderRegistry contract diff --git a/contracts/interfaces/ILendPoolConfigurator.sol b/contracts/interfaces/ILendPoolConfigurator.sol index 2f8e2d5..311ff97 100644 --- a/contracts/interfaces/ILendPoolConfigurator.sol +++ b/contracts/interfaces/ILendPoolConfigurator.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; interface ILendPoolConfigurator { struct InitReserveInput { diff --git a/contracts/interfaces/ILendPoolLiquidator.sol b/contracts/interfaces/ILendPoolLiquidator.sol index 167aba3..7dd2230 100644 --- a/contracts/interfaces/ILendPoolLiquidator.sol +++ b/contracts/interfaces/ILendPoolLiquidator.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {DataTypes} from "../libraries/types/DataTypes.sol"; diff --git a/contracts/interfaces/ILendPoolLoan.sol b/contracts/interfaces/ILendPoolLoan.sol index ad80e77..8005c9d 100644 --- a/contracts/interfaces/ILendPoolLoan.sol +++ b/contracts/interfaces/ILendPoolLoan.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {DataTypes} from "../libraries/types/DataTypes.sol"; diff --git a/contracts/interfaces/INFTOracle.sol b/contracts/interfaces/INFTOracle.sol index 12b462f..171e72f 100644 --- a/contracts/interfaces/INFTOracle.sol +++ b/contracts/interfaces/INFTOracle.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; /************ @title INFTOracle interface diff --git a/contracts/interfaces/INFTOracleGetter.sol b/contracts/interfaces/INFTOracleGetter.sol index 18ad5f6..29a988a 100644 --- a/contracts/interfaces/INFTOracleGetter.sol +++ b/contracts/interfaces/INFTOracleGetter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; /************ @title INFTOracleGetter interface diff --git a/contracts/interfaces/IPunkGateway.sol b/contracts/interfaces/IPunkGateway.sol index 4b7e2d0..019e6b3 100644 --- a/contracts/interfaces/IPunkGateway.sol +++ b/contracts/interfaces/IPunkGateway.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; interface IPunkGateway { /** diff --git a/contracts/interfaces/IPunks.sol b/contracts/interfaces/IPunks.sol index cc2749a..e55d5ed 100644 --- a/contracts/interfaces/IPunks.sol +++ b/contracts/interfaces/IPunks.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; /** * @dev Interface for a permittable ERC721 contract diff --git a/contracts/interfaces/IReserveOracleGetter.sol b/contracts/interfaces/IReserveOracleGetter.sol index 2c4cd47..4cf8e7f 100644 --- a/contracts/interfaces/IReserveOracleGetter.sol +++ b/contracts/interfaces/IReserveOracleGetter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; /************ @title IReserveOracleGetter interface diff --git a/contracts/interfaces/IScaledBalanceToken.sol b/contracts/interfaces/IScaledBalanceToken.sol index 87cc3b4..69455f4 100644 --- a/contracts/interfaces/IScaledBalanceToken.sol +++ b/contracts/interfaces/IScaledBalanceToken.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; interface IScaledBalanceToken { /** diff --git a/contracts/interfaces/IUiPoolDataProvider.sol b/contracts/interfaces/IUiPoolDataProvider.sol index e4b11ba..06a8d01 100644 --- a/contracts/interfaces/IUiPoolDataProvider.sol +++ b/contracts/interfaces/IUiPoolDataProvider.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {ILendPoolAddressesProvider} from "./ILendPoolAddressesProvider.sol"; import {IIncentivesController} from "./IIncentivesController.sol"; diff --git a/contracts/interfaces/IWETH.sol b/contracts/interfaces/IWETH.sol index bcd6f7a..3121d06 100644 --- a/contracts/interfaces/IWETH.sol +++ b/contracts/interfaces/IWETH.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; interface IWETH { function deposit() external payable; diff --git a/contracts/interfaces/IWETHGateway.sol b/contracts/interfaces/IWETHGateway.sol index e61e3c0..363a008 100644 --- a/contracts/interfaces/IWETHGateway.sol +++ b/contracts/interfaces/IWETHGateway.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; interface IWETHGateway { /** diff --git a/contracts/interfaces/IWrappedPunks.sol b/contracts/interfaces/IWrappedPunks.sol index ab3b1c7..30aab75 100644 --- a/contracts/interfaces/IWrappedPunks.sol +++ b/contracts/interfaces/IWrappedPunks.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; diff --git a/contracts/libraries/configuration/NftConfiguration.sol b/contracts/libraries/configuration/NftConfiguration.sol index 4bbbce2..9f80b1c 100644 --- a/contracts/libraries/configuration/NftConfiguration.sol +++ b/contracts/libraries/configuration/NftConfiguration.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {Errors} from "../helpers/Errors.sol"; import {DataTypes} from "../types/DataTypes.sol"; diff --git a/contracts/libraries/configuration/ReserveConfiguration.sol b/contracts/libraries/configuration/ReserveConfiguration.sol index e304cbf..1a5f372 100644 --- a/contracts/libraries/configuration/ReserveConfiguration.sol +++ b/contracts/libraries/configuration/ReserveConfiguration.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {Errors} from "../helpers/Errors.sol"; import {DataTypes} from "../types/DataTypes.sol"; diff --git a/contracts/libraries/helpers/Errors.sol b/contracts/libraries/helpers/Errors.sol index 4b8fadc..2b5aff5 100644 --- a/contracts/libraries/helpers/Errors.sol +++ b/contracts/libraries/helpers/Errors.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; /** * @title Errors library diff --git a/contracts/libraries/logic/GenericLogic.sol b/contracts/libraries/logic/GenericLogic.sol index 0838897..27cdfb1 100644 --- a/contracts/libraries/logic/GenericLogic.sol +++ b/contracts/libraries/logic/GenericLogic.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {ILendPoolLoan} from "../../interfaces/ILendPoolLoan.sol"; import {IReserveOracleGetter} from "../../interfaces/IReserveOracleGetter.sol"; diff --git a/contracts/libraries/logic/NftLogic.sol b/contracts/libraries/logic/NftLogic.sol index 8e01eae..e5f543e 100644 --- a/contracts/libraries/logic/NftLogic.sol +++ b/contracts/libraries/logic/NftLogic.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {Errors} from "../helpers/Errors.sol"; import {DataTypes} from "../types/DataTypes.sol"; diff --git a/contracts/libraries/logic/ReserveLogic.sol b/contracts/libraries/logic/ReserveLogic.sol index 595b1d9..05a2da3 100644 --- a/contracts/libraries/logic/ReserveLogic.sol +++ b/contracts/libraries/logic/ReserveLogic.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {IBToken} from "../../interfaces/IBToken.sol"; import {IDebtToken} from "../../interfaces/IDebtToken.sol"; diff --git a/contracts/libraries/logic/ValidationLogic.sol b/contracts/libraries/logic/ValidationLogic.sol index 2a5c2f4..e8a51c2 100644 --- a/contracts/libraries/logic/ValidationLogic.sol +++ b/contracts/libraries/logic/ValidationLogic.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {ReserveLogic} from "./ReserveLogic.sol"; import {GenericLogic} from "./GenericLogic.sol"; diff --git a/contracts/libraries/math/MathUtils.sol b/contracts/libraries/math/MathUtils.sol index 2c3abf5..e1cb778 100644 --- a/contracts/libraries/math/MathUtils.sol +++ b/contracts/libraries/math/MathUtils.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {WadRayMath} from "./WadRayMath.sol"; diff --git a/contracts/libraries/math/PercentageMath.sol b/contracts/libraries/math/PercentageMath.sol index 20007ee..c2b76e4 100644 --- a/contracts/libraries/math/PercentageMath.sol +++ b/contracts/libraries/math/PercentageMath.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {Errors} from "../helpers/Errors.sol"; diff --git a/contracts/libraries/math/WadRayMath.sol b/contracts/libraries/math/WadRayMath.sol index ae142c6..2ab74bb 100644 --- a/contracts/libraries/math/WadRayMath.sol +++ b/contracts/libraries/math/WadRayMath.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {Errors} from "../helpers/Errors.sol"; @@ -11,10 +11,10 @@ import {Errors} from "../helpers/Errors.sol"; library WadRayMath { uint256 internal constant WAD = 1e18; - uint256 internal constant halfWAD = WAD / 2; + uint256 internal constant HALF_WAD = WAD / 2; uint256 internal constant RAY = 1e27; - uint256 internal constant halfRAY = RAY / 2; + uint256 internal constant HALF_RAY = RAY / 2; uint256 internal constant WAD_RAY_RATIO = 1e9; @@ -37,14 +37,14 @@ library WadRayMath { * @return Half ray, 1e27/2 **/ function halfRay() internal pure returns (uint256) { - return halfRAY; + return HALF_RAY; } /** * @return Half ray, 1e18/2 **/ function halfWad() internal pure returns (uint256) { - return halfWAD; + return HALF_WAD; } /** @@ -58,9 +58,9 @@ library WadRayMath { return 0; } - require(a <= (type(uint256).max - halfWAD) / b, Errors.MATH_MULTIPLICATION_OVERFLOW); + require(a <= (type(uint256).max - HALF_WAD) / b, Errors.MATH_MULTIPLICATION_OVERFLOW); - return (a * b + halfWAD) / WAD; + return (a * b + HALF_WAD) / WAD; } /** @@ -89,9 +89,9 @@ library WadRayMath { return 0; } - require(a <= (type(uint256).max - halfRAY) / b, Errors.MATH_MULTIPLICATION_OVERFLOW); + require(a <= (type(uint256).max - HALF_RAY) / b, Errors.MATH_MULTIPLICATION_OVERFLOW); - return (a * b + halfRAY) / RAY; + return (a * b + HALF_RAY) / RAY; } /** diff --git a/contracts/libraries/proxy/BendProxyAdmin.sol b/contracts/libraries/proxy/BendProxyAdmin.sol index 0a3b4bb..09425e2 100644 --- a/contracts/libraries/proxy/BendProxyAdmin.sol +++ b/contracts/libraries/proxy/BendProxyAdmin.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; diff --git a/contracts/libraries/proxy/BendUpgradeableProxy.sol b/contracts/libraries/proxy/BendUpgradeableProxy.sol index 592202e..353d4f2 100644 --- a/contracts/libraries/proxy/BendUpgradeableProxy.sol +++ b/contracts/libraries/proxy/BendUpgradeableProxy.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import "../helpers/Errors.sol"; diff --git a/contracts/libraries/types/DataTypes.sol b/contracts/libraries/types/DataTypes.sol index 74255f1..71550e2 100644 --- a/contracts/libraries/types/DataTypes.sol +++ b/contracts/libraries/types/DataTypes.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; library DataTypes { struct ReserveData { diff --git a/contracts/misc/BendCollector.sol b/contracts/misc/BendCollector.sol index 024c067..810477e 100644 --- a/contracts/misc/BendCollector.sol +++ b/contracts/misc/BendCollector.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; diff --git a/contracts/misc/BendProtocolDataProvider.sol b/contracts/misc/BendProtocolDataProvider.sol index 85fe399..5749fc9 100644 --- a/contracts/misc/BendProtocolDataProvider.sol +++ b/contracts/misc/BendProtocolDataProvider.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {IERC20Detailed} from "../interfaces/IERC20Detailed.sol"; import {IERC721Detailed} from "../interfaces/IERC721Detailed.sol"; diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index 236a01c..2544876 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {IERC20Detailed} from "../interfaces/IERC20Detailed.sol"; import {IERC721Detailed} from "../interfaces/IERC721Detailed.sol"; diff --git a/contracts/misc/WalletBalanceProvider.sol b/contracts/misc/WalletBalanceProvider.sol index 4a78c53..ec2361e 100644 --- a/contracts/misc/WalletBalanceProvider.sol +++ b/contracts/misc/WalletBalanceProvider.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; @@ -28,14 +28,6 @@ contract WalletBalanceProvider { address constant MOCK_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; - /** - @dev Fallback function, don't accept any ETH - **/ - receive() external payable { - //only contracts can send ETH to the core - require(msg.sender.isContract(), "22"); - } - /** @dev Check the reserve balance of a wallet in a reserve contract diff --git a/contracts/mock/BNFT/BNFT.sol b/contracts/mock/BNFT/BNFT.sol index 433422f..40d7665 100644 --- a/contracts/mock/BNFT/BNFT.sol +++ b/contracts/mock/BNFT/BNFT.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {IBNFT} from "../../interfaces/IBNFT.sol"; import {IFlashLoanReceiver} from "../../interfaces/IFlashLoanReceiver.sol"; diff --git a/contracts/mock/BNFT/BNFTRegistry.sol b/contracts/mock/BNFT/BNFTRegistry.sol index c02d363..de2912e 100644 --- a/contracts/mock/BNFT/BNFTRegistry.sol +++ b/contracts/mock/BNFT/BNFTRegistry.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {IBNFTRegistry} from "../../interfaces/IBNFTRegistry.sol"; import {IBNFT} from "../../interfaces/IBNFT.sol"; diff --git a/contracts/mock/CryptoPunksMarket.sol b/contracts/mock/CryptoPunksMarket.sol index cee28ca..c3ebc30 100644 --- a/contracts/mock/CryptoPunksMarket.sol +++ b/contracts/mock/CryptoPunksMarket.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/contracts/mock/MintableERC20.sol b/contracts/mock/MintableERC20.sol index b3fcec1..42b5315 100644 --- a/contracts/mock/MintableERC20.sol +++ b/contracts/mock/MintableERC20.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; diff --git a/contracts/mock/MintableERC721.sol b/contracts/mock/MintableERC721.sol index 1a67e93..d9977a8 100644 --- a/contracts/mock/MintableERC721.sol +++ b/contracts/mock/MintableERC721.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import {ERC721Enumerable} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; diff --git a/contracts/mock/MockBTokenVersionN.sol b/contracts/mock/MockBTokenVersionN.sol index af4dd3f..870106d 100644 --- a/contracts/mock/MockBTokenVersionN.sol +++ b/contracts/mock/MockBTokenVersionN.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import "../protocol/BToken.sol"; diff --git a/contracts/mock/MockChainlinkOracle.sol b/contracts/mock/MockChainlinkOracle.sol index c08aab6..a573279 100644 --- a/contracts/mock/MockChainlinkOracle.sol +++ b/contracts/mock/MockChainlinkOracle.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {AggregatorV2V3Interface} from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV2V3Interface.sol"; diff --git a/contracts/mock/MockDebtTokenVersionN.sol b/contracts/mock/MockDebtTokenVersionN.sol index 0aac003..37c4239 100644 --- a/contracts/mock/MockDebtTokenVersionN.sol +++ b/contracts/mock/MockDebtTokenVersionN.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import "../protocol/DebtToken.sol"; diff --git a/contracts/mock/MockIncentivesController.sol b/contracts/mock/MockIncentivesController.sol index 126fecd..b96cf33 100644 --- a/contracts/mock/MockIncentivesController.sol +++ b/contracts/mock/MockIncentivesController.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {IIncentivesController} from "../interfaces/IIncentivesController.sol"; diff --git a/contracts/mock/MockLendPoolVersionN.sol b/contracts/mock/MockLendPoolVersionN.sol index 4336d3f..1765273 100644 --- a/contracts/mock/MockLendPoolVersionN.sol +++ b/contracts/mock/MockLendPoolVersionN.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import "../protocol/LendPool.sol"; diff --git a/contracts/mock/MockNFTOracle.sol b/contracts/mock/MockNFTOracle.sol index 5eebcfa..019f6bb 100644 --- a/contracts/mock/MockNFTOracle.sol +++ b/contracts/mock/MockNFTOracle.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {NFTOracle} from "../protocol/NFTOracle.sol"; contract MockNFTOracle is NFTOracle { diff --git a/contracts/mock/MockReserveOracle.sol b/contracts/mock/MockReserveOracle.sol index 3c3d397..186037d 100644 --- a/contracts/mock/MockReserveOracle.sol +++ b/contracts/mock/MockReserveOracle.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; //import {IReserveOracle} from "../interfaces/IReserveOracle.sol"; import {ReserveOracle} from "../protocol/ReserveOracle.sol"; diff --git a/contracts/mock/SelfdestructTransfer.sol b/contracts/mock/SelfdestructTransfer.sol index 6d7dcbe..474e28e 100644 --- a/contracts/mock/SelfdestructTransfer.sol +++ b/contracts/mock/SelfdestructTransfer.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; contract SelfdestructTransfer { function destroyAndTransfer(address payable to) external payable { diff --git a/contracts/mock/WETH9.sol b/contracts/mock/WETH9.sol index 15c0d47..5a3aebd 100644 --- a/contracts/mock/WETH9.sol +++ b/contracts/mock/WETH9.sol @@ -15,7 +15,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity ^0.8.0; +pragma solidity 0.8.4; contract WETH9 { string public name = "Wrapped Ether"; diff --git a/contracts/mock/WETH9Mocked.sol b/contracts/mock/WETH9Mocked.sol index e17b028..768da2c 100644 --- a/contracts/mock/WETH9Mocked.sol +++ b/contracts/mock/WETH9Mocked.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {WETH9} from "./WETH9.sol"; diff --git a/contracts/mock/WrappedPunk/ICryptoPunk.sol b/contracts/mock/WrappedPunk/ICryptoPunk.sol index e840148..0a159cc 100644 --- a/contracts/mock/WrappedPunk/ICryptoPunk.sol +++ b/contracts/mock/WrappedPunk/ICryptoPunk.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; interface ICryptoPunk { function punkIndexToAddress(uint256 punkIndex) external returns (address); diff --git a/contracts/mock/WrappedPunk/UserProxy.sol b/contracts/mock/WrappedPunk/UserProxy.sol index 97649a5..e06f7ab 100644 --- a/contracts/mock/WrappedPunk/UserProxy.sol +++ b/contracts/mock/WrappedPunk/UserProxy.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; contract UserProxy { address private immutable _owner; diff --git a/contracts/mock/WrappedPunk/WrappedPunk.sol b/contracts/mock/WrappedPunk/WrappedPunk.sol index 65bb64c..3fbe1a5 100644 --- a/contracts/mock/WrappedPunk/WrappedPunk.sol +++ b/contracts/mock/WrappedPunk/WrappedPunk.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; diff --git a/contracts/protocol/BToken.sol b/contracts/protocol/BToken.sol index 5f20f43..1a4ff69 100644 --- a/contracts/protocol/BToken.sol +++ b/contracts/protocol/BToken.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {ILendPoolAddressesProvider} from "../interfaces/ILendPoolAddressesProvider.sol"; import {ILendPoolConfigurator} from "../interfaces/ILendPoolConfigurator.sol"; diff --git a/contracts/protocol/DebtToken.sol b/contracts/protocol/DebtToken.sol index ecbd11e..7f997eb 100644 --- a/contracts/protocol/DebtToken.sol +++ b/contracts/protocol/DebtToken.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {IDebtToken} from "../interfaces/IDebtToken.sol"; import {ILendPool} from "../interfaces/ILendPool.sol"; diff --git a/contracts/protocol/EmergencyTokenRecovery.sol b/contracts/protocol/EmergencyTokenRecovery.sol index f907270..f91b44c 100644 --- a/contracts/protocol/EmergencyTokenRecovery.sol +++ b/contracts/protocol/EmergencyTokenRecovery.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; @@ -12,6 +12,8 @@ import {IPunks} from "../interfaces/IPunks.sol"; * @author Bend **/ abstract contract EmergencyTokenRecovery is Ownable { + event EmergencyEtherTransfer(address indexed to, uint256 amount); + /** * @dev transfer ERC20 from the utility contract, for ERC20 recovery in case of stuck tokens due * direct transfers to the contract address. @@ -65,5 +67,6 @@ abstract contract EmergencyTokenRecovery is Ownable { function emergencyEtherTransfer(address to, uint256 amount) external onlyOwner { (bool success, ) = to.call{value: amount}(new bytes(0)); require(success, "ETH_TRANSFER_FAILED"); + emit EmergencyEtherTransfer(to, amount); } } diff --git a/contracts/protocol/IncentivizedERC20.sol b/contracts/protocol/IncentivizedERC20.sol index 33726b9..4a37168 100644 --- a/contracts/protocol/IncentivizedERC20.sol +++ b/contracts/protocol/IncentivizedERC20.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {IIncentivesController} from "../interfaces/IIncentivesController.sol"; import {ILendPoolAddressesProvider} from "../interfaces/ILendPoolAddressesProvider.sol"; diff --git a/contracts/protocol/InterestRate.sol b/contracts/protocol/InterestRate.sol index 37d79af..28c13f1 100644 --- a/contracts/protocol/InterestRate.sol +++ b/contracts/protocol/InterestRate.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {IInterestRate} from "../interfaces/IInterestRate.sol"; import {ILendPoolAddressesProvider} from "../interfaces/ILendPoolAddressesProvider.sol"; diff --git a/contracts/protocol/LendPool.sol b/contracts/protocol/LendPool.sol index b596754..ab70d3d 100644 --- a/contracts/protocol/LendPool.sol +++ b/contracts/protocol/LendPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {IBToken} from "../interfaces/IBToken.sol"; import {IDebtToken} from "../interfaces/IDebtToken.sol"; @@ -70,11 +70,6 @@ contract LendPool is Initializable, ILendPool, LendPoolStorage, ContextUpgradeab require(_addressesProvider.getLendPoolConfigurator() == _msgSender(), Errors.LP_CALLER_NOT_LEND_POOL_CONFIGURATOR); } - modifier onlyAddressProvider() { - require(address(_addressesProvider) == msg.sender, Errors.CALLER_NOT_ADDRESS_PROVIDER); - _; - } - /** * @dev Function is invoked by the proxy contract when the LendPool contract is added to the * LendPoolAddressesProvider of the market. @@ -797,7 +792,7 @@ contract LendPool is Initializable, ILendPool, LendPoolStorage, ContextUpgradeab /** * @dev Returns the maximum number of reserves supported to be listed in this LendPool */ - function MAX_NUMBER_RESERVES() public view override returns (uint256) { + function getMaxNumberOfReserves() public view override returns (uint256) { return _maxNumberOfReserves; } @@ -808,7 +803,7 @@ contract LendPool is Initializable, ILendPool, LendPoolStorage, ContextUpgradeab /** * @dev Returns the maximum number of nfts supported to be listed in this LendPool */ - function MAX_NUMBER_NFTS() public view override returns (uint256) { + function getMaxNumberOfNfts() public view override returns (uint256) { return _maxNumberOfNfts; } diff --git a/contracts/protocol/LendPoolAddressesProvider.sol b/contracts/protocol/LendPoolAddressesProvider.sol index 22e4d15..545c833 100644 --- a/contracts/protocol/LendPoolAddressesProvider.sol +++ b/contracts/protocol/LendPoolAddressesProvider.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; // Prettier ignore to prevent buidler flatter bug // prettier-ignore diff --git a/contracts/protocol/LendPoolAddressesProviderRegistry.sol b/contracts/protocol/LendPoolAddressesProviderRegistry.sol index 34aa575..d7939a1 100644 --- a/contracts/protocol/LendPoolAddressesProviderRegistry.sol +++ b/contracts/protocol/LendPoolAddressesProviderRegistry.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {Errors} from "../libraries/helpers/Errors.sol"; diff --git a/contracts/protocol/LendPoolConfigurator.sol b/contracts/protocol/LendPoolConfigurator.sol index e37669d..1d909d4 100644 --- a/contracts/protocol/LendPoolConfigurator.sol +++ b/contracts/protocol/LendPoolConfigurator.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {ILendPoolLoan} from "../interfaces/ILendPoolLoan.sol"; import {IBToken} from "../interfaces/IBToken.sol"; @@ -38,11 +38,6 @@ contract LendPoolConfigurator is Initializable, ILendPoolConfigurator { _; } - modifier onlyAddressProvider() { - require(address(_addressesProvider) == msg.sender, Errors.CALLER_NOT_ADDRESS_PROVIDER); - _; - } - modifier onlyEmergencyAdmin() { require(_addressesProvider.getEmergencyAdmin() == msg.sender, Errors.LPC_CALLER_NOT_EMERGENCY_ADMIN); _; @@ -415,7 +410,7 @@ contract LendPoolConfigurator is Initializable, ILendPoolConfigurator { function setMaxNumberOfReserves(uint256 newVal) external onlyPoolAdmin { ILendPool cachedPool = _getLendPool(); //default value is 32 - uint256 curVal = cachedPool.MAX_NUMBER_RESERVES(); + uint256 curVal = cachedPool.getMaxNumberOfReserves(); require(newVal > curVal, Errors.LPC_INVALID_CONFIGURATION); cachedPool.setMaxNumberOfReserves(newVal); } @@ -423,7 +418,7 @@ contract LendPoolConfigurator is Initializable, ILendPoolConfigurator { function setMaxNumberOfNfts(uint256 newVal) external onlyPoolAdmin { ILendPool cachedPool = _getLendPool(); //default value is 256 - uint256 curVal = cachedPool.MAX_NUMBER_NFTS(); + uint256 curVal = cachedPool.getMaxNumberOfNfts(); require(newVal > curVal, Errors.LPC_INVALID_CONFIGURATION); cachedPool.setMaxNumberOfNfts(newVal); } diff --git a/contracts/protocol/LendPoolLiquidator.sol b/contracts/protocol/LendPoolLiquidator.sol index 2724365..98322ad 100644 --- a/contracts/protocol/LendPoolLiquidator.sol +++ b/contracts/protocol/LendPoolLiquidator.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {IBToken} from "../interfaces/IBToken.sol"; import {IDebtToken} from "../interfaces/IDebtToken.sol"; diff --git a/contracts/protocol/LendPoolLoan.sol b/contracts/protocol/LendPoolLoan.sol index 45fe55c..9f276e8 100644 --- a/contracts/protocol/LendPoolLoan.sol +++ b/contracts/protocol/LendPoolLoan.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {IBNFT} from "../interfaces/IBNFT.sol"; import {ILendPoolLoan} from "../interfaces/ILendPoolLoan.sol"; @@ -37,11 +37,6 @@ contract LendPoolLoan is Initializable, ILendPoolLoan, ContextUpgradeable, IERC7 _; } - modifier onlyAddressProvider() { - require(address(_addressesProvider) == msg.sender, Errors.CALLER_NOT_ADDRESS_PROVIDER); - _; - } - // called once by the factory at time of deployment function initialize(ILendPoolAddressesProvider provider) external initializer { __Context_init(); diff --git a/contracts/protocol/LendPoolStorage.sol b/contracts/protocol/LendPoolStorage.sol index 06de622..3ec6557 100644 --- a/contracts/protocol/LendPoolStorage.sol +++ b/contracts/protocol/LendPoolStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {DataTypes} from "../libraries/types/DataTypes.sol"; import {ReserveLogic} from "../libraries/logic/ReserveLogic.sol"; diff --git a/contracts/protocol/NFTOracle.sol b/contracts/protocol/NFTOracle.sol index fe74365..7f77b46 100644 --- a/contracts/protocol/NFTOracle.sol +++ b/contracts/protocol/NFTOracle.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; @@ -14,6 +14,7 @@ contract NFTOracle is INFTOracle, Initializable, OwnableUpgradeable, BlockContex event AssetAdded(address indexed asset); event AssetRemoved(address indexed asset); + event FeedAdminUpdated(address indexed admin); event SetAssetData(address indexed asset, uint256 price, uint256 timestamp, uint256 roundId); struct NFTPriceData { @@ -40,6 +41,7 @@ contract NFTOracle is INFTOracle, Initializable, OwnableUpgradeable, BlockContex function setPriceFeedAdmin(address _admin) external onlyOwner { priceFeedAdmin = _admin; + emit FeedAdminUpdated(_admin); } function setAssets(address[] calldata _nftContracts) external onlyOwner { diff --git a/contracts/protocol/PunkGateway.sol b/contracts/protocol/PunkGateway.sol index 167cf16..785632d 100644 --- a/contracts/protocol/PunkGateway.sol +++ b/contracts/protocol/PunkGateway.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; @@ -24,9 +24,9 @@ contract PunkGateway is ERC721Holder, IPunkGateway, Ownable, EmergencyTokenRecov ILendPoolAddressesProvider internal _addressProvider; IWETHGateway internal _wethGateway; - IPunks public punks; + IPunks public immutable punks; IWrappedPunks public wrappedPunks; - address public proxy; + address public immutable proxy; constructor( address addressProvider, @@ -92,7 +92,8 @@ contract PunkGateway is ERC721Holder, IPunkGateway, Ownable, EmergencyTokenRecov function _withdrawPunk(uint256 punkIndex, address onBehalfOf) internal { address owner = wrappedPunks.ownerOf(punkIndex); - require(owner == onBehalfOf, "PunkGateway: invalid owner"); + require(owner == _msgSender(), "PunkGateway: caller is not owner"); + require(owner == onBehalfOf, "PunkGateway: onBehalfOf is not owner"); wrappedPunks.safeTransferFrom(onBehalfOf, address(this), punkIndex); wrappedPunks.burn(punkIndex); @@ -118,6 +119,7 @@ contract PunkGateway is ERC721Holder, IPunkGateway, Ownable, EmergencyTokenRecov (uint256 paybackAmount, bool burn) = cachedPool.repay(address(wrappedPunks), punkIndex, amount); if (burn) { + require(borrower == _msgSender(), "PunkGateway: caller is not borrower"); _withdrawPunk(punkIndex, borrower); } @@ -170,6 +172,7 @@ contract PunkGateway is ERC721Holder, IPunkGateway, Ownable, EmergencyTokenRecov require(loanId != 0, "PunkGateway: no loan with such punkIndex"); DataTypes.LoanData memory loan = cachedPoolLoan.getLoan(loanId); + require(loan.bidderAddress == _msgSender(), "PunkGateway: caller is not bidder"); if (amount > 0) { IERC20(loan.reserveAsset).transferFrom(msg.sender, address(this), amount); @@ -211,6 +214,7 @@ contract PunkGateway is ERC721Holder, IPunkGateway, Ownable, EmergencyTokenRecov ); if (burn) { + require(borrower == _msgSender(), "PunkGateway: caller is not borrower"); _withdrawPunk(punkIndex, borrower); } @@ -251,6 +255,7 @@ contract PunkGateway is ERC721Holder, IPunkGateway, Ownable, EmergencyTokenRecov require(loanId != 0, "PunkGateway: no loan with such punkIndex"); DataTypes.LoanData memory loan = cachedPoolLoan.getLoan(loanId); + require(loan.bidderAddress == _msgSender(), "PunkGateway: caller is not bidder"); uint256 extraAmount = _wethGateway.liquidateETH{value: msg.value}(address(wrappedPunks), punkIndex); diff --git a/contracts/protocol/ReserveOracle.sol b/contracts/protocol/ReserveOracle.sol index c0e4d04..19dfdcf 100644 --- a/contracts/protocol/ReserveOracle.sol +++ b/contracts/protocol/ReserveOracle.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; diff --git a/contracts/protocol/WETHGateway.sol b/contracts/protocol/WETHGateway.sol index e3f7449..05dc736 100644 --- a/contracts/protocol/WETHGateway.sol +++ b/contracts/protocol/WETHGateway.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; diff --git a/contracts/utils/BlockContext.sol b/contracts/utils/BlockContext.sol index 0a2ceff..522999e 100644 --- a/contracts/utils/BlockContext.sol +++ b/contracts/utils/BlockContext.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.4; // wrap block.xxx functions for testing // only support timestamp and number so far diff --git a/deployments/deployed-contracts-develop.json b/deployments/deployed-contracts-develop.json index a4cc076..3fb6e9f 100644 --- a/deployments/deployed-contracts-develop.json +++ b/deployments/deployed-contracts-develop.json @@ -164,7 +164,7 @@ "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" }, "PunkGateway": { - "address": "0x02a23AeD66567bC36C6dABB75959972cC7644bf7", + "address": "0xf70adB1845bf1F3cd2aec7E62DE9677B1b2Ea7Fa", "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" }, "InterestRate": { diff --git a/deployments/deployed-contracts-kovan.json b/deployments/deployed-contracts-kovan.json index b8125d9..e43b6ba 100644 --- a/deployments/deployed-contracts-kovan.json +++ b/deployments/deployed-contracts-kovan.json @@ -132,5 +132,64 @@ }, "LendPoolConfigurator": { "address": "0xF07AE7d0c3e5A1397eFa1cCE0334Bb22D1E4AB30" + }, + "BTokensAndBNFTsHelper": { + "address": "0x5cd4a270823CD1D93048533A949C0CFA6825b7bA", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "BToken": { + "address": "0xd7d8431Ed91dC5970235A25D2c27B85809e0E9A2", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "DebtToken": { + "address": "0xf8434B273daA3802C72a5a367Ce559e4395f8648", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "ReserveOracleImpl": { + "address": "0x8Ef40D7d1E2070B67877Db68E70499d825C6aC10" + }, + "ReserveOracle": { + "address": "0xE77723b525648d22dF1607E8Ec2C019B72636882", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "NFTOracleImpl": { + "address": "0xeA1162D7756788c044aeeE8b648BEc558c53C5FE" + }, + "NFTOracle": { + "address": "0x613749B186d571B2c7678C20C73cd16596E7246F", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "WETHGateway": { + "address": "0x5843d551cD07f9f257AC0984e7E3B3aD82DB607d", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "PunkGateway": { + "address": "0x4528e827996dB24f65c9937f19579F2E524630D0", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "InterestRate": { + "address": "0x9023777e7ef341D8209Ece331d8C77F144eAccaF", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "rateStrategyWETH": { + "address": "0x71f0245c113B9195a5cE4389B4D8D75bdf8Dba97" + }, + "rateStrategyStableTwo": { + "address": "0x3b8A2C34918ca50D692c62c2F425C1f26bFc3a3d" + }, + "rateStrategyStableThree": { + "address": "0x9023777e7ef341D8209Ece331d8C77F144eAccaF" + }, + "WalletBalanceProvider": { + "address": "0xeC6Fe4E8580F057E72154A7D2A6996f8a024847A", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "BendProtocolDataProvider": { + "address": "0x9D24E09D260EB519512c6fD55b467FdAEe777A03", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" + }, + "UIPoolDataProvider": { + "address": "0xdD52994b7265ef0603006Ca588D23Ed9a2550834", + "deployer": "0x249D0dF00d8ca96952A9fc29ddD3199bD035A05B" } } \ No newline at end of file diff --git a/deployments/deployed-contracts-rinkeby.json b/deployments/deployed-contracts-rinkeby.json index da5d37f..8e0f0ff 100644 --- a/deployments/deployed-contracts-rinkeby.json +++ b/deployments/deployed-contracts-rinkeby.json @@ -131,7 +131,7 @@ "deployer": "0xafF5C36642385b6c7Aaf7585eC785aB2316b5db6" }, "PunkGateway": { - "address": "0x34eB0565b587bbD31A32e82e74145bb6C122834D", + "address": "0x5746250bC863Cd510691789c606c5F6AcaBC6431", "deployer": "0xafF5C36642385b6c7Aaf7585eC785aB2316b5db6" }, "InterestRate": { diff --git a/tasks/misc/print-config.ts b/tasks/misc/print-config.ts index 867eb12..eb4c012 100644 --- a/tasks/misc/print-config.ts +++ b/tasks/misc/print-config.ts @@ -48,9 +48,9 @@ task("print-config", "Print config of all reserves and nfts") console.log(`- LendPool config`); const lendPoolProxy = await getLendPool(await addressesProvider.getLendPool()); - console.log(` - MAX_NUMBER_RESERVES: ${await lendPoolProxy.MAX_NUMBER_RESERVES()}`); - console.log(` - MAX_NUMBER_NFTS: ${await lendPoolProxy.MAX_NUMBER_NFTS()}`); - console.log(` - paused: ${await lendPoolProxy.paused()}`); + console.log(` - MaxNumberOfReserves: ${await lendPoolProxy.getMaxNumberOfReserves()}`); + console.log(` - MaxNumberOfNfts: ${await lendPoolProxy.getMaxNumberOfNfts()}`); + console.log(` - Paused: ${await lendPoolProxy.paused()}`); const reserveFields = ["decimals", "reserveFactor", "borrowingEnabled", "isActive", "isFrozen"]; const reserveTokensFields = ["bTokenSymbol", "bTokenAddress", "debtTokenSymbol", "debtTokenAddress"]; diff --git a/test/configurator-nft.spec.ts b/test/configurator-nft.spec.ts index 51a7d75..a2590b7 100644 --- a/test/configurator-nft.spec.ts +++ b/test/configurator-nft.spec.ts @@ -168,7 +168,7 @@ makeSuite("Configurator-NFT", (testEnv: TestEnv) => { const { configurator, users, pool } = testEnv; await configurator.setMaxNumberOfNfts(512); - const wantVal = await pool.MAX_NUMBER_NFTS(); + const wantVal = await pool.getMaxNumberOfNfts(); expect(wantVal).to.be.equal(512); }); diff --git a/test/configurator-reserve.spec.ts b/test/configurator-reserve.spec.ts index d781aa5..240c3d8 100644 --- a/test/configurator-reserve.spec.ts +++ b/test/configurator-reserve.spec.ts @@ -183,7 +183,7 @@ makeSuite("Configurator-Reserve", (testEnv: TestEnv) => { const { configurator, users, pool } = testEnv; await configurator.setMaxNumberOfReserves(64); - const wantVal = await pool.MAX_NUMBER_RESERVES(); + const wantVal = await pool.getMaxNumberOfReserves(); expect(wantVal).to.be.equal(64); }); From e4500f91b93c98ad33d60dd87c1c6d4f95f2db12 Mon Sep 17 00:00:00 2001 From: Thor Seldon Date: Thu, 17 Mar 2022 16:10:32 +0800 Subject: [PATCH 5/6] add redeem threshold parameter --- abis/BendProtocolDataProvider.json | 5 ++ abis/LendPool.json | 52 +++++++++---------- abis/LendPoolConfigurator.json | 11 ++++ abis/NFTOracle.json | 13 +++++ abis/PunkGateway.json | 19 +++++++ abis/UiPoolDataProvider.json | 10 ++++ abis/WETHGateway.json | 19 +++++++ abis/WalletBalanceProvider.json | 4 -- .../deployments/BTokensAndBNFTsHelper.sol | 4 +- .../interfaces/ILendPoolConfigurator.sol | 8 ++- contracts/interfaces/IUiPoolDataProvider.sol | 1 + .../configuration/NftConfiguration.sol | 31 ++++++++++- contracts/libraries/helpers/Errors.sol | 2 + contracts/misc/BendProtocolDataProvider.sol | 3 +- contracts/misc/UiPoolDataProvider.sol | 2 +- contracts/protocol/LendPoolConfigurator.sol | 6 ++- contracts/protocol/LendPoolLiquidator.sol | 4 ++ helpers/init-helpers.ts | 15 +++++- helpers/types.ts | 1 + markets/bend/nftsConfigs.ts | 5 ++ package.json | 2 +- tasks/helpers/init-nft-to-pool.ts | 8 ++- tasks/misc/print-config.ts | 1 + test/configurator-nft.spec.ts | 16 ++++-- test/liquidate-redeem.spec.ts | 4 +- 25 files changed, 197 insertions(+), 49 deletions(-) diff --git a/abis/BendProtocolDataProvider.json b/abis/BendProtocolDataProvider.json index a8d0593..1b2fdae 100644 --- a/abis/BendProtocolDataProvider.json +++ b/abis/BendProtocolDataProvider.json @@ -310,6 +310,11 @@ "name": "redeemFine", "type": "uint256" }, + { + "internalType": "uint256", + "name": "redeemThreshold", + "type": "uint256" + }, { "internalType": "bool", "name": "isActive", diff --git a/abis/LendPool.json b/abis/LendPool.json index 41c1de5..11b5974 100644 --- a/abis/LendPool.json +++ b/abis/LendPool.json @@ -391,32 +391,6 @@ "name": "Withdraw", "type": "event" }, - { - "inputs": [], - "name": "MAX_NUMBER_NFTS", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_NUMBER_RESERVES", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -562,6 +536,32 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "getMaxNumberOfNfts", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxNumberOfReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/abis/LendPoolConfigurator.json b/abis/LendPoolConfigurator.json index 44c6a13..81c673e 100644 --- a/abis/LendPoolConfigurator.json +++ b/abis/LendPoolConfigurator.json @@ -114,6 +114,12 @@ "internalType": "uint256", "name": "redeemFine", "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemThreshold", + "type": "uint256" } ], "name": "NftAuctionChanged", @@ -485,6 +491,11 @@ "internalType": "uint256", "name": "redeemFine", "type": "uint256" + }, + { + "internalType": "uint256", + "name": "redeemThreshold", + "type": "uint256" } ], "name": "configureNftAsAuction", diff --git a/abis/NFTOracle.json b/abis/NFTOracle.json index acdfeff..5cb6de9 100644 --- a/abis/NFTOracle.json +++ b/abis/NFTOracle.json @@ -25,6 +25,19 @@ "name": "AssetRemoved", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "FeedAdminUpdated", + "type": "event" + }, { "anonymous": false, "inputs": [ diff --git a/abis/PunkGateway.json b/abis/PunkGateway.json index 345efcc..3bfbd1e 100644 --- a/abis/PunkGateway.json +++ b/abis/PunkGateway.json @@ -25,6 +25,25 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "EmergencyEtherTransfer", + "type": "event" + }, { "anonymous": false, "inputs": [ diff --git a/abis/UiPoolDataProvider.json b/abis/UiPoolDataProvider.json index 8479e11..a3e80f4 100644 --- a/abis/UiPoolDataProvider.json +++ b/abis/UiPoolDataProvider.json @@ -77,6 +77,11 @@ "name": "redeemFine", "type": "uint256" }, + { + "internalType": "uint256", + "name": "redeemThreshold", + "type": "uint256" + }, { "internalType": "bool", "name": "isActive", @@ -472,6 +477,11 @@ "name": "redeemFine", "type": "uint256" }, + { + "internalType": "uint256", + "name": "redeemThreshold", + "type": "uint256" + }, { "internalType": "bool", "name": "isActive", diff --git a/abis/WETHGateway.json b/abis/WETHGateway.json index 1e8566e..31251f3 100644 --- a/abis/WETHGateway.json +++ b/abis/WETHGateway.json @@ -15,6 +15,25 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "EmergencyEtherTransfer", + "type": "event" + }, { "anonymous": false, "inputs": [ diff --git a/abis/WalletBalanceProvider.json b/abis/WalletBalanceProvider.json index d34ed6a..25d7ff7 100644 --- a/abis/WalletBalanceProvider.json +++ b/abis/WalletBalanceProvider.json @@ -244,9 +244,5 @@ ], "stateMutability": "view", "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" } ] diff --git a/contracts/deployments/BTokensAndBNFTsHelper.sol b/contracts/deployments/BTokensAndBNFTsHelper.sol index 072cfa0..8201980 100644 --- a/contracts/deployments/BTokensAndBNFTsHelper.sol +++ b/contracts/deployments/BTokensAndBNFTsHelper.sol @@ -25,6 +25,7 @@ contract BTokensAndBNFTsHelper is Ownable { uint256 redeemDuration; uint256 auctionDuration; uint256 redeemFine; + uint256 redeemThreshold; } constructor( @@ -60,7 +61,8 @@ contract BTokensAndBNFTsHelper is Ownable { inputParams[i].asset, inputParams[i].redeemDuration, inputParams[i].auctionDuration, - inputParams[i].redeemFine + inputParams[i].redeemFine, + inputParams[i].redeemThreshold ); } } diff --git a/contracts/interfaces/ILendPoolConfigurator.sol b/contracts/interfaces/ILendPoolConfigurator.sol index 311ff97..c8aa550 100644 --- a/contracts/interfaces/ILendPoolConfigurator.sol +++ b/contracts/interfaces/ILendPoolConfigurator.sol @@ -155,7 +155,13 @@ interface ILendPoolConfigurator { * @param auctionDuration The new redeem duration * @param redeemFine The new redeem fine **/ - event NftAuctionChanged(address indexed asset, uint256 redeemDuration, uint256 auctionDuration, uint256 redeemFine); + event NftAuctionChanged( + address indexed asset, + uint256 redeemDuration, + uint256 auctionDuration, + uint256 redeemFine, + uint256 redeemThreshold + ); /** * @dev Emitted when an bToken implementation is upgraded diff --git a/contracts/interfaces/IUiPoolDataProvider.sol b/contracts/interfaces/IUiPoolDataProvider.sol index 06a8d01..4b9fde9 100644 --- a/contracts/interfaces/IUiPoolDataProvider.sol +++ b/contracts/interfaces/IUiPoolDataProvider.sol @@ -47,6 +47,7 @@ interface IUiPoolDataProvider { uint256 redeemDuration; uint256 auctionDuration; uint256 redeemFine; + uint256 redeemThreshold; bool isActive; bool isFrozen; address bNftAddress; diff --git a/contracts/libraries/configuration/NftConfiguration.sol b/contracts/libraries/configuration/NftConfiguration.sol index 9f80b1c..e3c3f49 100644 --- a/contracts/libraries/configuration/NftConfiguration.sol +++ b/contracts/libraries/configuration/NftConfiguration.sol @@ -18,6 +18,7 @@ library NftConfiguration { uint256 constant REDEEM_DURATION_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFF; // prettier-ignore uint256 constant AUCTION_DURATION_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFF; // prettier-ignore uint256 constant REDEEM_FINE_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFF; // prettier-ignore + uint256 constant REDEEM_THRESHOLD_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore /// @dev For the LTV, the start bit is 0 (up to 15), hence no bitshifting is needed uint256 constant LIQUIDATION_THRESHOLD_START_BIT_POSITION = 16; @@ -27,6 +28,7 @@ library NftConfiguration { uint256 constant REDEEM_DURATION_START_BIT_POSITION = 64; uint256 constant AUCTION_DURATION_START_BIT_POSITION = 72; uint256 constant REDEEM_FINE_START_BIT_POSITION = 80; + uint256 constant REDEEM_THRESHOLD_START_BIT_POSITION = 96; uint256 constant MAX_VALID_LTV = 65535; uint256 constant MAX_VALID_LIQUIDATION_THRESHOLD = 65535; @@ -34,6 +36,7 @@ library NftConfiguration { uint256 constant MAX_VALID_REDEEM_DURATION = 255; uint256 constant MAX_VALID_AUCTION_DURATION = 255; uint256 constant MAX_VALID_REDEEM_FINE = 65535; + uint256 constant MAX_VALID_REDEEM_THRESHOLD = 65535; /** * @dev Sets the Loan to Value of the NFT @@ -191,6 +194,26 @@ library NftConfiguration { return (self.data & ~REDEEM_FINE_MASK) >> REDEEM_FINE_START_BIT_POSITION; } + /** + * @dev Sets the redeem threshold of the NFT + * @param self The NFT configuration + * @param redeemThreshold The redeem duration + **/ + function setRedeemThreshold(DataTypes.NftConfigurationMap memory self, uint256 redeemThreshold) internal pure { + require(redeemThreshold <= MAX_VALID_REDEEM_THRESHOLD, Errors.RC_INVALID_REDEEM_THRESHOLD); + + self.data = (self.data & REDEEM_THRESHOLD_MASK) | (redeemThreshold << REDEEM_THRESHOLD_START_BIT_POSITION); + } + + /** + * @dev Gets the redeem threshold of the NFT + * @param self The NFT configuration + * @return The redeem threshold + **/ + function getRedeemThreshold(DataTypes.NftConfigurationMap storage self) internal view returns (uint256) { + return (self.data & ~REDEEM_THRESHOLD_MASK) >> REDEEM_THRESHOLD_START_BIT_POSITION; + } + /** * @dev Gets the configuration flags of the NFT * @param self The NFT configuration @@ -243,6 +266,7 @@ library NftConfiguration { internal view returns ( + uint256, uint256, uint256, uint256 @@ -253,7 +277,8 @@ library NftConfiguration { return ( (dataLocal & ~REDEEM_DURATION_MASK) >> REDEEM_DURATION_START_BIT_POSITION, (dataLocal & ~AUCTION_DURATION_MASK) >> AUCTION_DURATION_START_BIT_POSITION, - (dataLocal & ~REDEEM_FINE_MASK) >> REDEEM_FINE_START_BIT_POSITION + (dataLocal & ~REDEEM_FINE_MASK) >> REDEEM_FINE_START_BIT_POSITION, + (dataLocal & ~REDEEM_THRESHOLD_MASK) >> REDEEM_THRESHOLD_START_BIT_POSITION ); } @@ -287,6 +312,7 @@ library NftConfiguration { internal pure returns ( + uint256, uint256, uint256, uint256 @@ -295,7 +321,8 @@ library NftConfiguration { return ( (self.data & ~REDEEM_DURATION_MASK) >> REDEEM_DURATION_START_BIT_POSITION, (self.data & ~AUCTION_DURATION_MASK) >> AUCTION_DURATION_START_BIT_POSITION, - (self.data & ~REDEEM_FINE_MASK) >> REDEEM_FINE_START_BIT_POSITION + (self.data & ~REDEEM_FINE_MASK) >> REDEEM_FINE_START_BIT_POSITION, + (self.data & ~REDEEM_THRESHOLD_MASK) >> REDEEM_THRESHOLD_START_BIT_POSITION ); } } diff --git a/contracts/libraries/helpers/Errors.sol b/contracts/libraries/helpers/Errors.sol index 2b5aff5..1d2f53c 100644 --- a/contracts/libraries/helpers/Errors.sol +++ b/contracts/libraries/helpers/Errors.sol @@ -62,6 +62,7 @@ library Errors { string public constant LP_NFT_HAS_USED_AS_COLLATERAL = "412"; string public constant LP_DELEGATE_CALL_FAILED = "413"; string public constant LP_AMOUNT_LESS_THAN_EXTRA_DEBT = "414"; + string public constant LP_AMOUNT_LESS_THAN_REDEEM_THRESHOLD = "415"; //lend pool loan errors string public constant LPL_INVALID_LOAN_STATE = "480"; @@ -108,6 +109,7 @@ library Errors { string public constant RC_INVALID_REDEEM_DURATION = "735"; string public constant RC_INVALID_AUCTION_DURATION = "736"; string public constant RC_INVALID_REDEEM_FINE = "737"; + string public constant RC_INVALID_REDEEM_THRESHOLD = "738"; //address provider erros string public constant LPAPR_PROVIDER_NOT_REGISTERED = "760"; // 'Provider is not registered' diff --git a/contracts/misc/BendProtocolDataProvider.sol b/contracts/misc/BendProtocolDataProvider.sol index 5749fc9..b3e34a3 100644 --- a/contracts/misc/BendProtocolDataProvider.sol +++ b/contracts/misc/BendProtocolDataProvider.sol @@ -128,6 +128,7 @@ contract BendProtocolDataProvider { uint256 redeemDuration, uint256 auctionDuration, uint256 redeemFine, + uint256 redeemThreshold, bool isActive, bool isFrozen ) @@ -136,7 +137,7 @@ contract BendProtocolDataProvider { .getNftConfiguration(asset); (ltv, liquidationThreshold, liquidationBonus) = configuration.getCollateralParamsMemory(); - (redeemDuration, auctionDuration, redeemFine) = configuration.getAuctionParamsMemory(); + (redeemDuration, auctionDuration, redeemFine, redeemThreshold) = configuration.getAuctionParamsMemory(); (isActive, isFrozen) = configuration.getFlagsMemory(); } diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index 2544876..9f3f0f8 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -253,7 +253,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { (nftData.ltv, nftData.liquidationThreshold, nftData.liquidationBonus) = baseData .configuration .getCollateralParamsMemory(); - (nftData.redeemDuration, nftData.auctionDuration, nftData.redeemFine) = baseData + (nftData.redeemDuration, nftData.auctionDuration, nftData.redeemFine, nftData.redeemThreshold) = baseData .configuration .getAuctionParamsMemory(); (nftData.isActive, nftData.isFrozen) = baseData.configuration.getFlagsMemory(); diff --git a/contracts/protocol/LendPoolConfigurator.sol b/contracts/protocol/LendPoolConfigurator.sol index 1d909d4..22c53d1 100644 --- a/contracts/protocol/LendPoolConfigurator.sol +++ b/contracts/protocol/LendPoolConfigurator.sol @@ -389,7 +389,8 @@ contract LendPoolConfigurator is Initializable, ILendPoolConfigurator { address asset, uint256 redeemDuration, uint256 auctionDuration, - uint256 redeemFine + uint256 redeemFine, + uint256 redeemThreshold ) external onlyPoolAdmin { ILendPool cachedPool = _getLendPool(); DataTypes.NftConfigurationMap memory currentConfig = cachedPool.getNftConfiguration(asset); @@ -401,10 +402,11 @@ contract LendPoolConfigurator is Initializable, ILendPoolConfigurator { currentConfig.setRedeemDuration(redeemDuration); currentConfig.setAuctionDuration(auctionDuration); currentConfig.setRedeemFine(redeemFine); + currentConfig.setRedeemThreshold(redeemThreshold); cachedPool.setNftConfiguration(asset, currentConfig.data); - emit NftAuctionChanged(asset, redeemDuration, auctionDuration, redeemFine); + emit NftAuctionChanged(asset, redeemDuration, auctionDuration, redeemFine, redeemThreshold); } function setMaxNumberOfReserves(uint256 newVal) external onlyPoolAdmin { diff --git a/contracts/protocol/LendPoolLiquidator.sol b/contracts/protocol/LendPoolLiquidator.sol index 98322ad..a7a98f6 100644 --- a/contracts/protocol/LendPoolLiquidator.sol +++ b/contracts/protocol/LendPoolLiquidator.sol @@ -161,6 +161,7 @@ contract LendPoolLiquidator is Initializable, ILendPoolLiquidator, LendPoolStora uint256 loanId; uint256 borrowAmount; uint256 repayAmount; + uint256 minRepayAmount; uint256 maxRepayAmount; uint256 bidFine; uint256 redeemEndTimestamp; @@ -216,6 +217,9 @@ contract LendPoolLiquidator is Initializable, ILendPoolLiquidator, LendPoolStora vars.repayAmount = amount - vars.bidFine; } + vars.minRepayAmount = vars.borrowAmount.percentMul(nftData.configuration.getRedeemThreshold()); + require(vars.repayAmount >= vars.minRepayAmount, Errors.LP_AMOUNT_LESS_THAN_REDEEM_THRESHOLD); + vars.maxRepayAmount = vars.borrowAmount.percentMul(PercentageMath.PERCENTAGE_FACTOR - PercentageMath.TEN_PERCENT); if (vars.repayAmount > vars.maxRepayAmount) { vars.repayAmount = vars.maxRepayAmount; diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 166d7c8..fbd43d8 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -300,12 +300,21 @@ export const configureNftsByHelper = async ( redeemDuration: BigNumberish; auctionDuration: BigNumberish; redeemFine: BigNumberish; + redeemThreshold: BigNumberish; }[] = []; console.log(`- Configure NFTs`); for (const [ assetSymbol, - { baseLTVAsCollateral, liquidationBonus, liquidationThreshold, redeemDuration, auctionDuration, redeemFine }, + { + baseLTVAsCollateral, + liquidationBonus, + liquidationThreshold, + redeemDuration, + auctionDuration, + redeemFine, + redeemThreshold, + }, ] of Object.entries(nftsParams) as [string, INftParams][]) { if (!nftAddresses[assetSymbol]) { console.log(`- Skipping init of ${assetSymbol} due nft address is not set at markets config`); @@ -325,6 +334,7 @@ export const configureNftsByHelper = async ( redeemDuration: redeemDuration, auctionDuration: auctionDuration, redeemFine: redeemFine, + redeemThreshold: redeemThreshold, }); tokens.push(tokenAddress); @@ -337,7 +347,8 @@ export const configureNftsByHelper = async ( liquidationBonus, redeemDuration, auctionDuration, - redeemFine + redeemFine, + redeemThreshold ); } if (tokens.length) { diff --git a/helpers/types.ts b/helpers/types.ts index 0f86adc..b06c312 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -317,6 +317,7 @@ export interface INftAuctionParams { redeemDuration: string; auctionDuration: string; redeemFine: string; + redeemThreshold: string; } export type iParamsPerNetwork = iEthereumParamsPerNetwork; diff --git a/markets/bend/nftsConfigs.ts b/markets/bend/nftsConfigs.ts index c36b481..ce0465f 100644 --- a/markets/bend/nftsConfigs.ts +++ b/markets/bend/nftsConfigs.ts @@ -7,6 +7,7 @@ export const strategyNftClassA: INftParams = { redeemDuration: "2", // 2 days auctionDuration: "2", // 2 days redeemFine: "100", // 1% + redeemThreshold: "5000", // 50% bNftImpl: eContractid.BNFT, }; @@ -17,6 +18,7 @@ export const strategyNftClassB: INftParams = { redeemDuration: "2", // 2 days auctionDuration: "2", // 2 days redeemFine: "100", // 1% + redeemThreshold: "5000", // 50% bNftImpl: eContractid.BNFT, }; @@ -27,6 +29,7 @@ export const strategyNftClassC: INftParams = { redeemDuration: "2", // 2 day auctionDuration: "2", // 2 day redeemFine: "100", // 1% + redeemThreshold: "5000", // 50% bNftImpl: eContractid.BNFT, }; @@ -37,6 +40,7 @@ export const strategyNftClassD: INftParams = { redeemDuration: "2", // 2 days auctionDuration: "2", // 2 days redeemFine: "100", // 1% + redeemThreshold: "5000", // 50% bNftImpl: eContractid.BNFT, }; @@ -47,6 +51,7 @@ export const strategyNftClassE: INftParams = { redeemDuration: "2", // 2 days auctionDuration: "2", // 2 days redeemFine: "100", // 1% + redeemThreshold: "5000", // 50% bNftImpl: eContractid.BNFT, }; diff --git a/package.json b/package.json index 759d88d..2f571c7 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "test:file": "npm run compile && TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test/__setup.spec.ts ./test/${TEST_FILE}", "test:subgraph:localhost": "npm run compile && npm run hardhat:localhost test ./test/__setup.spec.ts ./test/subgraph-scenarios.spec.ts", "dev:coverage": "hardhat compile --force && hardhat coverage --network coverage", - "dev:update-abis": "npm run compile && node ./scripts/updateAbis", + "dev:update-abis": "npm run compile && node ./scripts/updateAbis && npm run prettier:abis", "prettier:abis": "prettier --write 'abis/**/*.json'", "prettier:check": "npx prettier -c 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test/**/*.ts'", "prettier:write": "prettier --write 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test/**/*.ts'", diff --git a/tasks/helpers/init-nft-to-pool.ts b/tasks/helpers/init-nft-to-pool.ts index ea768db..60dead2 100644 --- a/tasks/helpers/init-nft-to-pool.ts +++ b/tasks/helpers/init-nft-to-pool.ts @@ -85,7 +85,13 @@ task("init-nft-to-pool", "Init and config new nft asset to lend pool") await waitForTx( await lendPoolConfiguratorProxy .connect(poolAdminSigner) - .configureNftAsAuction(asset, nftParam.redeemDuration, nftParam.auctionDuration, nftParam.redeemFine) + .configureNftAsAuction( + asset, + nftParam.redeemDuration, + nftParam.auctionDuration, + nftParam.redeemFine, + nftParam.redeemThreshold + ) ); console.log("WETHGateway authorizeLendPoolNFT"); diff --git a/tasks/misc/print-config.ts b/tasks/misc/print-config.ts index eb4c012..1469a6c 100644 --- a/tasks/misc/print-config.ts +++ b/tasks/misc/print-config.ts @@ -77,6 +77,7 @@ task("print-config", "Print config of all reserves and nfts") "redeemDuration", "auctionDuration", "redeemFine", + "redeemThreshold", "isActive", "isFrozen", ]; diff --git a/test/configurator-nft.spec.ts b/test/configurator-nft.spec.ts index a2590b7..d044fe3 100644 --- a/test/configurator-nft.spec.ts +++ b/test/configurator-nft.spec.ts @@ -114,30 +114,36 @@ makeSuite("Configurator-NFT", (testEnv: TestEnv) => { it("Deactivates the BAYC NFT as auction", async () => { const { configurator, dataProvider, bayc } = testEnv; - await configurator.configureNftAsAuction(bayc.address, 0, 0, 0); + await configurator.configureNftAsAuction(bayc.address, 0, 0, 0, 0); - const { redeemDuration, auctionDuration, redeemFine } = await dataProvider.getNftConfigurationData(bayc.address); + const { redeemDuration, auctionDuration, redeemFine, redeemThreshold } = await dataProvider.getNftConfigurationData( + bayc.address + ); expect(redeemDuration).to.be.equal(0); expect(auctionDuration).to.be.equal(0); expect(redeemFine).to.be.equal(0); + expect(redeemThreshold).to.be.equal(0); }); it("Activates the BAYC NFT as auction", async () => { const { configurator, dataProvider, bayc } = testEnv; - await configurator.configureNftAsAuction(bayc.address, "1", "1", "100"); + await configurator.configureNftAsAuction(bayc.address, "1", "1", "100", "5000"); - const { redeemDuration, auctionDuration, redeemFine } = await dataProvider.getNftConfigurationData(bayc.address); + const { redeemDuration, auctionDuration, redeemFine, redeemThreshold } = await dataProvider.getNftConfigurationData( + bayc.address + ); expect(redeemDuration).to.be.equal(1); expect(auctionDuration).to.be.equal(1); expect(redeemFine).to.be.equal(100); + expect(redeemThreshold).to.be.equal(5000); }); it("Check the onlyAdmin on configureNftAsAuction ", async () => { const { configurator, users, bayc } = testEnv; await expect( - configurator.connect(users[2].signer).configureNftAsAuction(bayc.address, "1", "1", "100"), + configurator.connect(users[2].signer).configureNftAsAuction(bayc.address, "1", "1", "100", "5000"), CALLER_NOT_POOL_ADMIN ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); diff --git a/test/liquidate-redeem.spec.ts b/test/liquidate-redeem.spec.ts index ed0047d..1b6cf4c 100644 --- a/test/liquidate-redeem.spec.ts +++ b/test/liquidate-redeem.spec.ts @@ -147,7 +147,7 @@ makeSuite("LendPool: Redeem", (testEnv) => { await increaseTime(nftCfgData.redeemDuration.mul(ONE_DAY).sub(ONE_HOUR).toNumber()); const debtDataBeforeRedeem = await pool.getNftDebtData(bayc.address, "101"); - const redeemAmount = new BigNumber(debtDataBeforeRedeem.totalDebt.toString()).multipliedBy(0.5).toFixed(0); + const redeemAmount = new BigNumber(debtDataBeforeRedeem.totalDebt.toString()).multipliedBy(0.6).toFixed(0); const repayDebtAmount = new BigNumber(redeemAmount).minus(auctionDataBefore.bidFine.toString()); await pool.connect(borrower.signer).redeem(bayc.address, "101", redeemAmount); @@ -343,7 +343,7 @@ makeSuite("LendPool: Redeem", (testEnv) => { await increaseTime(nftCfgData.redeemDuration.mul(ONE_DAY).sub(ONE_HOUR).toNumber()); const debtDataBeforeRedeem = await pool.getNftDebtData(bayc.address, "102"); - const redeemAmount = new BigNumber(debtDataBeforeRedeem.totalDebt.toString()).multipliedBy(0.5).toFixed(0); + const redeemAmount = new BigNumber(debtDataBeforeRedeem.totalDebt.toString()).multipliedBy(0.6).toFixed(0); const repayDebtAmount = new BigNumber(redeemAmount).minus(auctionDataBefore.bidFine.toString()); await pool.connect(borrower.signer).redeem(bayc.address, "102", redeemAmount); From 45a8afecd62616873e1cf3a424cca01d4218ef99 Mon Sep 17 00:00:00 2001 From: Thor Seldon Date: Fri, 18 Mar 2022 15:08:28 +0800 Subject: [PATCH 6/6] make gateway contracts upgradeable --- abis/LendPoolConfigurator.json | 48 +++++-- abis/PunkGateway.json | 60 +++++---- abis/WETHGateway.json | 40 +++--- .../deployments/BTokensAndBNFTsHelper.sol | 23 +--- .../interfaces/ILendPoolConfigurator.sol | 10 +- ... => EmergencyTokenRecoveryUpgradeable.sol} | 19 ++- contracts/protocol/LendPoolConfigurator.sol | 15 ++- contracts/protocol/PunkGateway.sol | 51 +++---- contracts/protocol/WETHGateway.sol | 23 ++-- deployments/deployed-contracts-develop.json | 47 ++++--- helpers/contracts-deployments.ts | 32 ++--- helpers/init-helpers.ts | 5 + helpers/types.ts | 2 + tasks/dev/initialize.ts | 8 +- tasks/dev/lend_pool.ts | 5 +- tasks/full/initialize.ts | 12 +- tasks/full/lend-pool.ts | 5 +- tasks/full/punk-gateway.ts | 71 ++++++++-- tasks/full/weth-gateway.ts | 67 ++++++++-- tasks/helpers/init-nft-to-pool.ts | 13 +- tasks/misc/new-implementation.ts | 125 +++++++++++------- test/__setup.spec.ts | 56 +++++--- test/configurator-nft.spec.ts | 12 +- test/helpers/actions.ts | 2 +- 24 files changed, 472 insertions(+), 279 deletions(-) rename contracts/protocol/{EmergencyTokenRecovery.sol => EmergencyTokenRecoveryUpgradeable.sol} (75%) diff --git a/abis/LendPoolConfigurator.json b/abis/LendPoolConfigurator.json index 81c673e..aa405af 100644 --- a/abis/LendPoolConfigurator.json +++ b/abis/LendPoolConfigurator.json @@ -114,12 +114,6 @@ "internalType": "uint256", "name": "redeemFine", "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "redeemThreshold", - "type": "uint256" } ], "name": "NftAuctionChanged", @@ -201,6 +195,25 @@ "name": "NftInitialized", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemThreshold", + "type": "uint256" + } + ], + "name": "NftRedeemThresholdChanged", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -491,11 +504,6 @@ "internalType": "uint256", "name": "redeemFine", "type": "uint256" - }, - { - "internalType": "uint256", - "name": "redeemThreshold", - "type": "uint256" } ], "name": "configureNftAsAuction", @@ -667,6 +675,24 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemThreshold", + "type": "uint256" + } + ], + "name": "setNftRedeemThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { diff --git a/abis/PunkGateway.json b/abis/PunkGateway.json index 3bfbd1e..19026d9 100644 --- a/abis/PunkGateway.json +++ b/abis/PunkGateway.json @@ -1,30 +1,4 @@ [ - { - "inputs": [ - { - "internalType": "address", - "name": "addressProvider", - "type": "address" - }, - { - "internalType": "address", - "name": "wethGateway", - "type": "address" - }, - { - "internalType": "address", - "name": "_punks", - "type": "address" - }, - { - "internalType": "address", - "name": "_wrappedPunks", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, { "anonymous": false, "inputs": [ @@ -111,9 +85,9 @@ { "inputs": [ { - "internalType": "address", - "name": "token", - "type": "address" + "internalType": "address[]", + "name": "tokens", + "type": "address[]" } ], "name": "authorizeLendPoolERC20", @@ -269,6 +243,34 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "addressProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "wethGateway", + "type": "address" + }, + { + "internalType": "address", + "name": "_punks", + "type": "address" + }, + { + "internalType": "address", + "name": "_wrappedPunks", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { diff --git a/abis/WETHGateway.json b/abis/WETHGateway.json index 31251f3..111fc41 100644 --- a/abis/WETHGateway.json +++ b/abis/WETHGateway.json @@ -1,20 +1,4 @@ [ - { - "inputs": [ - { - "internalType": "address", - "name": "addressProvider", - "type": "address" - }, - { - "internalType": "address", - "name": "weth", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, { "anonymous": false, "inputs": [ @@ -83,9 +67,9 @@ { "inputs": [ { - "internalType": "address", - "name": "nftAsset", - "type": "address" + "internalType": "address[]", + "name": "nftAssets", + "type": "address[]" } ], "name": "authorizeLendPoolNFT", @@ -244,6 +228,24 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "addressProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "weth", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { diff --git a/contracts/deployments/BTokensAndBNFTsHelper.sol b/contracts/deployments/BTokensAndBNFTsHelper.sol index 8201980..5b4ff84 100644 --- a/contracts/deployments/BTokensAndBNFTsHelper.sol +++ b/contracts/deployments/BTokensAndBNFTsHelper.sol @@ -1,15 +1,12 @@ // SPDX-License-Identifier: agpl-3.0 pragma solidity 0.8.4; -import {LendPool} from "../protocol/LendPool.sol"; import {LendPoolAddressesProvider} from "../protocol/LendPoolAddressesProvider.sol"; import {LendPoolConfigurator} from "../protocol/LendPoolConfigurator.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; contract BTokensAndBNFTsHelper is Ownable { - address payable private pool; - address private addressesProvider; - address private poolConfigurator; + LendPoolAddressesProvider public addressesProvider; struct ConfigureReserveInput { address asset; @@ -28,18 +25,12 @@ contract BTokensAndBNFTsHelper is Ownable { uint256 redeemThreshold; } - constructor( - address payable _pool, - address _addressesProvider, - address _poolConfigurator - ) { - pool = _pool; - addressesProvider = _addressesProvider; - poolConfigurator = _poolConfigurator; + constructor(address _addressesProvider) { + addressesProvider = LendPoolAddressesProvider(_addressesProvider); } function configureReserves(ConfigureReserveInput[] calldata inputParams) external onlyOwner { - LendPoolConfigurator configurator = LendPoolConfigurator(poolConfigurator); + LendPoolConfigurator configurator = LendPoolConfigurator(addressesProvider.getLendPoolConfigurator()); for (uint256 i = 0; i < inputParams.length; i++) { if (inputParams[i].borrowingEnabled) { configurator.enableBorrowingOnReserve(inputParams[i].asset); @@ -49,7 +40,7 @@ contract BTokensAndBNFTsHelper is Ownable { } function configureNfts(ConfigureNftInput[] calldata inputParams) external onlyOwner { - LendPoolConfigurator configurator = LendPoolConfigurator(poolConfigurator); + LendPoolConfigurator configurator = LendPoolConfigurator(addressesProvider.getLendPoolConfigurator()); for (uint256 i = 0; i < inputParams.length; i++) { configurator.configureNftAsCollateral( inputParams[i].asset, @@ -61,9 +52,9 @@ contract BTokensAndBNFTsHelper is Ownable { inputParams[i].asset, inputParams[i].redeemDuration, inputParams[i].auctionDuration, - inputParams[i].redeemFine, - inputParams[i].redeemThreshold + inputParams[i].redeemFine ); + configurator.setNftRedeemThreshold(inputParams[i].asset, inputParams[i].redeemThreshold); } } } diff --git a/contracts/interfaces/ILendPoolConfigurator.sol b/contracts/interfaces/ILendPoolConfigurator.sol index c8aa550..f7e9fac 100644 --- a/contracts/interfaces/ILendPoolConfigurator.sol +++ b/contracts/interfaces/ILendPoolConfigurator.sol @@ -155,13 +155,9 @@ interface ILendPoolConfigurator { * @param auctionDuration The new redeem duration * @param redeemFine The new redeem fine **/ - event NftAuctionChanged( - address indexed asset, - uint256 redeemDuration, - uint256 auctionDuration, - uint256 redeemFine, - uint256 redeemThreshold - ); + event NftAuctionChanged(address indexed asset, uint256 redeemDuration, uint256 auctionDuration, uint256 redeemFine); + + event NftRedeemThresholdChanged(address indexed asset, uint256 redeemThreshold); /** * @dev Emitted when an bToken implementation is upgraded diff --git a/contracts/protocol/EmergencyTokenRecovery.sol b/contracts/protocol/EmergencyTokenRecoveryUpgradeable.sol similarity index 75% rename from contracts/protocol/EmergencyTokenRecovery.sol rename to contracts/protocol/EmergencyTokenRecoveryUpgradeable.sol index f91b44c..f6b157f 100644 --- a/contracts/protocol/EmergencyTokenRecovery.sol +++ b/contracts/protocol/EmergencyTokenRecoveryUpgradeable.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: agpl-3.0 pragma solidity 0.8.4; -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; +import {IERC721Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol"; + import {IPunks} from "../interfaces/IPunks.sol"; /** @@ -11,9 +12,13 @@ import {IPunks} from "../interfaces/IPunks.sol"; * @notice Add Emergency Recovery Logic to contract implementation * @author Bend **/ -abstract contract EmergencyTokenRecovery is Ownable { +abstract contract EmergencyTokenRecoveryUpgradeable is OwnableUpgradeable { event EmergencyEtherTransfer(address indexed to, uint256 amount); + function __EmergencyTokenRecovery_init() internal onlyInitializing { + __Ownable_init(); + } + /** * @dev transfer ERC20 from the utility contract, for ERC20 recovery in case of stuck tokens due * direct transfers to the contract address. @@ -26,7 +31,7 @@ abstract contract EmergencyTokenRecovery is Ownable { address to, uint256 amount ) external onlyOwner { - IERC20(token).transfer(to, amount); + IERC20Upgradeable(token).transfer(to, amount); } /** @@ -41,7 +46,7 @@ abstract contract EmergencyTokenRecovery is Ownable { address to, uint256 id ) external onlyOwner { - IERC721(token).safeTransferFrom(address(this), to, id); + IERC721Upgradeable(token).safeTransferFrom(address(this), to, id); } /** @@ -69,4 +74,6 @@ abstract contract EmergencyTokenRecovery is Ownable { require(success, "ETH_TRANSFER_FAILED"); emit EmergencyEtherTransfer(to, amount); } + + uint256[50] private __gap; } diff --git a/contracts/protocol/LendPoolConfigurator.sol b/contracts/protocol/LendPoolConfigurator.sol index 22c53d1..0149d3b 100644 --- a/contracts/protocol/LendPoolConfigurator.sol +++ b/contracts/protocol/LendPoolConfigurator.sol @@ -389,8 +389,7 @@ contract LendPoolConfigurator is Initializable, ILendPoolConfigurator { address asset, uint256 redeemDuration, uint256 auctionDuration, - uint256 redeemFine, - uint256 redeemThreshold + uint256 redeemFine ) external onlyPoolAdmin { ILendPool cachedPool = _getLendPool(); DataTypes.NftConfigurationMap memory currentConfig = cachedPool.getNftConfiguration(asset); @@ -402,11 +401,21 @@ contract LendPoolConfigurator is Initializable, ILendPoolConfigurator { currentConfig.setRedeemDuration(redeemDuration); currentConfig.setAuctionDuration(auctionDuration); currentConfig.setRedeemFine(redeemFine); + + cachedPool.setNftConfiguration(asset, currentConfig.data); + + emit NftAuctionChanged(asset, redeemDuration, auctionDuration, redeemFine); + } + + function setNftRedeemThreshold(address asset, uint256 redeemThreshold) external onlyPoolAdmin { + ILendPool cachedPool = _getLendPool(); + DataTypes.NftConfigurationMap memory currentConfig = cachedPool.getNftConfiguration(asset); + currentConfig.setRedeemThreshold(redeemThreshold); cachedPool.setNftConfiguration(asset, currentConfig.data); - emit NftAuctionChanged(asset, redeemDuration, auctionDuration, redeemFine, redeemThreshold); + emit NftRedeemThresholdChanged(asset, redeemThreshold); } function setMaxNumberOfReserves(uint256 newVal) external onlyPoolAdmin { diff --git a/contracts/protocol/PunkGateway.sol b/contracts/protocol/PunkGateway.sol index 785632d..af7298c 100644 --- a/contracts/protocol/PunkGateway.sol +++ b/contracts/protocol/PunkGateway.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: agpl-3.0 pragma solidity 0.8.4; -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import {ERC721Holder} from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol"; +import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import {IERC721Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol"; +import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; +import {SafeERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; +import {ERC721HolderUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/utils/ERC721HolderUpgradeable.sol"; import {ILendPool} from "../interfaces/ILendPool.sol"; import {ILendPoolLoan} from "../interfaces/ILendPoolLoan.sol"; @@ -16,24 +16,27 @@ import {IPunkGateway} from "../interfaces/IPunkGateway.sol"; import {DataTypes} from "../libraries/types/DataTypes.sol"; import {IWETHGateway} from "../interfaces/IWETHGateway.sol"; -import {EmergencyTokenRecovery} from "./EmergencyTokenRecovery.sol"; +import {EmergencyTokenRecoveryUpgradeable} from "./EmergencyTokenRecoveryUpgradeable.sol"; -contract PunkGateway is ERC721Holder, IPunkGateway, Ownable, EmergencyTokenRecovery { - using SafeERC20 for IERC20; +contract PunkGateway is IPunkGateway, ERC721HolderUpgradeable, EmergencyTokenRecoveryUpgradeable { + using SafeERC20Upgradeable for IERC20Upgradeable; ILendPoolAddressesProvider internal _addressProvider; IWETHGateway internal _wethGateway; - IPunks public immutable punks; + IPunks public punks; IWrappedPunks public wrappedPunks; - address public immutable proxy; + address public proxy; - constructor( + function initialize( address addressProvider, address wethGateway, address _punks, address _wrappedPunks - ) { + ) public initializer { + __ERC721Holder_init(); + __EmergencyTokenRecovery_init(); + _addressProvider = ILendPoolAddressesProvider(addressProvider); _wethGateway = IWETHGateway(wethGateway); @@ -42,8 +45,8 @@ contract PunkGateway is ERC721Holder, IPunkGateway, Ownable, EmergencyTokenRecov wrappedPunks.registerProxy(); proxy = wrappedPunks.proxyInfo(address(this)); - IERC721(address(wrappedPunks)).setApprovalForAll(address(_getLendPool()), true); - IERC721(address(wrappedPunks)).setApprovalForAll(address(_wethGateway), true); + IERC721Upgradeable(address(wrappedPunks)).setApprovalForAll(address(_getLendPool()), true); + IERC721Upgradeable(address(wrappedPunks)).setApprovalForAll(address(_wethGateway), true); } function _getLendPool() internal view returns (ILendPool) { @@ -54,8 +57,10 @@ contract PunkGateway is ERC721Holder, IPunkGateway, Ownable, EmergencyTokenRecov return ILendPoolLoan(_addressProvider.getLendPoolLoan()); } - function authorizeLendPoolERC20(address token) external onlyOwner { - IERC20(token).approve(address(_getLendPool()), type(uint256).max); + function authorizeLendPoolERC20(address[] calldata tokens) external onlyOwner { + for (uint256 i = 0; i < tokens.length; i++) { + IERC20Upgradeable(tokens[i]).approve(address(_getLendPool()), type(uint256).max); + } } function _depositPunk(uint256 punkIndex) internal { @@ -87,7 +92,7 @@ contract PunkGateway is ERC721Holder, IPunkGateway, Ownable, EmergencyTokenRecov _depositPunk(punkIndex); cachedPool.borrow(reserveAsset, amount, address(wrappedPunks), punkIndex, onBehalfOf, referralCode); - IERC20(reserveAsset).transfer(onBehalfOf, amount); + IERC20Upgradeable(reserveAsset).transfer(onBehalfOf, amount); } function _withdrawPunk(uint256 punkIndex, address onBehalfOf) internal { @@ -114,7 +119,7 @@ contract PunkGateway is ERC721Holder, IPunkGateway, Ownable, EmergencyTokenRecov amount = debt; } - IERC20(reserve).transferFrom(msg.sender, address(this), amount); + IERC20Upgradeable(reserve).transferFrom(msg.sender, address(this), amount); (uint256 paybackAmount, bool burn) = cachedPool.repay(address(wrappedPunks), punkIndex, amount); @@ -139,7 +144,7 @@ contract PunkGateway is ERC721Holder, IPunkGateway, Ownable, EmergencyTokenRecov (, , address reserve, ) = cachedPoolLoan.getLoanCollateralAndReserve(loanId); - IERC20(reserve).transferFrom(msg.sender, address(this), bidPrice); + IERC20Upgradeable(reserve).transferFrom(msg.sender, address(this), bidPrice); cachedPool.auction(address(wrappedPunks), punkIndex, bidPrice, onBehalfOf); } @@ -153,12 +158,12 @@ contract PunkGateway is ERC721Holder, IPunkGateway, Ownable, EmergencyTokenRecov DataTypes.LoanData memory loan = cachedPoolLoan.getLoan(loanId); - IERC20(loan.reserveAsset).transferFrom(msg.sender, address(this), amount); + IERC20Upgradeable(loan.reserveAsset).transferFrom(msg.sender, address(this), amount); uint256 paybackAmount = cachedPool.redeem(address(wrappedPunks), punkIndex, amount); if (amount > paybackAmount) { - IERC20(loan.reserveAsset).safeTransfer(msg.sender, (amount - paybackAmount)); + IERC20Upgradeable(loan.reserveAsset).safeTransfer(msg.sender, (amount - paybackAmount)); } return paybackAmount; @@ -175,7 +180,7 @@ contract PunkGateway is ERC721Holder, IPunkGateway, Ownable, EmergencyTokenRecov require(loan.bidderAddress == _msgSender(), "PunkGateway: caller is not bidder"); if (amount > 0) { - IERC20(loan.reserveAsset).transferFrom(msg.sender, address(this), amount); + IERC20Upgradeable(loan.reserveAsset).transferFrom(msg.sender, address(this), amount); } uint256 extraRetAmount = cachedPool.liquidate(address(wrappedPunks), punkIndex, amount); @@ -183,7 +188,7 @@ contract PunkGateway is ERC721Holder, IPunkGateway, Ownable, EmergencyTokenRecov _withdrawPunk(punkIndex, loan.bidderAddress); if (amount > extraRetAmount) { - IERC20(loan.reserveAsset).safeTransfer(msg.sender, (amount - extraRetAmount)); + IERC20Upgradeable(loan.reserveAsset).safeTransfer(msg.sender, (amount - extraRetAmount)); } return (extraRetAmount); diff --git a/contracts/protocol/WETHGateway.sol b/contracts/protocol/WETHGateway.sol index 05dc736..b3172ce 100644 --- a/contracts/protocol/WETHGateway.sol +++ b/contracts/protocol/WETHGateway.sol @@ -1,10 +1,8 @@ // SPDX-License-Identifier: agpl-3.0 pragma solidity 0.8.4; -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {ERC721Holder} from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol"; -import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import {ERC721HolderUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/utils/ERC721HolderUpgradeable.sol"; +import {IERC721Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol"; import {IWETH} from "../interfaces/IWETH.sol"; import {IWETHGateway} from "../interfaces/IWETHGateway.sol"; @@ -14,9 +12,9 @@ import {ILendPoolLoan} from "../interfaces/ILendPoolLoan.sol"; import {IBToken} from "../interfaces/IBToken.sol"; import {DataTypes} from "../libraries/types/DataTypes.sol"; -import {EmergencyTokenRecovery} from "./EmergencyTokenRecovery.sol"; +import {EmergencyTokenRecoveryUpgradeable} from "./EmergencyTokenRecoveryUpgradeable.sol"; -contract WETHGateway is ERC721Holder, IWETHGateway, Ownable, EmergencyTokenRecovery { +contract WETHGateway is IWETHGateway, ERC721HolderUpgradeable, EmergencyTokenRecoveryUpgradeable { ILendPoolAddressesProvider internal _addressProvider; IWETH internal WETH; @@ -25,7 +23,10 @@ contract WETHGateway is ERC721Holder, IWETHGateway, Ownable, EmergencyTokenRecov * @dev Sets the WETH address and the LendPoolAddressesProvider address. Infinite approves lend pool. * @param weth Address of the Wrapped Ether contract **/ - constructor(address addressProvider, address weth) { + function initialize(address addressProvider, address weth) public initializer { + __ERC721Holder_init(); + __EmergencyTokenRecovery_init(); + _addressProvider = ILendPoolAddressesProvider(addressProvider); WETH = IWETH(weth); @@ -41,8 +42,10 @@ contract WETHGateway is ERC721Holder, IWETHGateway, Ownable, EmergencyTokenRecov return ILendPoolLoan(_addressProvider.getLendPoolLoan()); } - function authorizeLendPoolNFT(address nftAsset) external onlyOwner { - IERC721(nftAsset).setApprovalForAll(address(_getLendPool()), true); + function authorizeLendPoolNFT(address[] calldata nftAssets) external onlyOwner { + for (uint256 i = 0; i < nftAssets.length; i++) { + IERC721Upgradeable(nftAssets[i]).setApprovalForAll(address(_getLendPool()), true); + } } function depositETH(address onBehalfOf, uint16 referralCode) external payable override { @@ -84,7 +87,7 @@ contract WETHGateway is ERC721Holder, IWETHGateway, Ownable, EmergencyTokenRecov uint256 loanId = cachedPoolLoan.getCollateralLoanId(nftAsset, nftTokenId); if (loanId == 0) { - IERC721(nftAsset).safeTransferFrom(msg.sender, address(this), nftTokenId); + IERC721Upgradeable(nftAsset).safeTransferFrom(msg.sender, address(this), nftTokenId); } cachedPool.borrow(address(WETH), amount, nftAsset, nftTokenId, onBehalfOf, referralCode); WETH.withdraw(amount); diff --git a/deployments/deployed-contracts-develop.json b/deployments/deployed-contracts-develop.json index 3fb6e9f..12d41f9 100644 --- a/deployments/deployed-contracts-develop.json +++ b/deployments/deployed-contracts-develop.json @@ -93,48 +93,47 @@ "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" }, "ReserveLogic": { - "address": "0xBb70B549e0c7C75D2D7269AE15C84526febce459", + "address": "0xa9C66965618aDb7Fe038EDa43FB02e4950661e79", "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" }, "NftLogic": { - "address": "0x6E9936c3270d80F3fDCA1Eaee8F7F1fe8ff3D626", + "address": "0xfDE8e984F406FBdF609064D59fEA015B854Bc890", "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" }, "GenericLogic": { - "address": "0x259d4e7B47A2f46AA25D1BB4249daE4Ce8044924", + "address": "0x130f11A46baf275616A91aB7Beb815EC5e0fea7a", "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" }, "ValidationLogic": { - "address": "0x8A0F9F764949fA4DC30a31e6B1D49455A5b7c37e", + "address": "0x2B1f699E604511477242B07a93Bd9ACD348966fb", "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" }, "LendPoolImpl": { - "address": "0x061172D66E3b0d12f35AA5f4aa790d1b82584b81" + "address": "0xfD2Bfa1ce9d720cb75a30e8034b521945224007B" }, "LendPool": { "address": "0x7273847406a52B949F3E824fce7704E8e74244f5" }, "LendPoolLiquidatorImpl": { - "address": "0x0d7FD00F0eB15E2ac6F2A7e2A711EC3cF52C5af7" + "address": "0x394bC760f3Ea2559b8aa5B2d1A6C52936056a6E4" }, "LendPoolLiquidator": { - "address": "0x0d7FD00F0eB15E2ac6F2A7e2A711EC3cF52C5af7", - "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + "address": "0x394bC760f3Ea2559b8aa5B2d1A6C52936056a6E4" }, "LendPoolLoanImpl": { - "address": "0xfC65bB7444E53549ffE2ED019f7808Fa11054aF5" + "address": "0x967Fc83e00cDB6928b1aF87710D1C1654259F77d" }, "LendPoolLoan": { "address": "0xfD45825533513ABfCa3D767f407C86C1c522a659" }, "LendPoolConfiguratorImpl": { - "address": "0x51C7a63628E3020DCf79fB824C7B2EdbBCd19aD5" + "address": "0x58ce2dBCb05B9727ab9EbCd50CC2B93549826D9A" }, "LendPoolConfigurator": { "address": "0xB941fC3ceC2E83a9Df305Cc8A3285D6E8bc29A01" }, "BTokensAndBNFTsHelper": { - "address": "0x4C08584B7CbdEb2912Db3414f6480E4005AcF1E7", + "address": "0x16F1b281C36faB9F477944D6e503008f961F93E6", "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" }, "BToken": { @@ -146,25 +145,23 @@ "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" }, "ReserveOracleImpl": { - "address": "0x43398385ce07CE08351331A4e7937dD063F97faF" + "address": "0x4a44e0261800fE325Df5A8cf6D22e9D78C31EFE5" }, "ReserveOracle": { - "address": "0xd30179fbB087088a77E1DD0903cCc64510287cB2", - "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + "address": "0xd30179fbB087088a77E1DD0903cCc64510287cB2" }, "NFTOracleImpl": { - "address": "0x7f998b4caeeEd21c71ca3CC85c0917f70782a22A" + "address": "0xcFc4b72067c8a9F83DF5CeB80d0F5C4210130c4e" }, "NFTOracle": { - "address": "0xE283F4D306517200911F9c378aC68f020acb9f64", - "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + "address": "0xE283F4D306517200911F9c378aC68f020acb9f64" }, "WETHGateway": { - "address": "0x53EB7c083eFDc7505848263BB481bD93fA7Ad5B6", + "address": "0x564e1748ad5940cEA22f2a6Aa75F2849B6d22f32", "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" }, "PunkGateway": { - "address": "0xf70adB1845bf1F3cd2aec7E62DE9677B1b2Ea7Fa", + "address": "0xA979f811c3e2322845E99E8906bBB0a4f85e5A18", "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" }, "InterestRate": { @@ -181,15 +178,21 @@ "address": "0xbBbFaFACaBeEB2B3957eddf87e95434e81aeC25c" }, "WalletBalanceProvider": { - "address": "0x54028bF245F8b54C037e10DED960f1F10e228cd2", + "address": "0xfa32Dc864c5348e6a1ce8844609CD63Bd866152f", "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" }, "BendProtocolDataProvider": { - "address": "0xA8334E9BA1c4E1dD2d72C38258B43C30b6aeDEb0", + "address": "0x6BC4141B9623c05f260E231Ea8500c0cEE05776a", "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" }, "UIPoolDataProvider": { - "address": "0x291451555eF07441f4De67940b967a6B8D4033Df", + "address": "0xbB72f40766CF22498d60FFdC6b402Ad575fAc512", "deployer": "0xad93fB0e59eC703422dD38dCb7AcB8e323C8cc5B" + }, + "PunkGatewayImpl": { + "address": "0xbd2F5E6C5c1430B021bEaB70dBA90F2faE0D7a49" + }, + "WETHGatewayImpl": { + "address": "0x440183FDddAcE7661a8027B42e09fB78Ae2b6301" } } \ No newline at end of file diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index f4adcac..d5d553f 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -351,10 +351,7 @@ export const deployAllMockNfts = async (verify?: boolean) => { return tokens; }; -export const deployBTokensAndBNFTsHelper = async ( - args: [tEthereumAddress, tEthereumAddress, tEthereumAddress], - verify?: boolean -) => +export const deployBTokensAndBNFTsHelper = async (args: [tEthereumAddress], verify?: boolean) => withSaveAndVerify( await new BTokensAndBNFTsHelperFactory(await getDeploySigner()).deploy(...args), eContractid.BTokensAndBNFTsHelper, @@ -362,13 +359,11 @@ export const deployBTokensAndBNFTsHelper = async ( verify ); -export const deployWETHGateway = async (args: [tEthereumAddress, tEthereumAddress], verify?: boolean) => - withSaveAndVerify( - await new WETHGatewayFactory(await getDeploySigner()).deploy(...args), - eContractid.WETHGateway, - args, - verify - ); +export const deployWETHGateway = async (verify?: boolean) => { + const wethImpl = await new WETHGatewayFactory(await getDeploySigner()).deploy(); + await insertContractAddressInDb(eContractid.WETHGatewayImpl, wethImpl.address); + return withSaveAndVerify(wethImpl, eContractid.WETHGateway, [], verify); +}; export const deployWETHMocked = async (verify?: boolean) => withSaveAndVerify(await new WETH9MockedFactory(await getDeploySigner()).deploy(), eContractid.WETHMocked, [], verify); @@ -491,16 +486,11 @@ export const deployWrappedPunk = async (args: [tEthereumAddress], verify?: boole verify ); -export const deployPunkGateway = async ( - args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, tEthereumAddress], - verify?: boolean -) => - withSaveAndVerify( - await new PunkGatewayFactory(await getDeploySigner()).deploy(...args), - eContractid.PunkGateway, - args, - verify - ); +export const deployPunkGateway = async (verify?: boolean) => { + const punkImpl = await new PunkGatewayFactory(await getDeploySigner()).deploy(); + await insertContractAddressInDb(eContractid.PunkGatewayImpl, punkImpl.address); + return withSaveAndVerify(punkImpl, eContractid.PunkGateway, [], verify); +}; export const deployBendUpgradeableProxy = async ( id: string, diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index fbd43d8..23acc70 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -292,6 +292,11 @@ export const configureNftsByHelper = async ( const tokens: string[] = []; const symbols: string[] = []; + console.log("addressesProvider:", addressProvider.address); + const addressProviderInHelper = await getLendPoolAddressesProvider(await tokenHelperDeployer.addressesProvider()); + console.log("addressProviderInHelper:", addressProviderInHelper.address); + console.log("getLendPoolConfigurator:", await addressProviderInHelper.getLendPoolConfigurator()); + const inputParams: { asset: string; baseLTV: BigNumberish; diff --git a/helpers/types.ts b/helpers/types.ts index b06c312..173239d 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -58,6 +58,7 @@ export enum eContractid { FeeProvider = "FeeProvider", BTokensAndBNFTsHelper = "BTokensAndBNFTsHelper", WETHGateway = "WETHGateway", + WETHGatewayImpl = "WETHGatewayImpl", WETH = "WETH", WETHMocked = "WETHMocked", WPUNKSGateway = "WPUNKSGateway", @@ -73,6 +74,7 @@ export enum eContractid { CryptoPunksMarket = "CryptoPunksMarket", WrappedPunk = "WrappedPunk", PunkGateway = "PunkGateway", + PunkGatewayImpl = "PunkGatewayImpl", MockIncentivesController = "MockIncentivesController", UIPoolDataProvider = "UIPoolDataProvider", BendCollector = "BendCollector", diff --git a/tasks/dev/initialize.ts b/tasks/dev/initialize.ts index 8966023..f9cedb8 100644 --- a/tasks/dev/initialize.ts +++ b/tasks/dev/initialize.ts @@ -100,13 +100,17 @@ task("dev:initialize-lend-pool", "Initialize lend pool configuration.") //////////////////////////////////////////////////////////////////////////// const wethGateway = await getWETHGateway(); + let nftAddresses: string[] = []; for (const [assetSymbol, assetAddress] of Object.entries(allNftAddresses) as [string, string][]) { - await waitForTx(await wethGateway.authorizeLendPoolNFT(assetAddress)); + nftAddresses.push(assetAddress); } + await waitForTx(await wethGateway.authorizeLendPoolNFT(nftAddresses)); //////////////////////////////////////////////////////////////////////////// const punkGateway = await getPunkGateway(); + let reserveAddresses: string[] = []; for (const [assetSymbol, assetAddress] of Object.entries(allTokenAddresses) as [string, string][]) { - await waitForTx(await punkGateway.authorizeLendPoolERC20(assetAddress)); + reserveAddresses.push(assetAddress); } + await waitForTx(await punkGateway.authorizeLendPoolERC20(reserveAddresses)); }); diff --git a/tasks/dev/lend_pool.ts b/tasks/dev/lend_pool.ts index 9382ae5..7eb2f0f 100644 --- a/tasks/dev/lend_pool.ts +++ b/tasks/dev/lend_pool.ts @@ -76,10 +76,7 @@ task("dev:deploy-lend-pool", "Deploy lend pool for dev enviroment") //////////////////////////////////////////////////////////////////////////// // Deploy deployment helpers - await deployBTokensAndBNFTsHelper( - [lendPoolProxy.address, addressesProvider.address, lendPoolConfiguratorProxy.address], - verify - ); + await deployBTokensAndBNFTsHelper([addressesProvider.address], verify); // Generic BNFT Implementation at here await deployBTokenImplementations(pool, poolConfig.ReservesConfig, verify); diff --git a/tasks/full/initialize.ts b/tasks/full/initialize.ts index c0d9acd..870aa6c 100644 --- a/tasks/full/initialize.ts +++ b/tasks/full/initialize.ts @@ -84,16 +84,20 @@ task("full:initialize-gateway", "Initialize gateway configuration.") } const wethGateway = await getWETHGateway(); + let nftAddresses: string[] = []; for (const [assetSymbol, assetAddress] of Object.entries(nftsAssets) as [string, string][]) { - console.log("WETHGateway: authorizeLendPoolNFT:", assetSymbol); - await waitForTx(await wethGateway.authorizeLendPoolNFT(assetAddress)); + nftAddresses.push(assetAddress); } + console.log("WETHGateway: authorizeLendPoolNFT:", nftAddresses); + await waitForTx(await wethGateway.authorizeLendPoolNFT(nftAddresses)); const punkGateway = await getPunkGateway(); + let reserveAddresses: string[] = []; for (const [assetSymbol, assetAddress] of Object.entries(reserveAssets) as [string, string][]) { - console.log("PunkGateway: authorizeLendPoolERC20:", assetSymbol); - await waitForTx(await punkGateway.authorizeLendPoolERC20(assetAddress)); + reserveAddresses.push(assetAddress); } + console.log("PunkGateway: authorizeLendPoolERC20:", reserveAddresses); + await waitForTx(await punkGateway.authorizeLendPoolERC20(reserveAddresses)); } catch (err) { console.error(err); exit(1); diff --git a/tasks/full/lend-pool.ts b/tasks/full/lend-pool.ts index 0b9e18e..e2725b3 100644 --- a/tasks/full/lend-pool.ts +++ b/tasks/full/lend-pool.ts @@ -110,10 +110,7 @@ task("full:deploy-lend-pool", "Deploy lend pool for full enviroment") ////////////////////////////////////////////////////////////////////////// // Deploy deployment helpers - await deployBTokensAndBNFTsHelper( - [lendPoolProxy.address, addressesProvider.address, lendPoolConfiguratorProxy.address], - verify - ); + await deployBTokensAndBNFTsHelper([addressesProvider.address], verify); // Generic BToken & DebtToken Implementation in Pool await deployBTokenImplementations(pool, poolConfig.ReservesConfig, verify); diff --git a/tasks/full/punk-gateway.ts b/tasks/full/punk-gateway.ts index 6a04dd1..ee672a1 100644 --- a/tasks/full/punk-gateway.ts +++ b/tasks/full/punk-gateway.ts @@ -6,22 +6,39 @@ import { getCryptoPunksMarketAddress, } from "../../helpers/configuration"; import { ADDRESS_ID_PUNK_GATEWAY } from "../../helpers/constants"; -import { deployPunkGateway } from "../../helpers/contracts-deployments"; -import { getLendPoolAddressesProvider, getWETHGateway } from "../../helpers/contracts-getters"; -import { waitForTx } from "../../helpers/misc-utils"; +import { deployBendUpgradeableProxy, deployPunkGateway } from "../../helpers/contracts-deployments"; +import { + getBendProxyAdminById, + getBendUpgradeableProxy, + getLendPoolAddressesProvider, + getPunkGateway, + getWETHGateway, +} from "../../helpers/contracts-getters"; +import { insertContractAddressInDb } from "../../helpers/contracts-helpers"; +import { notFalsyOrZeroAddress, waitForTx } from "../../helpers/misc-utils"; +import { eContractid } from "../../helpers/types"; +import { BendUpgradeableProxy, PunkGateway } from "../../types"; task(`full:deploy-punk-gateway`, `Deploys the PunkGateway contract`) .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .addFlag("verify", `Verify contract via Etherscan API.`) - .setAction(async ({ verify, pool }, localBRE) => { - await localBRE.run("set-DRE"); + .setAction(async ({ verify, pool }, DRE) => { + await DRE.run("set-DRE"); - if (!localBRE.network.config.chainId) { + if (!DRE.network.config.chainId) { throw new Error("INVALID_CHAIN_ID"); } const poolConfig = loadPoolConfig(pool); const addressesProvider = await getLendPoolAddressesProvider(); + + const proxyAdmin = await getBendProxyAdminById(eContractid.BendProxyAdminPool); + if (proxyAdmin == undefined || !notFalsyOrZeroAddress(proxyAdmin.address)) { + throw Error("Invalid pool proxy admin in config"); + } + const proxyAdminOwnerAddress = await proxyAdmin.owner(); + const proxyAdminOwnerSigner = DRE.ethers.provider.getSigner(proxyAdminOwnerAddress); + const wethGateWay = await getWETHGateway(); const punk = await getCryptoPunksMarketAddress(poolConfig); @@ -31,9 +48,47 @@ task(`full:deploy-punk-gateway`, `Deploys the PunkGateway contract`) console.log("WPUNKS.address", wpunk); // this contract is not support upgrade, just deploy new contract - const punkGateWay = await deployPunkGateway([addressesProvider.address, wethGateWay.address, punk, wpunk], verify); - console.log("PunkGateway.address", punkGateWay.address); + const punkGateWayImpl = await deployPunkGateway(verify); + const initEncodedData = punkGateWayImpl.interface.encodeFunctionData("initialize", [ + addressesProvider.address, + wethGateWay.address, + punk, + wpunk, + ]); + + let punkGateWay: PunkGateway; + let punkGatewayProxy: BendUpgradeableProxy; + + const punkGatewayAddress = undefined; //await addressesProvider.getAddress(ADDRESS_ID_PUNK_GATEWAY); + + if (punkGatewayAddress != undefined && notFalsyOrZeroAddress(punkGatewayAddress)) { + console.log("Upgrading exist PunkGateway proxy to new implementation..."); + + await insertContractAddressInDb(eContractid.PunkGateway, punkGatewayAddress); + punkGatewayProxy = await getBendUpgradeableProxy(punkGatewayAddress); + + // only proxy admin can do upgrading + await waitForTx( + await proxyAdmin.connect(proxyAdminOwnerSigner).upgrade(punkGatewayProxy.address, punkGateWayImpl.address) + ); + + punkGateWay = await getPunkGateway(punkGatewayProxy.address); + } else { + console.log("Deploying new PunkGateway proxy & implementation..."); + const punkGatewayProxy = await deployBendUpgradeableProxy( + eContractid.PunkGateway, + proxyAdmin.address, + punkGateWayImpl.address, + initEncodedData, + verify + ); + + punkGateWay = await getPunkGateway(punkGatewayProxy.address); + } await waitForTx(await addressesProvider.setAddress(ADDRESS_ID_PUNK_GATEWAY, punkGateWay.address)); + + console.log("PunkGateway: proxy %s, implementation %s", punkGateWay.address, punkGateWayImpl.address); + console.log("Finished PunkGateway deployment"); }); diff --git a/tasks/full/weth-gateway.ts b/tasks/full/weth-gateway.ts index b8d9599..4c04dbb 100644 --- a/tasks/full/weth-gateway.ts +++ b/tasks/full/weth-gateway.ts @@ -1,30 +1,79 @@ import { task } from "hardhat/config"; import { loadPoolConfig, ConfigNames, getWrappedNativeTokenAddress } from "../../helpers/configuration"; import { ADDRESS_ID_WETH_GATEWAY } from "../../helpers/constants"; -import { deployWETHGateway } from "../../helpers/contracts-deployments"; -import { getLendPoolAddressesProvider } from "../../helpers/contracts-getters"; -import { waitForTx } from "../../helpers/misc-utils"; +import { deployBendUpgradeableProxy, deployWETHGateway } from "../../helpers/contracts-deployments"; +import { + getBendProxyAdminById, + getBendUpgradeableProxy, + getLendPoolAddressesProvider, + getWETHGateway, +} from "../../helpers/contracts-getters"; +import { insertContractAddressInDb } from "../../helpers/contracts-helpers"; +import { notFalsyOrZeroAddress, waitForTx } from "../../helpers/misc-utils"; +import { eContractid } from "../../helpers/types"; +import { BendUpgradeableProxy, WETHGateway } from "../../types"; task(`full:deploy-weth-gateway`, `Deploys the WETHGateway contract`) .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .addFlag("verify", `Verify contract via Etherscan API.`) - .setAction(async ({ verify, pool }, localBRE) => { - await localBRE.run("set-DRE"); + .setAction(async ({ verify, pool }, DRE) => { + await DRE.run("set-DRE"); - if (!localBRE.network.config.chainId) { + if (!DRE.network.config.chainId) { throw new Error("INVALID_CHAIN_ID"); } const poolConfig = loadPoolConfig(pool); const addressesProvider = await getLendPoolAddressesProvider(); + const proxyAdmin = await getBendProxyAdminById(eContractid.BendProxyAdminPool); + if (proxyAdmin == undefined || !notFalsyOrZeroAddress(proxyAdmin.address)) { + throw Error("Invalid pool proxy admin in config"); + } + const proxyAdminOwnerAddress = await proxyAdmin.owner(); + const proxyAdminOwnerSigner = DRE.ethers.provider.getSigner(proxyAdminOwnerAddress); + const weth = await getWrappedNativeTokenAddress(poolConfig); console.log("WETH.address", weth); - // this contract is not support upgrade, just deploy new contract - const wethGateWay = await deployWETHGateway([addressesProvider.address, weth], verify); - console.log("WETHGateway.address", wethGateWay.address); + const wethGatewayImpl = await deployWETHGateway(verify); + const initEncodedData = wethGatewayImpl.interface.encodeFunctionData("initialize", [ + addressesProvider.address, + weth, + ]); + + let wethGateWay: WETHGateway; + let wethGatewayProxy: BendUpgradeableProxy; + + const wethGatewayAddress = undefined; //await addressesProvider.getAddress(ADDRESS_ID_WETH_GATEWAY); + + if (wethGatewayAddress != undefined && notFalsyOrZeroAddress(wethGatewayAddress)) { + console.log("Upgrading exist WETHGateway proxy to new implementation..."); + + await insertContractAddressInDb(eContractid.WETHGateway, wethGatewayAddress); + wethGatewayProxy = await getBendUpgradeableProxy(wethGatewayAddress); + + // only proxy admin can do upgrading + await waitForTx( + await proxyAdmin.connect(proxyAdminOwnerSigner).upgrade(wethGatewayProxy.address, wethGatewayImpl.address) + ); + + wethGateWay = await getWETHGateway(wethGatewayProxy.address); + } else { + console.log("Deploying new WETHGateway proxy & implementation..."); + const wethGatewayProxy = await deployBendUpgradeableProxy( + eContractid.WETHGateway, + proxyAdmin.address, + wethGatewayImpl.address, + initEncodedData, + verify + ); + + wethGateWay = await getWETHGateway(wethGatewayProxy.address); + } await waitForTx(await addressesProvider.setAddress(ADDRESS_ID_WETH_GATEWAY, wethGateWay.address)); + + console.log("WETHGateway: proxy %s, implementation %s", wethGateWay.address, wethGatewayImpl.address); console.log("Finished WETHGateway deployment"); }); diff --git a/tasks/helpers/init-nft-to-pool.ts b/tasks/helpers/init-nft-to-pool.ts index 60dead2..34ef695 100644 --- a/tasks/helpers/init-nft-to-pool.ts +++ b/tasks/helpers/init-nft-to-pool.ts @@ -85,17 +85,14 @@ task("init-nft-to-pool", "Init and config new nft asset to lend pool") await waitForTx( await lendPoolConfiguratorProxy .connect(poolAdminSigner) - .configureNftAsAuction( - asset, - nftParam.redeemDuration, - nftParam.auctionDuration, - nftParam.redeemFine, - nftParam.redeemThreshold - ) + .configureNftAsAuction(asset, nftParam.redeemDuration, nftParam.auctionDuration, nftParam.redeemFine) + ); + await waitForTx( + await lendPoolConfiguratorProxy.connect(poolAdminSigner).setNftRedeemThreshold(asset, nftParam.redeemThreshold) ); console.log("WETHGateway authorizeLendPoolNFT"); - await waitForTx(await wethGateway.authorizeLendPoolNFT(asset)); + await waitForTx(await wethGateway.authorizeLendPoolNFT([asset])); console.log("OK"); }); diff --git a/tasks/misc/new-implementation.ts b/tasks/misc/new-implementation.ts index ebff801..a5de943 100644 --- a/tasks/misc/new-implementation.ts +++ b/tasks/misc/new-implementation.ts @@ -8,6 +8,9 @@ import { } from "../../helpers/configuration"; import { getBendProtocolDataProvider, + getBendProxyAdminByAddress, + getBendProxyAdminById, + getBendUpgradeableProxy, getDeploySigner, getLendPoolAddressesProvider, getPunkGateway, @@ -30,18 +33,19 @@ import { deployBendProtocolDataProvider, deployPunkGateway, deployWETHGateway, + deployBTokensAndBNFTsHelper, } from "../../helpers/contracts-deployments"; -import { waitForTx } from "../../helpers/misc-utils"; +import { notFalsyOrZeroAddress, waitForTx } from "../../helpers/misc-utils"; import { getEthersSignerByAddress, insertContractAddressInDb } from "../../helpers/contracts-helpers"; -import { ADDRESS_ID_PUNK_GATEWAY, ADDRESS_ID_WETH_GATEWAY } from "../../helpers/constants"; import { ethers } from "hardhat"; +import { ADDRESS_ID_PUNK_GATEWAY, ADDRESS_ID_WETH_GATEWAY } from "../../helpers/constants"; task("dev:deploy-new-implementation", "Deploy new implementation") .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .addFlag("verify", "Verify contracts at Etherscan") - .addFlag("setAddressProvider", "Set contract implementation in address provider") .addParam("contract", "Contract name") - .setAction(async ({ verify, pool, setAddressProvider, contract }, DRE) => { + .addFlag("upgrade", "Upgrade contract") + .setAction(async ({ verify, pool, contract, upgrade }, DRE) => { await DRE.run("set-DRE"); const network = DRE.network.name as eNetwork; @@ -61,7 +65,7 @@ task("dev:deploy-new-implementation", "Deploy new implementation") const lendPoolLiqImpl = await deployLendPoolLiquidator(verify); console.log("LendPoolLiquidator implementation address:", lendPoolLiqImpl.address); - if (setAddressProvider) { + if (upgrade) { await waitForTx(await addressesProvider.setLendPoolImpl(lendPoolImpl.address, [])); await waitForTx(await addressesProvider.setLendPoolLiquidator(lendPoolLiqImpl.address)); } @@ -73,7 +77,7 @@ task("dev:deploy-new-implementation", "Deploy new implementation") const lendPoolCfgImpl = await deployLendPoolConfigurator(verify); console.log("LendPoolConfigurator implementation address:", lendPoolCfgImpl.address); - if (setAddressProvider) { + if (upgrade) { await waitForTx(await addressesProvider.setLendPoolConfiguratorImpl(lendPoolCfgImpl.address, [])); } await insertContractAddressInDb( @@ -86,7 +90,7 @@ task("dev:deploy-new-implementation", "Deploy new implementation") const lendPoolLoanImpl = await deployLendPoolLoan(verify); console.log("LendPoolLoan implementation address:", lendPoolLoanImpl.address); - if (setAddressProvider) { + if (upgrade) { await waitForTx(await addressesProvider.setLendPoolLoanImpl(lendPoolLoanImpl.address, [])); } await insertContractAddressInDb(eContractid.LendPoolLoan, await addressesProvider.getLendPoolLoan()); @@ -96,31 +100,53 @@ task("dev:deploy-new-implementation", "Deploy new implementation") const reserveOracleImpl = await deployReserveOracle(verify); console.log("ReserveOracle implementation address:", reserveOracleImpl.address); - if (setAddressProvider) { - await waitForTx(await addressesProvider.setReserveOracle(reserveOracleImpl.address)); + const proxyAddress = await addressesProvider.getReserveOracle(); + await insertContractAddressInDb(eContractid.ReserveOracle, proxyAddress); + + if (upgrade) { + await DRE.run("dev:upgrade-implementation", { + pool: pool, + contract, + proxy: proxyAddress, + impl: reserveOracleImpl.address, + }); } - await insertContractAddressInDb(eContractid.ReserveOracle, await addressesProvider.getReserveOracle()); } if (contract == "NFTOracle") { const nftOracleImpl = await deployNFTOracle(verify); console.log("NFTOracle implementation address:", nftOracleImpl.address); - if (setAddressProvider) { - await waitForTx(await addressesProvider.setNFTOracle(nftOracleImpl.address)); + const proxyAddress = await addressesProvider.getNFTOracle(); + await insertContractAddressInDb(eContractid.NFTOracle, proxyAddress); + + if (upgrade) { + await DRE.run("dev:upgrade-implementation", { + pool: pool, + contract, + proxy: proxyAddress, + impl: nftOracleImpl.address, + }); } - await insertContractAddressInDb(eContractid.NFTOracle, await addressesProvider.getNFTOracle()); } if (contract == "WETHGateway") { const wethAddress = await getWrappedNativeTokenAddress(poolConfig); console.log("WETH.address", wethAddress); - const wethGatewayImpl = await deployWETHGateway([addressesProvider.address, wethAddress], verify); + const wethGatewayImpl = await deployWETHGateway(verify); console.log("WETHGateway implementation address:", wethGatewayImpl.address); - if (setAddressProvider) { - await waitForTx(await addressesProvider.setAddress(ADDRESS_ID_WETH_GATEWAY, wethGatewayImpl.address)); + const proxyAddress = await addressesProvider.getAddress(ADDRESS_ID_WETH_GATEWAY); + await insertContractAddressInDb(eContractid.WETHGateway, proxyAddress); + + if (upgrade) { + await DRE.run("dev:upgrade-implementation", { + pool: pool, + contract, + proxy: proxyAddress, + impl: wethGatewayImpl.address, + }); } } @@ -134,14 +160,19 @@ task("dev:deploy-new-implementation", "Deploy new implementation") const wpunkAddress = await getWrappedPunkTokenAddress(poolConfig, punkAddress); console.log("WPUNKS.address", wpunkAddress); - const punkGatewayImpl = await deployPunkGateway( - [addressesProvider.address, wethGateWay.address, punkAddress, wpunkAddress], - verify - ); + const punkGatewayImpl = await deployPunkGateway(verify); console.log("PunkGateway implementation address:", punkGatewayImpl.address); - if (setAddressProvider) { - await waitForTx(await addressesProvider.setAddress(ADDRESS_ID_PUNK_GATEWAY, punkGatewayImpl.address)); + const proxyAddress = await addressesProvider.getAddress(ADDRESS_ID_PUNK_GATEWAY); + await insertContractAddressInDb(eContractid.PunkGateway, proxyAddress); + + if (upgrade) { + await DRE.run("dev:upgrade-implementation", { + pool: pool, + contract, + proxy: proxyAddress, + impl: punkGatewayImpl.address, + }); } } @@ -149,7 +180,7 @@ task("dev:deploy-new-implementation", "Deploy new implementation") const contractImpl = await deployBendProtocolDataProvider(addressesProvider.address, verify); console.log("BendProtocolDataProvider implementation address:", contractImpl.address); - if (setAddressProvider) { + if (upgrade) { await waitForTx(await addressesProvider.setBendDataProvider(contractImpl.address)); } } @@ -162,7 +193,7 @@ task("dev:deploy-new-implementation", "Deploy new implementation") ); console.log("UiPoolDataProvider implementation address:", contractImpl.address); - if (setAddressProvider) { + if (upgrade) { await waitForTx(await addressesProvider.setUIDataProvider(contractImpl.address)); } } @@ -171,45 +202,39 @@ task("dev:deploy-new-implementation", "Deploy new implementation") const contractImpl = await deployWalletBalancerProvider(verify); console.log("WalletBalancerProvider implementation address:", contractImpl.address); - if (setAddressProvider) { + if (upgrade) { await waitForTx(await addressesProvider.setWalletBalanceProvider(contractImpl.address)); } } + + if (contract == "BTokensAndBNFTsHelper") { + const contractImpl = await deployBTokensAndBNFTsHelper([addressesProvider.address], verify); + console.log("BTokensAndBNFTsHelper implementation address:", contractImpl.address); + } }); -task("dev:update-implementation-to-address-provider", "Update implementation to address provider") +task("dev:upgrade-implementation", "Update implementation to address provider") .addParam("pool", `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) - .setAction(async ({ verify, pool }, DRE) => { + .addParam("contract", "Contract name") + .addParam("proxy", "Contract proxy address") + .addParam("impl", "Contract implementation address") + .setAction(async ({ pool, contract, proxy, impl }, DRE) => { await DRE.run("set-DRE"); const network = DRE.network.name as eNetwork; const poolConfig = loadPoolConfig(pool); - const addressesProviderRaw = await getLendPoolAddressesProvider(); - const providerOwnerSigner = await getEthersSignerByAddress(await addressesProviderRaw.owner()); - const addressesProvider = addressesProviderRaw.connect(providerOwnerSigner); - { - const wethGatewayImpl = await getWETHGateway(); - await waitForTx(await addressesProvider.setAddress(ADDRESS_ID_WETH_GATEWAY, wethGatewayImpl.address)); - } + const bendProxy = await getBendUpgradeableProxy(proxy); - { - const punkGatewayImpl = await getPunkGateway(); - await waitForTx(await addressesProvider.setAddress(ADDRESS_ID_PUNK_GATEWAY, punkGatewayImpl.address)); + const proxyAdmin = await getBendProxyAdminById(eContractid.BendProxyAdminPool); + if (proxyAdmin == undefined || !notFalsyOrZeroAddress(proxyAdmin.address)) { + throw Error("Invalid pool proxy admin in config"); } + const proxyAdminOwnerAddress = await proxyAdmin.owner(); + const proxyAdminOwnerSigner = DRE.ethers.provider.getSigner(proxyAdminOwnerAddress); - { - const bendProviderImpl = await getBendProtocolDataProvider(); - await waitForTx(await addressesProvider.setBendDataProvider(bendProviderImpl.address)); - } - - { - const uiProviderImpl = await getUIPoolDataProvider(); - await waitForTx(await addressesProvider.setUIDataProvider(uiProviderImpl.address)); - } + // only proxy admin can do upgrading + await waitForTx(await proxyAdmin.connect(proxyAdminOwnerSigner).upgrade(bendProxy.address, impl)); - { - const walletProviderImpl = await getWalletProvider(); - await waitForTx(await addressesProvider.setWalletBalanceProvider(walletProviderImpl.address)); - } + await insertContractAddressInDb(eContractid[contract], proxy); }); diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts index f1a7856..de26fd8 100644 --- a/test/__setup.spec.ts +++ b/test/__setup.spec.ts @@ -52,26 +52,24 @@ import { configureNftsByHelper, } from "../helpers/init-helpers"; import BendConfig from "../markets/bend"; -import { oneEther, ZERO_ADDRESS } from "../helpers/constants"; import { getSecondSigner, getDeploySigner, getPoolAdminSigner, getEmergencyAdminSigner, - getProxyAdminSigner, - getPoolOwnerSigner, getLendPool, getLendPoolConfiguratorProxy, getLendPoolLoanProxy, getBNFTRegistryProxy, - getPairsTokenAggregator, - getMockIncentivesController, getCryptoPunksMarket, getWrappedPunk, + getWETHGateway, + getPunkGateway, } from "../helpers/contracts-getters"; import { WETH9Mocked } from "../types/WETH9Mocked"; import { getNftAddressFromSymbol } from "./helpers/utils/helpers"; import { WrappedPunk } from "../types/WrappedPunk"; +import { ADDRESS_ID_PUNK_GATEWAY, ADDRESS_ID_WETH_GATEWAY } from "../helpers/constants"; const MOCK_USD_PRICE = BendConfig.ProtocolGlobalParams.MockUsdPrice; const ALL_ASSETS_INITIAL_PRICES = BendConfig.Mocks.AllAssetsInitialPrices; @@ -200,11 +198,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { ////////////////////////////////////////////////////////////////////////////// console.log("-> Prepare BToken and BNFT helper..."); - await deployBTokensAndBNFTsHelper([ - lendPoolProxy.address, - addressesProvider.address, - lendPoolConfiguratorProxy.address, - ]); + await deployBTokensAndBNFTsHelper([addressesProvider.address]); ////////////////////////////////////////////////////////////////////////////// console.log("-> Prepare mock reserve token aggregators..."); @@ -342,22 +336,46 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { ////////////////////////////////////////////////////////////////////////////// console.log("-> Prepare WETH gateway..."); - const wethGateway = await deployWETHGateway([addressesProvider.address, mockTokens.WETH.address]); - await waitForTx(await wethGateway.authorizeLendPoolNFT(await getNftAddressFromSymbol("BAYC"))); - await waitForTx(await wethGateway.authorizeLendPoolNFT(wrappedPunk.address)); + const wethGatewayImpl = await deployWETHGateway(); + const wethGwInitEncodedData = wethGatewayImpl.interface.encodeFunctionData("initialize", [ + addressesProvider.address, + mockTokens.WETH.address, + ]); + const wethGatewayProxy = await deployBendUpgradeableProxy( + eContractid.WETHGateway, + bendProxyAdmin.address, + wethGatewayImpl.address, + wethGwInitEncodedData + ); + await waitForTx(await addressesProvider.setAddress(ADDRESS_ID_WETH_GATEWAY, wethGatewayProxy.address)); + const wethGateway = await getWETHGateway(await addressesProvider.getAddress(ADDRESS_ID_WETH_GATEWAY)); + await waitForTx(await wethGateway.authorizeLendPoolNFT([allNftsAddresses.BAYC, allNftsAddresses.WPUNKS])); + await insertContractAddressInDb(eContractid.WETHGateway, wethGateway.address); console.log("-> Prepare PUNK gateway..."); - const punkGateway = await deployPunkGateway([ + const punkGatewayImpl = await deployPunkGateway(); + const punkGwInitEncodedData = punkGatewayImpl.interface.encodeFunctionData("initialize", [ addressesProvider.address, wethGateway.address, cryptoPunksMarket.address, wrappedPunk.address, ]); - console.log(`Deploy PunkGateway at ${punkGateway.address}`); - console.log(`Authorzie PunkGateway with LendPool and WETHGateway`); - await waitForTx(await punkGateway.authorizeLendPoolERC20(allReservesAddresses.WETH)); - await waitForTx(await punkGateway.authorizeLendPoolERC20(allReservesAddresses.DAI)); - await waitForTx(await punkGateway.authorizeLendPoolERC20(allReservesAddresses.USDC)); + const punkGatewayProxy = await deployBendUpgradeableProxy( + eContractid.PunkGateway, + bendProxyAdmin.address, + punkGatewayImpl.address, + punkGwInitEncodedData + ); + await waitForTx(await addressesProvider.setAddress(ADDRESS_ID_PUNK_GATEWAY, punkGatewayProxy.address)); + const punkGateway = await getPunkGateway(await addressesProvider.getAddress(ADDRESS_ID_PUNK_GATEWAY)); + await waitForTx( + await punkGateway.authorizeLendPoolERC20([ + allReservesAddresses.WETH, + allReservesAddresses.DAI, + allReservesAddresses.USDC, + ]) + ); + await insertContractAddressInDb(eContractid.PunkGateway, punkGateway.address); console.timeEnd("setup"); }; diff --git a/test/configurator-nft.spec.ts b/test/configurator-nft.spec.ts index d044fe3..088e812 100644 --- a/test/configurator-nft.spec.ts +++ b/test/configurator-nft.spec.ts @@ -114,7 +114,8 @@ makeSuite("Configurator-NFT", (testEnv: TestEnv) => { it("Deactivates the BAYC NFT as auction", async () => { const { configurator, dataProvider, bayc } = testEnv; - await configurator.configureNftAsAuction(bayc.address, 0, 0, 0, 0); + await configurator.configureNftAsAuction(bayc.address, 0, 0, 0); + await configurator.setNftRedeemThreshold(bayc.address, 0); const { redeemDuration, auctionDuration, redeemFine, redeemThreshold } = await dataProvider.getNftConfigurationData( bayc.address @@ -128,7 +129,8 @@ makeSuite("Configurator-NFT", (testEnv: TestEnv) => { it("Activates the BAYC NFT as auction", async () => { const { configurator, dataProvider, bayc } = testEnv; - await configurator.configureNftAsAuction(bayc.address, "1", "1", "100", "5000"); + await configurator.configureNftAsAuction(bayc.address, "1", "1", "100"); + await configurator.setNftRedeemThreshold(bayc.address, "5000"); const { redeemDuration, auctionDuration, redeemFine, redeemThreshold } = await dataProvider.getNftConfigurationData( bayc.address @@ -143,7 +145,11 @@ makeSuite("Configurator-NFT", (testEnv: TestEnv) => { it("Check the onlyAdmin on configureNftAsAuction ", async () => { const { configurator, users, bayc } = testEnv; await expect( - configurator.connect(users[2].signer).configureNftAsAuction(bayc.address, "1", "1", "100", "5000"), + configurator.connect(users[2].signer).configureNftAsAuction(bayc.address, "1", "1", "100"), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + await expect( + configurator.connect(users[2].signer).setNftRedeemThreshold(bayc.address, "5000"), CALLER_NOT_POOL_ADMIN ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); diff --git a/test/helpers/actions.ts b/test/helpers/actions.ts index a85b350..1c13a93 100644 --- a/test/helpers/actions.ts +++ b/test/helpers/actions.ts @@ -710,7 +710,7 @@ export const redeem = async ( if (amount !== "-1") { amountToRedeem = (await convertToCurrencyDecimals(reserveAsset, amount)).toString(); } else { - amountToRedeem = loanDataBefore.currentAmount.div(2).plus(loanDataBefore.bidFine).toFixed(0); //50% Debt + Bid Fine + amountToRedeem = loanDataBefore.currentAmount.multipliedBy(0.6).plus(loanDataBefore.bidFine).toFixed(0); //60% Debt + Bid Fine } amountToRedeem = "0x" + new BigNumber(amountToRedeem).toString(16);