Skip to content

Commit

Permalink
Feat/shperex (#169)
Browse files Browse the repository at this point in the history
* init

* sphereX integration

* changed to onlyOwner

* refactored

* added migration contract & made method external

* added integration & bugfixes

* rm debug lines

* fixed govPoolMigration

* rm param name

* rm import

* added protected public beacon proxy

* impl tiny improvements
  • Loading branch information
dovgopoly authored Oct 16, 2023
1 parent 02e0dde commit 3c9a08d
Show file tree
Hide file tree
Showing 15 changed files with 313 additions and 8 deletions.
35 changes: 35 additions & 0 deletions contracts/core/ContractsRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import "@solarity/solidity-lib/contracts-registry/presets/OwnableContractsRegist

import "../interfaces/core/IContractsRegistry.sol";

import "../proxy/ProtectedTransparentProxy.sol";

contract ContractsRegistry is IContractsRegistry, OwnableContractsRegistry, UUPSUpgradeable {
string public constant USER_REGISTRY_NAME = "USER_REGISTRY";

Expand Down Expand Up @@ -74,5 +76,38 @@ contract ContractsRegistry is IContractsRegistry, OwnableContractsRegistry, UUPS
return getContract(DEXE_EXPERT_NFT_NAME);
}

function setSphereXEngine(address sphereXEngine) external onlyOwner {
_setSphereXEngine(USER_REGISTRY_NAME, sphereXEngine);
_setSphereXEngine(POOL_FACTORY_NAME, sphereXEngine);
_setSphereXEngine(POOL_REGISTRY_NAME, sphereXEngine);
_setSphereXEngine(DEXE_EXPERT_NFT_NAME, sphereXEngine);
_setSphereXEngine(PRICE_FEED_NAME, sphereXEngine);
_setSphereXEngine(CORE_PROPERTIES_NAME, sphereXEngine);
}

function _setSphereXEngine(string memory contractName, address sphereXEngine) internal {
ProtectedTransparentProxy(payable(getContract(contractName))).changeSphereXEngine(
sphereXEngine
);
}

function _deployProxy(
address contractAddress,
address admin,
bytes memory data
) internal override returns (address) {
return
address(
new ProtectedTransparentProxy(
msg.sender,
address(this),
address(0),
contractAddress,
admin,
data
)
);
}

function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
}
47 changes: 47 additions & 0 deletions contracts/factory/PoolFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import "../gov/validators/GovValidators.sol";
import "../core/CoreProperties.sol";
import {PoolRegistry} from "./PoolRegistry.sol";

import "../proxy/ProtectedPublicBeaconProxy.sol";

import "../libs/factory/GovTokenDeployer.sol";

import "../core/Globals.sol";
Expand Down Expand Up @@ -249,6 +251,51 @@ contract PoolFactory is IPoolFactory, AbstractPoolFactory {
_injectDependencies(address(_poolRegistry), proxy);
}

function _deploy(
address poolRegistry,
string memory poolType
) internal override returns (address) {
return
address(
new ProtectedPublicBeaconProxy(
AbstractPoolContractsRegistry(poolRegistry).getProxyBeacon(poolType),
bytes("")
)
);
}

function _deploy2(
address poolRegistry,
string memory poolType,
bytes32 salt
) internal override returns (address) {
return
address(
new ProtectedPublicBeaconProxy{salt: salt}(
AbstractPoolContractsRegistry(poolRegistry).getProxyBeacon(poolType),
bytes("")
)
);
}

function _predictPoolAddress(
address poolRegistry,
string memory poolType,
bytes32 salt
) internal view override returns (address) {
bytes32 bytecodeHash = keccak256(
abi.encodePacked(
type(ProtectedPublicBeaconProxy).creationCode,
abi.encode(
AbstractPoolContractsRegistry(poolRegistry).getProxyBeacon(poolType),
bytes("")
)
)
);

return Create2.computeAddress(salt, bytecodeHash);
}

