diff --git a/contracts/libraries/helpers/Errors.sol b/contracts/libraries/helpers/Errors.sol index 4c9da21..e6cca0f 100644 --- a/contracts/libraries/helpers/Errors.sol +++ b/contracts/libraries/helpers/Errors.sol @@ -20,6 +20,8 @@ library Errors { string public constant INVALID_FROM_BALANCE_AFTER_TRANSFER = "102"; string public constant INVALID_TO_BALANCE_AFTER_TRANSFER = "103"; string public constant CALLER_NOT_ONBEHALFOF_OR_IN_WHITELIST = "104"; + string public constant CALLER_NOT_RISK_ADMIN = "105"; + string public constant CALLER_NOT_RISK_OR_POOL_ADMIN = "106"; //math library erros string public constant MATH_MULTIPLICATION_OVERFLOW = "200"; diff --git a/contracts/protocol/LendPoolAddressesProvider.sol b/contracts/protocol/LendPoolAddressesProvider.sol index 3509938..98ec6f3 100644 --- a/contracts/protocol/LendPoolAddressesProvider.sol +++ b/contracts/protocol/LendPoolAddressesProvider.sol @@ -34,6 +34,7 @@ contract LendPoolAddressesProvider is Ownable, ILendPoolAddressesProvider { bytes32 private constant BEND_DATA_PROVIDER = "BEND_DATA_PROVIDER"; bytes32 private constant UI_DATA_PROVIDER = "UI_DATA_PROVIDER"; bytes32 private constant WALLET_BALANCE_PROVIDER = "WALLET_BALANCE_PROVIDER"; + bytes32 public constant RISK_ADMIN = "RISK_ADMIN"; constructor(string memory marketId) { _setMarketId(marketId); diff --git a/contracts/protocol/LendPoolConfigurator.sol b/contracts/protocol/LendPoolConfigurator.sol index c2bfdf2..4db0dec 100644 --- a/contracts/protocol/LendPoolConfigurator.sol +++ b/contracts/protocol/LendPoolConfigurator.sol @@ -30,6 +30,7 @@ contract LendPoolConfigurator is Initializable, ILendPoolConfigurator { using NftConfiguration for DataTypes.NftConfigurationMap; ILendPoolAddressesProvider internal _addressesProvider; + bytes32 public constant RISK_ADMIN = "RISK_ADMIN"; modifier onlyPoolAdmin() { require(_addressesProvider.getPoolAdmin() == msg.sender, Errors.CALLER_NOT_POOL_ADMIN); @@ -41,6 +42,14 @@ contract LendPoolConfigurator is Initializable, ILendPoolConfigurator { _; } + modifier onlyRiskOrPoolAdmin() { + require( + (_addressesProvider.getAddress(RISK_ADMIN) == msg.sender) || (_addressesProvider.getPoolAdmin() == msg.sender), + Errors.CALLER_NOT_RISK_OR_POOL_ADMIN + ); + _; + } + function initialize(ILendPoolAddressesProvider provider) public initializer { _addressesProvider = provider; } @@ -86,7 +95,7 @@ contract LendPoolConfigurator is Initializable, ILendPoolConfigurator { } } - function setBorrowingFlagOnReserve(address[] calldata assets, bool flag) external onlyPoolAdmin { + function setBorrowingFlagOnReserve(address[] calldata assets, bool flag) external onlyRiskOrPoolAdmin { ILendPool cachedPool = _getLendPool(); for (uint256 i = 0; i < assets.length; i++) { DataTypes.ReserveConfigurationMap memory currentConfig = cachedPool.getReserveConfiguration(assets[i]); @@ -126,7 +135,7 @@ contract LendPoolConfigurator is Initializable, ILendPoolConfigurator { } } - function setFreezeFlagOnReserve(address[] calldata assets, bool flag) external onlyPoolAdmin { + function setFreezeFlagOnReserve(address[] calldata assets, bool flag) external onlyRiskOrPoolAdmin { ILendPool cachedPool = _getLendPool(); for (uint256 i = 0; i < assets.length; i++) { DataTypes.ReserveConfigurationMap memory currentConfig = cachedPool.getReserveConfiguration(assets[i]); @@ -205,7 +214,7 @@ contract LendPoolConfigurator is Initializable, ILendPoolConfigurator { } } - function setFreezeFlagOnNft(address[] calldata assets, bool flag) external onlyPoolAdmin { + function setFreezeFlagOnNft(address[] calldata assets, bool flag) external onlyRiskOrPoolAdmin { ILendPool cachedPool = _getLendPool(); for (uint256 i = 0; i < assets.length; i++) { DataTypes.NftConfigurationMap memory currentConfig = cachedPool.getNftConfiguration(assets[i]); @@ -322,7 +331,7 @@ contract LendPoolConfigurator is Initializable, ILendPoolConfigurator { address[] calldata assets, uint256 maxSupply, uint256 maxTokenId - ) external onlyPoolAdmin { + ) external onlyRiskOrPoolAdmin { ILendPool cachedPool = _getLendPool(); for (uint256 i = 0; i < assets.length; i++) { cachedPool.setNftMaxSupplyAndTokenId(assets[i], maxSupply, maxTokenId); diff --git a/deployments/deployed-contracts-goerli.json b/deployments/deployed-contracts-goerli.json index fcf1276..71d4490 100644 --- a/deployments/deployed-contracts-goerli.json +++ b/deployments/deployed-contracts-goerli.json @@ -53,7 +53,7 @@ "deployer": "0xafF5C36642385b6c7Aaf7585eC785aB2316b5db6" }, "ConfiguratorLogic": { - "address": "0x1580A5E24B0c80c6DDd93225F1D11B62AEA0EC2d", + "address": "0x935429b4eADc941d3af30F431844f86057242bDc", "deployer": "0xafF5C36642385b6c7Aaf7585eC785aB2316b5db6" }, "LendPoolImpl": { @@ -69,7 +69,7 @@ "address": "0x7F64c32a3c13Bd245a7141a607A7E60DA585BA86" }, "LendPoolConfiguratorImpl": { - "address": "0x1e53E338C7f6Eb1F9c70E30C369ed41782635344" + "address": "0x5F7Ae7Bb12712109500d9E4484170dE3A06eDd54" }, "LendPoolConfigurator": { "address": "0x365661b853845F90b2b5B28a1A61bE5c54aE9FB2" diff --git a/helpers/types.ts b/helpers/types.ts index 68b8cb4..59c2e99 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -118,6 +118,8 @@ export enum ProtocolErrors { INVALID_FROM_BALANCE_AFTER_TRANSFER = "102", INVALID_TO_BALANCE_AFTER_TRANSFER = "103", CALLER_NOT_ONBEHALFOF_OR_IN_WHITELIST = "104", + CALLER_NOT_RISK_ADMIN = "105", + CALLER_NOT_RISK_OR_POOL_ADMIN = "106", //math library erros MATH_MULTIPLICATION_OVERFLOW = "200", diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts index a3a8aaf..937d00f 100644 --- a/test/__setup.spec.ts +++ b/test/__setup.spec.ts @@ -163,6 +163,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { const addressesProvider = await deployLendPoolAddressesProvider(BendConfig.MarketId); await waitForTx(await addressesProvider.setPoolAdmin(poolAdmin)); await waitForTx(await addressesProvider.setEmergencyAdmin(emergencyAdmin)); + await waitForTx(await addressesProvider.setAddress(await addressesProvider.RISK_ADMIN(), poolAdmin)); await waitForTx( await addressesProviderRegistry.registerAddressesProvider(addressesProvider.address, BendConfig.ProviderId) diff --git a/test/configurator-nft.spec.ts b/test/configurator-nft.spec.ts index db3a531..04a1ad9 100644 --- a/test/configurator-nft.spec.ts +++ b/test/configurator-nft.spec.ts @@ -54,7 +54,7 @@ makeSuite("Configurator-NFT", (testEnv: TestEnv) => { expect(isActive).to.be.equal(true); }); - it("Check the onlyAdmin on deactivateRNft ", async () => { + it("Check the onlyPoolAdmin on deactivateRNft ", async () => { const { configurator, users, bayc } = testEnv; await expect( configurator.connect(users[2].signer).setActiveFlagOnNft([bayc.address], false), @@ -62,7 +62,7 @@ makeSuite("Configurator-NFT", (testEnv: TestEnv) => { ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); - it("Check the onlyAdmin on activateNft ", async () => { + it("Check the onlyPoolAdmin on activateNft ", async () => { const { configurator, users, bayc } = testEnv; await expect( configurator.connect(users[2].signer).setActiveFlagOnNft([bayc.address], true), @@ -93,7 +93,7 @@ makeSuite("Configurator-NFT", (testEnv: TestEnv) => { await expect( configurator.connect(users[2].signer).setFreezeFlagOnNft([bayc.address], true), CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + ).to.be.revertedWith(ProtocolErrors.CALLER_NOT_RISK_OR_POOL_ADMIN); }); it("Check the onlyAdmin on unfreezeNft ", async () => { @@ -101,7 +101,7 @@ makeSuite("Configurator-NFT", (testEnv: TestEnv) => { await expect( configurator.connect(users[2].signer).setFreezeFlagOnNft([bayc.address], false), CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + ).to.be.revertedWith(ProtocolErrors.CALLER_NOT_RISK_OR_POOL_ADMIN); }); it("Deactivates the BAYC NFT as collateral", async () => { @@ -126,7 +126,7 @@ makeSuite("Configurator-NFT", (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(500); }); - it("Check the onlyAdmin on configureNftAsCollateral ", async () => { + it("Check the onlyPoolAdmin on configureNftAsCollateral ", async () => { const { configurator, users, bayc } = testEnv; await expect( configurator.connect(users[2].signer).configureNftAsCollateral([bayc.address], "7500", "8000", "500"), @@ -166,7 +166,7 @@ makeSuite("Configurator-NFT", (testEnv: TestEnv) => { expect(minBidFine).to.be.equal(5000); }); - it("Check the onlyAdmin on configureNftAsAuction ", async () => { + it("Check the onlyPoolAdmin on configureNftAsAuction ", async () => { const { configurator, users, bayc } = testEnv; await expect( configurator.connect(users[2].signer).configureNftAsAuction([bayc.address], "1", "1", "100"), @@ -216,7 +216,7 @@ makeSuite("Configurator-NFT", (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(500); }); - it("Check the onlyAdmin on batchConfigNft ", async () => { + it("Check the onlyPoolAdmin on batchConfigNft ", async () => { const { configurator, users, bayc } = testEnv; await expect( configurator.connect(users[2].signer).batchConfigNft(cfgInputParams), @@ -303,7 +303,7 @@ makeSuite("Configurator-NFT", (testEnv: TestEnv) => { ); }); - it("Check the onlyAdmin on setMaxNumberOfNfts ", async () => { + it("Check the onlyPoolAdmin on setMaxNumberOfNfts ", async () => { const { configurator, users, pool } = testEnv; await expect( configurator.connect(users[2].signer).setMaxNumberOfNfts(512), @@ -325,7 +325,7 @@ makeSuite("Configurator-NFT", (testEnv: TestEnv) => { expect(wantVal2).to.be.equal(false); }); - it("Check the onlyAdmin on approve interceptor ", async () => { + it("Check the onlyPoolAdmin on approve interceptor ", async () => { const { configurator, users, pool } = testEnv; await expect( configurator.connect(users[2].signer).approveLoanRepaidInterceptor(pool.address, true), @@ -333,7 +333,7 @@ makeSuite("Configurator-NFT", (testEnv: TestEnv) => { ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); - it("Check the onlyAdmin on approve interceptor ", async () => { + it("Check the onlyPoolAdmin on approve interceptor ", async () => { const { configurator, users, pool, bBAYC } = testEnv; await expect( configurator.connect(users[2].signer).purgeLoanRepaidInterceptor(bBAYC.address, [100], pool.address), @@ -355,7 +355,7 @@ makeSuite("Configurator-NFT", (testEnv: TestEnv) => { expect(wantVal2).to.be.equal(false); }); - it("Check the onlyAdmin on approve locker ", async () => { + it("Check the onlyPoolAdmin on approve locker ", async () => { const { configurator, users, pool } = testEnv; await expect( configurator.connect(users[2].signer).approveFlashLoanLocker(pool.address, true), @@ -363,7 +363,7 @@ makeSuite("Configurator-NFT", (testEnv: TestEnv) => { ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); - it("Check the onlyAdmin on approve locker ", async () => { + it("Check the onlyPoolAdmin on approve locker ", async () => { const { configurator, users, pool, bBAYC } = testEnv; await expect( configurator.connect(users[2].signer).purgeFlashLoanLocking(bBAYC.address, [100], pool.address), diff --git a/test/configurator-reserve.spec.ts b/test/configurator-reserve.spec.ts index b90e899..7def2d9 100644 --- a/test/configurator-reserve.spec.ts +++ b/test/configurator-reserve.spec.ts @@ -39,7 +39,7 @@ makeSuite("Configurator-Reserve", (testEnv: TestEnv) => { expect(isActive).to.be.equal(true); }); - it("Check the onlyAdmin on deactivateReserve ", async () => { + it("Check the onlyPoolAdmin on deactivateReserve ", async () => { const { configurator, users, weth } = testEnv; await expect( configurator.connect(users[2].signer).setActiveFlagOnReserve([weth.address], false), @@ -47,7 +47,7 @@ makeSuite("Configurator-Reserve", (testEnv: TestEnv) => { ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); - it("Check the onlyAdmin on activateReserve ", async () => { + it("Check the onlyPoolAdmin on activateReserve ", async () => { const { configurator, users, weth } = testEnv; await expect( configurator.connect(users[2].signer).setActiveFlagOnReserve([weth.address], true), @@ -88,7 +88,7 @@ makeSuite("Configurator-Reserve", (testEnv: TestEnv) => { await expect( configurator.connect(users[2].signer).setFreezeFlagOnReserve([weth.address], true), CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + ).to.be.revertedWith(ProtocolErrors.CALLER_NOT_RISK_OR_POOL_ADMIN); }); it("Check the onlyAdmin on unfreezeReserve ", async () => { @@ -96,7 +96,7 @@ makeSuite("Configurator-Reserve", (testEnv: TestEnv) => { await expect( configurator.connect(users[2].signer).setFreezeFlagOnReserve([weth.address], false), CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + ).to.be.revertedWith(ProtocolErrors.CALLER_NOT_RISK_OR_POOL_ADMIN); }); it("Deactivates the ETH reserve for borrowing", async () => { @@ -134,7 +134,7 @@ makeSuite("Configurator-Reserve", (testEnv: TestEnv) => { await expect( configurator.connect(users[2].signer).setBorrowingFlagOnReserve([weth.address], false), CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + ).to.be.revertedWith(ProtocolErrors.CALLER_NOT_RISK_OR_POOL_ADMIN); }); it("Check the onlyAdmin on enableBorrowingOnReserve ", async () => { @@ -142,7 +142,7 @@ makeSuite("Configurator-Reserve", (testEnv: TestEnv) => { await expect( configurator.connect(users[2].signer).setBorrowingFlagOnReserve([weth.address], true), CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + ).to.be.revertedWith(ProtocolErrors.CALLER_NOT_RISK_OR_POOL_ADMIN); }); it("Changes the reserve factor of WETH", async () => { @@ -239,7 +239,7 @@ makeSuite("Configurator-Reserve", (testEnv: TestEnv) => { ); }); - it("Check the onlyAdmin on setMaxNumberOfReserves ", async () => { + it("Check the onlyPoolAdmin on setMaxNumberOfReserves ", async () => { const { configurator, users, pool } = testEnv; await expect( configurator.connect(users[2].signer).setMaxNumberOfReserves(512),