Skip to content

Commit

Permalink
Merge pull request #3 from QuantWealth/1-qwmanager-setup
Browse files Browse the repository at this point in the history
init QWManager setup
  • Loading branch information
sanchaymittal authored May 14, 2024
2 parents 3fc3eba + 8ae9cfe commit 37ed149
Show file tree
Hide file tree
Showing 17 changed files with 523 additions and 227 deletions.
3 changes: 2 additions & 1 deletion .husky/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
# 1. Build the contracts
# 2. Stage build output
# 2. Lint and stage style improvements
yarn build && npx lint-staged

# yarn build && npx lint-staged
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
"test/**/*.sol": "yarn lint:sol-tests",
"package.json": "sort-package-json"
},
"dependencies": {
"@aave/core-v3": "^1.19.3",
"@openzeppelin/contracts": "^5.0.2"
},
"devDependencies": {
"@commitlint/cli": "19.3.0",
"@commitlint/config-conventional": "19.2.2",
Expand Down
4 changes: 2 additions & 2 deletions script/Deploy.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import {Greeter} from 'contracts/Greeter.sol';
import {QWManager} from 'contracts/QWManager.sol';
import {Script} from 'forge-std/Script.sol';
import {IERC20} from 'forge-std/interfaces/IERC20.sol';

Expand All @@ -27,7 +27,7 @@ contract Deploy is Script {
DeploymentParams memory _params = _deploymentParams[block.chainid];

Check warning on line 27 in script/Deploy.sol

View workflow job for this annotation

GitHub Actions / Lint Commit Messages

Variable "_params" is unused

vm.startBroadcast();
new Greeter(_params.greeting, _params.token);
new QWManager();
vm.stopBroadcast();
}
}
59 changes: 0 additions & 59 deletions src/contracts/Greeter.sol

This file was deleted.

46 changes: 46 additions & 0 deletions src/contracts/QWGuardian.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: APACHE
pragma solidity 0.8.23;

// import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";

///
/// NOT PART OF FIRST MVP
///

// abstract contract QWGuardian is AccessControl {
// /// Errors
// error QWGuardian__onlyGuardian_notGuardian();

// /// Storage
// // Storage records for validated guardian agent addresses.
// mapping(address => bool) _guardians;
// // This role will be able to update validated guardian addresses.
// bytes32 public constant GUARDIAN_OPERATOR_ROLE =
// keccak256("GUARDIAN_OPERATOR_ROLE");

// constructor(address operator) {
// // Create operator role. Will be able to allow and disable assets.
// _grantRole(GUARDIAN_OPERATOR_ROLE, operator);
// }

// /// Modifiers
// /**
// * @notice Only accept a valid guardian address as msg.sender.
// */
// modifier onlyGuardian() {
// if (!_guardians[msg.sender])
// revert QWGuardian__onlyGuardian_notGuardian();
// _;
// }

// /**
// * @notice One-time function to set the GUARDIAN_OPERATOR_ROLE.
// */
// function initializeGuardianOperator(address operator) external {
// require(
// hasRole(DEFAULT_ADMIN_ROLE, msg.sender),
// "QWGuardian: Must have admin role to initialize"
// );
// _grantRole(GUARDIAN_OPERATOR_ROLE, operator);
// }
// }
93 changes: 93 additions & 0 deletions src/contracts/QWManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// SPDX-License-Identifier: APACHE
pragma solidity 0.8.23;

import {QWRegistry} from './QWRegistry.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';

import {IQWChild} from 'interfaces/IQWChild.sol';
import {IQWManager} from 'interfaces/IQWManager.sol';
import {IQWRegistry} from 'interfaces/IQWRegistry.sol';

