Skip to content

Commit

Permalink
fix: minor fixes
Browse files Browse the repository at this point in the history
In this commit:
- upgrade deps
- CF and CC no longer expect ACL as constructor argument
- credit factory reads WETH from AP in runtime and not in constructor
- aliased loss policy conforms to default constructor signature
- add missing serialization
- revert on non-v3 minor version
- `getLatestMinorVersion` and `getLatestPatchVersion` accept non-exact versions
  • Loading branch information
lekhovitsky committed Feb 10, 2025
1 parent e5e4836 commit 32eed86
Show file tree
Hide file tree
Showing 21 changed files with 74 additions and 56 deletions.
33 changes: 10 additions & 23 deletions contracts/factories/CreditFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ import {ICreditFacadeV3} from "@gearbox-protocol/core-v3/contracts/interfaces/IC
import {ICreditManagerV3} from "@gearbox-protocol/core-v3/contracts/interfaces/ICreditManagerV3.sol";
import {IPoolV3} from "@gearbox-protocol/core-v3/contracts/interfaces/IPoolV3.sol";

import {ICreditFactory, CreditFacadeParams} from "../interfaces/factories/ICreditFactory.sol";
import {ICreditConfigureActions} from "../interfaces/factories/ICreditConfigureActions.sol";
import {ICreditFactory} from "../interfaces/factories/ICreditFactory.sol";
import {
CreditFacadeParams,
CreditManagerParams,
ICreditConfigureActions
} from "../interfaces/factories/ICreditConfigureActions.sol";
import {ICreditEmergencyConfigureActions} from "../interfaces/factories/ICreditEmergencyConfigureActions.sol";
import {IFactory} from "../interfaces/factories/IFactory.sol";
import {IContractsRegister} from "../interfaces/IContractsRegister.sol";
Expand All @@ -34,19 +38,6 @@ import {

import {AbstractFactory} from "./AbstractFactory.sol";

struct CreditManagerParams {
uint8 maxEnabledTokens;
uint16 feeInterest;
uint16 feeLiquidation;
uint16 liquidationPremium;
uint16 feeLiquidationExpired;
uint16 liquidationPremiumExpired;
uint128 minDebt;
uint128 maxDebt;
string name;
DeployParams accountFactoryParams;
}

contract CreditFactory is AbstractFactory, ICreditFactory {
/// @notice Contract version
uint256 public constant override version = 3_10;
Expand All @@ -57,9 +48,6 @@ contract CreditFactory is AbstractFactory, ICreditFactory {
/// @notice Address of the bot list contract
address public immutable botList;

/// @notice Address of the WETH token
address public immutable weth;

error DegenNFTIsNotRegisteredException(address degenNFT);

error TargetContractIsNotAllowedException(address targetCotnract);
Expand All @@ -68,7 +56,6 @@ contract CreditFactory is AbstractFactory, ICreditFactory {
/// @param addressProvider_ Address provider contract address
constructor(address addressProvider_) AbstractFactory(addressProvider_) {
botList = _getAddressOrRevert(AP_BOT_LIST, NO_VERSION_CONTROL);
weth = _tryGetAddress(AP_WETH_TOKEN, NO_VERSION_CONTROL);
}

// ---------- //
Expand Down Expand Up @@ -314,8 +301,7 @@ contract CreditFactory is AbstractFactory, ICreditFactory {
}

function _deployCreditConfigurator(address marketConfigurator, address creditManager) internal returns (address) {
address acl = IMarketConfigurator(marketConfigurator).acl();
bytes memory constructorParams = abi.encode(acl, creditManager);
bytes memory constructorParams = abi.encode(creditManager);

return _deployLatestPatch({
contractType: AP_CREDIT_CONFIGURATOR,
Expand All @@ -329,7 +315,6 @@ contract CreditFactory is AbstractFactory, ICreditFactory {
internal
returns (address)
{
address acl = IMarketConfigurator(marketConfigurator).acl();
address contractsRegister = IMarketConfigurator(marketConfigurator).contractsRegister();
address lossPolicy = IContractsRegister(contractsRegister).getLossPolicy(ICreditManagerV3(creditManager).pool());

Expand All @@ -346,8 +331,10 @@ contract CreditFactory is AbstractFactory, ICreditFactory {
botList_ = ICreditFacadeV3(prevCreditFacade).botList();
}

address weth = _tryGetAddress(AP_WETH_TOKEN, NO_VERSION_CONTROL);

bytes memory constructorParams =
abi.encode(acl, creditManager, lossPolicy, botList_, weth, params.degenNFT, params.expirable);
abi.encode(creditManager, lossPolicy, botList_, weth, params.degenNFT, params.expirable);

return _deployLatestPatch({
contractType: AP_CREDIT_FACADE,
Expand Down
7 changes: 1 addition & 6 deletions contracts/factories/LossPolicyFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,7 @@ contract LossPolicyFactory is AbstractMarketFactory, ILossPolicyFactory {
onlyMarketConfigurators
returns (DeployResult memory)
{
if (params.postfix == "ALIASED") {
address decodedPool = abi.decode(params.constructorParams, (address));
if (decodedPool != pool) revert InvalidConstructorParamsException();
} else {
_validateDefaultConstructorParams(pool, params.constructorParams);
}
_validateDefaultConstructorParams(pool, params.constructorParams);

address lossPolicy = _deployLatestPatch({
contractType: _getContractType(DOMAIN_LOSS_POLICY, params.postfix),
Expand Down
15 changes: 8 additions & 7 deletions contracts/factories/PriceOracleFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ contract PriceOracleFactory is AbstractMarketFactory, IPriceOracleFactory {
address priceOracle = _priceOracle(pool);

bytes4 selector = bytes4(callData);
if (selector == IPriceOracleConfigureActions.setPriceFeed.selector) {
if (selector == IPriceOracleEmergencyConfigureActions.setPriceFeed.selector) {
(address token, address priceFeed) = abi.decode(callData[4:], (address, address));
_validatePriceFeed(pool, token, priceFeed, true);
if (block.timestamp < IPriceFeedStore(priceFeedStore).getAllowanceTimestamp(token, priceFeed) + 1 days) {
Expand Down Expand Up @@ -209,6 +209,7 @@ contract PriceOracleFactory is AbstractMarketFactory, IPriceOracleFactory {
}

function _getPriceFeed(address priceOracle, address token, bool reserve) internal view returns (address) {
// FIXME: doesn't work like that for price oracle v3.0
return reserve
? IPriceOracleV3(priceOracle).reservePriceFeeds(token)
: IPriceOracleV3(priceOracle).priceFeeds(token);
Expand All @@ -227,8 +228,8 @@ contract PriceOracleFactory is AbstractMarketFactory, IPriceOracleFactory {

Call[] memory calls = CallBuilder.build(
reserve
? _setReservePriceFeed(priceOracle, token, priceFeed, stalenessPeriod)
: _setPriceFeed(priceOracle, token, priceFeed, stalenessPeriod)
? _setReservePriceFeedCall(priceOracle, token, priceFeed, stalenessPeriod)
: _setPriceFeedCall(priceOracle, token, priceFeed, stalenessPeriod)
);
return _addUpdatableFeeds(priceOracle, priceFeed, calls);
}
Expand All @@ -239,7 +240,7 @@ contract PriceOracleFactory is AbstractMarketFactory, IPriceOracleFactory {
returns (Call[] memory)
{
try IUpdatablePriceFeed(priceFeed).updatable() returns (bool updatable) {
if (updatable) calls = calls.append(_addUpdatablePriceFeed(priceOracle, priceFeed));
if (updatable) calls = calls.append(_addUpdatablePriceFeedCall(priceOracle, priceFeed));
} catch {}
address[] memory underlyingFeeds = IPriceFeed(priceFeed).getUnderlyingFeeds();
uint256 numFeeds = underlyingFeeds.length;
Expand All @@ -249,15 +250,15 @@ contract PriceOracleFactory is AbstractMarketFactory, IPriceOracleFactory {
return calls;
}

function _setPriceFeed(address priceOracle, address token, address priceFeed, uint32 stalenessPeriod)
function _setPriceFeedCall(address priceOracle, address token, address priceFeed, uint32 stalenessPeriod)
internal
pure
returns (Call memory)
{
return Call(priceOracle, abi.encodeCall(IPriceOracleV3.setPriceFeed, (token, priceFeed, stalenessPeriod)));
}

function _setReservePriceFeed(address priceOracle, address token, address priceFeed, uint32 stalenessPeriod)
function _setReservePriceFeedCall(address priceOracle, address token, address priceFeed, uint32 stalenessPeriod)
internal
pure
returns (Call memory)
Expand All @@ -266,7 +267,7 @@ contract PriceOracleFactory is AbstractMarketFactory, IPriceOracleFactory {
Call(priceOracle, abi.encodeCall(IPriceOracleV3.setReservePriceFeed, (token, priceFeed, stalenessPeriod)));
}

function _addUpdatablePriceFeed(address priceOracle, address priceFeed) internal pure returns (Call memory) {
function _addUpdatablePriceFeedCall(address priceOracle, address priceFeed) internal pure returns (Call memory) {
return Call(priceOracle, abi.encodeCall(IPriceOracleV3.addUpdatablePriceFeed, (priceFeed)));
}
}
2 changes: 2 additions & 0 deletions contracts/global/BytecodeRepository.sol
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,7 @@ contract BytecodeRepository is ImmutableOwnableTrait, SanityCheckTrait, IBytecod
/// @param majorVersion Major version number
/// @return uint256 Latest minor version number
function getLatestMinorVersion(bytes32 _contractType, uint256 majorVersion) external view returns (uint256) {
majorVersion -= majorVersion % 100;
return latestMinorVersion[_contractType][majorVersion];
}

Expand All @@ -510,6 +511,7 @@ contract BytecodeRepository is ImmutableOwnableTrait, SanityCheckTrait, IBytecod
/// @param minorVersion Minor version number
/// @return uint256 Latest patch version number
function getLatestPatchVersion(bytes32 _contractType, uint256 minorVersion) external view returns (uint256) {
minorVersion -= minorVersion % 10;
return latestPatchVersion[_contractType][minorVersion];
}

Expand Down
4 changes: 4 additions & 0 deletions contracts/helpers/DefaultDegenNFT.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ contract DefaultDegenNFT is ERC721, IDegenNFT {
contractsRegister = IMarketConfigurator(marketConfigurator_).contractsRegister();
}

function serialize() external view override returns (bytes memory) {
return abi.encode(marketConfigurator, minter, name(), symbol(), baseURI, totalSupply);
}

function _baseURI() internal view override returns (string memory) {
return baseURI;
}
Expand Down
2 changes: 2 additions & 0 deletions contracts/helpers/DefaultIRM.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ contract DefaultIRM is IInterestRateModel {
uint256 public constant override version = 3_10;
bytes32 public constant override contractType = AP_INTEREST_RATE_MODEL_DEFAULT;

function serialize() external pure override returns (bytes memory) {}

function calcBorrowRate(uint256, uint256, bool) external pure override returns (uint256) {
return 0;
}
Expand Down
11 changes: 9 additions & 2 deletions contracts/helpers/DefaultLossPolicy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,23 @@
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.23;

import {ILossPolicy} from "@gearbox-protocol/core-v3/contracts/interfaces/base/ILossPolicy.sol";
import {ACLTrait} from "@gearbox-protocol/core-v3/contracts/traits/ACLTrait.sol";
import {AP_LOSS_POLICY_DEFAULT} from "../libraries/ContractLiterals.sol";

contract DefaultLossPolicy is ACLTrait {
contract DefaultLossPolicy is ILossPolicy, ACLTrait {
uint256 public constant version = 3_10;
bytes32 public constant contractType = AP_LOSS_POLICY_DEFAULT;

bool public enabled;

constructor(address _acl) ACLTrait(_acl) {}
// QUESTION: shouldn't it take pool address and AP so that it can be used with loss policy factory?
// that would make it hard to use in legacy market configurator
constructor(address acl_) ACLTrait(acl_) {}

function serialize() external view override returns (bytes memory) {
return abi.encode(enabled);
}

function isLiquidatable(address, address, bytes calldata) external view returns (bool) {
return enabled;
Expand Down
2 changes: 2 additions & 0 deletions contracts/instance/AddressProvider.sol
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,14 @@ contract AddressProvider is ImmutableOwnableTrait, IAddressProvider {
}

function getLatestMinorVersion(string memory key, uint256 majorVersion) external view override returns (uint256) {
majorVersion -= majorVersion % 100;
uint256 latestMinorVersion = latestMinorVersions[key][majorVersion];
if (latestMinorVersion == 0) revert VersionNotFoundException();
return latestMinorVersion;
}

function getLatestPatchVersion(string memory key, uint256 minorVersion) external view override returns (uint256) {
minorVersion -= minorVersion % 10;
uint256 latestPatchVersion = latestPatchVersions[key][minorVersion];
if (latestPatchVersion == 0) revert VersionNotFoundException();
return latestPatchVersion;
Expand Down
2 changes: 2 additions & 0 deletions contracts/interfaces/IMarketConfigurator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ interface IMarketConfigurator is IVersion, IDeployerTrait {

error CreditSuiteNotRegisteredException(address creditManager);

error IncorrectMinorVersionException(uint256 version);

error IncorrectPeripheryContractException(address peripheryContract);

error MarketNotRegisteredException(address pool);
Expand Down
20 changes: 19 additions & 1 deletion contracts/interfaces/factories/ICreditConfigureActions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,27 @@
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.23;

import {CreditFacadeParams} from "./ICreditFactory.sol";
import {DeployParams} from "../Types.sol";

struct CreditManagerParams {
uint8 maxEnabledTokens;
uint16 feeInterest;
uint16 feeLiquidation;
uint16 liquidationPremium;
uint16 feeLiquidationExpired;
uint16 liquidationPremiumExpired;
uint128 minDebt;
uint128 maxDebt;
string name;
DeployParams accountFactoryParams;
}

struct CreditFacadeParams {
address degenNFT;
bool expirable;
bool migrateBotList;
}

interface ICreditConfigureActions {
function upgradeCreditConfigurator() external;
function upgradeCreditFacade(CreditFacadeParams calldata params) external;
Expand Down
6 changes: 0 additions & 6 deletions contracts/interfaces/factories/ICreditFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@ pragma solidity ^0.8.23;
import {Call, DeployResult} from "../Types.sol";
import {IFactory} from "./IFactory.sol";

struct CreditFacadeParams {
address degenNFT;
bool expirable;
bool migrateBotList;
}

interface ICreditFactory is IFactory {
function deployCreditSuite(address pool, bytes calldata encodedParams) external returns (DeployResult memory);

Expand Down
2 changes: 2 additions & 0 deletions contracts/market/MarketConfigurator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,7 @@ contract MarketConfigurator is DeployerTrait, IMarketConfigurator {
}

function _getLatestMarketFactories(uint256 minorVersion) internal view returns (MarketFactories memory) {
if (minorVersion / 100 != 3) revert IncorrectMinorVersionException(minorVersion);
return MarketFactories({
poolFactory: _getLatestPatch(AP_POOL_FACTORY, minorVersion),
priceOracleFactory: _getLatestPatch(AP_PRICE_ORACLE_FACTORY, minorVersion),
Expand All @@ -806,6 +807,7 @@ contract MarketConfigurator is DeployerTrait, IMarketConfigurator {
}

function _getLatestCreditFactory(uint256 minorVersion) internal view returns (address) {
if (minorVersion / 100 != 3) revert IncorrectMinorVersionException(minorVersion);
return _getLatestPatch(AP_CREDIT_FACTORY, minorVersion);
}

Expand Down
2 changes: 0 additions & 2 deletions contracts/test/configuration/ConfigurationTestHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,6 @@ contract ConfigurationTestHelper is Test, GlobalSetup {
}

function _deployTestPool() internal returns (address) {
address poolFactory = IAddressProvider(addressProvider).getAddressOrRevert(AP_POOL_FACTORY, 3_10);

IERC20(WETH).transfer(address(marketConfigurator), 1e18);

address _pool = marketConfigurator.previewCreateMarket(3_10, WETH, name, symbol);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ contract CreditSuiteConfigurationUnitTest is ConfigurationTestHelper {
address expectedNewConfigurator = IBytecodeRepository(bytecodeRepository).computeAddress(
"CREDIT_CONFIGURATOR",
3_11,
abi.encode(marketConfigurator.acl(), address(creditManager)),
abi.encode(address(creditManager)),
bytes32(bytes20(address(marketConfigurator))),
creditFactory
);
Expand Down Expand Up @@ -321,7 +321,6 @@ contract CreditSuiteConfigurationUnitTest is ConfigurationTestHelper {
"CREDIT_FACADE",
3_10,
abi.encode(
marketConfigurator.acl(),
address(creditManager),
lossPolicy,
ICreditFacadeV3(oldFacade).botList(),
Expand Down
2 changes: 1 addition & 1 deletion contracts/test/mocks/MockCreditConfiguratorPatch.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {CreditConfiguratorV3} from "@gearbox-protocol/core-v3/contracts/credit/C
import {IVersion} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IVersion.sol";

contract MockCreditConfiguratorPatch is CreditConfiguratorV3, Test {
constructor(address _acl, address _creditManager) CreditConfiguratorV3(_acl, _creditManager) {
constructor(address _creditManager) CreditConfiguratorV3(_creditManager) {
vm.mockCall(address(this), abi.encodeCall(IVersion.version, ()), abi.encode(311));
}
}
6 changes: 5 additions & 1 deletion contracts/test/mocks/MockLossPolicy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.23;

contract MockLossPolicy {
import {ILossPolicy} from "@gearbox-protocol/core-v3/contracts/interfaces/base/ILossPolicy.sol";

contract MockLossPolicy is ILossPolicy {
uint256 public constant version = 3_10;
bytes32 public constant contractType = "LOSS_POLICY::MOCK";

bool public enabled;

constructor(address pool, address addressProvider) {}

function serialize() external pure override returns (bytes memory) {}

function isLiquidatable(address, address, bytes calldata) external view returns (bool) {
return enabled;
}
Expand Down
2 changes: 2 additions & 0 deletions contracts/test/mocks/MockPriceFeed.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ contract MockPriceFeed is IPriceFeed {
_price = 1e18; // Default price of 1
}

function serialize() external pure override returns (bytes memory) {}

function lastUpdateTime() external view returns (uint256) {
return _lastUpdateTime;
}
Expand Down
3 changes: 1 addition & 2 deletions contracts/test/suite/NewChainDeploySuite.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {PriceFeedStore} from "../../instance/PriceFeedStore.sol";
import {IBytecodeRepository} from "../../interfaces/IBytecodeRepository.sol";
import {IAddressProvider} from "../../interfaces/IAddressProvider.sol";
import {IInstanceManager} from "../../interfaces/IInstanceManager.sol";
import {ICreditConfigureActions} from "../../factories/CreditFactory.sol";
import {CreditManagerParams, CreditFacadeParams, ICreditConfigureActions} from "../../factories/CreditFactory.sol";

import {IWETH} from "@gearbox-protocol/core-v3/contracts/interfaces/external/IWETH.sol";
import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol";
Expand Down Expand Up @@ -67,7 +67,6 @@ import {CreditFacadeV3} from "@gearbox-protocol/core-v3/contracts/credit/CreditF
import {CreditConfiguratorV3} from "@gearbox-protocol/core-v3/contracts/credit/CreditConfiguratorV3.sol";

import {DeployParams} from "../../interfaces/Types.sol";
import {CreditFacadeParams, CreditManagerParams} from "../../factories/CreditFactory.sol";

import {GlobalSetup} from "../../test/helpers/GlobalSetup.sol";
import {MockLossPolicy} from "../../test/mocks/MockLossPolicy.sol";
Expand Down
2 changes: 1 addition & 1 deletion lib/@gearbox-protocol/core-v3
Submodule core-v3 updated 38 files
+3 −0 contracts/core/DefaultAccountFactoryV3.sol
+15 −4 contracts/credit/CreditConfiguratorV3.sol
+4 −4 contracts/credit/CreditFacadeV3.sol
+2 −1 contracts/interfaces/base/IAccountFactory.sol
+2 −1 contracts/interfaces/base/IAdapter.sol
+2 −1 contracts/interfaces/base/IBot.sol
+2 −1 contracts/interfaces/base/IDegenNFT.sol
+2 −1 contracts/interfaces/base/IInterestRateModel.sol
+2 −1 contracts/interfaces/base/ILossPolicy.sol
+2 −1 contracts/interfaces/base/IPriceFeed.sol
+2 −1 contracts/interfaces/base/IRateKeeper.sol
+11 −0 contracts/interfaces/base/IStateSerializer.sol
+2 −1 contracts/interfaces/base/IZapper.sol
+67 −0 contracts/libraries/MarketHelper.sol
+18 −0 contracts/libraries/OptionalCall.sol
+17 −2 contracts/pool/GaugeV3.sol
+9 −1 contracts/pool/LinearInterestRateModelV3.sol
+4 −2 contracts/pool/PoolQuotaKeeperV3.sol
+15 −1 contracts/pool/TumblerV3.sol
+34 −25 contracts/test/integration/credit/CreditConfigurator.int.t.sol
+2 −0 contracts/test/mocks/core/AccountFactoryMock.sol
+2 −0 contracts/test/mocks/core/AdapterMock.sol
+2 −0 contracts/test/mocks/core/BotMock.sol
+2 −0 contracts/test/mocks/core/LossPolicyMock.sol
+70 −0 contracts/test/mocks/oracles/PriceFeedFallbackMock.sol
+2 −0 contracts/test/mocks/oracles/PriceFeedMock.sol
+2 −0 contracts/test/mocks/token/DegenNFTMock.sol
+3 −1 contracts/test/mocks/token/PhantomTokenMock.sol
+76 −0 contracts/test/mocks/token/WETHFallbackMock.sol
+1 −10 contracts/test/suites/CreditManagerFactory.sol
+12 −0 contracts/test/unit/core/PriceOracleV3.unit.t.sol
+4 −0 contracts/test/unit/core/PriceOracleV3Harness.sol
+1 −9 contracts/test/unit/credit/CreditFacadeV3.unit.t.sol
+1 −2 contracts/test/unit/credit/CreditFacadeV3Harness.sol
+8 −0 contracts/test/unit/pool/GaugeV3.unit.t.sol
+1 −0 contracts/test/unit/pool/LinearInterestRateModelV3.unit.t.sol
+3 −0 contracts/test/unit/pool/TumblerV3.unit.t.sol
+25 −7 contracts/traits/PriceFeedValidationTrait.sol

0 comments on commit 32eed86

Please sign in to comment.