Skip to content

Commit 8541f1b

Browse files
authored
Merge pull request #18 from Gearbox-protocol/instance-manager
feat: instance manager and global contracts
2 parents 9d53869 + 7f8eaf6 commit 8541f1b

23 files changed

+2162
-295
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,5 @@ dist
132132
# Forge output
133133
out
134134
cache
135-
broadcast
135+
broadcast
136+
.DS_Store

contracts/global/AddressProvider.sol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ contract AddressProvider is Ownable2Step, IAddressProvider {
8383
_setAddress(key, value, saveVersion ? IVersion(value).version() : NO_VERSION_CONTROL);
8484
}
8585

86+
function setAddress(bytes32 key, address value, bool saveVersion) external override onlyOwner {
87+
_setAddress(key.fromSmallString(), value, saveVersion ? IVersion(value).version() : NO_VERSION_CONTROL);
88+
}
89+
8690
/// @notice Sets the address for the passed contract key
8791
/// @param addr Contract address
8892
/// @param saveVersion Whether to save contract's version

contracts/global/BytecodeRepository.sol

Lines changed: 386 additions & 244 deletions
Large diffs are not rendered by default.
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.23;
3+
4+
import {BytecodeRepository} from "./BytecodeRepository.sol";
5+
import {Ownable} from "@openzeppelin/contracts/access/Ownable2Step.sol";
6+
import {
7+
AP_INSTANCE_MANAGER,
8+
AP_CROSS_CHAIN_GOVERNANCE,
9+
AP_TREASURY,
10+
NO_VERSION_CONTROL,
11+
AP_BYTECODE_REPOSITORY,
12+
AP_ADDRESS_PROVIDER,
13+
AP_INSTANCE_MANAGER_PROXY,
14+
AP_CROSS_CHAIN_GOVERNANCE_PROXY,
15+
AP_TREASURY_PROXY
16+
} from "../libraries/ContractLiterals.sol";
17+
import {IAddressProvider} from "../interfaces/IAddressProvider.sol";
18+
import {ProxyCall} from "../helpers/ProxyCall.sol";
19+
import {LibString} from "@solady/utils/LibString.sol";
20+
import {IVersion} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IVersion.sol";
21+
import {AddressProvider} from "./AddressProvider.sol";
22+
23+
contract InstanceManager is Ownable {
24+
using LibString for string;
25+
26+
address public immutable addressProvider;
27+
address public immutable bytecodeRepository;
28+
29+
address public instanceManagerProxy;
30+
address public treasuryProxy;
31+
address public crossChainGovernanceProxy;
32+
33+
address public marketConfiguratorFactory;
34+
address public priceFeedStore;
35+
36+
bool public isActivated;
37+
38+
error InvalidKeyException(string key);
39+
40+
modifier onlyCrossChainGovernance() {
41+
require(
42+
msg.sender
43+
== IAddressProvider(addressProvider).getAddressOrRevert(AP_CROSS_CHAIN_GOVERNANCE, NO_VERSION_CONTROL),
44+
"Only financial multisig can call this function"
45+
);
46+
_;
47+
}
48+
49+
modifier onlyTreasury() {
50+
require(
51+
msg.sender == IAddressProvider(addressProvider).getAddressOrRevert(AP_TREASURY, NO_VERSION_CONTROL),
52+
"Only financial multisig can call this function"
53+
);
54+
_;
55+
}
56+
57+
constructor(address _owner) {
58+
bytecodeRepository = address(new BytecodeRepository(address(this)));
59+
addressProvider = address(new AddressProvider());
60+
61+
IAddressProvider(addressProvider).setAddress(AP_BYTECODE_REPOSITORY, address(bytecodeRepository), true);
62+
IAddressProvider(addressProvider).setAddress(AP_INSTANCE_MANAGER, address(this), true);
63+
IAddressProvider(addressProvider).setAddress(AP_CROSS_CHAIN_GOVERNANCE, _owner, false);
64+
65+
instanceManagerProxy = address(new ProxyCall());
66+
treasuryProxy = address(new ProxyCall());
67+
crossChainGovernanceProxy = address(new ProxyCall());
68+
69+
IAddressProvider(addressProvider).setAddress(AP_INSTANCE_MANAGER_PROXY, instanceManagerProxy, false);
70+
IAddressProvider(addressProvider).setAddress(AP_TREASURY_PROXY, treasuryProxy, false);
71+
IAddressProvider(addressProvider).setAddress(AP_CROSS_CHAIN_GOVERNANCE_PROXY, crossChainGovernanceProxy, false);
72+
73+
_transferOwnership(_owner);
74+
}
75+
76+
function activate(address _instanceOwner, address _treasury) external onlyOwner {
77+
if (!isActivated) {
78+
_verifyCoreContractsDeploy();
79+
_transferOwnership(_instanceOwner);
80+
81+
IAddressProvider(addressProvider).setAddress(AP_TREASURY, _treasury, false);
82+
isActivated = true;
83+
}
84+
}
85+
86+
function deploySystemContract(bytes32 _contractName, uint256 _version) external onlyCrossChainGovernance {
87+
// deploy contract
88+
// set address in address provider
89+
address newSystemContract =
90+
BytecodeRepository(bytecodeRepository).deploy(_contractName, _version, abi.encode(addressProvider), 0);
91+
IAddressProvider(addressProvider).setAddress(_contractName, newSystemContract, true);
92+
}
93+
94+
function setAddress(string memory key, address addr, bool saveVersion) external onlyCrossChainGovernance {
95+
IAddressProvider(addressProvider).setAddress(key, addr, saveVersion);
96+
}
97+
98+
function setLocalAddress(string memory key, address addr, bool saveVersion) external onlyOwner {
99+
if (!key.startsWith("LOCAL_")) {
100+
revert InvalidKeyException(key);
101+
}
102+
IAddressProvider(addressProvider).setAddress(key, addr, saveVersion);
103+
}
104+
105+
function _verifyCoreContractsDeploy() internal view {
106+
// verify that all core contracts are deployed
107+
}
108+
109+
function configureGlobal(address target, bytes calldata data) external onlyCrossChainGovernance {
110+
ProxyCall(crossChainGovernanceProxy).proxyCall(target, data);
111+
}
112+
113+
function configureLocal(address target, bytes calldata data) external onlyOwner {
114+
ProxyCall(instanceManagerProxy).proxyCall(target, data);
115+
}
116+
117+
function configureTreasury(address target, bytes calldata data) external onlyTreasury {
118+
ProxyCall(treasuryProxy).proxyCall(target, data);
119+
}
120+
}