/**
* @title Quant Wealth Manager Contract
* @notice This contract manages the execution, closing, and withdrawal of various strategies for Quant Wealth.
*/
contract QWManager is IQWManager {
// Variables
address public immutable REGISTRY;

// Custom errors
error InvalidInputLength(); // Error for mismatched input lengths
error ContractNotWhitelisted(); // Error for contract not whitelisted
error CallFailed(); // Error for call failed

// Constructor
constructor() {
QWRegistry _registry = new QWRegistry(address(this));
REGISTRY = address(_registry);
}

// External Functions
/**
* @notice Execute a series of investments.
* Transfers specified amounts of tokens and calls target contracts with provided calldata.
* @param _targetQwChild List of contract addresses to interact with.
* @param _callData Encoded function calls to be executed on the target contracts.
* @param _tokenAddress Token address to transfer.
* @param _amount Amount of tokens to transfer to each target contract.
*/
function execute(
address[] memory _targetQwChild,
bytes[] memory _callData,
address _tokenAddress,
uint256 _amount
) external override {
if (_targetQwChild.length != _callData.length) {
revert InvalidInputLength();
}

for (uint256 i = 0; i < _targetQwChild.length; i++) {
if (!IQWRegistry(REGISTRY).whitelist(_targetQwChild[i])) {
revert ContractNotWhitelisted();
}

IERC20 token = IERC20(_tokenAddress);
token.approve(_targetQwChild[i], _amount);
token.transferFrom(address(this), address(_targetQwChild[i]), _amount);

(bool success) = IQWChild(_targetQwChild[i]).create(_callData[i], _tokenAddress, _amount);
if (!success) {
revert CallFailed();
}
}
}

/**
* @notice Close a series of investments.
* Calls target contracts with provided calldata to close positions.
* @param _targetQwChild List of contract addresses to interact with.
* @param _callData Encoded function calls to be executed on the target contracts.
*/
function close(address[] memory _targetQwChild, bytes[] memory _callData) external override {
if (_targetQwChild.length != _callData.length) {
revert InvalidInputLength();
}

for (uint256 i = 0; i < _targetQwChild.length; i++) {
(bool success) = IQWChild(_targetQwChild[i]).close(_callData[i]);
if (!success) {
revert CallFailed();
}
}
}

/**
* @notice Withdraw funds to a specified user.
* Transfers a specified amount of funds to the user.
* @param user The address of the user to receive the funds.
* @param amount The amount of funds to transfer to the user.
*/
function withdraw(address user, uint256 amount) external override {
payable(user).transfer(amount);
}
}
58 changes: 58 additions & 0 deletions src/contracts/QWRegistry.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import {IQWChild} from 'interfaces/IQWChild.sol';
import {IQWRegistry} from 'interfaces/IQWRegistry.sol';

/**
* @title Quant Wealth Registry Contract
* @notice This contract manages the registration of child contracts and
* ensures that only valid child contracts can be registered.
*/
contract QWRegistry is IQWRegistry {
// Variables
address public immutable QW_MANAGER;
mapping(address => bool) public whitelist;

// Events
event ChildRegistered(address indexed child);

// Custom errors
error ParentMismatch(); // Error for mismatched parent contract
error InvalidAddress(); // Error for invalid address

// Constructor
/**
* @dev Initializes the QWRegistry contract with the address of the Quant Wealth Manager contract.
* @param _qwManager The address of the Quant Wealth Manager contract.
*/
constructor(address _qwManager) {
QW_MANAGER = _qwManager;
}

// External Functions

/**
* @notice Registers a child contract in the whitelist.
* @dev This function ensures that the child contract's parent matches the QWManager.
* @param _child The address of the child contract to register.
*/
function registerChild(address _child) external {
_validateInput(_child);
IQWChild childContract = IQWChild(_child);
if (childContract.QW_MANAGER() != QW_MANAGER) {
revert ParentMismatch();
}
whitelist[_child] = true;
emit ChildRegistered(_child); // Emit an event when a child contract is registered
}

// Internal Functions

// Error Handling: Ensure that input parameters are valid
function _validateInput(address _child) private pure {
if (_child == address(0)) {
revert InvalidAddress();
}
}
}
44 changes: 44 additions & 0 deletions src/contracts/QWWing.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: APACHE
pragma solidity 0.8.23;

// import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";

/// NOT PART OF MVP

// abstract contract QWWing is AccessControl {
// /// Errors
// error QWWing__onlyWing_notWing();

// /// Storage
// // Crispy, slow-cooked, storage records for validated wing agent addresses.
// mapping(address => bool) _wings; // alt: flight
// // This role will be able to update validated wing addresses.
// bytes32 public constant WING_OPERATOR_ROLE =
// keccak256("WING_OPERATOR_ROLE");

// /// Constructor
// constructor(address operator) {
// // Create operator role. Will be able to allow and disable assets.
// _grantRole(WING_OPERATOR_ROLE, operator);
// }

// /// Modifiers
// /**
// * @notice Only accept a valid wing address as msg.sender.
// */
// modifier onlyWing() {
// if (!_wings[msg.sender]) revert QWWing__onlyWing_notWing();
// _;
// }

// /**
// * @notice One-time function to set the WING_OPERATOR_ROLE.
// */
// function initializeWingOperator(address operator) external {
// require(
// hasRole(DEFAULT_ADMIN_ROLE, msg.sender),
// "QWWing: Must have admin role to initialize"
// );
// _grantRole(WING_OPERATOR_ROLE, operator);
// }
// }
Loading

0 comments on commit 37ed149

Please sign in to comment.