Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Diammond Pattern #40

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions hardhat/contracts/CoopHiveController.sol
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.6;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "./SharedStructs.sol";
import "./ICoopHiveController.sol";
import "./ICoopHiveStorage.sol";
import "./ICoopHivePayments.sol";
import "./ICoopHiveMediation.sol";

contract CoopHiveController is ICoopHiveController, Ownable, Initializable {
contract CoopHiveController is ICoopHiveController, OwnableUpgreadable, Initializable {

/**
* Types
Expand All @@ -25,6 +25,15 @@ contract CoopHiveController is ICoopHiveController, Ownable, Initializable {
ICoopHivePayments private paymentsContract;
ICoopHiveMediationHandler private mediationContract;

/**
* @notice _disableInitializers in the constructor,
* this prevents initialization of the implementation contract itself,
* as extra protection to prevent an attacker from initializing it.
*/
constructor() {
_disableInitializers();
}

/**
* Init
*/
Expand Down
9 changes: 9 additions & 0 deletions hardhat/contracts/CoopHivePayments.sol
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,15 @@ contract CoopHivePayments is ControllerOwnable, Initializable {
* Init
*/

/**
* @notice _disableInitializers in the constructor,
* this prevents initialization of the implementation contract itself,
* as extra protection to prevent an attacker from initializing it.
*/
constructor() {
_disableInitializers();
}

// used for debugging
mapping(address => string) private accountNames;

Expand Down
9 changes: 9 additions & 0 deletions hardhat/contracts/CoopHiveStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ contract CoopHiveStorage is ControllerOwnable, Initializable {
string dealId,
SharedStructs.AgreementState state
);

/**
* @notice _disableInitializers in the constructor,
* this prevents initialization of the implementation contract itself,
* as extra protection to prevent an attacker from initializing it.
*/
constructor() {
_disableInitializers();
}

/**
* Init
Expand Down
9 changes: 9 additions & 0 deletions hardhat/contracts/CoopHiveUsers.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ contract CoopHiveUsers is Ownable, Initializable {
// a map of user type => user address[]
mapping(SharedStructs.ServiceType => address[]) private usersByType;

/**
* @notice _disableInitializers in the constructor,
* this prevents initialization of the implementation contract itself,
* as extra protection to prevent an attacker from initializing it.
*/
constructor() {
_disableInitializers();
}

/**
* Init
*/
Expand Down
66 changes: 66 additions & 0 deletions hardhat/contracts/Diamond.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import {LibDiamond} from "./libraries/LibDiamond.sol";
import {IDiamondCut} from "./interfaces/IDiamondCut.sol";
import {IDiamondLoupe} from "./interfaces/IDiamondLoupe.sol";
import "@openzeppelin/contracts/interfaces/IERC165.sol";
import {IERC173} from "./interfaces/IERC173.sol";
import {DiamondCutFacet} from "./DiamondCutFacet.sol";
import {DiamondLoupeFacet} from "./DiamondLoupeFacet.sol";

/// @notice Struct used for `Diamond` constructor args
struct DiamondArgs {
address owner;
address init;
bytes initCalldata;
}

/**
* @notice Contract that implements diamond proxy pattern
* @dev Main protocol's entrypoint
*/
contract Diamond {
/**
* @notice Diamond constructor
* @param _args Init args
* @param _diamondCutFacets Facets with selectors to add
*/
constructor(
DiamondArgs memory _args,
IDiamondCut.FacetCut[] memory _diamondCutFacets
) {
LibDiamond.setContractOwner(_args.owner);
LibDiamond.diamondCut(
_diamondCutFacets,
_args.init,
_args.initCalldata
);
}

/**
* @notice Finds facet for function that is called and executes the
* function if a facet is found and returns any value
*/
fallback() external payable {
LibDiamond.DiamondStorage storage ds;
bytes32 position = LibDiamond.DIAMOND_STORAGE_POSITION;
assembly {
ds.slot := position
}
address facet = ds.selectorToFacetAndPosition[msg.sig].facetAddress;
require(facet != address(0), "Diamond: Function does not exist");
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
}
22 changes: 22 additions & 0 deletions hardhat/contracts/DiamondCut.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import {IDiamondCut} from "./interfaces/IDiamondCut.sol";
import {LibDiamond} from "./libraries/LibDiamond.sol";

/**
* @notice Facet used for diamond selector modifications
* @dev Remember to add the loupe functions from DiamondLoupeFacet to the diamond.
* The loupe functions are required by the EIP2535 Diamonds standard.
*/
contract DiamondCutFacet is IDiamondCut {
/// @inheritdoc IDiamondCut
function diamondCut(
FacetCut[] calldata _diamondCut,
address _init,
bytes calldata _calldata
) external override {
LibDiamond.enforceIsContractOwner();
LibDiamond.diamondCut(_diamondCut, _init, _calldata);
}
}
22 changes: 22 additions & 0 deletions hardhat/contracts/DiamondCutFacet.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import {IDiamondCut} from "./interfaces/IDiamondCut.sol";
import {LibDiamond} from "./libraries/LibDiamond.sol";

/**
* @notice Facet used for diamond selector modifications
* @dev Remember to add the loupe functions from DiamondLoupeFacet to the diamond.
* The loupe functions are required by the EIP2535 Diamonds standard.
*/
contract DiamondCutFacet is IDiamondCut {
/// @inheritdoc IDiamondCut
function diamondCut(
FacetCut[] calldata _diamondCut,
address _init,
bytes calldata _calldata
) external override {
LibDiamond.enforceIsContractOwner();
LibDiamond.diamondCut(_diamondCut, _init, _calldata);
}
}
95 changes: 95 additions & 0 deletions hardhat/contracts/DiamondInit.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import {LibDiamond} from "./libraries/LibDiamond.sol";
import {IDiamondLoupe} from "./interfaces/IDiamondLoupe.sol";
import {IDiamondCut} from "./interfaces/IDiamondCut.sol";
import {IERC173} from "./interfaces/IERC173.sol";


/**
* @notice It is expected that this contract is customized if you want to deploy your diamond
* with data from a deployment script. Use the init function to initialize state variables
* of your diamond. Add parameters to the init function if you need to.
*
* @notice How it works:
* 1. New `Diamond` contract is created
* 2. Inside the diamond's constructor there a `delegatecall()` to `DiamondInit` with the provided args
* 3. `DiamondInit` updates diamond storage
*/
contract DiamondInit is Modifiers {
/// @notice Struct used for diamond initialization
struct Args {
address admin;
address[] tos;
uint256[] amounts;
uint256[] stakingShareIDs;
uint256 governancePerBlock;
uint256 creditNftLengthBlocks;
}

/**
* @notice Initializes a diamond with state variables
* @dev You can add parameters to this function in order to pass in data to set your own state variables
* @param _args Init args
*/
function init(Args memory _args) external {
// adding ERC165 data
LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();
ds.supportedInterfaces[type(IERC165).interfaceId] = true;
ds.supportedInterfaces[type(IDiamondCut).interfaceId] = true;
ds.supportedInterfaces[type(IDiamondLoupe).interfaceId] = true;
ds.supportedInterfaces[type(IERC173).interfaceId] = true;

LibAccessControl.grantRole(DEFAULT_ADMIN_ROLE, _args.admin);
LibAccessControl.grantRole(GOVERNANCE_TOKEN_MINTER_ROLE, _args.admin);
LibAccessControl.grantRole(GOVERNANCE_TOKEN_BURNER_ROLE, _args.admin);
LibAccessControl.grantRole(CREDIT_TOKEN_MINTER_ROLE, _args.admin);
LibAccessControl.grantRole(CREDIT_TOKEN_BURNER_ROLE, _args.admin);
LibAccessControl.grantRole(DOLLAR_TOKEN_MINTER_ROLE, _args.admin);
LibAccessControl.grantRole(DOLLAR_TOKEN_BURNER_ROLE, _args.admin);
LibAccessControl.grantRole(PAUSER_ROLE, _args.admin);
LibAccessControl.grantRole(CREDIT_NFT_MANAGER_ROLE, _args.admin);
LibAccessControl.grantRole(STAKING_MANAGER_ROLE, _args.admin);
LibAccessControl.grantRole(INCENTIVE_MANAGER_ROLE, _args.admin);
LibAccessControl.grantRole(GOVERNANCE_TOKEN_MANAGER_ROLE, _args.admin);

AppStorage storage appStore = LibAppStorage.appStorage();

appStore.paused = false;
appStore.treasuryAddress = _args.admin;
// staking
LibStaking.StakingData storage ls = LibStaking.stakingStorage();
ls.stakingDiscountMultiplier = uint256(0.001 ether); // 0.001
ls.blockCountInAWeek = 45361;

// reentrancy guard
_initReentrancyGuard();

// ubiquity chef before doing that we should have a metapool address
LibChef.initialize(
_args.tos,
_args.amounts,
_args.stakingShareIDs,
_args.governancePerBlock
);
// creditNftManager
/// @param _creditNftLengthBlocks how many blocks Credit NFT last. can't be changed
/// once set (unless migrated)
LibCreditNftManager.creditNftStorage().creditNftLengthBlocks = _args
.creditNftLengthBlocks;
LibCreditNftManager
.creditNftStorage()
.expiredCreditNftConversionRate = 2;

LibCreditRedemptionCalculator
.creditRedemptionCalculatorStorage()
.coef = 1 ether;
// add your own state variables
// EIP-2535 specifies that the `diamondCut` function takes two optional
// arguments: address _init and bytes calldata _calldata
// These arguments are used to execute an arbitrary function using delegatecall
// in order to set state variables in the diamond during deployment or an upgrade
// More info here: https://eips.ethereum.org/EIPS/eip-2535#diamond-interface
}
}
79 changes: 79 additions & 0 deletions hardhat/contracts/DiamondLoupe.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import {LibDiamond} from "./libraries/LibDiamond.sol";
import {IDiamondLoupe} from "./interfaces/IDiamondLoupe.sol";
import "@openzeppelin/contracts/interfaces/IERC165.sol";

/**
* @notice A loupe is a small magnifying glass used to look at diamonds.
* These functions look at diamonds.
* @dev These functions are expected to be called frequently by 3rd party tools.
* @dev The functions in DiamondLoupeFacet MUST be added to a diamond.
* The EIP-2535 Diamond standard requires these functions.
*/
contract DiamondLoupeFacet is IDiamondLoupe, IERC165 {
/// @inheritdoc IDiamondLoupe
function facets() external view override returns (Facet[] memory facets_) {
LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();
uint256 numFacets = ds.facetAddresses.length;
facets_ = new Facet[](numFacets);
for (uint256 i = 0; i < numFacets; ) {
address facetAddress_ = ds.facetAddresses[i];
facets_[i].facetAddress = facetAddress_;
facets_[i].functionSelectors = ds
.facetFunctionSelectors[facetAddress_]
.functionSelectors;
unchecked {
i++;
}
}
}

/// @inheritdoc IDiamondLoupe
function facetFunctionSelectors(
address _facet
) external view override returns (bytes4[] memory facetFunctionSelectors_) {
LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();
facetFunctionSelectors_ = ds
.facetFunctionSelectors[_facet]
.functionSelectors;
}

/// @inheritdoc IDiamondLoupe
function facetAddresses()
external
view
override
returns (address[] memory facetAddresses_)
{
LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();
facetAddresses_ = ds.facetAddresses;
}

/// @inheritdoc IDiamondLoupe
function facetAddress(
bytes4 _functionSelector
) external view override returns (address facetAddress_) {
LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();
facetAddress_ = ds
.selectorToFacetAndPosition[_functionSelector]
.facetAddress;
}

/**
* @notice Returns `true` if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
* @return Whether contract supports a provided interface
*/
function supportsInterface(
bytes4 _interfaceId
) external view override returns (bool) {
LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();
return ds.supportedInterfaces[_interfaceId];
}
}
Loading