function _predictPoolAddress(
string memory poolType,
bytes32 salt
Expand Down
23 changes: 23 additions & 0 deletions contracts/factory/PoolRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import "@solarity/solidity-lib/libs/arrays/Paginator.sol";
import "../interfaces/factory/IPoolRegistry.sol";
import "../interfaces/core/IContractsRegistry.sol";

import "../proxy/PoolBeacon.sol";

contract PoolRegistry is IPoolRegistry, OwnablePoolContractsRegistry {
using EnumerableSet for EnumerableSet.AddressSet;
using Paginator for EnumerableSet.AddressSet;
Expand Down Expand Up @@ -48,11 +50,32 @@ contract PoolRegistry is IPoolRegistry, OwnablePoolContractsRegistry {
_addProxyPool(name, poolAddress);
}

function setSphereXEngine(address sphereXEngine) external onlyOwner {
_setSphereXEngine(GOV_POOL_NAME, sphereXEngine);
_setSphereXEngine(SETTINGS_NAME, sphereXEngine);
_setSphereXEngine(VALIDATORS_NAME, sphereXEngine);
_setSphereXEngine(USER_KEEPER_NAME, sphereXEngine);
_setSphereXEngine(DISTRIBUTION_PROPOSAL_NAME, sphereXEngine);
_setSphereXEngine(TOKEN_SALE_PROPOSAL_NAME, sphereXEngine);
_setSphereXEngine(EXPERT_NFT_NAME, sphereXEngine);
_setSphereXEngine(NFT_MULTIPLIER_NAME, sphereXEngine);
_setSphereXEngine(LINEAR_POWER_NAME, sphereXEngine);
_setSphereXEngine(POLYNOMIAL_POWER_NAME, sphereXEngine);
}

function isGovPool(address potentialPool) external view override returns (bool) {
return isPool(GOV_POOL_NAME, potentialPool);
}

function _setSphereXEngine(string memory poolName, address sphereXEngine) internal {
PoolBeacon(getProxyBeacon(poolName)).changeSphereXEngine(sphereXEngine);
}

function _onlyPoolFactory() internal view {
require(_poolFactory == msg.sender, "PoolRegistry: Caller is not a factory");
}

function _deployProxyBeacon() internal override returns (address) {
return address(new PoolBeacon(msg.sender, address(this), address(0)));
}
}
4 changes: 4 additions & 0 deletions contracts/interfaces/core/IContractsRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ pragma solidity ^0.8.20;
* contracts, provide upgradeability mechanism and dependency injection mechanism.
*/
interface IContractsRegistry {
/// @notice The function to set the SphereX engine to all the contracts handled by the registry
/// @param sphereXEngine the address of the SphereX engine
function setSphereXEngine(address sphereXEngine) external;

/// @notice Used in dependency injection mechanism
/// @return UserRegistry contract address
function getUserRegistryContract() external view returns (address);
Expand Down
4 changes: 4 additions & 0 deletions contracts/interfaces/factory/IPoolRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ interface IPoolRegistry {
/// @param poolAddress the address of the pool to add
function addProxyPool(string calldata name, address poolAddress) external;

/// @notice The function to set the SphereX engine to all the contracts handled by the registry
/// @param sphereXEngine the address of the SphereX engine
function setSphereXEngine(address sphereXEngine) external;

/// @notice The function to check if the given address is a valid GovPool
/// @param potentialPool the address to inspect
/// @return true if the address is a GovPool, false otherwise
Expand Down
27 changes: 27 additions & 0 deletions contracts/mock/gov/GovPoolMigration.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@spherex-xyz/contracts/src/SphereXProtectedBase.sol";

contract GovPoolMigration {
address internal immutable DEPLOYER;

constructor() {
DEPLOYER = msg.sender;
}

modifier onlyDeployer() {
_onlyDeployer();
_;
}

function acceptSphereXAdmins(address[] calldata sphereXProxies) external onlyDeployer {
for (uint256 i = 0; i < sphereXProxies.length; ++i) {
SphereXProtectedBase(sphereXProxies[i]).acceptSphereXAdminRole();
}
}

function _onlyDeployer() internal {
require(msg.sender == DEPLOYER, "Gov: caller is not a deployer");
}
}
21 changes: 21 additions & 0 deletions contracts/proxy/PoolBeacon.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@spherex-xyz/contracts/src/SphereXProxyStorage.sol";
import "@spherex-xyz/contracts/src/ProtectedProxies/ISphereXBeacon.sol";

import "@solarity/solidity-lib/contracts-registry/pools/proxy/ProxyBeacon.sol";

contract PoolBeacon is ISphereXBeacon, SphereXProxyBase, ProxyBeacon {
constructor(
address sphereXAdmin,
address sphereXOperator,
address sphereXEngine
) SphereXProxyBase(sphereXAdmin, sphereXOperator, sphereXEngine) {}

function protectedImplementation(
bytes4 selector
) external view returns (address, address, bool) {
return (implementation(), sphereXEngine(), isProtectedFuncSig(selector));
}
}
14 changes: 14 additions & 0 deletions contracts/proxy/ProtectedPublicBeaconProxy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/proxy/beacon/IBeacon.sol";

import "@spherex-xyz/contracts/src/ProtectedProxies/ProtectedBeaconProxy.sol";

contract ProtectedPublicBeaconProxy is ProtectedBeaconProxy {
constructor(address beacon, bytes memory data) ProtectedBeaconProxy(beacon, data) {}

function implementation() external view returns (address) {
return IBeacon(_getBeacon()).implementation();
}
}
30 changes: 30 additions & 0 deletions contracts/proxy/ProtectedTransparentProxy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";

import "@spherex-xyz/contracts/src/SphereXProtectedProxy.sol";

contract ProtectedTransparentProxy is SphereXProtectedProxy, TransparentUpgradeableProxy {
constructor(
address sphereXAdmin,
address sphereXOperator,
address sphereXEngine,
address implementation,
address proxyAdmin,
bytes memory data
)
SphereXProtectedProxy(sphereXAdmin, sphereXOperator, sphereXEngine)
TransparentUpgradeableProxy(implementation, proxyAdmin, data)
{}

function _fallback() internal virtual override(Proxy, TransparentUpgradeableProxy) {
TransparentUpgradeableProxy._fallback();
}

function _delegate(
address implementation
) internal virtual override(Proxy, SphereXProtectedProxy) {
SphereXProtectedProxy._delegate(implementation);
}
}
58 changes: 58 additions & 0 deletions deploy/95_DEXEDAOSphereXAdmin.migration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
const Proxy = artifacts.require("ERC1967Proxy");
const ContractsRegistry = artifacts.require("ContractsRegistry");
const PoolRegistry = artifacts.require("PoolRegistry");
const SphereXProtectedBase = artifacts.require("ProtectedTransparentProxy");
const GovPool = artifacts.require("GovPool");
const GovPoolMigration = artifacts.require("GovPoolMigration");

module.exports = async (deployer, logger) => {
const contractsRegistry = await ContractsRegistry.at((await Proxy.deployed()).address);

const poolRegistry = await PoolRegistry.at(await contractsRegistry.getPoolRegistryContract());

const proxies = [
["PoolRegistry", poolRegistry.address],
["UserRegistry", await contractsRegistry.getUserRegistryContract()],
["PoolFactory", await contractsRegistry.getPoolFactoryContract()],
["DexeExpertNft", await contractsRegistry.getDexeExpertNftContract()],
["PriceFeed", await contractsRegistry.getPriceFeedContract()],
["CoreProperties", await contractsRegistry.getCorePropertiesContract()],
["GovPool", await poolRegistry.getProxyBeacon(await poolRegistry.GOV_POOL_NAME())],
["GovSettings", await poolRegistry.getProxyBeacon(await poolRegistry.SETTINGS_NAME())],
["GovValidators", await poolRegistry.getProxyBeacon(await poolRegistry.VALIDATORS_NAME())],
["GovUserKeeper", await poolRegistry.getProxyBeacon(await poolRegistry.USER_KEEPER_NAME())],
["DistributionProposal", await poolRegistry.getProxyBeacon(await poolRegistry.DISTRIBUTION_PROPOSAL_NAME())],
["TokenSaleProposal", await poolRegistry.getProxyBeacon(await poolRegistry.TOKEN_SALE_PROPOSAL_NAME())],
["ExpertNft", await poolRegistry.getProxyBeacon(await poolRegistry.EXPERT_NFT_NAME())],
["NftMultiplier", await poolRegistry.getProxyBeacon(await poolRegistry.NFT_MULTIPLIER_NAME())],
["LinearPower", await poolRegistry.getProxyBeacon(await poolRegistry.LINEAR_POWER_NAME())],
["PolynomialPower", await poolRegistry.getProxyBeacon(await poolRegistry.POLYNOMIAL_POWER_NAME())],
];

logger.logContracts(...proxies);

const govPoolImplementation = await poolRegistry.getImplementation(await poolRegistry.GOV_POOL_NAME());
const govPoolMigration = (await deployer.deploy(GovPoolMigration)).address;

logger.logTransaction(
await poolRegistry.setNewImplementations([await poolRegistry.GOV_POOL_NAME()], [govPoolMigration]),
"Setting a default GovPool implementation"
);

for (const [contractName, proxy] of proxies) {
logger.logTransaction(
await (await SphereXProtectedBase.at(proxy)).transferSphereXAdminRole(deployer.dexeDaoAddress),
`Transferring a SphereX admin role for the ${contractName} proxy`
);
}

logger.logTransaction(
await (await GovPoolMigration.at(deployer.dexeDaoAddress)).acceptSphereXAdmins(proxies.map((e) => e[1])),
"Accepting SphereX admin roles"
);

logger.logTransaction(
await poolRegistry.setNewImplementations([await poolRegistry.GOV_POOL_NAME()], [govPoolImplementation]),
"Setting a default GovPool implementation"
);
};
File renamed without changes.
15 changes: 15 additions & 0 deletions docs/core/IContractsRegistry.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,21 @@ the other contracts used by the protocol. Its purpose is to keep track of the pr
contracts, provide upgradeability mechanism and dependency injection mechanism.
## Functions info

### setSphereXEngine (0x44a63d1b)

```solidity
function setSphereXEngine(address sphereXEngine) external
```

The function to set the SphereX engine to all the contracts handled by the registry


Parameters:

| Name | Type | Description |
| :------------ | :------ | :-------------------------------- |
| sphereXEngine | address | the address of the SphereX engine |

### getUserRegistryContract (0x435403b4)

```solidity
Expand Down
15 changes: 15 additions & 0 deletions docs/factory/IPoolRegistry.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,21 @@ Parameters:
| name | string | the type of the pool |
| poolAddress | address | the address of the pool to add |

### setSphereXEngine (0x44a63d1b)

```solidity
function setSphereXEngine(address sphereXEngine) external
```

The function to set the SphereX engine to all the contracts handled by the registry


Parameters:

| Name | Type | Description |
| :------------ | :------ | :-------------------------------- |
| sphereXEngine | address | the address of the SphereX engine |

### isGovPool (0x9e475551)

```solidity
Expand Down
Loading

0 comments on commit 3c9a08d

Please sign in to comment.