diff --git a/contracts/Vault/VaultDiamond.sol b/contracts/Vault/VaultDiamond.sol index 6d2d4c7..3cac10d 100644 --- a/contracts/Vault/VaultDiamond.sol +++ b/contracts/Vault/VaultDiamond.sol @@ -1,17 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.4; -/******************************************************************************\ -* Author: Nick Mudge (https://twitter.com/mudgen) -* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 -* -* Implementation of a diamond. -/******************************************************************************/ +/** + * Implementation of a diamond. + * /***************************************************************************** + */ import {LibDiamond} from "./libraries/LibDiamond.sol"; import {IDiamondCut} from "../interfaces/IDiamondCut.sol"; -import {FacetAndSelectorData,DMSData} from "./libraries/LibLayoutSilo.sol"; +import {FacetAndSelectorData, DMSData} from "./libraries/LibLayoutSilo.sol"; import {LibStorageBinder} from "./libraries/LibStorageBinder.sol"; @@ -20,42 +18,31 @@ import {LibStorageBinder} from "./libraries/LibStorageBinder.sol"; import "../interfaces/IVaultDiamond.sol"; contract VaultDiamond { - bool _init; + address public vaultFactoryDiamond; - constructor() payable { - address _contractOwner = tx.origin; - LibDiamond.setVaultOwner(_contractOwner); - } - - function init(address _diamondCutFacet, address _backup) public { - VaultData storage vaultData = LibStorageBinder - ._bindAndReturnVaultStorage(); - assert(!_init); - assert( - msg.sender == LibDiamond.vaultOwner() || - tx.origin == LibDiamond.vaultOwner() - ); - // Add the diamondCut external function from the diamondCutFacet - IDiamondCut.FacetCut[] memory cut = new IDiamondCut.FacetCut[](1); - bytes4[] memory functionSelectors = new bytes4[](2); - functionSelectors[0] = IDiamondCut.diamondCut.selector; - functionSelectors[1] = IVaultDiamond.tempOwner.selector; - cut[0] = IDiamondCut.FacetCut({ - facetAddress: _diamondCutFacet, - action: IDiamondCut.FacetCutAction.Add, - functionSelectors: functionSelectors - }); - - LibDiamond.diamondCut(cut, address(0), ""); - vaultData.backupAddress = _backup; - _init = true; + /// @notice sets selector and token module at deployment + constructor( + IDiamondCut.FacetCut[] memory _selectorModule, + IDiamondCut.FacetCut[] memory _tokenModule, + address _vaultOwner + ) payable { + LibDiamond.diamondCut(_selectorModule, address(0), ""); + LibDiamond.diamondCut(_tokenModule, address(0), ""); + //set module installation record to true + FacetAndSelectorData storage fsData = LibStorageBinder._bindAndReturnFacetStorage(); + fsData.activeModule["Selector"] = true; + fsData.activeModule["Token"] = true; + fsData.activeModules.push("Selector"); + fsData.activeModules.push("Token"); + LibDiamond.setVaultOwner(_vaultOwner); + vaultFactoryDiamond = msg.sender; } // Find facet for function that is called and execute the // function if a facet is found and return any value. + fallback() external payable { - FacetAndSelectorData storage fsData = LibStorageBinder - ._bindAndReturnFacetStorage(); + FacetAndSelectorData storage fsData = LibStorageBinder._bindAndReturnFacetStorage(); // get facet from function selector address facet = fsData.selectorToFacetAndPosition[msg.sig].facetAddress; @@ -70,12 +57,8 @@ contract VaultDiamond { returndatacopy(0, 0, returndatasize()) // return any return value or error back to the caller switch result - case 0 { - revert(0, returndatasize()) - } - default { - return(0, returndatasize()) - } + case 0 { revert(0, returndatasize()) } + default { return(0, returndatasize()) } } } diff --git a/contracts/Vault/facets/DMSFacet.sol b/contracts/Vault/facets/DMSFacet.sol index 83892fd..366cfa8 100644 --- a/contracts/Vault/facets/DMSFacet.sol +++ b/contracts/Vault/facets/DMSFacet.sol @@ -50,8 +50,7 @@ contract DMSFacet { uint256 amount; } - - + /// @notice checks throgh the vault and return dataa associated with it function inspectVault() public view returns (VaultInfo memory info) { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); FacetAndSelectorData storage fsData = LibStorageBinder._bindAndReturnFacetStorage(); @@ -63,6 +62,7 @@ contract DMSFacet { info.inheritors = vaultData.inheritors; } + /// @notice returns all ethers that has been allocated from the vault function allEtherAllocations() public view returns (AllInheritorEtherAllocs[] memory eAllocs) { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); uint256 count = vaultData.inheritors.length; @@ -73,6 +73,7 @@ contract DMSFacet { } } + /// @notice returns all ether allocates to _inheritor function inheritorEtherAllocation(address _inheritor) public view returns (uint256 _allocatedEther) { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); if (!LibDMSGuards._anInheritor(_inheritor)) { @@ -81,10 +82,12 @@ contract DMSFacet { _allocatedEther = vaultData.inheritorWeishares[_inheritor]; } + // @notice retuns the amount of all ether that has been allocated in the vault function getAllocatedEther() public view returns (uint256) { return LibDMS.getCurrentAllocatedEth(); } + /// @notice returns the amoounf of free(unallocated) ether in the vault function getUnallocatedEther() public view returns (uint256 unallocated_) { uint256 currentBalance = address(this).balance; if (currentBalance > 0) { @@ -92,10 +95,12 @@ contract DMSFacet { } } + /// @notice returns the current ether balance of the vault function etherBalance() public view returns (uint256) { return address(this).balance; } + /// @notice gets the aloocated ERC20 tokens to inheritor function getAllocatedERC20Tokens(address _inheritor) public view returns (AllocatedERC20Tokens[] memory tAllocs) { LibDMSGuards._activeInheritor(_inheritor); DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); @@ -110,11 +115,13 @@ contract DMSFacet { } } + /// @notice returns the amount of a token aloocated to an inheritor function inheritorERC20TokenAllocation(address _inheritor, address _token) public view returns (uint256) { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); return vaultData.inheritorTokenShares[_inheritor][_token]; } + /// @notice returns free(unallocated) ERC20 tokens in the vault function getUnallocatedTokens(address _token) public view returns (uint256 unallocated_) { uint256 bal = IERC20(_token).balanceOf(address(this)); uint256 allocated = LibDMS.getCurrentAllocatedTokens(_token); @@ -122,7 +129,7 @@ contract DMSFacet { unallocated_ = bal - allocated; } } - + /// @notice returns allocated ERC721 tokens to an inheritor function getAllocatedERC721Tokens(address _inheritor) public view @@ -141,18 +148,21 @@ contract DMSFacet { } } + /// @notice returns the amount of an ERC721 token allocated to an inheritor function getAllocatedERC721TokenIds(address _inheritor, address _token) external view returns (uint256[] memory) { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); LibDMSGuards._activeInheritor(_inheritor); return vaultData.inheritorAllocatedTokenIds[_inheritor][_token]; } + /// @notice returns ERC721 token addresses allocated to an inheritor function getAllocatedERC721TokenAddresses(address _inheritor) public view returns (address[] memory) { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); LibDMSGuards._activeInheritor(_inheritor); return vaultData.inheritorAllocatedERC721TokenAddresses[_inheritor]; } + /// @notice returns the amount of an ERC1155 token allocated to an inheritor function getAllocatedERC1155Tokens(address _token, address _inheritor) public view @@ -171,6 +181,7 @@ contract DMSFacet { } } + /// @notice returns all ERC1155 tokens allocated to an inheritor function getAllAllocatedERC1155Tokens(address _inheritor) public view @@ -192,6 +203,7 @@ contract DMSFacet { } } + /// @notice retuns free(unallocated) ERC1155 tokens in the vault function getUnallocatedERC115Tokens(address _token, uint256 _tokenId) public view returns (uint256 remaining_) { uint256 allocated = LibDMS.getCurrentAllocated1155tokens(_token, _tokenId); uint256 available = IERC1155(_token).balanceOf(address(this), _tokenId); @@ -204,26 +216,30 @@ contract DMSFacet { ///WRITE FUNCTIONS/// //////////////////// //note: owner restriction is in external fns + /// @notice adds inheritors and weishares to the vault function addInheritors(address[] calldata _newInheritors, uint256[] calldata _weiShare) external { LibGuards._onlyVaultOwner(); LibDMS._addInheritors(_newInheritors, _weiShare); } + /// @notice removes inheritors from the vault function removeInheritors(address[] calldata _inheritors) external { LibGuards._onlyVaultOwner(); LibDMS._removeInheritors(_inheritors); } - + /// @notice allocate ether to inheritors function allocateEther(address[] calldata _inheritors, uint256[] calldata _ethShares) external { LibGuards._onlyVaultOwner(); LibDMS._allocateEther(_inheritors, _ethShares); } + /// @notice allocate ERC20 tokens to inheritors function allocateERC20Tokens(address token, address[] calldata _inheritors, uint256[] calldata _shares) external { LibGuards._onlyVaultOwner(); LibDMS._allocateERC20Tokens(token, _inheritors, _shares); } + /// @notice allocate ERC721 tokens to inheritors function allocateERC721Tokens(address token, address[] calldata _inheritors, uint256[] calldata _tokenIDs) external { @@ -231,6 +247,7 @@ contract DMSFacet { LibDMS._allocateERC721Tokens(token, _inheritors, _tokenIDs); } + /// @notice allocate ERC1155 tokens to inheritors function allocateERC1155Tokens( address token, address[] calldata _inheritors, @@ -241,26 +258,29 @@ contract DMSFacet { LibDMS._allocateERC1155Tokens(token, _inheritors, _tokenIDs, _amounts); } + /// @notice transfer vault ownership to _newVaultOwner function transferOwnership(address _newVaultOwner) public { LibGuards._onlyVaultOwner(); LibDMS._transferOwnerShip(_newVaultOwner); } - + /// @notice transfer vault backup to _newBackupAddress function transferBackup(address _newBackupAddress) public { LibDMSGuards._onlyVaultOwnerOrBackup(); LibDMS._transferBackup(_newBackupAddress); } //CLAIMS + /// @notice allow backup address to claim ownership function claimOwnership(address _newBackupAddress) public { LibDMSGuards._enforceIsBackupAddress(); LibDMS._claimOwnership(_newBackupAddress); } + /// @notice allow inheritor to claim all allocated assets function claimAllAllocations() external { LibDMS._claimAll(); } - + /// @notice pings vault and resets inactivity timer function ping() external { LibGuards._onlyVaultOwner(); LibDMS._ping(); diff --git a/contracts/Vault/facets/DiamondCutFacet.sol b/contracts/Vault/facets/DiamondCutFacet.sol index 0e8beaa..1ea0719 100644 --- a/contracts/Vault/facets/DiamondCutFacet.sol +++ b/contracts/Vault/facets/DiamondCutFacet.sol @@ -1,38 +1,32 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.4; -/******************************************************************************\ -* Author: Nick Mudge (https://twitter.com/mudgen) -* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 -/******************************************************************************/ +/** + * \ + * Author: Nick Mudge (https://twitter.com/mudgen) + * EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 + * /***************************************************************************** + */ -import { IDiamondCut } from "../../interfaces/IDiamondCut.sol"; +import {IDiamondCut} from "../../interfaces/IDiamondCut.sol"; -import { LibErrors } from "../libraries/LibErrors.sol"; -import { LibDiamond } from "../libraries/LibDiamond.sol"; +import {LibErrors} from "../libraries/LibErrors.sol"; +import {LibDiamond} from "../libraries/LibDiamond.sol"; import "../libraries/LibLayoutSilo.sol"; import "../libraries/LibStorageBinder.sol"; -contract DiamondCutFacet is IDiamondCut { - /// @notice Add/replace/remove any number of functions and optionally execute - /// a function with delegatecall - /// @param _diamondCut Contains the facet addresses and function selectors - /// @param _init The address of the contract or facet to execute _calldata - /// @param _calldata A function call, including function selector and arguments - /// _calldata is executed with delegatecall on _init - function diamondCut( - FacetCut[] calldata _diamondCut, - address _init, - bytes calldata _calldata - ) external override { -// restrict upgrades to VaultFactoryDiamond only - if (msg.sender !=IVaultDiamond(address(this)).vaultFactoryDiamond()) revert LibErrors.NoPermissions(); - LibDiamond.diamondCut(_diamondCut, _init, _calldata); - } +import {IVaultDiamond} from "../../interfaces/IVaultDiamond.sol"; - //temp call made from factory to confirm ownership - function tempOwner() public view returns (address owner_) { - VaultData storage vaultData=LibStorageBinder._bindAndReturnVaultStorage(); - owner_ = vaultData.vaultOwner; - } +contract DiamondCutFacet is IDiamondCut { + /// @notice Add/replace/remove any number of functions and optionally execute + /// a function with delegatecall + /// @param _diamondCut Contains the facet addresses and function selectors + /// @param _init The address of the contract or facet to execute _calldata + /// @param _calldata A function call, including function selector and arguments + /// _calldata is executed with delegatecall on _init + function diamondCut(FacetCut[] calldata _diamondCut, address _init, bytes calldata _calldata) external override { + // restrict upgrades to VaultFactoryDiamond only + // if (msg.sender !=IVaultDiamond(address(this)).vaultFactoryDiamond()) revert LibErrors.NoPermissions(); + LibDiamond.diamondCut(_diamondCut, _init, _calldata); + } } diff --git a/contracts/Vault/facets/DiamondLoupeFacet.sol b/contracts/Vault/facets/DiamondLoupeFacet.sol index 119d765..3f8cf09 100644 --- a/contracts/Vault/facets/DiamondLoupeFacet.sol +++ b/contracts/Vault/facets/DiamondLoupeFacet.sol @@ -1,30 +1,29 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.4; -/******************************************************************************\ -* Author: Nick Mudge (https://twitter.com/mudgen) -* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 -/******************************************************************************/ +/** + * \ + * Author: Nick Mudge (https://twitter.com/mudgen) + * EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 + * /***************************************************************************** + */ //import "../libraries/LibVaultStorage.sol"; import "../libraries/LibDiamond.sol"; -import { IDiamondLoupe } from "../../interfaces/IDiamondLoupe.sol"; -import { IERC165 } from "../../interfaces/IERC165.sol"; +import {IDiamondLoupe} from "../../interfaces/IDiamondLoupe.sol"; +import {IERC165} from "../../interfaces/IERC165.sol"; import "../libraries/LibLayoutSilo.sol"; import "../libraries/LibStorageBinder.sol"; - contract DiamondLoupeFacet is IDiamondLoupe, IERC165 { - // Diamond Loupe Functions //////////////////////////////////////////////////////////////////// /// These functions are expected to be called frequently by tools. - /// @notice Gets all facets and their selectors. /// @return facets_ Facet - function facets() external override view returns (Facet[] memory facets_) { - FacetAndSelectorData storage fsData=LibStorageBinder._bindAndReturnFacetStorage(); + function facets() external view override returns (Facet[] memory facets_) { + FacetAndSelectorData storage fsData = LibStorageBinder._bindAndReturnFacetStorage(); uint256 numFacets = fsData.facetAddresses.length; facets_ = new Facet[](numFacets); for (uint256 i; i < numFacets; i++) { @@ -37,15 +36,20 @@ contract DiamondLoupeFacet is IDiamondLoupe, IERC165 { /// @notice Gets all the function selectors provided by a facet. /// @param _facet The facet address. /// @return facetFunctionSelectors_ - function facetFunctionSelectors(address _facet) external override view returns (bytes4[] memory facetFunctionSelectors_) { - FacetAndSelectorData storage fsData=LibStorageBinder._bindAndReturnFacetStorage(); + function facetFunctionSelectors(address _facet) + external + view + override + returns (bytes4[] memory facetFunctionSelectors_) + { + FacetAndSelectorData storage fsData = LibStorageBinder._bindAndReturnFacetStorage(); facetFunctionSelectors_ = fsData.facetFunctionSelectors[_facet].functionSelectors; } /// @notice Get all the facet addresses used by a diamond. /// @return facetAddresses_ - function facetAddresses() external override view returns (address[] memory facetAddresses_) { - FacetAndSelectorData storage fsData=LibStorageBinder._bindAndReturnFacetStorage(); + function facetAddresses() external view override returns (address[] memory facetAddresses_) { + FacetAndSelectorData storage fsData = LibStorageBinder._bindAndReturnFacetStorage(); facetAddresses_ = fsData.facetAddresses; } @@ -53,14 +57,14 @@ contract DiamondLoupeFacet is IDiamondLoupe, IERC165 { /// @dev If facet is not found return address(0). /// @param _functionSelector The function selector. /// @return facetAddress_ The facet address. - function facetAddress(bytes4 _functionSelector) external override view returns (address facetAddress_) { - FacetAndSelectorData storage fsData=LibStorageBinder._bindAndReturnFacetStorage(); + function facetAddress(bytes4 _functionSelector) external view override returns (address facetAddress_) { + FacetAndSelectorData storage fsData = LibStorageBinder._bindAndReturnFacetStorage(); facetAddress_ = fsData.selectorToFacetAndPosition[_functionSelector].facetAddress; } // This implements ERC-165. - function supportsInterface(bytes4 _interfaceId) external override view returns (bool) { - FacetAndSelectorData storage fsData=LibStorageBinder._bindAndReturnFacetStorage(); + function supportsInterface(bytes4 _interfaceId) external view override returns (bool) { + FacetAndSelectorData storage fsData = LibStorageBinder._bindAndReturnFacetStorage(); return fsData.supportedInterfaces[_interfaceId]; } } diff --git a/contracts/Vault/facets/ERC1155Facet.sol b/contracts/Vault/facets/ERC1155Facet.sol index 99d111a..4caf2c9 100644 --- a/contracts/Vault/facets/ERC1155Facet.sol +++ b/contracts/Vault/facets/ERC1155Facet.sol @@ -2,88 +2,68 @@ pragma solidity 0.8.4; import "../libraries/LibDMS.sol"; -import {LibTokens,ERC1155_ACCEPTED,ERC1155_BATCH_ACCEPTED} from "../libraries/LibTokens.sol"; +import {LibTokens, ERC1155_ACCEPTED, ERC1155_BATCH_ACCEPTED} from "../libraries/LibTokens.sol"; import "../libraries/LibLayoutSilo.sol"; import "../libraries/LibStorageBinder.sol"; import "../libraries/LibGuards.sol"; contract ERC1155Facet { - //DEPOSITS - function depositERC1155Token( - address _token, - uint256 _tokenID, - uint256 _amount - ) external { - // LibGuards._onlyVaultOwner(); - LibTokens._safeInputERC1155Token(_token, _tokenID, _amount); - } - - function batchDepositERC1155Tokens( - address _token, - uint256[] calldata _tokenIDs, - uint256[] calldata _amounts - ) external { - // LibGuards._onlyVaultOwner(); - LibTokens._safeBatchInputERC1155Tokens(_token, _tokenIDs, _amounts); - } - - //WITHDRAWALS - - function withdrawERC1155Token( - address _token, - uint256 _tokenID, - uint256 _amount, - address _to - ) public { - LibGuards._onlyVaultOwner(); - LibTokens._withdrawERC1155Token(_token, _tokenID, _amount, _to); - } + //DEPOSITS + /// @notice deposits ERC1155 token into the vault + function depositERC1155Token(address _token, uint256 _tokenID, uint256 _amount) external { + // LibGuards._onlyVaultOwner(); + LibTokens._safeInputERC1155Token(_token, _tokenID, _amount); + } + /// @notice allows caller to deposit an ERC1155 with multiple tokenIDs into the vault + function batchDepositERC1155Tokens(address _token, uint256[] calldata _tokenIDs, uint256[] calldata _amounts) + external + { + // LibGuards._onlyVaultOwner(); + LibTokens._safeBatchInputERC1155Tokens(_token, _tokenIDs, _amounts); + } - function batchWithdrawERC1155Token( - address _token, - uint256[] calldata _tokenIDs, - uint256[] calldata _amount, - address _to - ) public { - LibGuards._onlyVaultOwner(); - if (_tokenIDs.length > 0) { - for (uint256 i; i < _tokenIDs.length; i++) { - withdrawERC1155Token(_token, _tokenIDs[i], _amount[i], _to); - } + //WITHDRAWALS + /// @notice withdraws an ERC1155 token from the vault + function withdrawERC1155Token(address _token, uint256 _tokenID, uint256 _amount, address _to) public { + LibGuards._onlyVaultOwner(); + LibTokens._withdrawERC1155Token(_token, _tokenID, _amount, _to); } - } - //APPROVALS - function approveERC1155Token( - address _token, - address _to, - bool _approved - ) external { - LibGuards._onlyVaultOwner(); - LibTokens._approveAllERC1155Token(_token, _to, _approved); - } + /// @notice allows caller to withdraw a unit of ERC155 token with multiple tokenIDs from the vault + function batchWithdrawERC1155Token( + address _token, + uint256[] calldata _tokenIDs, + uint256[] calldata _amount, + address _to + ) public { + LibGuards._onlyVaultOwner(); + if (_tokenIDs.length > 0) { + for (uint256 i; i < _tokenIDs.length; i++) { + withdrawERC1155Token(_token, _tokenIDs[i], _amount[i], _to); + } + } + } - //DEPOSIT COMPATIBILITY + //APPROVALS + /// @notice approves an ERC1155 token to be spent by _to + function approveERC1155Token(address _token, address _to, bool _approved) external { + LibGuards._onlyVaultOwner(); + LibTokens._approveAllERC1155Token(_token, _to, _approved); + } -function onERC1155Received( - address, - address, - uint256, - uint256, - bytes memory - ) public pure returns (bytes4) { + //DEPOSIT COMPATIBILITY + /// @notice checks if ERC155 token deposit is allowed in the vault + function onERC1155Received(address, address, uint256, uint256, bytes memory) public pure returns (bytes4) { return ERC1155_ACCEPTED; } - function onERC1155BatchReceived( - address, - address, - uint256[] memory, - uint256[] memory, - bytes memory - ) public pure returns (bytes4) { + /// @notice checks if ERC155 token batch deposit is allowed in the vault + function onERC1155BatchReceived(address, address, uint256[] memory, uint256[] memory, bytes memory) + public + pure + returns (bytes4) + { return ERC1155_BATCH_ACCEPTED; } - } diff --git a/contracts/Vault/facets/ERC20Facet.sol b/contracts/Vault/facets/ERC20Facet.sol index 58ab3fb..22a6244 100644 --- a/contracts/Vault/facets/ERC20Facet.sol +++ b/contracts/Vault/facets/ERC20Facet.sol @@ -1,42 +1,40 @@ pragma solidity 0.8.4; - import {LibTokens} from "../libraries/LibTokens.sol"; import "../libraries/LibLayoutSilo.sol"; import "../libraries/LibStorageBinder.sol"; - import {LibGuards} from "../libraries/LibGuards.sol"; -contract ERC20Facet { - - - +contract ERC20Facet { //DEPOSITS + /// @notice deposits ERC20 token into the vault function depositERC20Token(address _token, uint256 _amount) external { // LibGuards._onlyVaultOwner(); LibTokens._inputERC20Token(_token, _amount); } + /// @notice deposits multiple ERC20 tokens into the vault function depositERC20Tokens(address[] calldata _tokens, uint256[] calldata _amounts) external { //LibGuards._onlyVaultOwner(); LibTokens._inputERC20Tokens(_tokens, _amounts); } //WITHDRAWALS - + /// @notice withdraws an ERC20 token from the vault function withdrawERC20Token(address _token, uint256 _amount, address _to) public { LibGuards._onlyVaultOwner(); LibTokens._withdrawERC20Token(_token, _amount, _to); } - + /// @notice allows caller to withdraw multiple ERC20 tokens from the vault function batchWithdrawERC20Token(address[] calldata _tokens, uint256[] calldata _amounts, address _to) public { LibGuards._onlyVaultOwner(); LibTokens._withdrawERC20Tokens(_tokens, _amounts, _to); } //APPROVALS + /// @notice approves an ERC20 token to be spent by _to function approveERC20Token(address _token, address _to, uint256 _amount) external { LibGuards._onlyVaultOwner(); LibTokens._approveERC20Token(_token, _to, _amount); diff --git a/contracts/Vault/facets/ERC721Facet.sol b/contracts/Vault/facets/ERC721Facet.sol index 3aaa42d..4a190dd 100644 --- a/contracts/Vault/facets/ERC721Facet.sol +++ b/contracts/Vault/facets/ERC721Facet.sol @@ -9,82 +9,56 @@ import "../libraries/LibStorageBinder.sol"; import {LibDMSGuards} from "../libraries/LibDMSGuards.sol"; import {LibGuards} from "../libraries/LibGuards.sol"; -import {ERC1155_BATCH_ACCEPTED,ERC1155_ACCEPTED,ERC721WithCall} from "../libraries/LibTokens.sol"; - -contract ERC721Facet { - - - //DEPOSITS - - function depositERC721Token( - address _token, - uint256 _tokenID - ) external { - // LibDMSGuards._onlyVaultOwner(); - LibTokens._inputERC721Token(_token, _tokenID); - } - - function depositERC721Tokens(address _token,uint256[] calldata _tokenIDs) external{ - for(uint256 i;i<_tokenIDs.length;i++){ - LibTokens._inputERC721Token(_token,_tokenIDs[i]); +import {ERC1155_BATCH_ACCEPTED, ERC1155_ACCEPTED, ERC721WithCall} from "../libraries/LibTokens.sol"; + +contract ERC721Facet { + //DEPOSITS + /// @notice deposits ERC721 token into the vault + function depositERC721Token(address _token, uint256 _tokenID) external { + // LibDMSGuards._onlyVaultOwner(); + LibTokens._inputERC721Token(_token, _tokenID); + } + /// @notice allows caller to deposit an ERC721 token with multiple Ids into the vault + function depositERC721Tokens(address _token, uint256[] calldata _tokenIDs) external { + for (uint256 i; i < _tokenIDs.length; i++) { + LibTokens._inputERC721Token(_token, _tokenIDs[i]); + } } - } - - function safeDepositERC721Token( - address _token, - uint256 _tokenID - ) external { - // LibDMSGuards._onlyVaultOwner(); - LibTokens._safeInputERC721Token(_token, _tokenID); - } - - - - function safeDepositERC721TokenAndCall( - address _token, - uint256 _tokenID,bytes calldata data - ) external { - //LibDMSGuards._onlyVaultOwner(); - LibTokens._safeInputERC721TokenAndCall(_token, _tokenID,data); - } - - - //WITHDRAWALS - function withdrawERC721Token( - address _token, - uint256 _tokenID, - address _to - ) public { - LibGuards._onlyVaultOwner(); - LibTokens._withdrawERC721Token(_token, _tokenID, _to); - } + /// @notice allows user to deposit an ERC721 token via the safeTransferFrom method + function safeDepositERC721Token(address _token, uint256 _tokenID) external { + // LibDMSGuards._onlyVaultOwner(); + LibTokens._safeInputERC721Token(_token, _tokenID); + } -//APPROVALS - function approveSingleERC721Token( - address _token, - address _to, - uint256 _tokenID - ) external { - LibGuards._onlyVaultOwner(); - LibTokens._approveERC721Token(_token, _tokenID,_to); - } + /// @notice allow safe deposit of ERC721 token with data + function safeDepositERC721TokenAndCall(address _token, uint256 _tokenID, bytes calldata data) external { + //LibDMSGuards._onlyVaultOwner(); + LibTokens._safeInputERC721TokenAndCall(_token, _tokenID, data); + } -function approveAllERC721Token(address _token,address _to,bool _approved) external { - LibGuards._onlyVaultOwner(); - LibTokens._approveAllERC721Token(_token,_to,_approved); -} + //WITHDRAWALS + /// @notice withdraws an ERC721 token from the vault + function withdrawERC721Token(address _token, uint256 _tokenID, address _to) public { + LibGuards._onlyVaultOwner(); + LibTokens._withdrawERC721Token(_token, _tokenID, _to); + } -//DEPOSIT COMPATIBILITY + //APPROVALS + /// @notice approves a unit of ERC721 token to be spent by _to + function approveSingleERC721Token(address _token, address _to, uint256 _tokenID) external { + LibGuards._onlyVaultOwner(); + LibTokens._approveERC721Token(_token, _tokenID, _to); + } + /// @notice approves all ERC721 tokens to be spent by _to + function approveAllERC721Token(address _token, address _to, bool _approved) external { + LibGuards._onlyVaultOwner(); + LibTokens._approveAllERC721Token(_token, _to, _approved); + } - function onERC721Received( - address, - address, - uint256, - bytes memory - ) public pure returns (bytes4) { + //DEPOSIT COMPATIBILITY + /// @notice checks if onERC721Received is implemented + function onERC721Received(address, address, uint256, bytes memory) public pure returns (bytes4) { return ERC721WithCall; } - - -} \ No newline at end of file +} diff --git a/contracts/Vault/facets/EtherFacet.sol b/contracts/Vault/facets/EtherFacet.sol index 78ee55c..2aea4e3 100644 --- a/contracts/Vault/facets/EtherFacet.sol +++ b/contracts/Vault/facets/EtherFacet.sol @@ -1,18 +1,19 @@ - pragma solidity 0.8.4; import {LibErrors} from "../libraries/LibErrors.sol"; import {LibDiamond} from "../libraries/LibDiamond.sol"; import {LibGuards} from "../libraries/LibGuards.sol"; import {LibEther} from "../libraries/LibEther.sol"; -contract EtherFacet { - function depositEther(uint256 _amount) external payable { - LibEther._depositEther(_amount); +contract EtherFacet { + //DEPOSITS + /// @notice deposits Ether into the vault + function depositEther(uint256 _amount) external payable { + LibEther._depositEther(_amount); } - + /// @notice allows caller to withdraw Ether from the vault function withdrawEther(uint256 _amount, address _to) external { LibGuards._onlyVaultOwner(); LibEther._withdrawEth(_amount, _to); } -} \ No newline at end of file +} diff --git a/contracts/Vault/facets/ModuleManagerFacet.sol b/contracts/Vault/facets/ModuleManagerFacet.sol new file mode 100644 index 0000000..7671af3 --- /dev/null +++ b/contracts/Vault/facets/ModuleManagerFacet.sol @@ -0,0 +1,31 @@ +pragma solidity 0.8.4; + +import "../libraries/LibStorageBinder.sol"; +import "../libraries/LibLayoutSilo.sol"; +import "../libraries/LibModuleUpgrades.sol"; + +contract ModuleManagerFacet { + /// @notice returns the active modules in the vault + function getActiveModules() external view returns (string[] memory) { + FacetAndSelectorData storage fsData = LibStorageBinder._bindAndReturnFacetStorage(); + return fsData.activeModules; + } + + /// @notice checks if a module is active in vault + function isActiveModule(string memory _name) external view returns (bool exists_) { + FacetAndSelectorData storage fsData = LibStorageBinder._bindAndReturnFacetStorage(); + exists_ = fsData.activeModule[_name]; + } + + //upgrade + /// @notice allows vaul to be upgraded with a module + function upgradeVaultWithModule(string calldata _name) external { + LibModuleUpgrades._upgradeVaultWithModule(_name); + } + + //downgrade + /// @notice allows vault to be downgraded by removing a module + function downgradeVaultWithModule(string calldata _name) external { + LibModuleUpgrades._downgradeVaultWithModule(_name); + } +} diff --git a/contracts/Vault/facets/OwnershipFacet.sol b/contracts/Vault/facets/OwnershipFacet.sol new file mode 100644 index 0000000..7c3b2d3 --- /dev/null +++ b/contracts/Vault/facets/OwnershipFacet.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.4; + +import {LibDiamond} from "../libraries/LibDiamond.sol"; + +contract OwnershipFacet { + /// @notice returns the owner of the vault + function owner() external view returns (address owner_) { + owner_ = LibDiamond.vaultOwner(); + } +} diff --git a/contracts/Vault/libraries/LibArrayHelpers.sol b/contracts/Vault/libraries/LibArrayHelpers.sol index e0f5dc9..b124042 100644 --- a/contracts/Vault/libraries/LibArrayHelpers.sol +++ b/contracts/Vault/libraries/LibArrayHelpers.sol @@ -1,7 +1,13 @@ pragma solidity 0.8.4; -library LibKeepHelpers { - function findAddIndex(address _item, address[] memory addressArray) internal pure returns (uint256 i) { +library LibArrayHelpers { + /// @notice check an address index in an array + /// @param _item address to be checked + /// @param addressArray arrays to be checked + function findAddIndex( + address _item, + address[] memory addressArray + ) internal pure returns (uint256 i) { for (i; i < addressArray.length; i++) { //using the conventional method since we cannot have duplicate addresses if (addressArray[i] == _item) { @@ -10,11 +16,14 @@ library LibKeepHelpers { } } - function findUintIndex(uint _item, uint[] memory noArray) - internal - pure - returns (uint256 i) - { + /// @dev checks item index in an array + /// @param _item to be checked + /// @param noArray array to be looped through + + function findUintIndex( + uint256 _item, + uint256[] memory noArray + ) internal pure returns (uint256 i) { for (i; i < noArray.length; i++) { if (noArray[i] == _item) { return i; @@ -22,7 +31,47 @@ library LibKeepHelpers { } } - function removeUint(uint[] storage _noArray, uint to) internal { + /// @notice check for sring index given an array + function findStringIndex( + string memory _item, + string[] memory stringArray + ) internal pure returns (uint256 i) { + for (i; i < stringArray.length; i++) { + if (__equalTo__(stringArray[i], _item)) { + return i; + } + } + } + + /// @dev checks for eqaulity of two strings + function __equalTo__( + string memory a, + string memory b + ) private pure returns (bool) { + return (keccak256(abi.encodePacked((a))) == + keccak256(abi.encodePacked((b)))); + } + + /// @dev removes string from an array + function removeString( + string[] storage _stringArray, + string memory to + ) internal { + require(_stringArray.length > 0, "Non-elemented number array"); + uint256 index = findStringIndex(to, _stringArray); + if (_stringArray.length == 1) { + _stringArray.pop(); + } + if (_stringArray.length > 1) { + for (uint256 i = index; i < _stringArray.length - 1; i++) { + _stringArray[i] = _stringArray[i + 1]; + } + _stringArray.pop(); + } + } + + /// @dev removes uint from an array + function removeUint(uint256[] storage _noArray, uint256 to) internal { require(_noArray.length > 0, "Non-elemented number array"); uint256 index = findUintIndex(to, _noArray); if (_noArray.length == 1) { @@ -36,6 +85,7 @@ library LibKeepHelpers { } } + /// @notice removes address form _array[] function removeAddress(address[] storage _array, address _add) internal { require(_array.length > 0, "Non-elemented address array"); uint256 index = findAddIndex(_add, _array); @@ -51,8 +101,12 @@ library LibKeepHelpers { } } - function _inUintArray(uint256[] memory _array,uint256 _targ) internal pure returns (bool exists_) { - if(_array.length>0){ + /// @notice checks fif an integer is included in the selected array + function _inUintArray( + uint256[] memory _array, + uint256 _targ + ) internal pure returns (bool exists_) { + if (_array.length > 0) { for (uint256 i; i < _array.length; i++) { if (_targ == _array[i]) { exists_ = true; @@ -61,8 +115,12 @@ library LibKeepHelpers { } } - function _inAddressArray(address[] memory _array,address _targ) internal pure returns (bool exists_) { - if(_array.length>0){ + /// @dev checks for _targ address in _array + function _inAddressArray( + address[] memory _array, + address _targ + ) internal pure returns (bool exists_) { + if (_array.length > 0) { for (uint256 i; i < _array.length; i++) { if (_targ == _array[i]) { exists_ = true; diff --git a/contracts/Vault/libraries/LibDMS.sol b/contracts/Vault/libraries/LibDMS.sol index ab406f1..54137b0 100644 --- a/contracts/Vault/libraries/LibDMS.sol +++ b/contracts/Vault/libraries/LibDMS.sol @@ -43,14 +43,14 @@ library LibDMS { error InactiveInheritor(); error NoAllocatedTokens(); - //owner check is in external fn + /// @notice pings vault and resets the timeline for inactivity function _ping() internal { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); vaultData.lastPing = block.timestamp; emit VaultPinged(block.timestamp, LibDiamond.vaultID()); } - - function getCurrentAllocatedEth() internal view returns (uint256) { + /// @notice gets the total ETH allocated in a vault + function getCurrentAllocatedEth() internal view returns (uint256) { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); uint256 totalEthAllocated; for (uint256 x; x < vaultData.inheritors.length; x++) { @@ -59,6 +59,7 @@ library LibDMS { return totalEthAllocated; } + /// @dev returns the total amount of an allocated token function getCurrentAllocatedTokens(address _token) internal view returns (uint256) { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); uint256 totalTokensAllocated; @@ -68,6 +69,7 @@ library LibDMS { return totalTokensAllocated; } + /// @notice returns the allocated amount of an Erc1155 id function getCurrentAllocated1155tokens(address _token, uint256 _tokenID) internal view returns (uint256 alloc_) { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); for (uint256 x; x < vaultData.inheritors.length; x++) { @@ -75,11 +77,14 @@ library LibDMS { } } + /// @notice checks if an ERC 721 token has been allocated function _isERC721Allocated(address _token, uint256 _tokenId) internal view returns (bool allocated_) { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); allocated_ = vaultData.allocatedERC721Tokens[_token][_tokenId]; } + /// @notice this removes all the tokens that have + /// been previously allocated to an inheritor for all token types function _resetClaimed(address _inheritor) internal { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); vaultData.inheritorWeishares[_inheritor] = 0; @@ -98,7 +103,8 @@ library LibDMS { } } - //only used for multiple address elemented arrays + /// @notice resets allocated tokens + /// only used for multiple address elemented arrays function reset(address _inheritor) internal { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); vaultData.inheritorWeishares[_inheritor] = 0; @@ -106,7 +112,8 @@ library LibDMS { if (vaultData.inheritorAllocatedERC20Tokens[_inheritor].length > 0) { for (uint256 x; x < vaultData.inheritorAllocatedERC20Tokens[_inheritor].length; x++) { vaultData.inheritorTokenShares[_inheritor][vaultData.inheritorAllocatedERC20Tokens[_inheritor][x]] = 0; - vaultData.inheritorActiveTokens[_inheritor][vaultData.inheritorAllocatedERC20Tokens[_inheritor][x]] = false; + vaultData.inheritorActiveTokens[_inheritor][vaultData.inheritorAllocatedERC20Tokens[_inheritor][x]] = + false; } //remove all token addresses delete vaultData.inheritorAllocatedERC20Tokens[_inheritor]; @@ -141,7 +148,7 @@ library LibDMS { } //INHERITOR MUTATING OPERATIONS - + /// @dev adds new set of inheritors to a vault with their wei shares function _addInheritors(address[] calldata _newInheritors, uint256[] calldata _weiShare) internal { if (_newInheritors.length == 0 || _weiShare.length == 0) { revert LibErrors.EmptyArray(); @@ -172,6 +179,7 @@ library LibDMS { emit EthAllocated(_newInheritors, _weiShare, LibDiamond.vaultID()); } + /// @notice removes inheritors from vaulr function _removeInheritors(address[] calldata _inheritors) internal { if (_inheritors.length == 0) { revert LibErrors.EmptyArray(); @@ -194,6 +202,7 @@ library LibDMS { //ALLOCATION MUTATING OPERATIONS + /// @notice allocate ether to active inheritors of a vault function _allocateEther(address[] calldata _inheritors, uint256[] calldata _ethShares) internal { if (_inheritors.length == 0 || _ethShares.length == 0) { revert LibErrors.EmptyArray(); @@ -218,6 +227,7 @@ library LibDMS { emit EthAllocated(_inheritors, _ethShares, LibDiamond.vaultID()); } + /// @notice allocate token to aactive inheritors with their respective shares function _allocateERC20Tokens(address token, address[] calldata _inheritors, uint256[] calldata _shares) internal { if (_inheritors.length == 0 || _shares.length == 0) { revert LibErrors.EmptyArray(); @@ -255,6 +265,7 @@ library LibDMS { emit ERC20TokensAllocated(token, _inheritors, _shares, LibDiamond.vaultID()); } + /// @notice allocates ERC721 tokens to active inheritors function _allocateERC721Tokens(address _token, address[] calldata _inheritors, uint256[] calldata _tokenIDs) internal { @@ -337,14 +348,16 @@ library LibDMS { _ping(); } + /// @notice allocates ERC115 tokens to active inheritors + /// @param _inheritors to be added + /// @param _tokenIDs of ERC155 to be allocated + /// @param _amounts of the token to be allocated to inheritor function _allocateERC1155Tokens( address _token, address[] calldata _inheritors, uint256[] calldata _tokenIDs, uint256[] calldata _amounts - ) - internal - { + ) internal { if (_inheritors.length == 0 || _tokenIDs.length == 0) { revert LibErrors.EmptyArray(); } @@ -399,7 +412,7 @@ library LibDMS { } //ACCESS TRANSFER - + //// @notice transfers vault ownership to new owner function _transferOwnerShip(address _newOwner) internal { FacetAndSelectorData storage fsData = LibStorageBinder._bindAndReturnFacetStorage(); address prevOwner = fsData.vaultOwner; @@ -407,6 +420,7 @@ library LibDMS { emit OwnershipTransferred(prevOwner, _newOwner, LibDiamond.vaultID()); } + /// @notice sets a new backup address function _transferBackup(address _newBackupAddress) internal { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); address prevBackup = vaultData.backupAddress; @@ -416,6 +430,7 @@ library LibDMS { ///CLAIMS + /// @notice transfers vault ownership to caller and sets new backup address function _claimOwnership(address _newBackup) internal { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); FacetAndSelectorData storage fsData = LibStorageBinder._bindAndReturnFacetStorage(); @@ -429,6 +444,7 @@ library LibDMS { emit BackupTransferred(prevBackup, _newBackup, LibDiamond.vaultID()); } + /// @notice allows an inheritor to claim their ERC20 tokens share from the vault function _claimERC20Tokens() internal { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); uint256 tokens = vaultData.inheritorAllocatedERC20Tokens[msg.sender].length; @@ -449,6 +465,7 @@ library LibDMS { } } + /// @notice allows inheritor to claim the ERC721 token allocated to them from the vault function _claimERC721Tokens() internal { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); uint256 tokens = vaultData.inheritorAllocatedERC721TokenAddresses[msg.sender].length; @@ -481,6 +498,7 @@ library LibDMS { } } + /// @notice allows inheritors to claim the ERC1155 tokens allocated to them from the vault function _claimERC1155Tokens() internal { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); uint256 tokens = vaultData.inheritorAllocatedERC1155TokenAddresses[msg.sender].length; @@ -506,6 +524,7 @@ library LibDMS { } } + /// @notice allows an inheritor to claim all tokens allocated to them in a single transaction function _claimAll() internal { LibDMSGuards._anInheritor(msg.sender); LibDMSGuards._activeInheritor(msg.sender); diff --git a/contracts/Vault/libraries/LibDMSGuards.sol b/contracts/Vault/libraries/LibDMSGuards.sol index caf849b..bfe1d79 100644 --- a/contracts/Vault/libraries/LibDMSGuards.sol +++ b/contracts/Vault/libraries/LibDMSGuards.sol @@ -1,6 +1,7 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.4; - -import {DMSData,FacetAndSelectorData} from "../libraries/LibLayoutSilo.sol"; +import {DMSData, FacetAndSelectorData} from "../libraries/LibLayoutSilo.sol"; import {LibStorageBinder} from "../libraries/LibStorageBinder.sol"; error NotBackupAddress(); @@ -10,15 +11,15 @@ error HasExpired(); error Claimed(); library LibDMSGuards { - -//check -function _onlyVaultOwnerOrBackup() internal view { + /// @notice ensures that a caller is vault owner or backup address + function _onlyVaultOwnerOrBackup() internal view { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); - FacetAndSelectorData storage fsData=LibStorageBinder._bindAndReturnFacetStorage(); + FacetAndSelectorData storage fsData = LibStorageBinder._bindAndReturnFacetStorage(); if (msg.sender != vaultData.backupAddress && msg.sender != fsData.vaultOwner) { revert NotOwnerOrBackupAddress(); } } + /// @dev checks that caller is a backup address function _enforceIsBackupAddress() internal view { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); @@ -26,6 +27,7 @@ function _onlyVaultOwnerOrBackup() internal view { revert NotBackupAddress(); } } + /// checks if an address is an active inheritor on a vault function _activeInheritor(address _inheritor) internal view returns (bool active_) { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); @@ -35,6 +37,7 @@ function _onlyVaultOwnerOrBackup() internal view { active_ = (vaultData.activeInheritors[_inheritor]); } } + /// checks if an address has been set as inheritor function _anInheritor(address _inheritor) internal view returns (bool inh) { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); @@ -48,7 +51,7 @@ function _onlyVaultOwnerOrBackup() internal view { } } } - + /// checks if address is an inheritor or address(0) function _anInheritorOrZero(address _inheritor) internal view returns (bool inh) { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); if (_inheritor == address(0)) { @@ -62,6 +65,7 @@ function _onlyVaultOwnerOrBackup() internal view { } } + /// checks if the vault timeline for inactivity has expired function _expired() internal view { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); if (block.timestamp - vaultData.lastPing <= 24 weeks) { @@ -69,19 +73,18 @@ function _onlyVaultOwnerOrBackup() internal view { } } + /// checks if the vault timeline for inactivity is still valid function _notExpired() internal view { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); if (block.timestamp - vaultData.lastPing > 24 weeks) { revert HasExpired(); } } - + /// @notice check if an inheritor has claimed the assets allocated to them function _notClaimed(address _inheritor) internal view { DMSData storage vaultData = LibStorageBinder._bindAndReturnDMSStorage(); if (vaultData.claimed[_inheritor]) { revert Claimed(); } } - - -} \ No newline at end of file +} diff --git a/contracts/Vault/libraries/LibDiamond.sol b/contracts/Vault/libraries/LibDiamond.sol index d4cfeac..9004ff9 100644 --- a/contracts/Vault/libraries/LibDiamond.sol +++ b/contracts/Vault/libraries/LibDiamond.sol @@ -9,6 +9,7 @@ import {IDiamondCut} from "../../interfaces/IDiamondCut.sol"; import {FacetAndSelectorData} from "../libraries/LibLayoutSilo.sol"; import "../libraries/LibStorageBinder.sol"; +import "../../interfaces/IVaultDiamond.sol"; library LibDiamond { error InValidFacetCutAction(); @@ -24,40 +25,45 @@ library LibDiamond { error NonEmptyCalldata(); error EmptyCalldata(); error InitCallFailed(); - // bytes32 constant VAULT_STORAGE_POSITION = - // keccak256("diamond.standard.keep.storage"); - - // function vaultStorage() internal pure returns (VaultStorage storage vaultData) { - // bytes32 position = VAULT_STORAGE_POSITION; - // assembly { - // vaultData.slot := position - // } - // } event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); + /// @dev sets vault owner address + /// @param _newOwner address function setVaultOwner(address _newOwner) internal { - FacetAndSelectorData storage fsData=LibStorageBinder._bindAndReturnFacetStorage(); + FacetAndSelectorData storage fsData = LibStorageBinder + ._bindAndReturnFacetStorage(); address previousOwner = fsData.vaultOwner; fsData.vaultOwner = _newOwner; emit OwnershipTransferred(previousOwner, _newOwner); } - - + /// @notice returns the address current vault owner function vaultOwner() internal view returns (address contractOwner_) { - contractOwner_ = LibStorageBinder._bindAndReturnFacetStorage().vaultOwner; + contractOwner_ = LibStorageBinder + ._bindAndReturnFacetStorage() + .vaultOwner; } - function vaultID() internal view returns(uint256 vaultID_){ - vaultID_=LibStorageBinder._bindAndReturnFacetStorage().vaultID; + /// @dev returns the ID assigned to a vault + function vaultID() internal view returns (uint256 vaultID_) { + vaultID_ = LibStorageBinder._bindAndReturnFacetStorage().vaultID; } - function enforceIsContractOwner() internal view{ - if (msg.sender != LibStorageBinder._bindAndReturnFacetStorage().vaultOwner) revert NotVaultOwner(); + /// @notice ensures that caller is the owner + function enforceIsContractOwner() internal view { + if ( + msg.sender != + LibStorageBinder._bindAndReturnFacetStorage().vaultOwner + ) revert NotVaultOwner(); + } + + /// @notice returns Vault Factory Diamond address + function vaultFactory() internal view returns (address) { + return IVaultDiamond(address(this)).vaultFactoryDiamond(); } event DiamondCut( @@ -66,7 +72,10 @@ library LibDiamond { bytes _calldata ); - // Internal function version of diamondCut + /// @notice Add/replace/remove any number of functions + /// @param _diamondCut Contains the facet addresses and function selectors + /// @param _init The address of the contract or facet to execute _calldata + /// @param _calldata A function call, including function selector and arguments function diamondCut( IDiamondCut.FacetCut[] memory _diamondCut, address _init, @@ -101,15 +110,22 @@ library LibDiamond { initializeDiamondCut(_init, _calldata); } + /// @notice adds new functions to a facet + /// @param _facetAddress facet where the function will be added + /// @param _functionSelectors arrays of functions to be added function addFunctions( address _facetAddress, bytes4[] memory _functionSelectors ) internal { if (_functionSelectors.length <= 0) revert NoSelectorsInFacet(); - FacetAndSelectorData storage fsData=LibStorageBinder._bindAndReturnFacetStorage(); + FacetAndSelectorData storage fsData = LibStorageBinder + ._bindAndReturnFacetStorage(); if (_facetAddress == address(0)) revert NoZeroAddress(); uint96 selectorPosition = uint96( - fsData.facetFunctionSelectors[_facetAddress].functionSelectors.length + fsData + .facetFunctionSelectors[_facetAddress] + .functionSelectors + .length ); // add new facet address if it does not exist if (selectorPosition == 0) { @@ -130,15 +146,20 @@ library LibDiamond { } } + /// @notice replaces functions in a selected facet function replaceFunctions( address _facetAddress, bytes4[] memory _functionSelectors ) internal { if (_functionSelectors.length <= 0) revert NoSelectorsInFacet(); - FacetAndSelectorData storage fsData=LibStorageBinder._bindAndReturnFacetStorage(); + FacetAndSelectorData storage fsData = LibStorageBinder + ._bindAndReturnFacetStorage(); if (_facetAddress == address(0)) revert NoZeroAddress(); uint96 selectorPosition = uint96( - fsData.facetFunctionSelectors[_facetAddress].functionSelectors.length + fsData + .facetFunctionSelectors[_facetAddress] + .functionSelectors + .length ); // add new facet address if it does not exist if (selectorPosition == 0) { @@ -161,12 +182,14 @@ library LibDiamond { } } + /// @notice removes functions in a facet function removeFunctions( address _facetAddress, bytes4[] memory _functionSelectors ) internal { if (_functionSelectors.length <= 0) revert NoSelectorsInFacet(); - FacetAndSelectorData storage fsData=LibStorageBinder._bindAndReturnFacetStorage(); + FacetAndSelectorData storage fsData = LibStorageBinder + ._bindAndReturnFacetStorage(); // if function does not exist then do nothing and return if (_facetAddress != address(0)) revert MustBeZeroAddress(); for ( @@ -182,14 +205,24 @@ library LibDiamond { } } - function addFacet(FacetAndSelectorData storage fsData, address _facetAddress) internal { + /// @notice add facet to a diamond + /// @param fsData contains function selectors of the facet + /// @param _facetAddress facet t0 be added + function addFacet( + FacetAndSelectorData storage fsData, + address _facetAddress + ) internal { enforceHasContractCode(_facetAddress); - fsData.facetFunctionSelectors[_facetAddress].facetAddressPosition = fsData - .facetAddresses - .length; + fsData + .facetFunctionSelectors[_facetAddress] + .facetAddressPosition = fsData.facetAddresses.length; fsData.facetAddresses.push(_facetAddress); } + /// @dev adds a functions to a selected facet + /// @param fsData the details of the facet + /// @param _selector of the functions to be added + /// _facetAddress of the function function addFunction( FacetAndSelectorData storage fsData, bytes4 _selector, @@ -202,9 +235,12 @@ library LibDiamond { fsData.facetFunctionSelectors[_facetAddress].functionSelectors.push( _selector ); - fsData.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress; + fsData + .selectorToFacetAndPosition[_selector] + .facetAddress = _facetAddress; } + /// @notice removes a function from a a facet function removeFunction( FacetAndSelectorData storage fsData, address _facetAddress, @@ -260,9 +296,11 @@ library LibDiamond { } } - function initializeDiamondCut(address _init, bytes memory _calldata) - internal - { + /// @notice initialise a diamond address + function initializeDiamondCut( + address _init, + bytes memory _calldata + ) internal { if (_init == address(0)) { if (_calldata.length > 0) revert NonEmptyCalldata(); } else { @@ -282,6 +320,7 @@ library LibDiamond { } } + /// @notice checks if an addreess is a conttract function enforceHasContractCode(address _contract) internal view { uint256 contractSize; assembly { diff --git a/contracts/Vault/libraries/LibErrors.sol b/contracts/Vault/libraries/LibErrors.sol index f586657..034dd14 100644 --- a/contracts/Vault/libraries/LibErrors.sol +++ b/contracts/Vault/libraries/LibErrors.sol @@ -1,9 +1,8 @@ pragma solidity 0.8.4; - //list of shared Errors across Modules -library LibErrors{ -error LengthMismatch(); -error EmptyArray(); -error NoPermissions(); -} \ No newline at end of file +library LibErrors { + error LengthMismatch(); + error EmptyArray(); + error NoPermissions(); +} diff --git a/contracts/Vault/libraries/LibEther.sol b/contracts/Vault/libraries/LibEther.sol index 4320039..15b9a7d 100644 --- a/contracts/Vault/libraries/LibEther.sol +++ b/contracts/Vault/libraries/LibEther.sol @@ -8,18 +8,21 @@ import {LibDiamond} from "../libraries/LibDiamond.sol"; library LibEther { error InsufficientEth(); error EthWithdrawalError(); -error AmountMismatch(); + error AmountMismatch(); - event EthDeposited(uint256 _amount,address _from, uint256 _vaultID); - event EthWithdrawn(uint256 _amount,address _to, uint256 _vaultID); + event EthDeposited(uint256 _amount, address _from, uint256 _vaultID); + event EthWithdrawn(uint256 _amount, address _to, uint256 _vaultID); - function _depositEther(uint256 _amount) internal { + /// @notice allows caller to deposit ETH + /// @param _amount of ETH to be deposited ensures that _amount == msg.value + function _depositEther(uint256 _amount) internal { if (_amount != msg.value) { revert AmountMismatch(); } - emit EthDeposited(_amount,msg.sender, LibDiamond.vaultID()); + emit EthDeposited(_amount, msg.sender, LibDiamond.vaultID()); } + /// @dev allow caller to withdraw ETH if _amount is not greater than available ether function _withdrawEth(uint256 _amount, address _to) internal { //confirm free eth is sufficient uint256 availableEther = address(this).balance; @@ -30,13 +33,11 @@ error AmountMismatch(); if (_amount > availableEther) revert InsufficientEth(); } if (availableEther >= _amount) { - (bool success,) = _to.call{value: _amount}(""); + (bool success, ) = _to.call{value: _amount}(""); assert(success); } else { revert EthWithdrawalError(); } - emit EthWithdrawn(_amount,_to, LibDiamond.vaultID()); + emit EthWithdrawn(_amount, _to, LibDiamond.vaultID()); } - - } diff --git a/contracts/Vault/libraries/LibGuards.sol b/contracts/Vault/libraries/LibGuards.sol index 2f80514..b12c848 100644 --- a/contracts/Vault/libraries/LibGuards.sol +++ b/contracts/Vault/libraries/LibGuards.sol @@ -6,6 +6,7 @@ import "../libraries/LibLayoutSilo.sol"; import "../libraries/LibStorageBinder.sol"; library LibGuards { + /// @notice ensure that caller is vault owner function _onlyVaultOwner() internal view { LibDiamond.enforceIsContractOwner(); } diff --git a/contracts/Vault/libraries/LibLayoutSilo.sol b/contracts/Vault/libraries/LibLayoutSilo.sol index e096fb7..1b3570d 100644 --- a/contracts/Vault/libraries/LibLayoutSilo.sol +++ b/contracts/Vault/libraries/LibLayoutSilo.sol @@ -2,24 +2,25 @@ pragma solidity 0.8.4; //A record of data layouts...these are immutable and cannot be extended - ///DIAMOND_FACET_SELECTOR ////START///// struct FacetAddressAndPosition { address facetAddress; uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array } + struct FacetFunctionSelectors { bytes4[] functionSelectors; uint256 facetAddressPosition; // position of facetAddress in facetAddresses array } + struct FacetAndSelectorData { // maps function selector to the facet address and // the position of the selector in the facetFunctionSelectors.selectors array mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition; // maps facet addresses to function selectors mapping(address => FacetFunctionSelectors) facetFunctionSelectors; - // Used to query if a contract implements an interface. + // Used to query if a contract implements an interface. // Used to implement ERC-165. mapping(bytes4 => bool) supportedInterfaces; // facet addresses @@ -29,13 +30,15 @@ struct FacetAndSelectorData { // owner of the vault address vaultOwner; //Modules + // module's status mapping(string => bool) activeModule; - mapping(string=>uint256) moduleStorageCounter; + /// maps Module to counter + mapping(string => uint256) moduleStorageCounter; + // arrays of active modules string[] activeModules; } /////STOP///// - //DMS_GLOB_DATA ////START//// struct DMSData { @@ -56,20 +59,26 @@ struct DMSData { mapping(address => mapping(address => uint256)) inheritorTokenShares; //address of tokens allocated mapping(address => address[]) inheritorAllocatedERC20Tokens; + //ERC721 + // maps token address to inheritor mapping(address => mapping(address => bool)) whitelist; + // maps number of ERC721 token aloocated to inheritor mapping(address => mapping(address => uint256)) inheritorERC721Tokens; + // maps an address to token and inheritor mapping(address => mapping(uint256 => address)) ERC721ToInheritor; + // allocated ERC721 tokens mapping(address => mapping(uint256 => bool)) allocatedERC721Tokens; + // Erc721 tokens allocated to an inheritor mapping(address => address[]) inheritorAllocatedERC721TokenAddresses; + //ERC1155 + // maps token address and id to inheritor mapping(address => mapping(address => mapping(uint256 => uint256))) inheritorERC1155TokenAllocations; mapping(address => address[]) inheritorAllocatedERC1155TokenAddresses; //GLOBAL + // total tokens Id's allocated to an inheritor mapping(address => mapping(address => uint256[])) inheritorAllocatedTokenIds; mapping(address => bool) claimed; } ////STOP//// - - - diff --git a/contracts/Vault/libraries/LibModuleManager.sol b/contracts/Vault/libraries/LibModuleManager.sol index bb99a97..16675a9 100644 --- a/contracts/Vault/libraries/LibModuleManager.sol +++ b/contracts/Vault/libraries/LibModuleManager.sol @@ -4,9 +4,9 @@ import {FacetAndSelectorData} from "../libraries/LibLayoutSilo.sol"; import {LibStorageBinder} from "../libraries/LibStorageBinder.sol"; library LibModuleManager { - -function _isActiveModule(string memory _name) internal view returns(bool active_){ -FacetAndSelectorData storage fs=LibStorageBinder._bindAndReturnFacetStorage(); -active_=fs.activeModule[_name]; -} -} \ No newline at end of file + /// @notice checks if the module parsed in with _name is active + function _isActiveModule(string memory _name) internal view returns (bool active_) { + FacetAndSelectorData storage fs = LibStorageBinder._bindAndReturnFacetStorage(); + active_ = fs.activeModule[_name]; + } +} diff --git a/contracts/Vault/libraries/LibModuleUpgrades.sol b/contracts/Vault/libraries/LibModuleUpgrades.sol new file mode 100644 index 0000000..24a846f --- /dev/null +++ b/contracts/Vault/libraries/LibModuleUpgrades.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.4; + +import {IDiamondCut} from "../../interfaces/IDiamondCut.sol"; +import {LibStorageBinder} from "../../Vault/libraries/LibStorageBinder.sol"; +import {IModuleData} from "../../interfaces/IModuleData.sol"; +import {IVaultFactory} from "../../interfaces/IVaultFactory.sol"; +import {FacetAndSelectorData} from "../libraries/LibLayoutSilo.sol"; +import {LibStorageBinder} from "../libraries/LibStorageBinder.sol"; +import {LibDiamond} from "../libraries/LibDiamond.sol"; +import {LibArrayHelpers} from "../libraries/LibArrayHelpers.sol"; + +error ModuleAlreadyInstalled(); +error ModuleNotInstalled(); + +//basically allows vault owners to make atomic module upgrades to their vaults + +library LibModuleUpgrades { + /** + * address _vault* + */ + event VaultUpgraded(string indexed _moduleName); + /** + * address _vault* + */ + event VaultDowngraded(string indexed _moduleName); + + /// @notice allows a vault to be upgraded by adding a module + function _upgradeVaultWithModule(string calldata _name) internal { + LibDiamond.enforceIsContractOwner(); + //make sure this module doesn't currently exist in this vault + FacetAndSelectorData storage fsData = LibStorageBinder._bindAndReturnFacetStorage(); + if (fsData.activeModule[_name]) revert ModuleAlreadyInstalled(); + //get facet data + //no need to check for existence in registry as this will revert if it does not exist + IDiamondCut.FacetCut[] memory facetData = IVaultFactory(LibDiamond.vaultFactory()).getFacetCuts(_name); + //upgrade vault + IDiamondCut(address(this)).diamondCut(facetData, address(0), ""); + + fsData.activeModule[_name] = true; + fsData.activeModules.push(_name); + + emit VaultUpgraded(_name); + //consider gossiping this upgrade to vaultFactory + } + + /// @notice allows vault to be downgraded by removing module + function _downgradeVaultWithModule(string calldata _name) internal { + LibDiamond.enforceIsContractOwner(); + //make sure this module doesn't currently exist in this vault + FacetAndSelectorData storage fsData = LibStorageBinder._bindAndReturnFacetStorage(); + if (!fsData.activeModule[_name]) revert ModuleNotInstalled(); + //get facet data + //no need to check for existence in registry as this will revert if it does not exist + IDiamondCut.FacetCut[] memory facetData = IVaultFactory(LibDiamond.vaultFactory()).getFacetCuts(_name); + //upgrade vault + //remove them + for (uint256 i = 0; i < facetData.length; i++) { + facetData[i].action = IDiamondCut.FacetCutAction.Remove; + facetData[i].facetAddress = address(0); + } + //downgrade vault + IDiamondCut(address(this)).diamondCut(facetData, address(0), ""); + fsData.activeModule[_name] = true; + LibArrayHelpers.removeString(fsData.activeModules, _name); + emit VaultDowngraded(_name); + //consider gossiping this downgrade to vaultFactory + } +} diff --git a/contracts/Vault/libraries/LibStorageBinder.sol b/contracts/Vault/libraries/LibStorageBinder.sol index 8a926eb..259a62e 100644 --- a/contracts/Vault/libraries/LibStorageBinder.sol +++ b/contracts/Vault/libraries/LibStorageBinder.sol @@ -1,7 +1,7 @@ pragma solidity 0.8.4; //import "../VaultDiamond.sol"; -import {FacetAndSelectorData,DMSData} from "../libraries/LibLayoutSilo.sol"; +import {FacetAndSelectorData, DMSData} from "../libraries/LibLayoutSilo.sol"; import "../facets/DiamondCutFacet.sol"; import "../facets/DiamondLoupeFacet.sol"; import "../facets/ERC1155Facet.sol"; @@ -9,60 +9,45 @@ import "../facets/ERC721Facet.sol"; import "../facets/ERC20Facet.sol"; import "../facets/DMSFacet.sol"; - //~(keccak256(abi.encode(slot,200))) library LibStorageBinder { - bytes32 constant SLOT_SALT = keccak256(type(LibKeep).creationCode); + bytes32 constant SLOT_SALT = keccak256("storage_offset_salt"); - function _getStorageSlot(string memory _facetName1) - internal - pure - returns (bytes32 slot) - { + /// @notice gets the location where a facet is stored + function _getStorageSlot(string memory _facetName1) internal pure returns (bytes32 slot) { slot = keccak256(bytes(_facetName1)); } - function _getStorageSlot( - string memory _facetName1, - string memory _facetName2 - ) internal pure returns (bytes32 slot) { - slot = keccak256(bytes(abi.encode(_facetName1, _facetName2))); - } - function _getStorageSlot( - string memory _facetName1, - string memory _facetName2, - string memory _facetName3, - string memory _facetName4, - string memory _facetName5 - ) internal pure returns (bytes32 slot) { - slot = keccak256(bytes(abi.encode(_facetName1, _facetName2,_facetName3,_facetName4,_facetName5))); - } - - function _bindAndReturnFacetStorage() + /// @notice returns slot of two facets + function _getStorageSlot(string memory _facetName1, string memory _facetName2) internal pure - returns (FacetAndSelectorData storage selectorData) + returns (bytes32 slot) { - bytes32 _slot = _getStorageSlot( - type(DiamondCutFacet).name, - type(DiamondLoupeFacet).name - ); + slot = keccak256(bytes(abi.encode(_facetName1, _facetName2))); + } + // function _getStorageSlot( + // string memory _facetName1, + // string memory _facetName2, + // string memory _facetName3, + // string memory _facetName4, + // string memory _facetName5 + // ) internal pure returns (bytes32 slot) { + // slot = keccak256(bytes(abi.encode(_facetName1, _facetName2,_facetName3,_facetName4,_facetName5))); + // } + + /// @notice binds a facet to its storage slot from the diamon loupe facet + function _bindAndReturnFacetStorage() internal pure returns (FacetAndSelectorData storage selectorData) { + bytes32 _slot = _getStorageSlot(type(DiamondCutFacet).name, type(DiamondLoupeFacet).name); bytes32 saltedOffset = _slot ^ SLOT_SALT; assembly { selectorData.slot := saltedOffset } } -function _bindAndReturnDMSStorage() - internal - pure - returns (DMSData storage vaultData) - { - bytes32 _slot = _getStorageSlot( - type(DiamondCutFacet).name, - type(DMSFacet).name - - ); + /// @notice binds vault Data to a slot from DMS facet + function _bindAndReturnDMSStorage() internal pure returns (DMSData storage vaultData) { + bytes32 _slot = _getStorageSlot(type(DiamondCutFacet).name, type(DMSFacet).name); bytes32 saltedOffset = _slot ^ SLOT_SALT; assembly { vaultData.slot := saltedOffset diff --git a/contracts/Vault/libraries/LibTokens.sol b/contracts/Vault/libraries/LibTokens.sol index 807a81c..001b568 100644 --- a/contracts/Vault/libraries/LibTokens.sol +++ b/contracts/Vault/libraries/LibTokens.sol @@ -14,12 +14,11 @@ bytes4 constant ERC1155_ACCEPTED = 0xf23a6e61; bytes4 constant ERC1155_BATCH_ACCEPTED = 0xbc197c81; bytes4 constant ERC721WithCall = 0xb88d4fde; - error InsufficientTokens(); - error NotERC721Owner(); +error InsufficientTokens(); +error NotERC721Owner(); //token deposit events might be deprecated since deposits can occur without any contract triggers for the vault library LibTokens { - event ErrorHandled(address); event ERC20ErrorHandled(address); event ERC721ErrorHandled(address); @@ -31,23 +30,16 @@ library LibTokens { event ERC721TokenWIthdrawal(address token, uint256 tokenID, address to, uint256 vaultID); event ERC1155TokenDeposit( - address indexed token, - address indexed from, - uint256 tokenID, - uint256 amount, - uint256 vaultID + address indexed token, address indexed from, uint256 tokenID, uint256 amount, uint256 vaultID ); event ERC1155TokenWithdrawal(address token, uint256 tokenID, uint256 amount, address to, uint256 vaultID); event BatchERC1155TokenDeposit( - address indexed token, - address indexed from, - uint256[] tokenIDs, - uint256[] amounts, - uint256 vaultID + address indexed token, address indexed from, uint256[] tokenIDs, uint256[] amounts, uint256 vaultID ); //ERC20 + /// @notice allows caller to deposit several tokens to the vault with the respective amounts function _inputERC20Tokens(address[] calldata _tokenDeps, uint256[] calldata _amounts) internal { if (_tokenDeps.length == 0 || _amounts.length == 0) { revert LibErrors.EmptyArray(); @@ -72,45 +64,41 @@ library LibTokens { } } + /// @notice deposit a token to the vault contract function _inputERC20Token(address _token, uint256 _amount) internal { assert(IERC20(_token).transferFrom(msg.sender, address(this), _amount)); emit ERC20TokenDeposit(_token, msg.sender, _amount, LibDiamond.vaultID()); } - function _approveERC20Token( - address _spender, - address _token, - uint256 _amount - ) - internal - { + /// @notice caller approves spender to use amount of tokens + function _approveERC20Token(address _spender, address _token, uint256 _amount) internal { IERC20(_token).approve(_spender, _amount); - //ping if DMS is installed - if(LibModuleManager._isActiveModule("DMS")){ - LibDMS._ping(); -} + //ping if DMS is installed + if (LibModuleManager._isActiveModule("DMS")) { + LibDMS._ping(); + } } + /// @notice allows caller to withdraw unallocated ether in the vault function _withdrawERC20Token(address _token, uint256 _amount, address _to) internal { - uint256 availableTokens; -uint256 currentBalance = IERC20(_token).balanceOf(address(this)); -//check if DMS module is installed -//also ping if DMS is installed -if(LibModuleManager._isActiveModule("DMS")){ - if(currentBalance > LibDMS.getCurrentAllocatedTokens(_token)){ - availableTokens=currentBalance - LibDMS.getCurrentAllocatedTokens(_token); - LibDMS._ping(); -} -else{ - revert InsufficientTokens(); -} -} -else{ - availableTokens=currentBalance; -} + uint256 availableTokens; + uint256 currentBalance = IERC20(_token).balanceOf(address(this)); + //check if DMS module is installed + //also ping if DMS is installed + uint256 alloc = LibDMS.getCurrentAllocatedTokens(_token); + if (LibModuleManager._isActiveModule("DMS")) { + if (currentBalance > alloc) { + availableTokens = currentBalance - alloc; + LibDMS._ping(); + } else { + revert InsufficientTokens(); + } + } else { + availableTokens = currentBalance; + } bool success; if (currentBalance >= availableTokens) { - if (currentBalance - availableTokens < _amount) { + if (currentBalance - alloc < _amount) { revert InsufficientTokens(); } try IERC20(_token).transfer(_to, _amount) { @@ -127,7 +115,7 @@ else{ } } - + /// @notice alows caller to withdraw tokens that haven't been allocated function _withdrawERC20Tokens(address[] calldata _tokenAdds, uint256[] calldata _amounts, address _to) internal { if (_tokenAdds.length == 0 || _amounts.length == 0) { revert LibErrors.EmptyArray(); @@ -138,25 +126,22 @@ else{ for (uint256 x; x < _tokenAdds.length; x++) { address token = _tokenAdds[x]; uint256 amount = _amounts[x]; - uint256 currentBalance = IERC20(token).balanceOf(address(this)); - uint256 availableTokens; - if(LibModuleManager._isActiveModule("DMS")){ -uint256 allocated=LibDMS.getCurrentAllocatedTokens(token); - if(currentBalance >allocated ){ - availableTokens=currentBalance - allocated; - LibDMS._ping(); -} -else{ - revert InsufficientTokens(); -} - } - -else{ - availableTokens=currentBalance; -} + uint256 currentBalance = IERC20(token).balanceOf(address(this)); + uint256 availableTokens; + uint256 allocated = LibDMS.getCurrentAllocatedTokens(token); + if (LibModuleManager._isActiveModule("DMS")) { + if (currentBalance > allocated) { + availableTokens = currentBalance - allocated; + LibDMS._ping(); + } else { + revert InsufficientTokens(); + } + } else { + availableTokens = currentBalance; + } bool success; if (currentBalance >= availableTokens) { - if (currentBalance - availableTokens < _amounts[x]) { + if (currentBalance - allocated < _amounts[x]) { revert InsufficientTokens(); } //for other errors caused by malformed tokens @@ -172,45 +157,45 @@ else{ } else { revert InsufficientTokens(); } - - } + } } + /// @notice allows user to transfer ERC721 tokens to the vault //ERC721 function _inputERC721Token(address _token, uint256 _tokenID) internal { - IERC721(_token).transferFrom(msg.sender, address(this), _tokenID); emit ERC721TokenDeposit(_token, msg.sender, _tokenID, LibDiamond.vaultID()); } - + /// @notice allows user to deposut ERC721 tokens to the vault via the safeTransferFrom method function _safeInputERC721Token(address _token, uint256 _tokenID) internal { - IERC721(_token).safeTransferFrom(msg.sender, address(this), _tokenID); emit ERC721TokenDeposit(_token, msg.sender, _tokenID, LibDiamond.vaultID()); } - + /// @notice allows user to deposut ERC721 tokens to the vault + /// and pass data alongside function _safeInputERC721TokenAndCall(address _token, uint256 _tokenID, bytes calldata _data) internal { - IERC721(_token).safeTransferFrom(msg.sender, address(this), _tokenID, _data); } + /// @notice approves _to to spend specific token ID function _approveERC721Token(address _token, uint256 _tokenID, address _to) internal { - IERC721(_token).approve(_to, _tokenID); } + /// @notice set approval for all token ID's of the token function _approveAllERC721Token(address _token, address _to, bool _approved) internal { - IERC721(_token).setApprovalForAll(_to, _approved); } - function _withdrawERC721Token(address _token, uint256 _tokenID, address _to) internal { + /// @notice allows caller to withdraw a token ID + function _withdrawERC721Token(address _token, uint256 _tokenID, address _to) internal { if (IERC721(_token).ownerOf(_tokenID) != address(this)) { revert NotERC721Owner(); } - if(LibModuleManager._isActiveModule("DMS")){ - if(LibDMS._isERC721Allocated(_token,_tokenID)) - revert("UnAllocate Token First"); + if (LibModuleManager._isActiveModule("DMS")) { + if (LibDMS._isERC721Allocated(_token, _tokenID)) { + revert("UnAllocate Token First"); + } LibDMS._ping(); } try IERC721(_token).safeTransferFrom(address(this), _to, _tokenID) {} @@ -225,61 +210,51 @@ else{ } //ERC1155 - + /// aloows caller to deposit a unit of ERC1155 to the vault function _safeInputERC1155Token(address _token, uint256 _tokenID, uint256 _value) internal { - IERC1155(_token).safeTransferFrom(msg.sender, address(this), _tokenID, _value, ""); emit ERC1155TokenDeposit(_token, msg.sender, _tokenID, _value, LibDiamond.vaultID()); } - function _safeBatchInputERC1155Tokens( - address _token, - uint256[] calldata _tokenIDs, - uint256[] calldata _values - ) + /// @notice allows deposits of multiple Id's of ERC1155 token to the vault + function _safeBatchInputERC1155Tokens(address _token, uint256[] calldata _tokenIDs, uint256[] calldata _values) internal { - IERC1155(_token).safeBatchTransferFrom(msg.sender, address(this), _tokenIDs, _values, ""); emit BatchERC1155TokenDeposit(_token, msg.sender, _tokenIDs, _values, LibDiamond.vaultID()); } + /// @notice caller approves _to to spend all tokens function _approveAllERC1155Token(address _token, address _to, bool _approved) internal { - IERC1155(_token).setApprovalForAll(_to, _approved); } - + /// @notice allow user to withdraw a unit of ERC1155 token function _withdrawERC1155Token(address _token, uint256 _tokenID, uint256 _amount, address _to) internal { - uint256 currentBalance = IERC1155(_token).balanceOf(address(this), _tokenID); - uint256 availableTokens; -if(LibModuleManager._isActiveModule("DMS")){ - uint256 allocated=LibDMS.getCurrentAllocated1155tokens(_token, _tokenID); - if(currentBalance>allocated){ -availableTokens=currentBalance-allocated; -LibDMS._ping(); - } - if (currentBalance < _amount) { - revert InsufficientTokens(); - } + uint256 currentBalance = IERC1155(_token).balanceOf(address(this), _tokenID); + uint256 availableTokens; + if (LibModuleManager._isActiveModule("DMS")) { + uint256 allocated = LibDMS.getCurrentAllocated1155tokens(_token, _tokenID); + if (currentBalance > allocated) { + availableTokens = currentBalance - allocated; + LibDMS._ping(); + } + if (currentBalance < _amount) { + revert InsufficientTokens(); + } - if (currentBalance - allocated < _amount) { - revert("UnAllocate TokensFirst"); + if (currentBalance - allocated < _amount) { + revert("UnAllocate TokensFirst"); + } + } else { + availableTokens = currentBalance; } - -} -else{ - availableTokens=currentBalance; -} - -if(availableTokens<_amount){ - revert InsufficientTokens(); -} + if (availableTokens < _amount) { + revert InsufficientTokens(); + } IERC1155(_token).safeTransferFrom(address(this), _to, _tokenID, _amount, ""); emit ERC1155TokenWithdrawal(_token, _tokenID, _amount, _to, LibDiamond.vaultID()); - + } } - -} \ No newline at end of file diff --git a/contracts/VaultFactory/VaultFactoryDiamond.sol b/contracts/VaultFactory/VaultFactoryDiamond.sol index 71b6a18..c07d657 100644 --- a/contracts/VaultFactory/VaultFactoryDiamond.sol +++ b/contracts/VaultFactory/VaultFactoryDiamond.sol @@ -2,10 +2,6 @@ pragma solidity ^0.8.0; /** - * \ - * Author: Nick Mudge (https://twitter.com/mudgen) - * EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 - * * Implementation of a diamond. * /***************************************************************************** */ @@ -13,9 +9,14 @@ pragma solidity ^0.8.0; import {LibFactoryDiamond} from "./libraries/LibFactoryDiamond.sol"; import {IDiamondCut} from "../interfaces/IDiamondCut.sol"; -import "./libraries/LibAppStorage.sol"; +import "./libraries/LibFactoryAppStorage.sol"; +// struct Facet { +// address facetAddress; +// bytes4[] functionSelectors; +// } contract VaultFactoryDiamond { + /// @notice sts contract owner and the diamond cut facet constructor(address _contractOwner, address _diamondCutFacet) payable { LibFactoryDiamond.setContractOwner(_contractOwner); @@ -31,32 +32,10 @@ contract VaultFactoryDiamond { LibFactoryDiamond.diamondCut(cut, address(0), ""); } - function setAddresses(address[] calldata _addresses) external { - LibFactoryDiamond.enforceIsContractOwner(); - FactoryAppStorage storage s = LibAppStorage.factoryAppStorage(); - s.diamondCutFacet = _addresses[0]; - s.erc20Facet = _addresses[1]; - s.erc721Facet = _addresses[2]; - s.erc1155Facet = _addresses[3]; - s.diamondLoupeFacet = _addresses[4]; - s.vaultFacet = _addresses[5]; - s.slotChecker=_addresses[6]; - } - - function setSelectors(bytes4[][] calldata _selectors) external { - LibFactoryDiamond.enforceIsContractOwner(); - FactoryAppStorage storage fs = LibAppStorage.factoryAppStorage(); - assert(_selectors.length == 6); - fs.ERC20SELECTORS = _selectors[0]; - fs.ERC721SELECTORS = _selectors[1]; - fs.ERC1155SELECTORS = _selectors[2]; - fs.DIAMONDLOUPEFACETSELECTORS = _selectors[3]; - fs.VAULTFACETSELECTORS = _selectors[4]; - fs.SLOTCHECKERSELECTORS = _selectors[5]; - } - + /// @notice returns contract owner function owner() public view returns (address owner_) { - LibFactoryDiamond.DiamondStorage storage ds = LibFactoryDiamond.diamondStorage(); + LibFactoryDiamond.DiamondStorage storage ds = LibFactoryDiamond + .diamondStorage(); owner_ = ds.contractOwner; } @@ -82,8 +61,12 @@ contract VaultFactoryDiamond { returndatacopy(0, 0, returndatasize()) // return any return value or error back to the caller switch result - case 0 { revert(0, returndatasize()) } - default { return(0, returndatasize()) } + case 0 { + revert(0, returndatasize()) + } + default { + return(0, returndatasize()) + } } } diff --git a/contracts/VaultFactory/facets/DiamondLoupeFactoryFacet.sol b/contracts/VaultFactory/facets/DiamondLoupeFactoryFacet.sol index d96cc48..f50ce3c 100644 --- a/contracts/VaultFactory/facets/DiamondLoupeFactoryFacet.sol +++ b/contracts/VaultFactory/facets/DiamondLoupeFactoryFacet.sol @@ -15,11 +15,6 @@ contract DiamondLoupeFactoryFacet is IDiamondLoupe, IERC165 { // Diamond Loupe Functions //////////////////////////////////////////////////////////////////// /// These functions are expected to be called frequently by tools. - // - // struct Facet { - // address facetAddress; - // bytes4[] functionSelectors; - // } /// @notice Gets all facets and their selectors. /// @return facets_ Facet diff --git a/contracts/VaultFactory/facets/ModuleRegistryFacet.sol b/contracts/VaultFactory/facets/ModuleRegistryFacet.sol index 6633668..689be3a 100644 --- a/contracts/VaultFactory/facets/ModuleRegistryFacet.sol +++ b/contracts/VaultFactory/facets/ModuleRegistryFacet.sol @@ -4,10 +4,33 @@ import {StorageLayout} from "../libraries/LibFactoryAppStorage.sol"; import {LibModuleRegistry} from "../libraries/LibModuleRegistry.sol"; import {IModuleData} from "../../interfaces/IModuleData.sol"; -contract ModuleRegistryFacet is StorageLayout{ +import {IDiamondCut} from "../../interfaces/IDiamondCut.sol"; +contract ModuleRegistryFacet is StorageLayout { + /// @notice add modules to the registry + /// @param _modules to be added + /// @param _names of modules + function addModules(IModuleData.ModuleData[] calldata _modules, string[] calldata _names) external { + LibModuleRegistry._addModules(_modules, _names); + } - function addModules(IModuleData.ModuleData[] calldata _modules, string[] calldata _names) external{ - LibModuleRegistry._addModules(_modules,_names); - } -} \ No newline at end of file + /// @notice returns the details multiple modules stored in the registry + function getModules(string[] calldata _names) external view returns (IModuleData.ModuleData[] memory modules_) { + modules_ = LibModuleRegistry._getModules(_names); + } + + /// @notice gets the details of a specific module from regigistry + function getModule(string calldata _name) external view returns (IModuleData.ModuleData memory module_) { + module_ = LibModuleRegistry._getModule(_name); + } + /// @dev returns the facet cuts attached to a module + + function getFacetCuts(string memory _name) external view returns (IDiamondCut.FacetCut[] memory cuts_) { + cuts_ = LibModuleRegistry._getFacetCuts(_name); + } + + /// Checks if a module extist, returns false if module is not found + function moduleExists(string calldata _name) external view returns (bool exists_) { + exists_ = LibModuleRegistry._moduleExists(_name); + } +} diff --git a/contracts/VaultFactory/facets/VaultSpawnerFacet.sol b/contracts/VaultFactory/facets/VaultSpawnerFacet.sol index 765bce7..9e62c2c 100644 --- a/contracts/VaultFactory/facets/VaultSpawnerFacet.sol +++ b/contracts/VaultFactory/facets/VaultSpawnerFacet.sol @@ -4,89 +4,36 @@ import "../../Vault/VaultDiamond.sol"; import "../../Vault/libraries/LibDMS.sol"; import "../../interfaces/IVaultDiamond.sol"; -import "../../interfaces/IDiamondCut.sol"; +import {IDiamondCut} from "../../interfaces/IDiamondCut.sol"; import "../../interfaces/IVaultFacet.sol"; +import {FactoryAppStorage, StorageLayout} from "../libraries/LibFactoryAppStorage.sol"; + contract VaultSpawnerFacet is StorageLayout { - event VaultCreated(address indexed owner, address indexed backup, uint256 indexed startingBalance, uint256 vaultID); + event VaultCreated(address indexed owner, uint256 indexed startingBalance, uint256 vaultID); error BackupAddressError(); - - function createVault( - address[] calldata _inheritors, - uint256[] calldata _weiShare, - uint256 _startingBal, - address _backupAddress - ) - external - payable - returns (address addr) - { - if (_backupAddress == msg.sender) { - revert BackupAddressError(); - } + + /// @notice creates vault attached with token and selector modules + /// @param _vaultOwner address to be set + /// @param _startingBal of the vault which must be sent in the same transaction + function createVault(address _vaultOwner, uint256 _startingBal) external payable returns (address addr) { if (_startingBal > 0) { assert(_startingBal == msg.value); } - assert(_inheritors.length == _weiShare.length); //spawn contract - bytes memory code = type(VaultDiamond).creationCode; - bytes32 entropy = keccak256(abi.encode(msg.sender, block.timestamp, fs.VAULTID)); - assembly { - addr := create2(0, add(code, 0x20), mload(code), entropy) - if iszero(extcodesize(addr)) { revert(0, 0) } - } - //init diamond with diamondCut facet - //insert a constant cut facet...modular and reusable across diamonds - IVaultDiamond(addr).init(fs.diamondCutFacet, _backupAddress); - //assert diamond owner - //confirm for EOA auth in same call frame - assert(IVaultDiamond(addr).tempOwner() == tx.origin); - //deposit startingBal - (bool success,) = addr.call{value: _startingBal}(""); - assert(success); - - //proceed to upgrade new diamond with default facets - IDiamondCut.FacetCut[] memory cut = new IDiamondCut.FacetCut[](6); - cut[0] = IDiamondCut.FacetCut({ - facetAddress: fs.erc20Facet, - action: IDiamondCut.FacetCutAction.Add, - functionSelectors: fs.ERC20SELECTORS - }); - cut[1] = IDiamondCut.FacetCut({ - facetAddress: fs.erc721Facet, - action: IDiamondCut.FacetCutAction.Add, - functionSelectors: fs.ERC721SELECTORS - }); - cut[2] = IDiamondCut.FacetCut({ - facetAddress: fs.erc1155Facet, - action: IDiamondCut.FacetCutAction.Add, - functionSelectors: fs.ERC1155SELECTORS - }); - cut[3] = IDiamondCut.FacetCut({ - facetAddress: fs.diamondLoupeFacet, - action: IDiamondCut.FacetCutAction.Add, - functionSelectors: fs.DIAMONDLOUPEFACETSELECTORS - }); - cut[4] = IDiamondCut.FacetCut({ - facetAddress: fs.vaultFacet, - action: IDiamondCut.FacetCutAction.Add, - functionSelectors: fs.VAULTFACETSELECTORS - }); - - cut[5] = IDiamondCut.FacetCut({ - facetAddress: fs.slotChecker, - action: IDiamondCut.FacetCutAction.Add, - functionSelectors: fs.SLOTCHECKERSELECTORS - }); - //upgrade - IDiamondCut(addr).diamondCut(cut, address(0), ""); - //add inheritors if any - if (_inheritors.length > 0) { - IVaultFacet(addr).addInheritors(_inheritors, _weiShare); - } - - emit VaultCreated(msg.sender, _backupAddress, _startingBal, fs.VAULTID); + bytes32 entropy = keccak256(abi.encode(_vaultOwner, fs.VAULTID)); + + //get Selector and Token Module FacetCuts + IDiamondCut.FacetCut[] storage selectorModuleCut = fs.masterModules["Selector"].facetData; + IDiamondCut.FacetCut[] storage tokenModuleCut = fs.masterModules["Token"].facetData; + + VaultDiamond vDiamond = new VaultDiamond{ + salt: entropy, + value: _startingBal + }(selectorModuleCut, tokenModuleCut, _vaultOwner); + addr = address(vDiamond); + emit VaultCreated(msg.sender, _startingBal, fs.VAULTID); fs.VAULTID++; } } diff --git a/contracts/VaultFactory/libraries/LibAppStorage.sol b/contracts/VaultFactory/libraries/LibAppStorage.sol deleted file mode 100644 index 3519c1a..0000000 --- a/contracts/VaultFactory/libraries/LibAppStorage.sol +++ /dev/null @@ -1,48 +0,0 @@ -pragma solidity 0.8.4; - -import "../../Vault/libraries/LibKeepHelpers.sol"; - -struct FactoryAppStorage { - //master vaultID - uint256 VAULTID; - //mapping(address=>uint[]) userVaults; - - //set during Master Diamond Deployment - //used to upgrade individual vaults - address diamondCutFacet; - address erc20Facet; - address erc721Facet; - address erc1155Facet; - address diamondLoupeFacet; - address vaultFacet; - address slotChecker; - - //facet selector data for spawned vaults - - bytes4[] ERC20SELECTORS; - bytes4[] ERC721SELECTORS; - bytes4[] ERC1155SELECTORS; - bytes4[] DIAMONDLOUPEFACETSELECTORS; - bytes4[] VAULTFACETSELECTORS; - bytes4[] SLOTCHECKERSELECTORS; -} - -library LibAppStorage { - function factoryAppStorage() internal pure returns (FactoryAppStorage storage fs) { - assembly { - fs.slot := 0 - } - } -} - -abstract contract StorageLayout { - FactoryAppStorage internal fs; - - // function removeArray(uint256 _val,address _inheritor) public { - // LibKeepHelpers.removeUint(fs.userVaults[_inheritor],_val); - // } - - // function addArray(uint256 _val,address _inheritor) public { - // LibKeepHelpers.removeUint(fs.userVaults[_inheritor],_val); - // } -} diff --git a/contracts/VaultFactory/libraries/LibFactoryAppStorage.sol b/contracts/VaultFactory/libraries/LibFactoryAppStorage.sol index e36b69a..75ffbec 100644 --- a/contracts/VaultFactory/libraries/LibFactoryAppStorage.sol +++ b/contracts/VaultFactory/libraries/LibFactoryAppStorage.sol @@ -2,11 +2,12 @@ pragma solidity 0.8.4; import "../../Vault/libraries/LibArrayHelpers.sol"; import {IModuleData} from "../../interfaces/IModuleData.sol"; + struct FactoryAppStorage { //master vaultID uint256 VAULTID; //human readable names to Module data - mapping(string=>IModuleData.ModuleData) masterModules; + mapping(string => IModuleData.ModuleData) masterModules; } library LibFactoryAppStorage { diff --git a/contracts/VaultFactory/libraries/LibFactoryDiamond.sol b/contracts/VaultFactory/libraries/LibFactoryDiamond.sol index 9204a56..8b51751 100644 --- a/contracts/VaultFactory/libraries/LibFactoryDiamond.sol +++ b/contracts/VaultFactory/libraries/LibFactoryDiamond.sol @@ -49,6 +49,7 @@ library LibFactoryDiamond { address contractOwner; } + /// @notice sets the slot where diamond is stored function diamondStorage() internal pure returns (DiamondStorage storage ds) { bytes32 position = DIAMOND_STORAGE_POSITION; assembly { @@ -58,6 +59,7 @@ library LibFactoryDiamond { event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + /// @notice sets address as the conttact owner function setContractOwner(address _newOwner) internal { DiamondStorage storage ds = diamondStorage(); address previousOwner = ds.contractOwner; @@ -65,10 +67,12 @@ library LibFactoryDiamond { emit OwnershipTransferred(previousOwner, _newOwner); } + /// @notice returns the address of current contract owner function contractOwner() internal view returns (address contractOwner_) { contractOwner_ = diamondStorage().contractOwner; } + /// @notice ensures that calller is contract owner function enforceIsContractOwner() internal view { if (msg.sender != diamondStorage().contractOwner) revert NotDiamondOwner(); } @@ -76,6 +80,12 @@ library LibFactoryDiamond { event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata); // Internal function version of diamondCut + + /// @notice Add/replace/remove any number of functions + /// @param _diamondCut Contains the facet addresses and function selectors + /// @param _init The address of the contract or facet to execute _calldata + /// @param _calldata A function call, including function selector and arguments + function diamondCut( IDiamondCut.FacetCut[] memory _diamondCut, address _init, @@ -97,6 +107,9 @@ library LibFactoryDiamond { initializeDiamondCut(_init, _calldata); } + /// @notice adds new functions to a facet + /// @param _facetAddress facet where the function will be added + /// @param _functionSelectors arrays of functions to be added function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal { if (_functionSelectors.length <= 0) revert NoSelectorsInFacet(); DiamondStorage storage ds = diamondStorage(); @@ -114,7 +127,7 @@ library LibFactoryDiamond { selectorPosition++; } } - + /// @notice replaces functions in a selected facet function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal { if (_functionSelectors.length <= 0) revert NoSelectorsInFacet(); DiamondStorage storage ds = diamondStorage(); @@ -134,6 +147,7 @@ library LibFactoryDiamond { } } + /// @notice removes functions from a facet function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal { if (_functionSelectors.length <= 0) revert NoSelectorsInFacet(); DiamondStorage storage ds = diamondStorage(); @@ -146,12 +160,16 @@ library LibFactoryDiamond { } } + /// @notice add facet to diamond function addFacet(DiamondStorage storage ds, address _facetAddress) internal { enforceHasContractCode(_facetAddress); ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds.facetAddresses.length; ds.facetAddresses.push(_facetAddress); } + /// @dev adds a functions to a selected facet + /// @param _selector of the functions to be added + /// _facetAddress of the function function addFunction( DiamondStorage storage ds, bytes4 _selector, @@ -163,6 +181,7 @@ library LibFactoryDiamond { ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress; } + /// @notice removes a function from a a facet function removeFunction( DiamondStorage storage ds, address _facetAddress, @@ -199,6 +218,7 @@ library LibFactoryDiamond { } } + /// initilize diamond cut with associated calldata function initializeDiamondCut(address _init, bytes memory _calldata) internal { if (_init == address(0)) { if (_calldata.length > 0) revert NonEmptyCalldata(); @@ -218,7 +238,7 @@ library LibFactoryDiamond { } } } - + /// @notice ensures that address is a contract type function enforceHasContractCode(address _contract) internal view { uint256 contractSize; assembly { diff --git a/contracts/VaultFactory/libraries/LibModuleRegistry.sol b/contracts/VaultFactory/libraries/LibModuleRegistry.sol index 340ed48..1c10f6e 100644 --- a/contracts/VaultFactory/libraries/LibModuleRegistry.sol +++ b/contracts/VaultFactory/libraries/LibModuleRegistry.sol @@ -1,18 +1,21 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.4; -import "../../interfaces/IDiamondCut.sol"; +import {IDiamondCut} from "../../interfaces/IDiamondCut.sol"; import "../../Vault/libraries/LibStorageBinder.sol"; import {LibFactoryDiamond} from "./LibFactoryDiamond.sol"; import {FactoryAppStorage, LibFactoryAppStorage} from "./LibFactoryAppStorage.sol"; import {IModuleData} from "../../interfaces/IModuleData.sol"; error ModuleExists(string moduleName); +error NonExistentModule(string moduleName); - library LibModuleRegistry { - event ModuleAdded(string indexed _name,IModuleData.ModuleData _module); + event ModuleAdded(string indexed _name, IModuleData.ModuleData _module); + //allow Proxy Factory admin(multisig) to add modules to Module Registry + /// @param _modules data to be registered + /// @param _names of modules to be regustered function _addModules(IModuleData.ModuleData[] calldata _modules, string[] calldata _names) internal { assert(_modules.length == _names.length); LibFactoryDiamond.enforceIsContractOwner(); @@ -25,5 +28,38 @@ library LibModuleRegistry { emit ModuleAdded(_names[i], _modules[i]); } } - //to-do _removeModules + //TODO: _removeModules + + /// @notice get the details of modules + function _getModules(string[] memory _names) internal view returns (IModuleData.ModuleData[] memory modules_) { + modules_ = new IModuleData.ModuleData[](_names.length); + for (uint256 i = 0; i < _names.length; i++) { + modules_[i] = _getModule(_names[i]); + } + } + + /// @notice checks for details of a specific module + /// reverrts if module does not exist + function _getModule(string memory _name) internal view returns (IModuleData.ModuleData memory module_) { + FactoryAppStorage storage fs = LibFactoryAppStorage.factoryAppStorage(); + IModuleData.ModuleData storage m = fs.masterModules[_name]; + if (m.facetData.length == 0) revert NonExistentModule(_name); + module_ = m; + } + + /// @notice returns the facet cuts attached to a module + /// reverts if module parsed in with _name does not exist + function _getFacetCuts(string memory _name) internal view returns (IDiamondCut.FacetCut[] memory cuts_) { + FactoryAppStorage storage fs = LibFactoryAppStorage.factoryAppStorage(); + IModuleData.ModuleData storage m = fs.masterModules[_name]; + if (m.facetData.length == 0) revert NonExistentModule(_name); + cuts_ = fs.masterModules[_name].facetData; + } + + /// @notice checks if a module exist, returns false if its not available + function _moduleExists(string memory _name) internal view returns (bool exists_) { + FactoryAppStorage storage fs = LibFactoryAppStorage.factoryAppStorage(); + IModuleData.ModuleData storage m = fs.masterModules[_name]; + if (m.facetData.length > 0) exists_ = true; + } } diff --git a/contracts/VaultFactory/libraries/LibModuleUpgrades.sol b/contracts/VaultFactory/libraries/LibModuleUpgrades.sol deleted file mode 100644 index 8e4118a..0000000 --- a/contracts/VaultFactory/libraries/LibModuleUpgrades.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.4; - -import {IDiamondCut} from "../../interfaces/IDiamondCut.sol"; -import {LibStorageBinder} from "../../Vault/libraries/LibStorageBinder.sol"; -//import {LibLayoutSilo} from "../../Vault/libraries/LibLayoutSilo.sol"; -import {LibFactoryDiamond} from "./LibFactoryDiamond.sol"; -import {FactoryAppStorage, LibFactoryAppStorage} from "./LibFactoryAppStorage.sol"; -import {IModuleData} from "../../interfaces/IModuleData.sol"; - -error NonExistentModule(); -error ModuleAlreadyAdded(); -error ModuleAlreadyRemoved(); -//basically allows vault owners to make atomic module upgrades to their vaults - -library LibModuleUpgrades { - event VaultUpgraded(address _vault, string indexed _moduleName); - event VaultDowngraded(address _vault, string indexed _moduleName); - - function _upgradeVaultWithModule(string calldata _name, address _vault) internal { - //first make sure this module exists in the onchain registry - FactoryAppStorage storage fs = LibFactoryAppStorage.factoryAppStorage(); - if (fs.masterModules[_name].facetData.length == 0) revert NonExistentModule(); - //make sure this module hasn't been added to the vault before - if (IModuleData(_vault).isActiveModule(_name)) revert ModuleAlreadyAdded(); - //get module details - IModuleData.ModuleData storage moduleData = fs.masterModules[_name]; - IDiamondCut.FacetCut[] storage facetCut = moduleData.facetData; - //upgrade vault - IDiamondCut(_vault).diamondCut(facetCut, address(0), ""); - emit VaultUpgraded(_vault, _name); - } - - function _downgradeVaultWithModule(string calldata _name, address _vault) internal { - //first make sure this module exists in the onchain registry - FactoryAppStorage storage fs = LibFactoryAppStorage.factoryAppStorage(); - if (fs.masterModules[_name].facetData.length == 0) revert NonExistentModule(); - //make sure this module has been added to the vault before - if (!IModuleData(_vault).isActiveModule(_name)) revert ModuleAlreadyRemoved(); - //get module details - IModuleData.ModuleData storage moduleData = fs.masterModules[_name]; - IDiamondCut.FacetCut[] storage facetCut = moduleData.facetData; - //remove them - for (uint256 i = 0; i < facetCut.length; i++) { - facetCut[i].action = IDiamondCut.FacetCutAction.Remove; - } - //downgrade vault - IDiamondCut(_vault).diamondCut(facetCut, address(0), ""); - emit VaultDowngraded(_vault, _name); - } -} diff --git a/contracts/interfaces/IDiamondCut.sol b/contracts/interfaces/IDiamondCut.sol index 2972f69..c83cfce 100644 --- a/contracts/interfaces/IDiamondCut.sol +++ b/contracts/interfaces/IDiamondCut.sol @@ -1,13 +1,19 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -/******************************************************************************\ -* Author: Nick Mudge (https://twitter.com/mudgen) -* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 -/******************************************************************************/ +/** + * \ + * Author: Nick Mudge + * EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 + * /***************************************************************************** + */ interface IDiamondCut { - enum FacetCutAction {Add, Replace, Remove} + enum FacetCutAction { + Add, + Replace, + Remove + } // Add=0, Replace=1, Remove=2 struct FacetCut { @@ -22,11 +28,7 @@ interface IDiamondCut { /// @param _init The address of the contract or facet to execute _calldata /// @param _calldata A function call, including function selector and arguments /// _calldata is executed with delegatecall on _init - function diamondCut( - FacetCut[] calldata _diamondCut, - address _init, - bytes calldata _calldata - ) external; + function diamondCut(FacetCut[] calldata _diamondCut, address _init, bytes calldata _calldata) external; event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata); } diff --git a/contracts/interfaces/IDiamondLoupe.sol b/contracts/interfaces/IDiamondLoupe.sol index c3b2570..1d9bc46 100644 --- a/contracts/interfaces/IDiamondLoupe.sol +++ b/contracts/interfaces/IDiamondLoupe.sol @@ -1,10 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -/******************************************************************************\ -* Author: Nick Mudge (https://twitter.com/mudgen) -* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 -/******************************************************************************/ +/** + * \ + * Author: Nick Mudge + * EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 + * /***************************************************************************** + */ // A loupe is a small magnifying glass used to look at diamonds. // These functions look at diamonds diff --git a/contracts/interfaces/IERC1155.sol b/contracts/interfaces/IERC1155.sol index 8e49ec5..1920cc1 100644 --- a/contracts/interfaces/IERC1155.sol +++ b/contracts/interfaces/IERC1155.sol @@ -1,26 +1,35 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.4; + interface IERC1155 { - - event TransferSingle(address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value); - event TransferBatch(address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values); + event TransferSingle( + address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value + ); + event TransferBatch( + address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values + ); - event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); - event URI(string _value, uint256 indexed _id); - function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external; - function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external; + function safeBatchTransferFrom( + address _from, + address _to, + uint256[] calldata _ids, + uint256[] calldata _values, + bytes calldata _data + ) external; function balanceOf(address _owner, uint256 _id) external view returns (uint256); - function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory); + function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) + external + view + returns (uint256[] memory); function setApprovalForAll(address _operator, bool _approved) external; - function isApprovedForAll(address _owner, address _operator) external view returns (bool); -} \ No newline at end of file +} diff --git a/contracts/interfaces/IERC721.sol b/contracts/interfaces/IERC721.sol index d30ce0d..a52d908 100644 --- a/contracts/interfaces/IERC721.sol +++ b/contracts/interfaces/IERC721.sol @@ -1,40 +1,21 @@ pragma solidity 0.8.4; -interface IERC721{ -function balanceOf(address owner) external view returns (uint256 balance); - - function ownerOf(uint256 tokenId) external view returns (address owner); - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes calldata data - ) external; - - function safeTransferFrom( - address from, - address to, - uint256 tokenId - ) external; - - function transferFrom( - address from, - address to, - uint256 tokenId - ) external; - - function approve(address to, uint256 tokenId) external; - - function setApprovalForAll(address operator, bool _approved) external; - - function getApproved(uint256 tokenId) - external - view - returns (address operator); - - function isApprovedForAll(address owner, address operator) - external - view - returns (bool); -} \ No newline at end of file +interface IERC721 { + function balanceOf(address owner) external view returns (uint256 balance); + + function ownerOf(uint256 tokenId) external view returns (address owner); + + function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; + + function safeTransferFrom(address from, address to, uint256 tokenId) external; + + function transferFrom(address from, address to, uint256 tokenId) external; + + function approve(address to, uint256 tokenId) external; + + function setApprovalForAll(address operator, bool _approved) external; + + function getApproved(uint256 tokenId) external view returns (address operator); + + function isApprovedForAll(address owner, address operator) external view returns (bool); +} diff --git a/contracts/interfaces/IModuleData.sol b/contracts/interfaces/IModuleData.sol index 15df21c..74fecb5 100644 --- a/contracts/interfaces/IModuleData.sol +++ b/contracts/interfaces/IModuleData.sol @@ -12,11 +12,12 @@ interface IModuleData { //storage location bytes32 slot; //keccak hash of facets involved - bytes32 fileHash; + uint256 timeAdded; //human readable names of facets involved in alphabetical order string[] facetNames; } - + /// @notice returns acive modules in a vault function getActiveModules() external view returns (string[] memory); + /// @notice checks for the status of a module function isActiveModule(string memory _name) external view returns (bool exists_); } diff --git a/contracts/interfaces/IVaultDiamond.sol b/contracts/interfaces/IVaultDiamond.sol index 288be9b..685cc69 100644 --- a/contracts/interfaces/IVaultDiamond.sol +++ b/contracts/interfaces/IVaultDiamond.sol @@ -1,10 +1,10 @@ pragma solidity 0.8.4; +import "../interfaces/IModuleData.sol"; + interface IVaultDiamond { - function init(address _diamondCutFacet, address _backupAddress) external; + function vaultFactoryDiamond() external view returns (address); //via delegatecall on diamond function vaultOwner() external view returns (address); - - function tempOwner() external view returns (address owner_); } diff --git a/contracts/interfaces/IVaultFacet.sol b/contracts/interfaces/IVaultFacet.sol index 1d7dacd..26ce71d 100644 --- a/contracts/interfaces/IVaultFacet.sol +++ b/contracts/interfaces/IVaultFacet.sol @@ -20,9 +20,10 @@ interface IVaultFacet { ); event EthDeposited(uint256 _amount, uint256 _vaultID); - + // adda inheritors and weishares to a vault function addInheritors(address[] calldata _newInheritors, uint256[] calldata _weiShare) external; - + // sets a new backup address function transferBackup(address _newBackupAddress) external; + /// @notice returns allocated ether in a a vault function allEtherAllocations() external view returns (AllInheritorEtherAllocs[] memory eAllocs); } diff --git a/contracts/interfaces/IVaultFactory.sol b/contracts/interfaces/IVaultFactory.sol new file mode 100644 index 0000000..7d29a80 --- /dev/null +++ b/contracts/interfaces/IVaultFactory.sol @@ -0,0 +1,22 @@ +pragma solidity 0.8.4; + +import {IModuleData} from "../interfaces/IModuleData.sol"; +import {IDiamondCut} from "../interfaces/IDiamondCut.sol"; + +interface IVaultFactory { + /// @notice This is used to get the details of several modules + /// @param _names the name of the modules to be fetched + function getModules(string[] memory _names) external view returns (IModuleData.ModuleData[] memory modules_); + + /// @notice used to get the details of a a single module + /// @param _name of the module + function getModule(string calldata _name) external view returns (IModuleData.ModuleData memory module_); + + /// @notice checks if a module exists + /// @param _name the name of the module to be checked + function moduleExists(string calldata _name) external view returns (bool exists_); + + /// @notice return the cuts associated with a facet + /// @param _name of a facet + function getFacetCuts(string memory _name) external view returns (IDiamondCut.FacetCut[] memory cuts_); +} diff --git a/foundry.toml b/foundry.toml index 876bcef..7a36d1c 100644 --- a/foundry.toml +++ b/foundry.toml @@ -8,6 +8,9 @@ remappings = [ 'eth-gas-reporter/=node_modules/eth-gas-reporter/', 'hardhat/=node_modules/hardhat/', ] +via_ir = false verbosity= 5 ffi=true +optimizer = true +optimizer_runs = 200 # See more config options https://github.com/foundry-rs/foundry/tree/master/config \ No newline at end of file diff --git a/lib/solmate.git b/lib/solmate.git index d155ee8..352e1e9 160000 --- a/lib/solmate.git +++ b/lib/solmate.git @@ -1 +1 @@ -Subproject commit d155ee8d58f96426f57c015b34dee8a410c1eacc +Subproject commit 352e1e91e9deec9f3961a8abc49dab89d560cfe3 diff --git a/test/DMSFacetTests.t.sol b/test/DMSFacetTests.t.sol new file mode 100644 index 0000000..c94281c --- /dev/null +++ b/test/DMSFacetTests.t.sol @@ -0,0 +1,102 @@ +import "./DiamondDeployments.sol"; + +import "../contracts/Vault/libraries/LibDMS.sol"; + +contract DMSFacetTest is DDeployments { + function testDMSOperations() public { + address depositor1 = mkaddr("depositor1"); + //mint some tokens to depositor1 + vm.startPrank(depositor1); + //mint and deposit all token types + erc1155t.mint(depositor1, 0, 2); + erc20t.mint(depositor1, 100e18); + erc721t.mint(depositor1, 0); + + //approve + erc1155t.setApprovalForAll(vault1, true); + erc20t.approve(vault1, 10000e18); + erc721t.setApprovalForAll(vault1, true); + + //deposit + v1ERC20Facet.depositERC20Tokens(toSingletonAdd(address(erc20t)), toSingletonUINT(100e18)); + + v1ERC721Facet.depositERC721Tokens(address(erc721t), toSingletonUINT(0)); + + v1ERC1155Facet.batchDepositERC1155Tokens(address(erc1155t), toSingletonUINT(0), toSingletonUINT(2)); + + vm.stopPrank(); + + vm.startPrank(vault1Owner); + //test inheritor addition and removal + //add another inheritor + v1dmsFacet.addInheritors(toSingletonAdd(vault1Inheritor2), toSingletonUINT(1000 wei)); + + DMSFacet.VaultInfo memory vInfo = v1dmsFacet.inspectVault(); + assertEq(vInfo.inheritors.length, 2); + + //cannot remove a non existent inheritor + vm.expectRevert(LibDMS.NotInheritor.selector); + v1dmsFacet.removeInheritors(toSingletonAdd(mkaddr("non-existent"))); + + //allocate some erc20,erc721 and erc1155 tokens to an inheritor + //erc20 + v1dmsFacet.allocateERC20Tokens(address(erc20t), toSingletonAdd(vault1Inheritor1), toSingletonUINT(100e18)); + + // //erc721 + v1dmsFacet.allocateERC721Tokens(address(erc721t), toSingletonAdd(vault1Inheritor1), toSingletonUINT(0)); + + // //erc1155 + v1dmsFacet.allocateERC1155Tokens( + address(erc1155t), toSingletonAdd(vault1Inheritor1), toSingletonUINT(0), toSingletonUINT(2) + ); + + // //confirm allocations + v1dmsFacet.getAllAllocatedERC1155Tokens(vault1Inheritor1); + v1dmsFacet.getAllocatedERC20Tokens(vault1Inheritor1); + v1dmsFacet.getAllocatedERC721Tokens(vault1Inheritor1); + + v1dmsFacet.removeInheritors(toSingletonAdd(vault1Inheritor1)); + + //re-confirm allocations + assertEq(v1dmsFacet.getAllAllocatedERC1155Tokens(vault1Inheritor1).length, 0); + assertEq(v1dmsFacet.getAllocatedERC20Tokens(vault1Inheritor1).length, 0); + assertEq(v1dmsFacet.getAllocatedERC721Tokens(vault1Inheritor1).length, 0); + + vInfo = v1dmsFacet.inspectVault(); + assertEq(vInfo.inheritors.length, 1); + + // //TESTS FOR OWNERSHIP TRANSFER AND BACKUP + address newVault1Owner = mkaddr("NewVault1Owner"); + //transfer ownership to another address + v1dmsFacet.transferOwnership(newVault1Owner); + address newOwner = ownerFacet.owner(); + assertEq(newOwner, newVault1Owner); + vm.stopPrank(); + vm.startPrank(newVault1Owner); + + // //add inheritor1 again and allocate + v1dmsFacet.addInheritors(toSingletonAdd(vault1Inheritor1), toSingletonUINT(10000000 wei)); + + // //erc20 + v1dmsFacet.allocateERC20Tokens(address(erc20t), toSingletonAdd(vault1Inheritor1), toSingletonUINT(100e18)); + + // //erc721 + v1dmsFacet.allocateERC721Tokens(address(erc721t), toSingletonAdd(vault1Inheritor1), toSingletonUINT(0)); + + // //erc1155 + v1dmsFacet.allocateERC1155Tokens( + address(erc1155t), toSingletonAdd(vault1Inheritor1), toSingletonUINT(0), toSingletonUINT(2) + ); + + vm.stopPrank(); + + // //attempt to claim + vm.warp(block.timestamp + 190 days); + vm.prank(vault1Inheritor1); + v1dmsFacet.claimAllAllocations(); + // //ALSO TEST BACKUP-OWNER RECLAMATION HERE + // vm.prank(vault1Backup); + // v1dmsFacet.claimOwnership(mkaddr("newBackup")); + //There should be a timelock after reclamation before a backup can make vault changes + } +} diff --git a/test/DiamondDeployments.sol b/test/DiamondDeployments.sol index 0e54962..3fef3f6 100644 --- a/test/DiamondDeployments.sol +++ b/test/DiamondDeployments.sol @@ -1,188 +1,266 @@ - // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.4; import "forge-std/Test.sol"; +import {IModuleData} from "../contracts/interfaces/IModuleData.sol"; + import "../contracts/Vault/facets/ERC1155Facet.sol"; import "../contracts/Vault/facets/ERC20Facet.sol"; import "../contracts/Vault/facets/ERC721Facet.sol"; +import "../contracts/Vault/facets/EtherFacet.sol"; +import "../contracts/Vault/facets/OwnershipFacet.sol"; + +import "../contracts/Vault/facets/ModuleManagerFacet.sol"; + import "../contracts/Vault/facets/DiamondCutFacet.sol"; import "../contracts/Vault/facets/DiamondLoupeFacet.sol"; -import "../contracts/Vault/facets/VaultFacet.sol"; +import "../contracts/Vault/facets/DMSFacet.sol"; import "../contracts/VaultFactory/facets/VaultSpawnerFacet.sol"; +import "../contracts/VaultFactory/facets/ModuleRegistryFacet.sol"; + import "../contracts/VaultFactory/facets/DiamondCutFactoryFacet.sol"; import "../contracts/VaultFactory/facets/DiamondLoupeFactoryFacet.sol"; import "../contracts/Vault/VaultDiamond.sol"; import "../contracts/VaultFactory/VaultFactoryDiamond.sol"; -import "../contracts/Vault/facets/SlotChecker.sol"; -//import "../contracts/Vault/facets/DiamondCutFacet.sol"; -//import "../contracts/Vault/facets/DiamondLoupeFacet.sol"; +import {ModuleAlreadyInstalled} from "../contracts/Vault/libraries/LibModuleUpgrades.sol"; import "./MockERC1155.sol"; - import "./MockERC20.sol"; - import "./MockERC721.sol"; - - -contract DDeployments is Test,IDiamondCut { -//separate script to deploy all diamonds and expose them for interaction - - - -ERC1155Facet erc1155Facet; -ERC721Facet erc721Facet; -ERC20Facet erc20Facet; -VaultSpawnerFacet spawner; -VaultFacet vFacet; -//VaultDiamond VDiamond; -VaultFactoryDiamond vFactoryDiamond; -DiamondCutFacet dCutFacet; -DiamondLoupeFacet dLoupeFacet; -SlotChecker sChecker; - -DiamondCutFactoryFacet dCutFactoryFacet; -DiamondLoupeFactoryFacet dloupeFactoryFacet; - -//2 instances of eachMocktoken -VaultERC1155Token erc1155t; -VaultERC20Token erc20t; -VaultERC721Token erc721t; - -VaultERC1155Token erc1155t2; -VaultERC20Token erc20t2; -VaultERC721Token erc721t2; - -address vault1; -address vault1Inheritor1; -address vault1Inheritor2; -address vault1Owner; -address vault1Backup; - -//Facet types tied to vaultAddresses -ERC20Facet v1ERC20Facet; -ERC721Facet v1ERC721Facet; -ERC1155Facet v1ERC1155Facet; -VaultFacet v1VaultFacet; - -function setUp() public{ - //deploy Vault facets -erc1155Facet=new ERC1155Facet(); -erc721Facet=new ERC721Facet(); -erc20Facet=new ERC20Facet(); -vFacet=new VaultFacet(); -dCutFacet=new DiamondCutFacet(); -dLoupeFacet=new DiamondLoupeFacet(); - -//just a periphery -sChecker=new SlotChecker(); - -//deploy factory facets -spawner=new VaultSpawnerFacet(); -dCutFactoryFacet=new DiamondCutFactoryFacet(); -dloupeFactoryFacet=new DiamondLoupeFactoryFacet(); -vm.label(address(this),"Factory Lord"); -vFactoryDiamond=new VaultFactoryDiamond(address(this),address(dCutFactoryFacet)); - -//deploy mock tokens -erc1155t=new VaultERC1155Token(); -erc20t=new VaultERC20Token(); -erc721t=new VaultERC721Token(); - -erc1155t2=new VaultERC1155Token(); -erc20t2=new VaultERC20Token(); -erc721t2=new VaultERC721Token(); - - -//upgrade factory diamond -IDiamondCut.FacetCut[] memory cut = new IDiamondCut.FacetCut[](2); - cut[0] = IDiamondCut.FacetCut({ - facetAddress: address(spawner), - action: IDiamondCut.FacetCutAction.Add, - functionSelectors: generateSelectors("VaultSpawnerFacet") - }); - cut[1] = IDiamondCut.FacetCut({ - facetAddress: address(dloupeFactoryFacet), - action: IDiamondCut.FacetCutAction.Add, - functionSelectors: generateSelectors("DiamondLoupeFactoryFacet") - }); - IDiamondCut(address(vFactoryDiamond)).diamondCut(cut, address(0), ""); - - //add facet addresses and selectors to Appstorage - address[] memory vaultFacetAddresses=new address[](7); - vaultFacetAddresses[0]=address(dCutFacet); - vaultFacetAddresses[1]=address(erc20Facet); - vaultFacetAddresses[2]=address(erc721Facet); - vaultFacetAddresses[3]=address(erc1155Facet); - vaultFacetAddresses[4]=address(dLoupeFacet); - vaultFacetAddresses[5]=address(vFacet); - vaultFacetAddresses[6]=address(sChecker); - - vFactoryDiamond.setAddresses(vaultFacetAddresses); - - //set selectors - bytes4[][] memory _selectors=new bytes4[][](6); -_selectors[0]=generateSelectors("ERC20Facet"); -_selectors[1]=generateSelectors("ERC721Facet"); -_selectors[2]=generateSelectors("ERC1155Facet"); -_selectors[3]=generateSelectors("DiamondLoupeFacet"); -_selectors[4]=generateSelectors("VaultFacet"); -_selectors[5]=generateSelectors("SlotChecker"); -vFactoryDiamond.setSelectors(_selectors); - -//create a vault -vault1Inheritor1=mkaddr("inheritor1"); -vault1Inheritor2=mkaddr("vault1Inheritor2"); -vault1Owner=mkaddr("vault1Owner"); -//make sure vault1Owner is tx.origin -vm.prank(address(this),vault1Owner); -vault1Backup=mkaddr("lucky guy"); -vault1=VaultSpawnerFacet(address(vFactoryDiamond)).createVault{value: 1 ether}(toSingletonAdd(vault1Inheritor1),toSingletonUINT(10000),1e18,vault1Backup); - -//export contract types - v1ERC20Facet=ERC20Facet(vault1); - v1ERC721Facet=ERC721Facet(vault1); - v1ERC1155Facet=ERC1155Facet(vault1); - v1VaultFacet=VaultFacet(vault1); - - -//do slot checks -bytes32 i=SlotChecker(vault1).getFacetStorageSlot(); -bytes32 j=SlotChecker(vault1).InterFaceStorageSlot(); -bytes32 k=SlotChecker(vault1).vaultStorageSlot(); -assert(uint256(i)!=uint256(j)); -assert(uint256(k)!=uint256(j)); -assert(uint256(i)!=uint256(k)); - -//check ranges - -unchecked { -assert(stdMath.delta(uint256(i),uint256(j))>100_000); -assert(stdMath.delta(uint256(i),uint256(k))>100_000); -assert(stdMath.delta(uint256(j),uint256(k))>100_000); -//log them out -console.log(stdMath.delta(uint256(i),uint256(j))); -console.log(stdMath.delta(uint256(i),uint256(k))); -console.log(stdMath.delta(uint256(j),uint256(k))); -} - - - -//erc20t.approve(vault1,10000000000000); -// //run a function on the new vault +import "./MockERC20.sol"; +import "./MockERC721.sol"; + +import {IModuleData} from "../contracts/interfaces/IModuleData.sol"; + +contract DDeployments is Test { + //Vault facet Addresss + ERC1155Facet erc1155Facet; + ERC721Facet erc721Facet; + ERC20Facet erc20Facet; + EtherFacet etherFacet; + OwnershipFacet ownerFacet; + // VaultFacet vFacet; + DMSFacet switchFacet; + + //UpgradeVault facet + ModuleManagerFacet managerFacet; + // UpgradeFacetWithModule VUpgraderFacet; + + //Diamond script + DiamondCutFacet dCutFacet; + DiamondLoupeFacet dLoupeFacet; + + //factory + VaultSpawnerFacet spawner; + ModuleRegistryFacet registry; + // ModuleUpgraderFacet FUpgradeFacet; + VaultFactoryDiamond vFactoryDiamond; + + DiamondCutFactoryFacet dCutFactoryFacet; + DiamondLoupeFactoryFacet dloupeFactoryFacet; + + //2 instances of eachMocktoken + VaultERC1155Token erc1155t; + VaultERC20Token erc20t; + VaultERC721Token erc721t; + + VaultERC1155Token erc1155t2; + VaultERC20Token erc20t2; + VaultERC721Token erc721t2; + + address vault1; + address vault1Owner; + address vault1Inheritor1; + address vault1Inheritor2; + + //Facet types tied to vaultAddresses + ERC20Facet v1ERC20Facet; + ERC721Facet v1ERC721Facet; + ERC1155Facet v1ERC1155Facet; + EtherFacet v1EtherFacet; + DMSFacet v1dmsFacet; + + function setUp() public { + //deploy mock tokens + erc1155t = new VaultERC1155Token(); + erc20t = new VaultERC20Token(); + erc721t = new VaultERC721Token(); + + //second tokens + erc1155t2 = new VaultERC1155Token(); + erc20t2 = new VaultERC20Token(); + erc721t2 = new VaultERC721Token(); + + //deploy Vault Token facets + erc1155Facet = new ERC1155Facet(); + erc721Facet = new ERC721Facet(); + erc20Facet = new ERC20Facet(); + etherFacet = new EtherFacet(); + switchFacet = new DMSFacet(); + + //selector facet + dCutFacet = new DiamondCutFacet(); + dLoupeFacet = new DiamondLoupeFacet(); + ownerFacet = new OwnershipFacet(); + managerFacet = new ModuleManagerFacet(); + + //deploy factory facets + spawner = new VaultSpawnerFacet(); + registry = new ModuleRegistryFacet(); + dCutFactoryFacet = new DiamondCutFactoryFacet(); + dloupeFactoryFacet = new DiamondLoupeFactoryFacet(); + vm.label(address(this), "Factory Lord"); + vFactoryDiamond = new VaultFactoryDiamond( + address(this), + address(dCutFactoryFacet) + ); + + //upgrade factory diamond + IDiamondCut.FacetCut[] memory cut = new IDiamondCut.FacetCut[](3); + cut[0] = IDiamondCut.FacetCut({ + facetAddress: address(spawner), + action: IDiamondCut.FacetCutAction.Add, + functionSelectors: generateSelectors("VaultSpawnerFacet") + }); + cut[1] = IDiamondCut.FacetCut({ + facetAddress: address(dloupeFactoryFacet), + action: IDiamondCut.FacetCutAction.Add, + functionSelectors: generateSelectors("DiamondLoupeFactoryFacet") + }); + + cut[2] = IDiamondCut.FacetCut({ + facetAddress: address(registry), + action: IDiamondCut.FacetCutAction.Add, + functionSelectors: generateSelectors("ModuleRegistryFacet") + }); + IDiamondCut(address(vFactoryDiamond)).diamondCut(cut, address(0), ""); + + //upgrade Selector Module Vault diamond + + IDiamondCut.FacetCut[] memory selectorCut = new IDiamondCut.FacetCut[]( + 4 + ); + selectorCut[0] = IDiamondCut.FacetCut({ + facetAddress: address(dCutFacet), + action: IDiamondCut.FacetCutAction.Add, + functionSelectors: generateSelectors("DiamondCutFacet") + }); + selectorCut[1] = IDiamondCut.FacetCut({ + facetAddress: address(dLoupeFacet), + action: IDiamondCut.FacetCutAction.Add, + functionSelectors: generateSelectors("DiamondLoupeFacet") + }); + + selectorCut[2] = IDiamondCut.FacetCut({ + facetAddress: address(ownerFacet), + action: IDiamondCut.FacetCutAction.Add, + functionSelectors: generateSelectors("OwnershipFacet") + }); + selectorCut[3] = IDiamondCut.FacetCut({ + facetAddress: address(managerFacet), + action: IDiamondCut.FacetCutAction.Add, + functionSelectors: generateSelectors("ModuleManagerFacet") + }); + + //upgrade Token Module Vault diamond + + IDiamondCut.FacetCut[] memory TokenCut = new IDiamondCut.FacetCut[](4); + + TokenCut[0] = IDiamondCut.FacetCut({ + facetAddress: address(erc20Facet), + action: IDiamondCut.FacetCutAction.Add, + functionSelectors: generateSelectors("ERC20Facet") + }); + TokenCut[1] = IDiamondCut.FacetCut({ + facetAddress: address(erc721Facet), + action: IDiamondCut.FacetCutAction.Add, + functionSelectors: generateSelectors("ERC721Facet") + }); + + TokenCut[2] = IDiamondCut.FacetCut({ + facetAddress: address(erc1155Facet), + action: IDiamondCut.FacetCutAction.Add, + functionSelectors: generateSelectors("ERC1155Facet") + }); + + TokenCut[3] = IDiamondCut.FacetCut({ + facetAddress: address(etherFacet), + action: IDiamondCut.FacetCutAction.Add, + functionSelectors: generateSelectors("EtherFacet") + }); + + IModuleData.ModuleData[] memory data = new IModuleData.ModuleData[](2); + data[0].facetData = selectorCut; + data[1].facetData = TokenCut; + + string[] memory selectorName = new string[](2); + selectorName[0] = "Selector"; + selectorName[1] = "Token"; + //Register Selector and Token Modules in Factory + ModuleRegistryFacet(address(vFactoryDiamond)).addModules(data, selectorName); + + vault1Owner = mkaddr("vault1Owner"); + vault1Inheritor1 = mkaddr("vault1Inheritor1"); + vault1Inheritor2 = mkaddr("vault1Inheritor2"); + + //make sure vault1Owner is tx.origin + vm.prank(address(this), vault1Owner); + vault1 = VaultSpawnerFacet(address(vFactoryDiamond)).createVault{value: 1 ether}(vault1Owner, 1e18); + + //Register DMS Module in factory diamond + + IDiamondCut.FacetCut[] memory DMSCut = new IDiamondCut.FacetCut[](1); + DMSCut[0] = IDiamondCut.FacetCut({ + facetAddress: address(switchFacet), + action: IDiamondCut.FacetCutAction.Add, + functionSelectors: generateSelectors("DMSFacet") + }); + + IModuleData.ModuleData[] memory DMSdata = new IModuleData.ModuleData[]( + 1 + ); + DMSdata[0].facetData = DMSCut; + + string[] memory DMSselectorName = new string[](1); + DMSselectorName[0] = "DMS"; + + ModuleRegistryFacet(address(vFactoryDiamond)).addModules(DMSdata, DMSselectorName); + //upgrade DMS Module Vault diamond + vm.prank(vault1Owner); + ModuleManagerFacet(address(vault1)).upgradeVaultWithModule("DMS"); + + //export contract types + v1ERC20Facet = ERC20Facet(vault1); + v1ERC721Facet = ERC721Facet(vault1); + v1ERC1155Facet = ERC1155Facet(vault1); + v1EtherFacet = EtherFacet(vault1); + v1dmsFacet = DMSFacet(vault1); + ownerFacet = OwnershipFacet(vault1); + + vm.prank(vault1Owner); + v1dmsFacet.addInheritors(toSingletonAdd(vault1Inheritor1), toSingletonUINT(10000)); + } -// erc20t.balanceOf(msg.sender); + function testDefaultModules() public { + // OwnershipFacet(address(vault1)).owner(); -// ERC20Facet(vault1).depositERC20Token(address(erc20t),1000000); -// VaultFacet(vault1).inspectVault(); -// VaultFacet(vault1).allEtherAllocations(); - } + vm.startPrank(vault1Owner); + OwnershipFacet(address(vault1)).owner(); + // upgrade an already existing vault + ModuleManagerFacet(address(vault1)).getActiveModules(); + vm.expectRevert(ModuleAlreadyInstalled.selector); + ModuleManagerFacet(address(vault1)).upgradeVaultWithModule("Selector"); + // downgrade an already exosting vault + ModuleManagerFacet(address(vault1)).downgradeVaultWithModule("Selector"); + // vm.stopPrank(); + } + function testUpgradeModule() public { + ModuleManagerFacet(address(vault1)).getActiveModules(); + ModuleManagerFacet(address(vault1)).isActiveModule("DMS"); + } - function generateSelectors(string memory _facetName) - internal - returns (bytes4[] memory selectors) - { + function generateSelectors(string memory _facetName) internal returns (bytes4[] memory selectors) { string[] memory cmd = new string[](3); cmd[0] = "node"; cmd[1] = "scripts/genSelectors.js"; @@ -191,119 +269,51 @@ console.log(stdMath.delta(uint256(j),uint256(k))); selectors = abi.decode(res, (bytes4[])); } - function diamondCut( - FacetCut[] calldata _diamondCut, - address _init, - bytes calldata _calldata - ) external override {} - - function mkaddr(string memory name) public returns (address){ - address addr=address(uint160(uint256(keccak256(abi.encodePacked(name))))); - vm.label(addr,name); + function mkaddr(string memory name) public returns (address) { + address addr = address(uint160(uint256(keccak256(abi.encodePacked(name))))); + vm.label(addr, name); return addr; } - - function onERC1155Received( - address, - address, - uint256, - uint256, - bytes calldata - ) external virtual returns (bytes4) { - return ERC1155TokenReceiver.onERC1155Received.selector; - } - - function onERC1155BatchReceived( - address, - address, - uint256[] calldata, - uint256[] calldata, - bytes calldata - ) external virtual returns (bytes4) { - return ERC1155TokenReceiver.onERC1155BatchReceived.selector; - } - - function onERC721Received( - address, - address, - uint256, - bytes calldata - ) external virtual returns (bytes4) { - return ERC721TokenReceiver.onERC721Received.selector; - } - } -//free functions - - function toSingletonUINT(uint256 _no) - - pure - returns (uint256[] memory) - { - uint256[] memory arr = new uint256[](1); - arr[0] = _no; - return arr; - } - - function toSingletonAdd(address _no) - - pure - returns (address[] memory) - { - address[] memory arr = new address[](1); - arr[0] = _no; - return arr; - } - - function toDualUINT(uint256 _no,uint256 _no2) - - pure - returns (uint256[] memory) - { - uint256[] memory arr = new uint256[](2); - arr[0] = _no; - arr[1]=_no2; - return arr; - } - - function toDualAdd(address _no,address _no2) - - pure - returns (address[] memory) - { - address[] memory arr = new address[](2); - arr[0] = _no; - arr[1]=_no2; - return arr; - } - - function toTriUINT(uint256 _no,uint256 _no2,uint256 _no3) - - pure - returns (uint256[] memory) - { - uint256[] memory arr = new uint256[](3); - arr[0] = _no; - arr[1]=_no2; - arr[2]=_no3; - return arr; - } +function toSingletonUINT(uint256 _no) pure returns (uint256[] memory) { + uint256[] memory arr = new uint256[](1); + arr[0] = _no; + return arr; +} - function toTriAddress(address _add,address _add2,address _add3) - - pure - returns (address[] memory) - { - address[] memory arr = new address[](3); - arr[0] = _add; - arr[1]=_add2; - arr[2]=_add3; - return arr; - } +function toSingletonAdd(address _no) pure returns (address[] memory) { + address[] memory arr = new address[](1); + arr[0] = _no; + return arr; +} - +function toDualUINT(uint256 _no, uint256 _no2) pure returns (uint256[] memory) { + uint256[] memory arr = new uint256[](2); + arr[0] = _no; + arr[1] = _no2; + return arr; +} - +function toDualAdd(address _no, address _no2) pure returns (address[] memory) { + address[] memory arr = new address[](2); + arr[0] = _no; + arr[1] = _no2; + return arr; +} +function toTriUINT(uint256 _no, uint256 _no2, uint256 _no3) pure returns (uint256[] memory) { + uint256[] memory arr = new uint256[](3); + arr[0] = _no; + arr[1] = _no2; + arr[2] = _no3; + return arr; +} +function toTriAddress(address _add, address _add2, address _add3) pure returns (address[] memory) { + address[] memory arr = new address[](3); + arr[0] = _add; + arr[1] = _add2; + arr[2] = _add3; + return arr; +} diff --git a/test/ERC1155FacetTest.t.sol b/test/ERC1155FacetTest.t.sol index 7bd0503..db1c4fe 100644 --- a/test/ERC1155FacetTest.t.sol +++ b/test/ERC1155FacetTest.t.sol @@ -3,92 +3,152 @@ pragma solidity 0.8.4; import "./DiamondDeployments.sol"; import "../contracts/Vault/libraries/LibDMS.sol"; -import "../contracts/Vault/facets/ERC1155Facet.sol"; - - -contract ERC1155FacetTest is DDeployments{ -address depositor1; - -function testERC1155VaultOperations() public{ -depositor1=mkaddr('depositor1'); - -//mint some tokens to depositor1 -vm.startPrank(depositor1); -//NFT 1 -erc1155t.mint(depositor1,0,2); -erc1155t.mint(depositor1,1,2); -erc1155t.mint(depositor1,2,2); -erc1155t.mint(depositor1,3,2); - -//NFT 2 -erc1155t2.mint(depositor1,0,2); -erc1155t2.mint(depositor1,1,2); -erc1155t2.mint(depositor1,2,2); -erc1155t2.mint(depositor1,3,2); - - -//approve diamond to spend all tokens -erc1155t.setApprovalForAll(vault1,true); -erc1155t2.setApprovalForAll(vault1,true); - -//deposit NFTs singlularly -v1ERC1155Facet.depositERC1155Token(address(erc1155t),0,2); -v1ERC1155Facet.depositERC1155Token(address(erc1155t2),0,2); - -//batch deposit -//make sure a failure does not reverts the whole txn -vm.expectRevert(stdError.arithmeticError -); -v1ERC1155Facet.batchDepositERC1155Tokens(address(erc1155t),toTriUINT(1,2,3),toTriUINT(2,2,5)); - - -//deposit tokens normally -v1ERC1155Facet.batchDepositERC1155Tokens(address(erc1155t),toTriUINT(1,2,3),toTriUINT(2,2,2)); -v1ERC1155Facet.batchDepositERC1155Tokens(address(erc1155t2),toTriUINT(1,2,3),toTriUINT(2,2,2)); - -vm.stopPrank(); - -vm.startPrank(vault1Owner); - -///ALLOCATIONS -//try to allocate a token with overflowing balance -vm.expectRevert(abi.encodeWithSelector(LibDMS.TokenAllocationOverflow.selector,address(erc1155t),1)); -v1VaultFacet.allocateERC1155Tokens(address(erc1155t),toDualAdd(vault1Inheritor1,vault1Inheritor2),toDualUINT(0,1),toDualUINT(3,3)); - -//add inheritor2 -v1VaultFacet.addInheritors(toSingletonAdd(vault1Inheritor2),toSingletonUINT(1000 wei)); - -//allocate normally -//allocating id 0 and 1 -v1VaultFacet.allocateERC1155Tokens(address(erc1155t),toDualAdd(vault1Inheritor1,vault1Inheritor2),toDualUINT(0,1),toDualUINT(2,2)); -v1VaultFacet.allocateERC1155Tokens(address(erc1155t2),toDualAdd(vault1Inheritor1,vault1Inheritor2),toDualUINT(0,1),toDualUINT(2,2)); - - -//allocating id 2 and 3 -v1VaultFacet.allocateERC1155Tokens(address(erc1155t),toDualAdd(vault1Inheritor1,vault1Inheritor2),toDualUINT(2,3),toDualUINT(2,2)); -v1VaultFacet.allocateERC1155Tokens(address(erc1155t2),toDualAdd(vault1Inheritor1,vault1Inheritor2),toDualUINT(2,3),toDualUINT(2,2)); - -//confirm storage -ERC1155Facet.AllAllocatedERC1155Tokens[] memory inheritor1Allocs=v1ERC1155Facet.getAllAllocatedERC1155Tokens(vault1Inheritor1); -ERC1155Facet.AllAllocatedERC1155Tokens[] memory inheritor2Allocs=v1ERC1155Facet.getAllAllocatedERC1155Tokens(vault1Inheritor2); - -//2 tokens allocated -assertEq(inheritor2Allocs.length,2); - -//cannot withdraw allocated tokens -vm.expectRevert('UnAllocate TokensFirst'); -v1ERC1155Facet.withdrawERC1155Token(address(erc1155t2),3,2,depositor1); - -//make sure unallocation removes address completely -//completely unallocating tokenID 3 from inheritor2 -v1VaultFacet.allocateERC1155Tokens(address(erc1155t2),toSingletonAdd(vault1Inheritor2),toSingletonUINT(3),toSingletonUINT(0)); - inheritor2Allocs=v1ERC1155Facet.getAllAllocatedERC1155Tokens(vault1Inheritor2); - assertEq(inheritor2Allocs.length,1); - -//can successfully withdraw now -v1ERC1155Facet.withdrawERC1155Token(address(erc1155t2),3,2,depositor1); - +contract ERC1155FacetTest is DDeployments { + address depositor1; + + function testERC1155VaultOperations() public { + depositor1 = mkaddr("depositor1"); + + //mint some tokens to depositor1 + vm.startPrank(depositor1); + //NFT 1 + erc1155t.mint(depositor1, 0, 2); + erc1155t.mint(depositor1, 1, 2); + erc1155t.mint(depositor1, 2, 2); + erc1155t.mint(depositor1, 3, 2); + + //NFT 2 + erc1155t2.mint(depositor1, 0, 2); + erc1155t2.mint(depositor1, 1, 2); + erc1155t2.mint(depositor1, 2, 2); + erc1155t2.mint(depositor1, 3, 2); + + //approve diamond to spend all tokens + erc1155t.setApprovalForAll(vault1, true); + erc1155t2.setApprovalForAll(vault1, true); + + //deposit NFTs singlularly + v1ERC1155Facet.depositERC1155Token(address(erc1155t), 0, 2); + v1ERC1155Facet.depositERC1155Token(address(erc1155t2), 0, 2); + + //batch deposit + //make sure a failure does not reverts the whole txn + vm.expectRevert(stdError.arithmeticError); + v1ERC1155Facet.batchDepositERC1155Tokens( + address(erc1155t), + toTriUINT(1, 2, 3), + toTriUINT(2, 2, 5) + ); + + //deposit tokens normally + v1ERC1155Facet.batchDepositERC1155Tokens( + address(erc1155t), + toTriUINT(1, 2, 3), + toTriUINT(2, 2, 2) + ); + v1ERC1155Facet.batchDepositERC1155Tokens( + address(erc1155t2), + toTriUINT(1, 2, 3), + toTriUINT(2, 2, 2) + ); + + vm.stopPrank(); + + vm.startPrank(vault1Owner); + + ///ALLOCATIONS + //try to allocate a token with overflowing balance + vm.expectRevert( + abi.encodeWithSelector( + LibDMS.TokenAllocationOverflow.selector, + address(erc1155t), + 1 + ) + ); + v1dmsFacet.allocateERC1155Tokens( + address(erc1155t), + toDualAdd(vault1Inheritor1, vault1Inheritor2), + toDualUINT(0, 1), + toDualUINT(3, 3) + ); + + //add inheritor2 + v1dmsFacet.addInheritors( + toSingletonAdd(vault1Inheritor2), + toSingletonUINT(1000 wei) + ); + + //allocate normally + //allocating id 0 and 1 + v1dmsFacet.allocateERC1155Tokens( + address(erc1155t), + toDualAdd(vault1Inheritor1, vault1Inheritor2), + toDualUINT(0, 1), + toDualUINT(2, 2) + ); + v1dmsFacet.allocateERC1155Tokens( + address(erc1155t2), + toDualAdd(vault1Inheritor1, vault1Inheritor2), + toDualUINT(0, 1), + toDualUINT(2, 2) + ); + + //allocating id 2 and 3 + v1dmsFacet.allocateERC1155Tokens( + address(erc1155t), + toDualAdd(vault1Inheritor1, vault1Inheritor2), + toDualUINT(2, 3), + toDualUINT(2, 2) + ); + v1dmsFacet.allocateERC1155Tokens( + address(erc1155t2), + toDualAdd(vault1Inheritor1, vault1Inheritor2), + toDualUINT(2, 3), + toDualUINT(2, 2) + ); + + //confirm storage + DMSFacet.AllAllocatedERC1155Tokens[] + memory inheritor1Allocs = v1dmsFacet.getAllAllocatedERC1155Tokens( + vault1Inheritor1 + ); + DMSFacet.AllAllocatedERC1155Tokens[] + memory inheritor2Allocs = v1dmsFacet.getAllAllocatedERC1155Tokens( + vault1Inheritor2 + ); + + //2 tokens allocated + assertEq(inheritor2Allocs.length, 2); + + //cannot withdraw allocated tokens + vm.expectRevert("UnAllocate TokensFirst"); + v1ERC1155Facet.withdrawERC1155Token( + address(erc1155t2), + 3, + 2, + depositor1 + ); + + //make sure unallocation removes address completely + //completely unallocating tokenID 3 from inheritor2 + v1dmsFacet.allocateERC1155Tokens( + address(erc1155t2), + toSingletonAdd(vault1Inheritor2), + toSingletonUINT(3), + toSingletonUINT(0) + ); + inheritor2Allocs = v1dmsFacet.getAllAllocatedERC1155Tokens( + vault1Inheritor2 + ); + assertEq(inheritor2Allocs.length, 1); + + //can successfully withdraw now + v1ERC1155Facet.withdrawERC1155Token( + address(erc1155t2), + 3, + 2, + depositor1 + ); + } } - -} \ No newline at end of file diff --git a/test/ERC20FacetTest.t.sol b/test/ERC20FacetTest.t.sol index 8b4912b..b24046f 100644 --- a/test/ERC20FacetTest.t.sol +++ b/test/ERC20FacetTest.t.sol @@ -2,8 +2,11 @@ pragma solidity 0.8.4; import "./DiamondDeployments.sol"; import "../contracts/Vault/libraries/LibDiamond.sol"; +import {InsufficientTokens} from "../contracts/Vault/libraries/LibTokens.sol"; import "../contracts/Vault/libraries/LibDMS.sol"; +// import "../contracts/Vault/libraries/LibKeep.sol"; + contract ERC20FacetTest is DDeployments { uint256 snapshotId; address depositor1; @@ -24,19 +27,20 @@ contract ERC20FacetTest is DDeployments { //attempt to deposit 2 tokens //making sure a failure doesn't revert the whole txn v1ERC20Facet.depositERC20Tokens( - toDualAdd(address(erc20t), address(erc20t2)), toDualUINT(maxDepositorBalance + 10, maxDepositorBalance) + toDualAdd(address(erc20t), address(erc20t2)), + toDualUINT(maxDepositorBalance + 10, maxDepositorBalance) ); //confirm deposit assertEq(erc20t2.balanceOf(vault1), maxDepositorBalance); assertEq(erc20t.balanceOf(vault1), 0); - //finally deposit properly + // finally deposit properly v1ERC20Facet.depositERC20Token(address(erc20t), maxDepositorBalance); assertEq(erc20t.balanceOf(vault1), maxDepositorBalance); - //withdraw some erc20 tokens - //you have to be the owner + // withdraw some erc20 tokens + // you have to be the owner vm.expectRevert(LibDiamond.NotVaultOwner.selector); v1ERC20Facet.withdrawERC20Token(address(erc20t), 10e18, depositor1); vm.stopPrank(); @@ -46,9 +50,11 @@ contract ERC20FacetTest is DDeployments { uint256 v1erc20BalanceT1 = erc20t.balanceOf(vault1); uint256 v1erc20BalanceT2 = erc20t2.balanceOf(vault1); vm.startPrank(vault1Owner); - vm.expectRevert(LibDMS.InsufficientTokens.selector); + vm.expectRevert(InsufficientTokens.selector); v1ERC20Facet.batchWithdrawERC20Token( - toDualAdd(address(erc20t), address(erc20t2)), toDualUINT(v1erc20BalanceT1, v1erc20BalanceT2 + 10), depositor1 + toDualAdd(address(erc20t), address(erc20t2)), + toDualUINT(v1erc20BalanceT1, v1erc20BalanceT2 + 10), + depositor1 ); //withdraw normally @@ -63,61 +69,121 @@ contract ERC20FacetTest is DDeployments { assertEq(erc20t2.balanceOf(vault1), 0); assertEq(erc20t.balanceOf(vault1), maxDepositorBalance - 10e18); + ////ADD INHERITORS ///ALLOCATIONS - //Allocating a non-existent token - vm.expectRevert(abi.encodeWithSelector(LibDMS.TokenAllocationOverflow.selector, address(erc20t2), 100e18)); - v1VaultFacet.allocateERC20Tokens(address(erc20t2), toSingletonAdd(vault1Inheritor1), toSingletonUINT(100e18)); + // Allocating a non-existent token + vm.expectRevert( + abi.encodeWithSelector( + LibDMS.TokenAllocationOverflow.selector, + address(erc20t2), + 100e18 + ) + ); + v1dmsFacet.allocateERC20Tokens( + address(erc20t2), + toSingletonAdd(vault1Inheritor1), + toSingletonUINT(100e18) + ); - //Allocating to a non-inheritor + // Allocating to a non-inheritor vm.expectRevert(LibDMS.NotInheritor.selector); - v1VaultFacet.allocateERC20Tokens(address(erc20t2), toSingletonAdd(vault1Inheritor2), toSingletonUINT(100e18)); + v1dmsFacet.allocateERC20Tokens( + address(erc20t2), + toSingletonAdd(vault1Inheritor2), + toSingletonUINT(100e18) + ); - //add inheritor 2 - v1VaultFacet.addInheritors(toSingletonAdd(vault1Inheritor2), toSingletonUINT(1000 wei)); + // add inheritor 2 + v1dmsFacet.addInheritors( + toSingletonAdd(vault1Inheritor2), + toSingletonUINT(1000 wei) + ); //Allocate normally //Allocate all token T1 present in vault 1 v1erc20BalanceT1 = erc20t.balanceOf(vault1); - v1VaultFacet.allocateERC20Tokens( - address(erc20t), toSingletonAdd(vault1Inheritor2), toSingletonUINT(v1erc20BalanceT1) + v1dmsFacet.allocateERC20Tokens( + address(erc20t), + toSingletonAdd(vault1Inheritor2), + toSingletonUINT(v1erc20BalanceT1) ); //try to allocate token T1 to the first inheritor //should overflow - vm.expectRevert(abi.encodeWithSelector(LibDMS.TokenAllocationOverflow.selector, address(erc20t), 50e18)); - v1VaultFacet.allocateERC20Tokens(address(erc20t), toSingletonAdd(vault1Inheritor1), toSingletonUINT(50e18)); + vm.expectRevert( + abi.encodeWithSelector( + LibDMS.TokenAllocationOverflow.selector, + address(erc20t), + 50e18 + ) + ); + v1dmsFacet.allocateERC20Tokens( + address(erc20t), + toSingletonAdd(vault1Inheritor1), + toSingletonUINT(50e18) + ); //free up 50 tokens from inheritor2 by unallocating them - uint256 inheritor2T1Alloc = v1ERC20Facet.inheritorERC20TokenAllocation(vault1Inheritor2, address(erc20t)); - v1VaultFacet.allocateERC20Tokens( - address(erc20t), toSingletonAdd(vault1Inheritor2), toSingletonUINT(inheritor2T1Alloc - 50e18) + uint256 inheritor2T1Alloc = v1dmsFacet.inheritorERC20TokenAllocation( + vault1Inheritor2, + address(erc20t) + ); + v1dmsFacet.allocateERC20Tokens( + address(erc20t), + toSingletonAdd(vault1Inheritor2), + toSingletonUINT(inheritor2T1Alloc - 50e18) ); //allocate to inheritor1 normally now - v1VaultFacet.allocateERC20Tokens(address(erc20t), toSingletonAdd(vault1Inheritor1), toSingletonUINT(50e18)); + v1dmsFacet.allocateERC20Tokens( + address(erc20t), + toSingletonAdd(vault1Inheritor1), + toSingletonUINT(50e18) + ); - //confirm allocation - assertEq(v1ERC20Facet.inheritorERC20TokenAllocation(vault1Inheritor1, address(erc20t)), 50e18); + // confirm allocation + assertEq( + v1dmsFacet.inheritorERC20TokenAllocation( + vault1Inheritor1, + address(erc20t) + ), + 50e18 + ); - //vault owner cannot withdraw any T1 tokens - vm.expectRevert(LibDMS.InsufficientTokens.selector); - v1ERC20Facet.withdrawERC20Token(address(erc20t), v1erc20BalanceT1, depositor1); + // //vault owner cannot withdraw any T1 tokens + vm.expectRevert(InsufficientTokens.selector); + v1ERC20Facet.withdrawERC20Token( + address(erc20t), + v1erc20BalanceT1, + depositor1 + ); //unallocate from an inheritor to free up some tokens - inheritor2T1Alloc = v1ERC20Facet.inheritorERC20TokenAllocation(vault1Inheritor2, address(erc20t)); - v1VaultFacet.allocateERC20Tokens( - address(erc20t), toSingletonAdd(vault1Inheritor1), toSingletonUINT(inheritor2T1Alloc - 20e18) + inheritor2T1Alloc = v1dmsFacet.inheritorERC20TokenAllocation( + vault1Inheritor2, + address(erc20t) + ); + v1dmsFacet.allocateERC20Tokens( + address(erc20t), + toSingletonAdd(vault1Inheritor2), + toSingletonUINT(inheritor2T1Alloc - 20e18) ); - //withdraw all free tokens - uint256 unall = v1ERC20Facet.getUnallocatedTokens(address(erc20t)); + // //withdraw all free tokens + uint256 unall = v1dmsFacet.getUnallocatedTokens(address(erc20t)); v1ERC20Facet.withdrawERC20Token(address(erc20t), unall, depositor1); - //vault T1 balance should now be made up of all inheritor allocations ONLY - uint256 inheritor1T1Alloc = v1ERC20Facet.inheritorERC20TokenAllocation(vault1Inheritor1, address(erc20t)); - inheritor2T1Alloc = v1ERC20Facet.inheritorERC20TokenAllocation(vault1Inheritor2, address(erc20t)); + // //vault T1 balance should now be made up of all inheritor allocations ONLY + uint256 inheritor1T1Alloc = v1dmsFacet.inheritorERC20TokenAllocation( + vault1Inheritor1, + address(erc20t) + ); + inheritor2T1Alloc = v1dmsFacet.inheritorERC20TokenAllocation( + vault1Inheritor2, + address(erc20t) + ); v1erc20BalanceT1 = erc20t.balanceOf(vault1); assertEq(v1erc20BalanceT1, inheritor1T1Alloc + inheritor2T1Alloc); } diff --git a/test/ERC721FacetTest.t.sol b/test/ERC721FacetTest.t.sol index fc91826..0fbe4f1 100644 --- a/test/ERC721FacetTest.t.sol +++ b/test/ERC721FacetTest.t.sol @@ -1,98 +1,100 @@ pragma solidity 0.8.4; import "./DiamondDeployments.sol"; - +import "../contracts/Vault/libraries/LibDiamond.sol"; +import {InsufficientTokens} from "../contracts/Vault/libraries/LibTokens.sol"; import "../contracts/Vault/libraries/LibDMS.sol"; -import "../contracts/Vault/facets/ERC721Facet.sol"; - - -contract ERC721FacetTest is DDeployments{ -address depositor1; - -function testERC721VaultOperations() public{ -depositor1=mkaddr('depositor1'); - -//mint some tokens to depositor1 -vm.startPrank(depositor1); -//NFT 1 -erc721t.mint(depositor1,0); -erc721t.mint(depositor1,1); -erc721t.mint(depositor1,2); -erc721t.mint(depositor1,3); - -//NFT 2 -erc721t2.mint(depositor1,0); -erc721t2.mint(depositor1,1); -erc721t2.mint(depositor1,2); -erc721t2.mint(depositor1,3); - - -//approve diamond to spend all tokens -erc721t.setApprovalForAll(vault1,true); -erc721t2.setApprovalForAll(vault1,true); - - -// deposit multiple tokens -v1ERC721Facet.depositERC721Tokens(address(erc721t),toTriUINT(0,1,2)); -v1ERC721Facet.depositERC721Tokens(address(erc721t2),toTriUINT(0,1,2)); - -//confirm deposit -assertEq(erc721t.balanceOf(vault1),3); -assertEq(erc721t2.balanceOf(vault1),3); - -vm.stopPrank(); -vm.startPrank(vault1Owner); - - -//ALLOCATIONS -//trying to allocate a non existent token should not revert the whole txn -v1VaultFacet.allocateERC721Tokens(address(erc721t),toSingletonAdd(vault1Inheritor1),toSingletonUINT(9)); - -//trying to allocate a token not owned by the vault should not revert the whole txn -v1VaultFacet.allocateERC721Tokens(address(erc721t),toDualAdd(vault1Inheritor1,vault1Inheritor1),toDualUINT(0,3)); - -//confirm storage -ERC721Facet.AllocatedERC721Tokens[] memory vault1Inheritor1Alloc= v1ERC721Facet.getAllocatedERC721Tokens(vault1Inheritor1); -assertEq(vault1Inheritor1Alloc[0].token,address(erc721t)); -assertEq(vault1Inheritor1Alloc[0].tokenIDs[0],0); - -//cannot withdraw an allocated NFT -vm.expectRevert("UnAllocate Token First"); -v1ERC721Facet.withdrawERC721Token(address(erc721t),0,vault1Owner); - -//add inheritor2 -v1VaultFacet.addInheritors(toSingletonAdd(vault1Inheritor2),toSingletonUINT(1000 wei)); - -//can easily reallocate tokens to inheritor2 -v1VaultFacet.allocateERC721Tokens(address(erc721t),toSingletonAdd(vault1Inheritor2),toSingletonUINT(0)); - -//confirm storage -ERC721Facet.AllocatedERC721Tokens[] memory vault1Inheritor2Alloc= v1ERC721Facet.getAllocatedERC721Tokens(vault1Inheritor2); -assertEq(vault1Inheritor2Alloc[0].token,address(erc721t)); -assertEq(vault1Inheritor2Alloc[0].tokenIDs[0],0); - -//make sure token is unallocated from previous inheritor -vault1Inheritor1Alloc= v1ERC721Facet.getAllocatedERC721Tokens(vault1Inheritor1); -assertEq(vault1Inheritor1Alloc.length,0); - - -//unallocate and withdraw -v1VaultFacet.allocateERC721Tokens(address(erc721t),toSingletonAdd(address(0)),toSingletonUINT(0)); -assertEq(v1ERC721Facet.getAllocatedERC721TokenIds(vault1Inheritor2,address(erc721t)).length,0); - //withdraw the token -v1ERC721Facet.withdrawERC721Token(address(erc721t),0,vault1Owner); -//confirm ownership -assertEq(erc721t.ownerOf(0),vault1Owner); - -//cannot allocate to non existent inheritor -vm.expectRevert(LibDMS.NotInheritor.selector); -v1VaultFacet.allocateERC721Tokens(address(erc721t2),toSingletonAdd(mkaddr('noninheritor')),toSingletonUINT(1)); - -//mass allocate tokens -v1VaultFacet.allocateERC721Tokens(address(erc721t2),toTriAddress(vault1Inheritor2,vault1Inheritor2,vault1Inheritor2),toTriUINT(0,1,2)); - -//double check storage -vault1Inheritor2Alloc= v1ERC721Facet.getAllocatedERC721Tokens(vault1Inheritor2); -assertEq(vault1Inheritor2Alloc[0].tokenIDs.length,3); -}} \ No newline at end of file +contract ERC721FacetTest is DDeployments { + address depositor1; + + function testERC721VaultOperations() public { + depositor1 = mkaddr("depositor1"); + + //mint some tokens to depositor1 + vm.startPrank(depositor1); + //NFT 1 + erc721t.mint(depositor1, 0); + erc721t.mint(depositor1, 1); + erc721t.mint(depositor1, 2); + erc721t.mint(depositor1, 3); + + //NFT 2 + erc721t2.mint(depositor1, 0); + erc721t2.mint(depositor1, 1); + erc721t2.mint(depositor1, 2); + erc721t2.mint(depositor1, 3); + + //approve diamond to spend all tokens + erc721t.setApprovalForAll(vault1, true); + erc721t2.setApprovalForAll(vault1, true); + + // deposit multiple tokens + v1ERC721Facet.depositERC721Tokens(address(erc721t), toTriUINT(0, 1, 2)); + v1ERC721Facet.depositERC721Tokens(address(erc721t2), toTriUINT(0, 1, 2)); + + //confirm deposit + assertEq(erc721t.balanceOf(vault1), 3); + assertEq(erc721t2.balanceOf(vault1), 3); + + vm.stopPrank(); + vm.startPrank(vault1Owner); + + // //ALLOCATIONS + // //trying to allocate a non existent token should not revert the whole txn + v1dmsFacet.allocateERC721Tokens(address(erc721t), toSingletonAdd(vault1Inheritor1), toSingletonUINT(9)); + + // //trying to allocate a token not owned by the vault should not revert the whole txn + v1dmsFacet.allocateERC721Tokens( + address(erc721t), toDualAdd(vault1Inheritor1, vault1Inheritor1), toDualUINT(0, 3) + ); + + // //confirm storage + DMSFacet.AllocatedERC721Tokens[] memory vault1Inheritor1Alloc = + v1dmsFacet.getAllocatedERC721Tokens(vault1Inheritor1); + assertEq(vault1Inheritor1Alloc[0].token, address(erc721t)); + assertEq(vault1Inheritor1Alloc[0].tokenIDs[0], 0); + + // //cannot withdraw an allocated NFT + vm.expectRevert("UnAllocate Token First"); + v1ERC721Facet.withdrawERC721Token(address(erc721t), 0, vault1Owner); + + // //add inheritor2 + v1dmsFacet.addInheritors(toSingletonAdd(vault1Inheritor2), toSingletonUINT(1000 wei)); + + // //can easily reallocate tokens to inheritor2 + v1dmsFacet.allocateERC721Tokens(address(erc721t), toSingletonAdd(vault1Inheritor2), toSingletonUINT(0)); + v1dmsFacet.allocateERC721Tokens(address(erc721t), toSingletonAdd(vault1Inheritor2), toSingletonUINT(0)); + + // //confirm storage + DMSFacet.AllocatedERC721Tokens[] memory vault1Inheritor2Alloc = + v1dmsFacet.getAllocatedERC721Tokens(vault1Inheritor2); + assertEq(vault1Inheritor2Alloc[0].token, address(erc721t)); + assertEq(vault1Inheritor2Alloc[0].tokenIDs[0], 0); + + // //make sure token is unallocated from previous inheritor + vault1Inheritor1Alloc = v1dmsFacet.getAllocatedERC721Tokens(vault1Inheritor1); + assertEq(vault1Inheritor1Alloc.length, 0); + + // //unallocate and withdraw + v1dmsFacet.allocateERC721Tokens(address(erc721t), toSingletonAdd(address(0)), toSingletonUINT(0)); + assertEq(v1dmsFacet.getAllocatedERC721TokenIds(vault1Inheritor2, address(erc721t)).length, 0); + // //withdraw the token + v1ERC721Facet.withdrawERC721Token(address(erc721t), 0, vault1Owner); + // //confirm ownership + assertEq(erc721t.ownerOf(0), vault1Owner); + + // //cannot allocate to non existent inheritor + vm.expectRevert((LibDMS.NotInheritor.selector)); + v1dmsFacet.allocateERC721Tokens(address(erc721t2), toSingletonAdd(mkaddr("noninheritor")), toSingletonUINT(1)); + + // //mass allocate tokens + v1dmsFacet.allocateERC721Tokens( + address(erc721t2), toTriAddress(vault1Inheritor2, vault1Inheritor2, vault1Inheritor2), toTriUINT(0, 1, 2) + ); + + // //double check storage + vault1Inheritor2Alloc = v1dmsFacet.getAllocatedERC721Tokens(vault1Inheritor2); + assertEq(vault1Inheritor2Alloc[0].tokenIDs.length, 3); + } +} diff --git a/test/EtherOpsTests.t.sol b/test/EtherOpsTests.t.sol index 7b99295..8230fe0 100644 --- a/test/EtherOpsTests.t.sol +++ b/test/EtherOpsTests.t.sol @@ -1,61 +1,60 @@ pragma solidity 0.8.4; import "./DiamondDeployments.sol"; -import "../contracts/Vault/libraries/LibDiamond.sol"; +// import "../contracts/Vault/libraries/LibDiamond.sol"; import "../contracts/Vault/libraries/LibDMS.sol"; - -contract EtherOpsTest is DDeployments{ -// struct VaultFacet.AllInheritorEtherAllocs { -// address inheritor; -// uint256 weiAlloc; -// } - - -function testAllVaultEtherOperations() public{ -vm.startPrank(vault1Owner); - - -//get ether allocation data for all inheritors -//only one inheritor currently present -VaultFacet.AllInheritorEtherAllocs[] memory eAllocs=new VaultFacet.AllInheritorEtherAllocs[](1); -eAllocs[0]=VaultFacet.AllInheritorEtherAllocs({inheritor:vault1Inheritor1,weiAlloc:10000}); -//get data onchain -VaultFacet.AllInheritorEtherAllocs[] memory onchainAllocs=v1VaultFacet.allEtherAllocations(); -assertEq(onchainAllocs[0].inheritor,eAllocs[0].inheritor); -assertEq(onchainAllocs[0].weiAlloc,eAllocs[0].weiAlloc); - -//confirm free ether available for withdrawal -uint256 freeEther=v1VaultFacet.getUnallocatedEther(); -uint256 onchainFreeEther=v1VaultFacet.getUnallocatedEther(); -assertEq(freeEther,onchainFreeEther); - -//add another inheritor and allocate some ether -uint256 v1Inheritor2eAlloc=freeEther - 10000000; - -//try to allocate more thn available ether -vm.expectRevert(abi.encodeWithSelector(LibDMS.EtherAllocationOverflow.selector,2 ether -freeEther)); -v1VaultFacet.addInheritors(toSingletonAdd(vault1Inheritor2),toSingletonUINT(2 ether)); - -//allocate normally -v1VaultFacet.addInheritors(toSingletonAdd(vault1Inheritor2),toSingletonUINT(v1Inheritor2eAlloc)); -uint256 v1Inheritor2EtherAlloc= v1VaultFacet.inheritorEtherAllocation(vault1Inheritor2); -assertEq(v1Inheritor2EtherAlloc,freeEther - 10000000); - -//try to withdraw more than available -freeEther=v1VaultFacet.getUnallocatedEther(); -vm.expectRevert(LibDMS.InsufficientEth.selector); -v1VaultFacet.withdrawEther(freeEther+1000,vault1Owner); - -//unallocate from both inheritors -//ORDER matters(not really anymore) -v1VaultFacet.allocateEther(toDualAdd(vault1Inheritor2,vault1Inheritor1),toDualUINT(v1Inheritor2eAlloc-500,10000-500)); -v1VaultFacet.withdrawEther(freeEther+1000,vault1Owner); - -//no more free ether -freeEther=v1VaultFacet.getUnallocatedEther(); -assertEq(freeEther,0); -v1VaultFacet.allEtherAllocations(); - +import "../contracts/Vault/libraries/LibEther.sol"; + +contract EtherOpsTests is DDeployments { + // struct VaultFacet.AllInheritorEtherAllocs { + // address inheritor; + // uint256 weiAlloc; + // } + + function testAllVaultEtherOperations() public { + vm.startPrank(vault1Owner); + + // get ether allocation data for all inheritors + // only one inheritor currently present + DMSFacet.AllInheritorEtherAllocs[] memory eAllocs = new DMSFacet.AllInheritorEtherAllocs[](1); + eAllocs[0] = DMSFacet.AllInheritorEtherAllocs({inheritor: vault1Inheritor1, weiAlloc: 10000}); + //get data onchain + DMSFacet.AllInheritorEtherAllocs[] memory onchainAllocs = v1dmsFacet.allEtherAllocations(); + assertEq(onchainAllocs[0].inheritor, eAllocs[0].inheritor); + assertEq(onchainAllocs[0].weiAlloc, eAllocs[0].weiAlloc); + + //confirm free ether available for withdrawal + uint256 freeEther = v1dmsFacet.getUnallocatedEther(); + uint256 onchainFreeEther = v1dmsFacet.getUnallocatedEther(); + assertEq(freeEther, onchainFreeEther); + + //add another inheritor and allocate some ether + uint256 v1Inheritor2eAlloc = freeEther - 10000000; + + //try to allocate more thn available ether + vm.expectRevert(abi.encodeWithSelector(LibDMS.EtherAllocationOverflow.selector, 2 ether - freeEther)); + v1dmsFacet.addInheritors(toSingletonAdd(vault1Inheritor2), toSingletonUINT(2 ether)); + + //allocate normally + v1dmsFacet.addInheritors(toSingletonAdd(vault1Inheritor2), toSingletonUINT(v1Inheritor2eAlloc)); + uint256 v1Inheritor2EtherAlloc = v1dmsFacet.inheritorEtherAllocation(vault1Inheritor2); + assertEq(v1Inheritor2EtherAlloc, freeEther - 10000000); + + //try to withdraw more than available + freeEther = v1dmsFacet.getUnallocatedEther(); + vm.expectRevert(LibEther.InsufficientEth.selector); + v1EtherFacet.withdrawEther(freeEther + 1000, vault1Owner); + + //unallocate from both inheritors + //ORDER matters(not really anymore) + v1dmsFacet.allocateEther( + toDualAdd(vault1Inheritor2, vault1Inheritor1), toDualUINT(v1Inheritor2eAlloc - 500, 10000 - 500) + ); + v1EtherFacet.withdrawEther(freeEther + 1000, vault1Owner); + + //no more free ether + freeEther = v1dmsFacet.getUnallocatedEther(); + assertEq(freeEther, 0); + v1dmsFacet.allEtherAllocations(); + } } - -} \ No newline at end of file diff --git a/test/MockERC1155.sol b/test/MockERC1155.sol index ee15922..322edb9 100644 --- a/test/MockERC1155.sol +++ b/test/MockERC1155.sol @@ -1,9 +1,9 @@ pragma solidity 0.8.4; -import "solmate.git/tokens/ERC1155.sol"; -contract VaultERC1155Token is ERC1155{ +import "solmate.git/tokens/ERC1155.sol"; - function mint(address _to,uint256 _id,uint256 _amount) public{ - _mint(_to,_id,_amount,""); +contract VaultERC1155Token is ERC1155 { + function mint(address _to, uint256 _id, uint256 _amount) public { + _mint(_to, _id, _amount, ""); } -} \ No newline at end of file +} diff --git a/test/MockERC20.sol b/test/MockERC20.sol index 3411afc..f7ca00b 100644 --- a/test/MockERC20.sol +++ b/test/MockERC20.sol @@ -2,10 +2,8 @@ pragma solidity 0.8.4; import "solmate.git/tokens/ERC20.sol"; -contract VaultERC20Token is ERC20("VAULTTOKEN", "VLT",18) { - - - function mint(address _to,uint256 _amount) public{ - _mint(_to,_amount); +contract VaultERC20Token is ERC20("VAULTTOKEN", "VLT", 18) { + function mint(address _to, uint256 _amount) public { + _mint(_to, _amount); } } diff --git a/test/MockERC721.sol b/test/MockERC721.sol index 4901cb4..57e832d 100644 --- a/test/MockERC721.sol +++ b/test/MockERC721.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.4; import "solmate.git/tokens/ERC721.sol"; contract VaultERC721Token is ERC721("VAULTNFT", "VNFT") { - function mint(address _to,uint256 _id) public{ - _mint(_to,_id); + function mint(address _to, uint256 _id) public { + _mint(_to, _id); } } diff --git a/test/VaultFacetTests.t.sol b/test/VaultFacetTests.t.sol deleted file mode 100644 index ea2d827..0000000 --- a/test/VaultFacetTests.t.sol +++ /dev/null @@ -1,150 +0,0 @@ -import "./DiamondDeployments.sol"; - -import "../contracts/Vault/libraries/LibDMS.sol"; -import "../contracts/Vault/facets/VaultFacet.sol"; - -contract VaultFacetTest is DDeployments { - function testVaultOperations() public { - address depositor1 = mkaddr("depositor1"); - //mint some tokens to depositor1 - vm.startPrank(depositor1); - //mint and deposit all token types - erc1155t.mint(depositor1, 0, 2); - erc20t.mint(depositor1, 100e18); - erc721t.mint(depositor1, 0); - - //approve - erc1155t.setApprovalForAll(vault1, true); - erc20t.approve(vault1, 10000e18); - erc721t.setApprovalForAll(vault1, true); - - //deposit - v1ERC20Facet.depositERC20Tokens( - toSingletonAdd(address(erc20t)), - toSingletonUINT(100e18) - ); - - v1ERC721Facet.depositERC721Tokens(address(erc721t), toSingletonUINT(0)); - - v1ERC1155Facet.batchDepositERC1155Tokens( - address(erc1155t), - toSingletonUINT(0), - toSingletonUINT(2) - ); - - vm.stopPrank(); - - vm.startPrank(vault1Owner); - //test inheritor addition and removal - //add another inheritor - v1VaultFacet.addInheritors( - toSingletonAdd(vault1Inheritor2), - toSingletonUINT(1000 wei) - ); - VaultFacet.VaultInfo memory vInfo = v1VaultFacet.inspectVault(); - assertEq(vInfo.inheritors.length, 2); - - //cannot remove a non existent inheritor - vm.expectRevert(LibDMS.NotInheritor.selector); - v1VaultFacet.removeInheritors(toSingletonAdd(mkaddr("non-existent"))); - - //allocate some erc20,erc721 and erc1155 tokens to an inheritor - //erc20 - v1VaultFacet.allocateERC20Tokens( - address(erc20t), - toSingletonAdd(vault1Inheritor1), - toSingletonUINT(100e18) - ); - - //erc721 - v1VaultFacet.allocateERC721Tokens( - address(erc721t), - toSingletonAdd(vault1Inheritor1), - toSingletonUINT(0) - ); - - //erc1155 - v1VaultFacet.allocateERC1155Tokens( - address(erc1155t), - toSingletonAdd(vault1Inheritor1), - toSingletonUINT(0), - toSingletonUINT(2) - ); - - //confirm allocations - v1ERC1155Facet.getAllAllocatedERC1155Tokens(vault1Inheritor1); - v1ERC20Facet.getAllocatedERC20Tokens(vault1Inheritor1); - v1ERC721Facet.getAllocatedERC721Tokens(vault1Inheritor1); - - v1VaultFacet.removeInheritors(toSingletonAdd(vault1Inheritor1)); - - //re-confirm allocations - assertEq( - v1ERC1155Facet - .getAllAllocatedERC1155Tokens(vault1Inheritor1) - .length, - 0 - ); - assertEq( - v1ERC20Facet.getAllocatedERC20Tokens(vault1Inheritor1).length, - 0 - ); - assertEq( - v1ERC721Facet.getAllocatedERC721Tokens(vault1Inheritor1).length, - 0 - ); - - vInfo = v1VaultFacet.inspectVault(); - assertEq(vInfo.inheritors.length, 1); - - -//TESTS FOR OWNERSHIP TRANSFER AND BACKUP -address newVault1Owner=mkaddr('NewVault1Owner'); -//transfer ownership to another address -v1VaultFacet.transferOwnership(newVault1Owner); -address newOwner=v1VaultFacet.vaultOwner(); -assertEq(newOwner,newVault1Owner); -vm.stopPrank(); -vm.startPrank(newVault1Owner); - - - //add inheritor1 again and allocate - v1VaultFacet.addInheritors( - toSingletonAdd(vault1Inheritor1), - toSingletonUINT(10000000 wei) - ); - - //erc20 - v1VaultFacet.allocateERC20Tokens( - address(erc20t), - toSingletonAdd(vault1Inheritor1), - toSingletonUINT(100e18) - ); - - //erc721 - v1VaultFacet.allocateERC721Tokens( - address(erc721t), - toSingletonAdd(vault1Inheritor1), - toSingletonUINT(0) - ); - - //erc1155 - v1VaultFacet.allocateERC1155Tokens( - address(erc1155t), - toSingletonAdd(vault1Inheritor1), - toSingletonUINT(0), - toSingletonUINT(2) - ); - - vm.stopPrank(); - - //attempt to claim - vm.warp(block.timestamp+190 days); - vm.prank(vault1Inheritor1); - v1VaultFacet.claimAllAllocations(); - //ALSO TEST BACKUP-OWNER RECLAMATION HERE -vm.prank(vault1Backup); -v1VaultFacet.claimOwnership(mkaddr('newBackup')); -//There should be a timelock after reclamation before a backup can make vault changes - } -}