contracts/global/PriceFeedStore.sol

Lines changed: 143 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,148 @@
33
// (c) Gearbox Foundation, 2024.
44
pragma solidity ^0.8.23;
55

6+
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
7+
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
8+
9+
import {SanityCheckTrait} from "@gearbox-protocol/core-v3/contracts/traits/SanityCheckTrait.sol";
10+
import {PriceFeedValidationTrait} from "@gearbox-protocol/core-v3/contracts/traits/PriceFeedValidationTrait.sol";
11+
import {IPriceFeed} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IPriceFeed.sol";
12+
613
import {IPriceFeedStore} from "../interfaces/IPriceFeedStore.sol";
14+
import {AP_PRICE_FEED_STORE, AP_INSTANCE_MANAGER_PROXY, NO_VERSION_CONTROL} from "../libraries/ContractLiterals.sol";
15+
import {IAddressProvider} from "../interfaces/IAddressProvider.sol";
16+
import {PriceFeedInfo} from "../interfaces/Types.sol";
17+
18+
contract PriceFeedStore is Ownable, SanityCheckTrait, PriceFeedValidationTrait, IPriceFeedStore {
19+
using EnumerableSet for EnumerableSet.AddressSet;
20+
21+
//
22+
// CONSTANTS
23+
//
24+
25+
/// @notice Meta info about contract type & version
26+
uint256 public constant override version = 3_10;
27+
bytes32 public constant override contractType = AP_PRICE_FEED_STORE;
28+
29+
//
30+
// VARIABLES
31+
//
32+
33+
/// @dev Set of all known price feeds
34+
EnumerableSet.AddressSet internal _knownPriceFeeds;
35+
36+
/// @dev Set of all known price feeds
37+
EnumerableSet.AddressSet internal _knownTokens;
38+
39+
/// @dev Mapping from token address to its set of allowed price feeds
40+
mapping(address => EnumerableSet.AddressSet) internal _allowedPriceFeeds;
41+
42+
/// @notice Mapping from price feed address to its data
43+
mapping(address => PriceFeedInfo) public priceFeedInfo;
44+
45+
constructor(address _addressProvider) {
46+
address instanceManager =
47+
IAddressProvider(_addressProvider).getAddressOrRevert(AP_INSTANCE_MANAGER_PROXY, NO_VERSION_CONTROL);
48+
_transferOwnership(instanceManager);
49+
}
50+
51+
/// @notice Returns the list of price feeds available for a token
52+
function getPriceFeeds(address token) external view returns (address[] memory) {
53+
return _allowedPriceFeeds[token].values();
54+
}
55+
56+
/// @notice Returns whether a price feed is allowed to be used for a token
57+
function isAllowedPriceFeed(address token, address priceFeed) external view returns (bool) {
58+
return _allowedPriceFeeds[token].contains(priceFeed);
59+
}
60+
61+
/// @notice Returns the staleness period for a price feed
62+
function getStalenessPeriod(address priceFeed) external view returns (uint32) {
63+
return priceFeedInfo[priceFeed].stalenessPeriod;
64+
}
65+
66+
function getKnownTokens() external view returns (address[] memory) {
67+
return _knownTokens.values();
68+
}
69+
70+
/**
71+
* @notice Adds a new price feed
72+
* @param priceFeed The address of the new price feed
73+
* @param stalenessPeriod Staleness period of the new price feed
74+
* @dev Reverts if the price feed's result is stale based on the staleness period
75+
*/
76+
function addPriceFeed(address priceFeed, uint32 stalenessPeriod) external onlyOwner nonZeroAddress(priceFeed) {
77+
if (_knownPriceFeeds.contains(priceFeed)) revert PriceFeedAlreadyAddedException(priceFeed);
78+
79+
_validatePriceFeed(priceFeed, stalenessPeriod);
80+
81+
bytes32 priceFeedType;
82+
uint256 priceFeedVersion;
83+
84+
try IPriceFeed(priceFeed).contractType() returns (bytes32 _cType) {
85+
priceFeedType = _cType;
86+
priceFeedVersion = IPriceFeed(priceFeed).version();
87+
} catch {
88+
priceFeedType = "PF_EXTERNAL_ORACLE";
89+
priceFeedVersion = 0;
90+
}
91+
92+
_knownPriceFeeds.add(priceFeed);
93+
priceFeedInfo[priceFeed].author = msg.sender;
94+
priceFeedInfo[priceFeed].priceFeedType = priceFeedType;
95+
priceFeedInfo[priceFeed].stalenessPeriod = stalenessPeriod;
96+
priceFeedInfo[priceFeed].version = priceFeedVersion;
97+
98+
emit AddPriceFeed(priceFeed, stalenessPeriod);
99+
}
100+
101+
/**
102+
* @notice Sets the staleness period for an existing price feed
103+
* @param priceFeed The address of the price feed
104+
* @param stalenessPeriod New staleness period for the price feed
105+
* @dev Reverts if the price feed is not added to the global list
106+
*/
107+
function setStalenessPeriod(address priceFeed, uint32 stalenessPeriod)
108+
external
109+
onlyOwner
110+
nonZeroAddress(priceFeed)
111+
{
112+
if (!_knownPriceFeeds.contains(priceFeed)) revert PriceFeedNotKnownException(priceFeed);
113+
uint32 oldStalenessPeriod = priceFeedInfo[priceFeed].stalenessPeriod;
114+
115+
if (stalenessPeriod != oldStalenessPeriod) {
116+
_validatePriceFeed(priceFeed, stalenessPeriod);
117+
priceFeedInfo[priceFeed].stalenessPeriod = stalenessPeriod;
118+
emit SetStalenessPeriod(priceFeed, stalenessPeriod);
119+
}
120+
}
121+
122+
/**
123+
* @notice Allows a price feed for use with a particular token
124+
* @param token Address of the token
125+
* @param priceFeed Address of the price feed
126+
* @dev Reverts if the price feed is not added to the global list
127+
*/
128+
function allowPriceFeed(address token, address priceFeed) external onlyOwner nonZeroAddress(token) {
129+
if (!_knownPriceFeeds.contains(priceFeed)) revert PriceFeedNotKnownException(priceFeed);
130+
131+
_allowedPriceFeeds[token].add(priceFeed);
132+
133+
emit AllowPriceFeed(token, priceFeed);
134+
}
135+
136+
/**
137+
* @notice Forbids a price feed for use with a particular token
138+
* @param token Address of the token
139+
* @param priceFeed Address of the price feed
140+
* @dev Reverts if the price feed is not added to the global list or the per-token list
141+
*/
142+
function forbidPriceFeed(address token, address priceFeed) external onlyOwner nonZeroAddress(token) {
143+
if (!_knownPriceFeeds.contains(priceFeed)) revert PriceFeedNotKnownException(priceFeed);
144+
if (!_allowedPriceFeeds[token].contains(priceFeed)) revert PriceFeedIsNotAllowedException(token, priceFeed);
145+
146+
_allowedPriceFeeds[token].remove(priceFeed);
7147

8-
abstract contract PriceFeedStore is IPriceFeedStore {}
148+
emit ForbidPriceFeed(token, priceFeed);
149+
}
150+
}

0 commit comments

Comments
 (0)